Skip to content

机器学习:学习记录(ML02)

Q&A

我与偏导的第一次接触始于高中的一道双变量求最值的题目。冥思苦想许久而一筹莫展之际,我突发奇想:“能不能只逮着一个未知数导?”——那时候老师说,这就是偏导。

​ 随着对“机器学习”的了解逐渐加深,我对它也有了更高层次的理解:它是一个用来衡量函数对于某个元素变化的敏感程度的工具。虽然它对我来说一直都是工具,但是从高中的“做题”工具转化为了帮助我理解机器学习模型的工具,也算是完成了一次进化。

  • 什么是偏导数

    让我们假设一个关于x,y双变量的函数

    z=f(x,y)=x2+y2

    其中,关于x的偏导数

    dzdx=df(x,y)dx=limΔx0f(x+Δx,y)f(x,y)Δx

    假设中,该函数关于x的偏导数就为

dzdx=2x
  • 梯度和偏导数有什么联系?

    首先我们需要解决一个问题:梯度是什么?

    假定一个具有多个自变量的光滑函数:

    g(x0,x1,x2,...,xn)

    其梯度(gradient)定义如下:

    g(x0,x1,...,xn)=(gx0,gx1,...,gxn)

    单看形式,不难发现其梯度是由该函数的所有偏导数组成的向量,而对于一个单变量函数而言,梯度就是导数。

    我们知道,偏导数表示的是该函数对于某一个变量而言的变化率。那么作为偏导数的集合梯度这一向量指向的方向就代表了函数值变化最快的方向。

    也就是说,**对于一个多变量函数,梯度包含了函数对每个变量的偏导数,而函数在变量空间的某一点处,沿着梯度方向有着最大的变化率。**此外,我了解到梯度的模长就是变化率的最大值,真是太神奇了


​ 我们曾在高中学习过“线性回归”:为了找到最合适、最接近一条未知函数的直线/曲线,我们需要通过“回归”来确定最适合的斜率/参数。这个过程与我所了解到的“梯度下降”似乎有异曲同工之妙,我也愿意相信它就是我接下来将要学习的模块中的一部分。

  • 什么是梯度下降?

​ 在机器学习中,一个算法里不同的参数会产生不同的拟合曲线,也就意味着不同的误差值。沿用上文提到的“线性回归”以方便理解:我们需要在许许多多的可选择的函数中挑选一个误差最小、最贴合原函数的直线,实现对未来数据的预测。

​ 高中时期,我们使用e来命名残差,或者说“误差”:

ek=kk

​ 为了尽可能减小误差、以及定义所有数据的误差,最简单的办法就是求平方误差的总和,即

C=k=1nek2

​ 为了使C达到最小,我们需要对其进行偏导然后求得最值,偏导的对象分别为回归直线方程的斜率和截距,由于上文解释了偏导用法,这里不多赘叙。

​ 其实,C 函数就是在机器学习中常用的一种损失函数。损失函数是一个自变量为算法参数,函数值为误差值的函数,本质上是计算预测值和真实值的差距的函数。

​ 这个过程的核心在于最小化损失函数,也就是梯度下降:寻找误差值最小的所对应的那一个参数。也就是所谓的“将函数图像看作斜坡,沿着坡度最陡的方向一步一步下降”。

  • 什么是反向传播?

​ 最简单的理解是,反向传播法通过不断更新参数来最小化误差。

​ 例如:继续沿用上文设定,定义一个损失函数C

C=k=1n(ykaxkb)2

​ 其中y为实际值,a、b分别为回归方程的斜率和截距。

​ 令a=1,我们得出误差e。为了减小这个误差,我们试着将a的值增大到2,这里假设误差增大,继续增大参数的值没有意义,那么我们就减小它,注意到误差变小。

至此,我们就完成了两次“反向传播”:在参数初始化后开始计算(向前传播)的过程中,为了减小误差,回头进行增加或减小参数的值(反向传播),以达到减小误差的目的。

​ 定义一个“神经单元误差”δ:

δji=Czji(i=1,2,3,...)

​ 其中C为损失函数,z为神经网络中关于某变量的函数(或者称其为关于偏置和权重的函数,其中偏置可以简单理解为上文的“截距”,权重则是“斜率”),i、j表示神经层中第i层、第j个神经单元。

​ 神经单元误差就是关于z的偏导数,也就是关于所谓斜率和截距的偏导数。

​ (PS:主要是方便我自己理解,故下文均使用“斜率和截距”来代替“权重和偏置”,如果有理解错误的地方希望前辈们能指出,不要介意qwq)

