《从零开始:机器学习的数学原理和算法实践》chap6

news2025/7/26 7:57:33

《从零开始:机器学习的数学原理和算法实践》chap6 学习笔记

文章目录

    • 6.1 凸函数
    • 6.2 梯度下降
      • 引入
      • 梯度是什么
        • 为啥梯度是上升最快的方向捏
      • 梯度下降与参数求解
      • 梯度下降过程演示
    • 6.3 代码实践 梯度下降
      • 一元函数的梯度下降
      • 多元函数的梯度下降

6.1 凸函数

  • 凸集

    • 何为凸集

      • 凸集表示一个欧几里得空间中的区域,这个区域具有如下特点:区域内任意两点之间的线 段都包含在该区域内;更为数学化的表述为,集合 C 内任意两点间的线段也均在集合 C 内,则 称集合 C 为凸集

      • 常见图形示例

        image-20221125095834411

  • 凸函数

    • 如果某函数的上镜图(函数曲线上的点和函数曲线上方所有的点的集合)是凸集,那么 该函数就是凸函数。

    我记得这里有些地方定义不同 👇,去查了查

    • 为什么不同教材中凸函数和凹函数的定义是不同的? 知乎 https://www.zhihu.com/question/31160556/answer/50926576

    • 算了算了,都是凸的,上凸下凸,还有头秃(bushi)

    • wiki百科关于凹凸函数的定义

    • 在这里插入图片描述

  • 机器学习”热爱“凸函数

    在这里插入图片描述

6.2 梯度下降

引入

  • 很多机器学习算法都可归结为凸优化问题的求解,因此凸优化问题在机器学习中具有特别重要的地位,而梯度下降法是最简单、也是最常见的一种最优化问题求解方法

  • 机器学习中一般将 凸优化问题统一表述为函数极小值求解问题,即 min ⁡ f ( x ) \min{f(x)} minf(x)。其中 x 是需要被优化的变量,f 为目标函 数。

    • 如果碰到极大值问题,则可以将目标函数加上负号,从而将其转换成极小值问题来求解。
    • 目标函数的自变量 x 往往受到各种约束,满足约束条件的自变量 x 的集合称为自变量的可行域。
  • 以山作比

    • 梯度下降法是一种逐步迭代、逐步缩减损失函数值,从而使损失函数值最小的方法。
    • 如果 把损失函数的值看作一个山谷,我们刚开始站立的位置可能是在半山腰,甚至可能是在山顶。 但是,只要我们往下不断迭代、不断前进,总可以到达山谷,也就是损失函数的最小值处。
    • 例 如,假设一个高度近视的人在山的某个位置上(起始点),需要从山上走下来,也就是走到山的 最低点。这个时候,他可以以当前位置点(起始点)为基准,寻找这个位置点附近最陡峭的地方,然后朝着山的高度下降的方向走,如此循环迭代,最后就可以到达山谷位置。
    • 首先,选择起始值(任意参数 ω \omega ω b b b), 由此得到损失函数的起始值
    • 其次,明确迭代方向,逐步迭代
      • 我们站在半山腰或者山顶,环顾四周,找到一个最陡的 方向下山,也就是直接指向山谷的方向下山,这样下山的速度是最快的。这个最陡在数学上的 表现就是梯度,也就是说沿着负梯度方向下降能够最快到达山谷
    • 最后确定迭代步长
      • 如果步长太大,虽然能够更快逼近山谷,但是也可能由于步子太大,踩不到谷底点, 直接就跨过了山谷的谷底,从而造成来回振荡。
      • 如果步长太小,则延长了到达山谷的时间。所 以,这需要做一下权衡和调试

image-20221125101100539

梯度是什么

  • 梯度的本质是一个向量,表示某一函数在该 点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最 快,变化率(该梯度的模)最大。一般来说,梯度可以定义为一个函数的全部偏导数构成的向 量。总结来说有如下两种情况

    • 在单变量函数中,梯度就是函数的导数,表示函数在某个给定点的切线斜率,表示单 位自变量变化引起的因变量变化值
    • 在多变量函数中,梯度就是函数分别对每个变量进行微分的结果,表示函数在给定点 上升最快的方向和单位自变量(每个自变量)变化引起的因变量变化值
  • 梯度是一个向量,它的方向就是函数在给定点上升最快的方向,因此负梯度方向就是函数 在给定点下降最快的方向。一旦我们知道了梯度,就相当于知道了凸函数下降最快的方向

