05 从 MLP 到 LeNet:损失函数到底在衡量什么?
第5讲 损失函数到底在衡量什么模型已经能够根据输入给出预测结果也能够通过输出层把结果整理成更适合分类任务使用的形式。接下来的问题是模型怎么知道自己当前做得好不好训练模型不是单纯地“给出一个答案”而是要不断调整参数让预测结果越来越接近真实答案。如果连“当前结果到底好不好”都无法衡量那么参数更新就没有依据训练过程也无从谈起。损失函数正是为了解决这个问题而出现的。从最直观的角度看损失函数的作用很明确把模型预测结果和真实答案之间的差距变成一个可以计算、可以比较、可以优化的数值。这个数值越小通常说明模型做得越好这个数值越大通常说明模型离正确答案越远。1. 为什么训练模型一定需要损失函数先看一个简单例子。假设这是一个二分类问题某个样本的真实标签是[y 1]模型给出的两个预测分别是预测 A0.95预测 B0.55如果只看最终分类结果这两个预测都可能被判成正类。但直觉上很容易判断0.95比0.55更接近真实标签1也更可信。这说明一个问题训练模型时只知道“对了还是错了”是不够的。真正需要知道的是预测离真实答案有多远一次预测比另一次预测好在哪里参数更新之后模型到底是变好了还是变差了训练需要一个连续的、可计算的衡量标准损失函数就是这个标准。2. 损失函数到底是关于什么的函数这是理解损失函数时非常关键的一步。2.1 从最直接的形式看损失函数首先是关于真实标签 (y)和预测结果 (\hat{y})的函数可以写成[L L(y, \hat{y})]这里(y) 表示真实标签(\hat{y}) 表示模型预测值(L) 表示损失函数的输出这条式子的含义很直接给定真实答案和模型预测损失函数输出一个值用来表示这次预测到底偏差了多少。2.2 再往里展开一层但预测值 (\hat{y}) 本身不是凭空来的它来自模型对输入的计算结果[\hat{y} f(x; w, b)]这里(x) 是输入数据(f) 是模型(w, b) 是模型参数把这一层代回去之后损失函数还可以写成[L L(y, f(x; w, b))]这一步非常重要因为它说明损失函数表面上是在比较预测值和真实值但更深一层看它其实也和模型参数有关。2.3 从训练角度再理解一次在一次具体训练中如果当前拿到的是一个样本或一个 batch那么输入 (x) 是已知的真实标签 (y) 是已知的模型结构 (f) 是固定的真正需要被调整的是参数 (w,b)所以从训练和优化的角度说可以把损失函数理解为在当前这一步里(x) 和 (y) 可以看成常量而 (w,b) 才是真正需要优化的变量。这也是为什么训练时最终要去计算[\frac{\partial L}{\partial w}, \quad \frac{\partial L}{\partial b}]因为参数才是后面真正要被更新的部分。3. 为什么“只看分类结果”还不够在分类任务里很多时候会习惯只关心最终类别。例如真实标签是 1模型预测类别也是 1看起来模型已经做对了。但如果训练只看到这里就会忽略掉很多重要信息。例如下面两种情况预测 A0.51预测 B0.99如果阈值取 0.5这两个预测都会被判为正类。但它们显然不是同样质量的预测0.51说明模型只是勉强站到正确一边信心并不强0.99则说明模型对正确答案非常有把握如果训练过程把这两种情况都当成一样“正确”模型就很难继续优化。因此损失函数的重要作用之一就是把这种差异明确表达出来它不是只判断模型有没有预测对而是进一步衡量模型离理想答案到底还有多远。4. 先从最简单的损失理解均方误差最基础的一种损失函数是均方误差Mean Squared Error, MSE[L (\hat{y} - y)^2]这个公式的想法很直观先看预测值和真实值差多少再把这个差值平方差得越大损失越大差得越小损失越小虽然均方误差在分类任务里不是最常见的选择但它非常适合建立对“损失”这个概念的直觉。5. 三个可以直接算出来的均方误差例子设真实值固定为[y 1]现在看三个不同的预测结果。5.1 预测比较接近真实值[\hat{y} 0.9]则损失为[L (0.9 - 1)^2 0.01]5.2 预测有一定偏差[\hat{y} 0.6]则损失为[L (0.6 - 1)^2 0.16]5.3 预测离真实值很远[\hat{y} 0.1]则损失为[L (0.1 - 1)^2 0.81]这三个例子足以说明预测越接近真实值损失越小预测越偏离真实值损失越大。6. 用代码看损失值是怎么变化的defmse(y_true,y_pred):return(y_pred-y_true)**2y_true1predictions[0.9,0.6,0.1]forpredinpredictions:lossmse(y_true,pred)print(f真实值:{y_true}, 预测值:{pred}, MSE损失:{loss:.4f})输出结果如下真实值: 1, 预测值: 0.9, MSE损失: 0.0100 真实值: 1, 预测值: 0.6, MSE损失: 0.1600 真实值: 1, 预测值: 0.1, MSE损失: 0.8100这个结果很直观地说明损失函数把“预测得好不好”变成了一个具体数值而且这个数值可以比较大小。7. 为什么分类任务里更常见的是交叉熵均方误差很好理解但在分类任务里更常见的损失函数往往是交叉熵。原因在于分类任务中的输出通常是概率形式二分类里输出的是属于正类的概率多分类里softmax 输出的是各类别的概率分布在这种情况下真正关心的问题变成了模型给正确类别分配了多大概率如果模型对正确答案很没把握应该受到多大惩罚如果模型对错误答案反而特别自信损失应该有多大这类问题用交叉熵来衡量通常会更自然。8. 二分类交叉熵三个真实可算的例子在二分类任务中如果真实标签是[y 1]那么二分类交叉熵可以简化理解为[L -\log(\hat{y})]这里的 (\hat{y}) 表示模型给“正类”的预测概率。8.1 模型对正确答案很有把握[\hat{y} 0.9]则损失为[L -\log(0.9) \approx 0.105]8.2 模型比较犹豫[\hat{y} 0.5]则损失为[L -\log(0.5) \approx 0.693]8.3 模型几乎判断错了[\hat{y} 0.1]则损失为[L -\log(0.1) \approx 2.303]这个例子很好地体现了交叉熵的一个特点当模型对正确答案概率给得很低时交叉熵会给出更强烈的惩罚。9. 多分类交叉熵为什么看起来“只看正确类别”现在看一个三分类问题。假设真实标签是第 2 类可以写成 one-hot 形式[y [0,1,0]]更完整的多分类交叉熵写法是[L - \sum_i y_i \log(\hat{y}_i)]如果标签是 one-hot那么只有真实类别那个位置的 (y_i 1)其他位置都是 0。于是这个式子就会化简成[L -\log(\hat{y}_{\text{true}})]所以在数值上看起来交叉熵像是只直接取真实类别对应的预测概率来计算损失。例如9.1 模型把高概率分给了正确类别[\hat{y} [0.1, 0.8, 0.1]]则损失为[L -\log(0.8) \approx 0.223]9.2 模型没有把高概率分给正确类别[\hat{y} [0.4, 0.3, 0.3]]则损失为[L -\log(0.3) \approx 1.204]这说明正确类别概率越高损失越小正确类别概率越低损失越大9.3 那错误类别不重要吗不能简单说“不重要”。因为在多分类里softmax 输出的是一个总和为 1 的概率分布。这意味着如果某个错误类别概率很高那通常正确类别概率就会被挤小正确类别概率一变小交叉熵就会变大所以虽然交叉熵在 one-hot 情况下表面上只直接看正确类别对应的概率但错误类别并不是没作用而是会通过 softmax 的竞争关系间接影响损失。可以把这句话记成交叉熵直接奖励的是“给正确类别更高概率”而错误类别会通过概率竞争关系间接被约束。10. 损失函数在训练流程中的位置从完整训练流程看损失函数位于模型输出之后、参数更新之前。完整流程通常按顺序理解更清楚 [2]可以写成输入数据 ↓ 前向计算 ↓ 模型预测结果 ↓ 损失函数计算误差 ↓ 根据损失更新参数这意味着损失函数在训练中起到的是一个桥梁作用一边连接模型输出一边连接参数更新如果没有损失函数模型虽然可以输出结果但训练过程就失去了方向。因为参数更新必须依赖一个明确的问题当前预测到底错了多少11. 为什么说训练的目标其实是在让损失函数变小回到前面的式子[L L(y, f(x; w, b))]它揭示了一件非常重要的事输入 (x) 在当前样本下是已知的真实标签 (y) 是已知的模型结构 (f) 是给定的真正能调整的是参数 (w,b)因此训练的目标本质上就是不断调整参数让损失函数的值尽量变小。这也是为什么后面继续进入梯度下降时核心不是直接去“提高准确率”而是先去优化损失函数。12. 最容易混淆的几个点12.1 损失函数就是判断预测是否正确不完全是。损失函数不是简单判断对错而是衡量预测和真实答案之间的差距到底有多大。12.2 分类结果对了损失就一定很小不一定。例如 0.51 和 0.99 都可能预测为正类但它们的损失并不一样。12.3 交叉熵只看正确类别所以错误类别不重要不是。在 one-hot 标签下交叉熵数值上确实直接取真实类别对应的概率但错误类别会通过 softmax 的概率竞争关系间接影响损失。12.4 损失函数只和预测值有关和参数无关不是。损失函数表面上是关于真实值和预测值的函数但因为预测值来自模型参数所以损失函数最终也和参数有关。13. 总结损失函数的核心作用就是把模型预测结果和真实答案之间的差异变成一个可以计算、可以比较、可以优化的数值。从直接形式看它是关于真实标签 (y) 和预测值 (\hat{y}) 的函数[L L(y, \hat{y})]如果再展开一层由于预测值来自模型[\hat{y} f(x; w, b)]所以损失函数最终也可以写成[L L(y, f(x; w, b))]在一次具体训练里(x) 和 (y) 可以看成已知量而 (w,b) 才是真正需要优化的变量。因此从训练角度看模型学习的过程本质上就是不断调整参数让损失函数的值变得越来越小。如果把全文压缩成一句话可以概括为损失函数衡量的不是简单的“对错”而是模型预测结果与真实答案之间到底差了多少而这种差异最终会落实到参数是否需要继续调整。