​ 沿用上文斜率a、截距b的定义,这里假设z是关于a、b的二次函数,自变量为x。我们得到

Ca2=Cz2z2a2

​ 显然,

z2a2=x

​ 也就是说,

Ca2=δ2x

​ 通过同样的计算,我们可以得到

Cb2=δ2

​ 扩展到一般形式:

Caji=δjixji1,Cbji=δji

​ 通过对这两个式子进行变换,我们得到(这里省略了用偏导数将δ展开的过程):

δji={δ1i+1a1i+1+...+δmi+1ami+1}a2z2

该式表示第i层与第i+1层的神经单元误差的递推关系。

​ 虽然这个一般式对于一个真正的神经网络还过于简陋(没有输入、中间、输出层),并且上下标也标得一团乱麻(这主要是我自己的原因😰),但是它很好地展现了神经单元误差的递推关系:在真正的神经网络中,通过这样的关系,我们只需要求出输出层的神经单元误差,其他的误差就不需要通过偏导数计算,大大节省了时间。

​ 就好像不断从后往前推导——这就是“反向”。

​ 也就是说,反向传播法以梯度下降为基础,特点是将繁杂的导数计算替换为数列的递推关系式。


泰勒公式:高中数学的神级技巧。 ​ 好吧,如果每道题都通过高中学习的知识来回答问题实在有些无趣和班门弄斧(在前辈们面前),况且我对它也没有什么高深的见解,不如直接开门见山:

​ 假设函数在点a处有n+1阶连续导数,那么对于x在a附近的值,函数f(x)可表示为:

f(x)=f(a)+f(a)1!(xa)+f(a)2!+...+f(n)(a)n!

也即

i=0nf(i)(a)i!(xa)i

(手打这俩公式用了10分钟,期间一直试图弄明白n阶导怎么在上面显示,后来发现只要弄个上标就行了😭)

​ 它所表示的近似值与实际值有所偏差,在正式使用时需要加上其n阶余项。泰勒公式是微积分逼近法的里程碑,具有很高的精确度,在研究函数极限和估计误差等方面也同样不可或缺。


​ 向量是一个有序数列,也可以说是一条有向线段,可以为00代表零向量)。

​ 矩阵是一个元素按照矩形排列的矩形数组,可以表示多个向量或者多个线性方程,0矩阵即为所有元素都为0的矩阵。

​ 我们可以将矩阵看作是行向量和列向量的组合形式,也可以将向量看作是一个特殊的矩阵。零向量和零矩阵也不例外。

以下是一个m*n矩阵:

A=[a11a12a1na21a22a2nam1am2amn]

​ 其中每一行每一列都能看作是一个行向量/列向量:

a=(a11a21am1)or a=(a11,a12,...,a1n)

​ 矩阵乘法在入门题中有所考察,这里不多赘叙。


​ 现在是总结时间!

  1. 偏导数、梯度
  2. 梯度下降和反向传播:

    PS:其实我到现在为止才弄明白损失函数与代价函数的区别,按照上文的定义,我在第二题中写的C函数其实更偏向于代价函数😰

  3. 泰勒公式:

            
    例如在神经网络中常用的sigmoid函数,它是在神经网络中具有代表性的激活函数:

    σ(x)=11+ex


    (函数形式引用自《深度学习中的数学》)
    为了求得其在x=1处的近似值,通过泰勒展开式

    σ(x)12+14148=3548

    ​ 我们可以得到一个较为精确的近似。
    不过由于阶数提高,计算复杂度也显著提高,计算成本也呈指数型增长。一般来说,一阶和二阶就已经足够解决问题,但更高阶的优化法在理论上也是可行的。

  4. 矩阵和向量:

    机器学习中,数据点通常用向量来表示,而数据集可以看作是高维向量空间中的一组向量,向量组成了矩阵,而对矩阵的操作(例如矩阵乘法)则提供了更方便的数据表示和线性变换。


    用矩阵A(m*n)表示输入数据,向量a表示权重(斜率),用y表示预测结果。请出老朋友函数C:C=k=1n(kaxkb)2

    ​ 其中函数

    y=ax+b

    ​ 可以简单表示为

    y=Aa

    ​ 这是由于矩阵乘法的特性,A@a得到一个有m行的列向量,其中的每一个数据都可以视作为对应样本的预测结果。虽然最终结果是一个列向量,但是它表示所有样本的预测值,因此我们可以简单地写作这样的形式。

    ​ 最后,我们就可以将矩阵-向量乘法的线性变换与损失函数联系起来,通过这种方式,神经网络的每一层就能通过矩阵的运算来处理数据。