为啥梯度是上升最快的方向捏

  • 这需要用到方向导数的概念,下面这几个我觉得写的不错

    • 为什么梯度反方向是函数下降最快的方向?
    • 梯度的方向为什么是函数值增加最快的方向? 知乎 https://zhuanlan.zhihu.com/p/38525412
  • 我想尝试用直观的角度来理解

    • 很多例子用下山,说下山走最陡的方向,但是怎么判断最陡峭呢?

    • 我尝试用 z = x 2 + y 2 z=x^2+y^2 z=x2+y2,从物理上矢量合成的角度来不严谨地解释一下

      • 如图是 z = x 2 + y 2 z=x^2+y^2 z=x2+y2,每个点有x方向的偏导数和y方向的偏导数

        image-20221125124641936
        • 对于一元函数z=f(y)和z=f(x)来说,每个点都可以往两个方向去变化,就是往直线的一端去或者直线的另一端去,

        • 而当变成了二元函数,就可以往四面八方去了

          偏导数组成了向量{2x,2y},那这个变化率用矢量合成我们可以这样来看

          可以看成提供了2x,-2x,2y,-2y合成的四个方向基本的力,拉着自己在山上动,

          假设我们要从x>0,y>0那块区域上山,我们在x方向和y方向上的变化率分别为在这两个方向的偏导数,可以由图比较明显的看到,要往上走得快,那应该是x方向要往x变大的方向,y方向上也应该是往y变大的方向

          那么很显然,2x和2y由平行四边形法则合成的矢量方向是很合适的,上升最快的

          而图中蓝色和红色方向上提供的力都没有那么大(呜呜很不严谨,也不知道说的对不对)

          反过来,-2x和-2y合成的那个向量就是下降最快的方向

          这段话没有组织好😭… 感觉自己想表达的意思没表达出来而且说的很乱呜呜呜,等想好了再来更新

img
  • 关于泰勒公式和梯度下降

    • https://mp.weixin.qq.com/s/k26Fm0GL3fdVA9VbQIVAuQ

    • 从泰勒公式到梯度下降 - 知乎 https://zhuanlan.zhihu.com/p/144855529

    • https://sm1les.com/2019/03/01/gradient-descent-and-newton-method/

梯度下降与参数求解

这个好像很多地方说法略有不同

image-20221125152656111

image-20221125152705394

梯度下降过程演示

  • 梯度 下降法中最重要的是如下的迭代式。

    θ 1 = θ 0 − a ∇ J ( θ ) \\\\\theta^{1}=\theta^{0}-a \nabla J(\theta) θ1=θ0aJ(θ)

    上述公式表示的含义是, 任意给定一组初始参数值 θ 0 \theta^{0} θ0, 只要沿着损失函数$ J(\theta)$ 的梯度下降 方向前进一段距离 a, 就可以得到一组新的参数值 θ 1 \theta^{1} θ1 。这里的 θ 0 \theta^{0} θ0 θ 1 \theta^{1} θ1 对应到机器学习中就是指 模型参数 (如 ω \omega ω b b b )。

  • image-20221125153453064

在这里插入图片描述

  • 关于梯度下降法,迭代结束的常见情景有两种。
    • 设置阈值。设置一个迭代结束的阈值,当两次迭代结果的差值小于该阈值时,迭代结束。
    • 设置迭代次数。设置一个迭代次数(如200),当迭代次数达到设定值,迭代结束。一般来说,只要这个迭代次数设置得足够大,损失函数最终都会停留在极值点附近。同时,采用这种方法我们也不用担心迭代次数过多会导致损失函数“跑过”极值点的情况,因为损失函数在极值点时函数梯度为0,一旦过了极值点函数梯度正负性就发生变化了,会使函数围绕极值点再次“跑回来”。所以,即使设置的迭代次数过大,最终结果也会在极值点处“徘徊”。

