目标函数
想要拟合现实世界,首先就要定义什么是现实世界,或说,什么样的模型才能算拟合了现实世界。这里就需要引入目标函数的概念。目标函数,顾名思义就是描述了模型需要达成的目标的函数,比如在二分类任务中,我们会使用交叉熵来描述预测结果和真实结果的差距,这个距离越小说明模型越接近于真实;在图像任务中,我们会使用结构相似性来评价图像质量,这个值越大说明图像质量越好。值得一提的是,目标函数是一个较为宽泛的概念,并不局限于损失函数,如条件随机场中,目标函数就不是用来描述真实与预测差异的损失函数;在目标函数的选择上,往往需要综合考虑其的实际意义与求解难度。
梯度下降
有了目标函数,那下一步就要调整模型输出,来使目标函数尽可能地取得较好的值。而上一节中我们知道了,每个神经元都可以被表达成
其中偏置和权重
是可训练参数;而深度学习模型都可以看作若干个神经元的堆叠,所以想要调整模型输出,其实就是要调整每个神经元的这两个参数。至此,我们将问题转化成了“求解在什么条件下函数取得最值”的问题。
但显然这个寻找最优参数组合的问题还无法在数学上被一劳永逸地解决;而每次调整时,各个参数对最终结果的影响又不尽相同,需要有差别地进行调整,需要庞大的计算量。因此我们需要一种精细化调整每个参数、渐次逼近的算法来让计算机自行拟合最优组合。在这个场景下这个算法就是梯度下降法。
在讨论这个算法之前,首先要回答的一个问题是“为什么是梯度”。在数学上梯度的定义是
梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)。
这个工具很好地满足了我们的需求:1、可以针对每个参数进行精细化地调整来达到最优;2、可以由计算机完成。
梯度下降法的流程可以简单地用以下三步来描述:
- 对于目标函数
,与参数
计算每个参数的梯度
- 更新参数
- 迭代执行1、2两步,直到目标函数趋于稳定
为了解释清楚这三步,我们先来假设一个简单的场景。这是一个由三个神经元()堆叠而成的网络,激活函数为
,真实标签为
,目标函数为均方差损失函数
,则我们可以将这个网络归纳为以下表达式
梯度计算
由梯度计算公式及链式法则,我们很快就可以写出和
的梯度公式
类比地,我们也能推导出的梯度公式,这个链可以延申至模型中的每一个变量。观察这两个式子可以发现,
对
的敏感程度与上一层的输出
有关,结合上一节中提到的,神经元处于“非激活”状态时会输出一个接近于0的值,这就是所谓的
neurons that fire together wire together
一同激活的神经元关联在一起
有了上述公式,对于每一个输入和真实标签
,我们都可以计算出
,
,
,
,
,
,这些都是具体的值,从而我们就得到了模型对于某个样本的梯度
对每个样本的梯度取平均,则得到了每轮训练的梯度向量
参数更新
有了样本总体的梯度,参数就可以依据这个梯度进行更新了
这里的就是深度学习中最重要的参数之一——学习率。从这个式子就不难明白学习率对于模型训练的重要性,通过学习率对梯度进行缩放,可以有效调节每轮训练中参数更新的幅度。
那么,代价是什么
上文中我们了解了深度学习中最核心的算法“梯度下降”的来龙去脉。仔细研究这个过程,难免会觉得这套算法有点太理想化了。
没错,是有代价的——
- 计算量庞大。随着模型参数的增长,所需的计算量也呈几何增长,到llm时代模型预训练的开销已经超出了一般企业的承受范围。
- 局部最优问题。梯度下降的求解方式很容易让模型陷入局部最优之中。
- 训练中的坑。模型的好坏强烈依赖于超参数设置,参数初始值选择,目标函数选择,训练集质量等因素。这些变量往往需要大量实验来确定,且有时这种实验会是盲目的。
- 可解释性问题。对于这种关于特征的高维表达,往往很难找到令人信服的解释。这也导致了模型出现误报时很难定位原因并作出有效改进。
- ……
为了解决这些问题,更多精巧的算法正在路上。
致谢:该节参考了b站up主3Blue1Brown关于深度学习的内容,原版包含大量动图展示,更为直观