6.3 代码实践 梯度下降

一元函数的梯度下降

import matplotlib. pyplot as plt
import mpl_toolkits.axisartist as axisartist
import numpy as np
#创建画布
fig = plt.figure(figsize=(8,8))
#使用axisartist.Subplot方法创建绘图区对象ax
ax = axisartist.Subplot(fig,111)
#把绘图区对象添加至画布
fig.add_axes(ax)
#使用set_visible方法隐藏绘图区原有所有坐标轴
ax.axis[:].set_visible(False)
#使用ax.new_floating_axis添加新坐标轴
ax.axis["x"] = ax.new_floating_axis(0,0)
#给x轴添加箭头
ax.axis["x"].set_axisline_style("->", size = 1.0)
ax.axis["y"] = ax.new_floating_axis(1,0)
#给y轴添加箭头
ax.axis["y"].set_axisline_style("->", size = 1.0)
#设置刻度显示方向,x轴为下方显示,y轴为右侧显示
ax.axis["x"].set_axis_direction("bottom")
ax.axis["y"].set_axis_direction("right")
#x轴范围为-10~10,且分割为100份
x=np.linspace(-10,10,100)
y=x**2+3
#设置x、y轴范围
plt.xlim(-12,12)
plt.ylim(-10,100)
plt.plot(x, y)
plt.show()


def grad_1(x):
  return x*2

def grad_descent(grad,x_current,learning_rate,precision,iters_max):
  for i in range(iters_max):
    print ('第',i,'次迭代x值为:',x_current)
    grad_current=grad(x_current)
    if abs(grad_current)<precision:
      break # 当梯度值小于阈值时,停止迭代
    else:
      x_current=x_current-grad_current*learning_rate
  print ('极小值处x为:' ,x_current)
  return x_current

if __name__=="__main__":
    grad_descent(grad_1,x_current=5,learning_rate=0.1,precision=0.000001,iters_max=10000)
image-20221125155912520 	image-20221125155635902
  • 上述梯度下降中设置的 x 初始值为 5,学习率即迭代步长为 0.1
    • 当 x 初始值为 5 时,代价函数 y = x 2 + 3 y=x^2 +3 y=x2+3 的梯度为 2×5=10,学习率为 0.1。由于代价函数 的梯度值为 10,因此代价函数在 x=5 时并非极小值点。虽然该点并非极小值点,但给了我们继 续迭代的一个起始值。
    • 代价函数沿着负梯度方向下降最快,迭代步长为 0.1,因此 x 迭代的距离为 -10×0.1=-1。
    • 经过一次迭代后,x=5-1=4。此时代价函数的梯度为 2×4=8,学习率为 0.1。显然,在 x=4 处,代价函数仍然没有到达极小值点,于是继续迭代。
    • 代价函数的 x 值沿着负梯度方向迭代 -8×0.1=-0.8,于是得到新的 x=4-0.8=3.2。如此 继续……
    • 我们设置的最大迭代次数为 10 000,也就是说如果迭代次数达到 10 000,代价函数仍 然未能取到极小值,那么也要停止迭代过程,防止计算机无休止地迭代下去。 本例中迭代至第 73 次时,梯度值小于我们设置的阈值 0.000 001,我们可以认为代价函数达到 了极小值。于是,整个梯度下降过程停止

多元函数的梯度下降

import numpy as np
import matplotlib. pyplot as plt
import mpl_toolkits.mplot3d
x, y = np.mgrid[-2:2:20j,-2:2:20j] #测试数据
z=(x**2+y**2)#三维图形
ax = plt.subplot(111,projection='3d')
ax.set_title('f(x,y)=x^2+y^2') ;
ax.plot_surface(x,y,z,rstride=9,cstride=1,cmap=plt.cm.Blues_r)#设置坐标轴标签
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()

在这里插入图片描述

# 定义多元函数f(x,y)=x2+y2的梯度f'(x)=2x,f'(y)=2y, 
def grad_2(p):
      derivx = 2 * p[0]
      derivy = 2 * p[1]
      return np.array([derivx, derivy])
# 定义梯度下降函数 
def grad_descent(grad,p_current,learning_rate,precision,iters_max): 
     for i in range(iters_max):
          print ('第',i,'次迭代p值为:',p_current)
          grad_current=grad(p_current)
          if np.linalg.norm(grad_current, ord=2)<precision:
            break # 当梯度趋近于 0 时,视为收敛 
          else:
            p_current=p_current-grad_current* learning_rate 

     print ('极小值处p为:',p_current)
     return p_current
 #执行模块
if __name__=='__main__':
      grad_descent(grad_2,p_current=np.array([1,-1]),
      learning_rate=0.1,precision=0.000001,iters_max=10000) 
  	

在这里插入图片描述

image-20221125160901868

  • 上述梯度下降中设置的 p(x,y) 初始值为 [1,-1],学习率即迭代步长为 0.1
    • 当 p 初始值为 [1,-1] 时,代价函数 p(x,y)=$x^2 +y^2 $的梯度为向量 [ 2 × 1 , 2 × ( − 1 ) ] [2×1,2×(-1)] [2×1,2×(1)],学习率为 0.1。由于代价函数的梯度的模大于 0,因此代价函数在 p=[1,-1] 时并非极小值点。虽然该点并 非极小值点,但给了我们继续迭代的一个起始值。
    • 代价函数沿着负梯度方向下降最快,迭代步长为 0.1,因此 x 迭代的距离为 − [ 2 , − 2 ] × 0.1 = − [ 0.2 , − 0.2 ] -[2,-2]× 0.1=-[0.2,-0.2] [2,2]×0.1=[0.2,0.2]
    • 经过一次迭代后, p = [ 1 , − 1 ] − [ 0.2 , − 0.2 ] = [ 0.8 , − 0.8 ] p=[1,-1]-[0.2,-0.2]=[0.8,-0.8] p=[1,1][0.2,0.2]=[0.8,0.8]。此时代价函数的梯度为 2 × [ 0.8 , − 0.8 ] = [ 1.6 , − 1.6 ] 2×[0.8,-0.8]= [1.6,-1.6] 2×[0.8,0.8]=[1.6,1.6],学习率为 0.1。显然 p = [ 0.8 , − 0.8 ] p=[0.8,-0.8] p=[0.8,0.8] 处,代价函数仍然没有到达极小值点,于是继续迭代。
    • 代价函数的 p 值沿着负梯度方向迭代 − [ 1.6 , − 1.6 ] × 0.1 = − [ 0.16 , − 0.16 ] -[1.6,-1.6]×0.1=-[0.16,-0.16] [1.6,1.6]×0.1=[0.16,0.16],于是得到新的 p = [ 0.8 , − 0.8 ] − [ 0.16 , − 0.16 ] = [ 0.64 , − 0.64 ] p=[0.8,-0.8]-[0.16,-0.16]= [0.64,-0.64] p=[0.8,0.8][0.16,0.16]=[0.64,0.64]。如此继续……
      ,-2]× 0.1=-[0.2,-0.2]$。
    • 经过一次迭代后, p = [ 1 , − 1 ] − [ 0.2 , − 0.2 ] = [ 0.8 , − 0.8 ] p=[1,-1]-[0.2,-0.2]=[0.8,-0.8] p=[1,1][0.2,0.2]=[0.8,0.8]。此时代价函数的梯度为 2 × [ 0.8 , − 0.8 ] = [ 1.6 , − 1.6 ] 2×[0.8,-0.8]= [1.6,-1.6] 2×[0.8,0.8]=[1.6,1.6],学习率为 0.1。显然 p = [ 0.8 , − 0.8 ] p=[0.8,-0.8] p=[0.8,0.8] 处,代价函数仍然没有到达极小值点,于是继续迭代。
    • 代价函数的 p 值沿着负梯度方向迭代 − [ 1.6 , − 1.6 ] × 0.1 = − [ 0.16 , − 0.16 ] -[1.6,-1.6]×0.1=-[0.16,-0.16] [1.6,1.6]×0.1=[0.16,0.16],于是得到新的 p = [ 0.8 , − 0.8 ] − [ 0.16 , − 0.16 ] = [ 0.64 , − 0.64 ] p=[0.8,-0.8]-[0.16,-0.16]= [0.64,-0.64] p=[0.8,0.8][0.16,0.16]=[0.64,0.64]。如此继续……
    • 我们设置的最大迭代次数为 10 000,也就是说如果迭代次数达到 10 000,代价函数仍 然未能取到极小值,那么也要停止迭代过程,防止计算机无休止地迭代下去。不过,本例中迭代至第 67 次时,梯度的模小于我们设置的阈值 0.000 001,我们可以认为代价函数达 到了极小值。于是,整个梯度下降过程停止

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/35419.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c# 多线程

案例1 单线程与多线程对比 单线程会卡主线程,此时会将ui界面给卡住。而多线程开启以后就好了 不会卡住主线程,且运行速度快,相当于多个同时运动。 单线程按钮 private void singlethread_Click(object sender, EventArgs e){for

Kafka多生产者消费者自动配置

背景 项目中不同的业务可能会使用多个kafka&#xff0c;按默认的Kafka配置&#xff0c;最多是支持消费者和生产者使用不同的Kafka&#xff0c;如果两个生产者使用不同的Kafka则需要自定义配置&#xff0c;生成对应的bean。 解决方案 多生产者&#xff0c;多消费者&#xff0…

PowerDesigner 设置

PowerDesigner 设置前言推荐PowerDesigner 设置简单设置sql反向生成物理模型物理模型创建索引最后前言 以下内容源自自己 仅供学习交流使用 推荐 第11章 数据库的设计规范【2.索引及调优篇】【MySQL高级】 powerdesign 通过sql反向生成ER模型 PowerDesiner 15 在物理模型中…

Python测试框架之unittest和pytest 的区别

一、Unittest Unittest是Python标准库中自带的单元测试框架&#xff0c;Unittest有时候也被称为PyUnit&#xff0c;就像JUnit是Java语言的标准单元测试框架一样&#xff0c;Unittest则是Python语言的标准单元测试框架。 Unittest支持自动化测试&#xff0c;测试用例的初始化、…

FFN -> GLU -> GAU

1 GLU GLU的起源是2016年由Yann N. Dauphin在 论文:Language Modeling with Gated Convolutional Networks 在语言模型的建模方法上相比于循环神经网络更具有竞争力&#xff0c;提出了一种简单的线性门控单元来堆叠卷积层从而使得文本中的token可以并行化处理来获得上下文的语义…

HTTP响应详解

目录 一.状态码 小结&#xff08;记住&#xff09; 二.认识响应正文&#xff08;body&#xff09; 三.如何构造http请求 一.状态码 是一个数字&#xff0c;这个数字描述了当前这次请求的状态&#xff08;成功&#xff0c;失败&#xff0c;失败的原因&#xff09; http的状态…

Typora基础篇

Markdown基础 标题 #标题名字&#xff08;#号的个数代表标题的级数&#xff09; 文件-偏好设置-Markdown里面如果勾选了严格模式&#xff0c;那#与标题名称之间就需要加上一个空格一级标题用1个# 二级标题用2个# 三级标题用3个# 四级标题用4个# 五级标题用5个# ####### …

262-视口,布局视口,视觉视口,移动端适配,less语法,比哪里,DPR,RRI,less的弊端,运算,嵌套,混合,继承,混入,运算,

262-CSS中的单位 ◼ 前面编写的CSS中,我们经常会使用px来表示一个长度(大小),比如font-size设置为18px,width设置为100px。 ◼ px是一个长度(length)单位,事实上CSS中还有非常多的长度单位。 ◼ 整体可以分成两类:  绝对长度单位(Absolute length units);  相…

【uniapp】安装与使用uView组件库:

文章目录一、官网文档二、安装【1】进入控制台【2】初始化package.json【3】安装uView-ui【4】配置main.js【5】配置uni.scss【6】配置easycom组件模式【7】app.vue引入基础样式三、效果一、官网文档 https://www.uviewui.com/ 二、安装 【1】进入控制台 【2】初始化package…

基于sklearn的集成学习实战

集成学习投票法与bagging 投票法 sklearn提供了VotingRegressor和VotingClassifier两个投票方法。使用模型需要提供一个模型的列表&#xff0c;列表中每个模型采用tuple的结构表示&#xff0c;第一个元素代表名称&#xff0c;第二个元素代表模型&#xff0c;需要保证每个模型…

《计算机体系结构量化研究方法第六版》1.3 计算机体系结构的定义

1.3.1 指令集体系结构&#xff1a;计算机体系结构的近距离审视 1、这里通过指令集体系结构 ISA来指代程序员可以看到的实际指令集。ISA相当于软件和硬件之间的界限。 &#xff08;1&#xff09;ISA分类 几乎所有的ISA都被划分到了通用寄存器体系结构中&#xff0c;在这种体系…

能源消耗监测管理系统:实现企业用能定额、降低成本节能管理

现如今&#xff0c;很多企业还停留在安装各种节能产品或者是传统节能技术来达到节能目的&#xff0c;但是这些方法不能从根本上实现节能目标&#xff0c;从而导致企业效益。 在国家推动下&#xff0c;能源管理系统加入了互联网的技术以及数字化技术来协同管理&#xff0c;软硬…

二叉树链式结构的实现及简单操作(画图超详细解释)

二叉树链式结构的实现及简单操作前置说明前序遍历中序遍历后序遍历层序遍历如何判断一颗二叉树是完全二叉树通过前序遍历的数组构建二叉树销毁二叉树总结前置说明 由于我们要对二叉树进行操作&#xff0c;我们就得现有一个二叉树&#xff0c;而二叉树的构建又比较复杂&#xf…

李宏毅机器学习作业10——Adversarial Attack

目录 目标和方法 评价方法 导包 Global Settings Data transform Dataset 代理网络 评估模型在非攻击性图像上的表现 Attack Algorithm FGSM I-FGSM MI-FGSM Diverse Input (DIM) 攻击函数 Attack Ensemble Attack 集成模型函数 构建集成模型 进行攻击 FG…

【Node.js】第八章 express编写接口

目录 1. 编写接口 1.1 编写GET接口 2.2 编写POST接口 2. 接口跨域问题 2.1 跨域问题 2.2 使用cors中间件解决跨域问题 2.3 CORS ​2.4 JSONP接口 1. 编写接口 1.1 编写GET接口 2.2 编写POST接口 2. 接口跨域问题 2.1 跨域问题 2.2 使用cors中间件解决跨域问题 cor…

家里Win7电脑如何连接公司Win10电脑?快解析+远程桌面

什么是远程桌面&#xff1f;通俗地讲&#xff0c;就是可以在任何地点登陆位于其他地点的电脑&#xff0c;可以看到远程登陆电脑的一切东西&#xff0c;可以进行添加、改变、删除文件等任何操作&#xff0c;就像自己在那台电脑前操作一样。远程桌面有丰富的应用场景&#xff0c;…

如何在TIA博途中在线更新PLC的CPU固件版本?

如何在TIA博途中在线更新PLC的CPU固件版本? S7-1200PLC最新的V4.6.0版本的固件出来了,本次就以V4.6版本的固件为例,演示如何在博途中对PLC的固件版本进行更新。 (为防止更新过程中出现意外,强烈建议对PLC的程序进行备份!备份!备份!) 如下图所示,打开某个项目,选中PL…

nm命令使用详解,让你加快学习速度

nm 命令详解 符号是每个ELF文件的一个重要部分&#xff0c;因为它保存了程序实现或使用的所有(全局)变量和函数。符号表中保存了查找程序符号、为符号赋值、重定位符号所需要的全部信息。Linux中 nm用来列出目标文件的符号表;如果nm指令没有指出目标文件&#xff0c;则nm假定目…

模拟电路设计(34)---脉宽调制型开关电路

在开关稳压电源中&#xff0c;直流变换器中的功率晶体管工作在开关状态。目前开关电源的工作频率在几百kHz&#xff0c;有些甚至已经到了MHz量级。如下图所示是DC-DC开关变换器的原理框图&#xff1a; ​DC-DC开关变换器的原理框图 开关电源的实现方式有很多种&#xff0c;如最…

[附源码]Python计算机毕业设计二手图书回收销售网站

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…