正如我们所见,自编码器的主要作用是接收一些输入数据,经过压缩(编码)再解压缩(解码)处理,并尝试使最终输出尽可能与原始输入相同。但我们如何实际衡量自编码器在这一重构任务中的表现 有多好 呢?这正是损失函数发挥作用的地方。可以将损失函数看作是一种评估自编码器表现的方法。如果重构的输出与原始输入差别很大,损失函数会给出高分(高损失),表明表现不佳。如果重构结果与原始输入非常相似,损失函数会给出低分(低损失),这意味着自编码器表现良好。自编码器的整个学习过程都是为了尽量减少这个损失得分。digraph G { graph [fontname="Arial", fontsize=10]; node [shape=box, style="filled", fontname="Arial", fontsize=10]; edge [fontname="Arial", fontsize=10]; rankdir=TB; input_data [label="原始输入\n(x)", shape=cylinder, fillcolor="#a5d8ff", style="filled,rounded"]; reconstructed_data [label="重构输出\n(x̂)", shape=cylinder, fillcolor="#b2f2bb", style="filled,rounded"]; loss_function [ label="损失函数\n(例如:MSE, BCE)\n\n衡量原始输入 (x)\n与重构输出 (x̂) 之间的\n“距离”或“误差”。", shape=note, fillcolor="#ffc9c9", style="filled", width=3, height=1.5 ]; input_data -> loss_function [headlabel=" 目标 ", fontcolor="#0ca678", color="#0ca678"]; reconstructed_data -> loss_function [headlabel=" 预测 ", fontcolor="#f03e3e", color="#f03e3e"]; }损失函数同时接收原始输入和自编码器的重构结果,以计算误差得分。让我们来看看用于训练自编码器的两种常用损失函数:均方误差 (MSE) 和二元交叉熵 (BCE)。均方误差 (MSE)均方误差是一种非常常用的损失函数,特别是当你的输入数据(以及预期输出数据)包含连续的数值时。例如,如果你的自编码器正在学习重构灰度图像,其中像素值范围从0(黑色)到255(白色),或者可能是0.0到1.0之间的归一化值,那么MSE是一个不错的选择。MSE 计算原始输入与重构输出中每个单独元素之间平方差的平均值。 其数学表达式如下:$$ L(x, \hat{x}) = \frac{1}{n} \sum_{i=1}^{n} (x_i - \hat{x}_i)^2 $$我们来分析一下这个表达式:$x$ 表示原始输入(例如,像素值向量)。$\hat{x}$(读作“x-hat”)表示自编码器的重构输出。$x_i$ 是原始输入中第 $i$ 个元素(例如,第 $i$ 个像素)的值。$\hat{x}_i$ 是重构输出中第 $i$ 个元素的值。$(x_i - \hat{x}_i)$ 是该特定元素的差值或误差。$(x_i - \hat{x}_i)^2$ 是该差值的平方。我们将其平方主要有两个原因:它确保结果始终为正值。我们重视误差的绝对大小,而不是预测值高于或低于真实值。它对较大的误差进行更严厉的惩罚。2的误差平方后变为4,而0.5的误差平方后变为0.25。这意味着自编码器会更努力地修正大的错误。$\sum_{i=1}^{n}$ 表示我们将所有 $n$ 个输入元素(例如,图像中的所有像素)的这些平方差相加。$\frac{1}{n}$ 表示我们取这些相加的平方差的平均值。这使得损失值与元素数量无关,在比较不同输入大小的表现时非常有用。何时使用MSE:当你的输入数据(以及你想要的输出)包含实数值,并且差值的绝对大小有意义时(例如,图像像素强度,传感器读数)。它常常与解码器中可以产生任意实数(如线性激活)的输出层配对,或者在数据归一化后产生特定范围内的值(例如,使用Tanh激活函数得到[-1,1]范围,或Sigmoid激活函数得到[0,1]范围,尽管Sigmoid通常更多地与BCE用于概率输出)。MSE值越小,意味着重构输出平均而言与原始输入非常接近。MSE值越大,表明重构效果越差。二元交叉熵 (BCE)二元交叉熵,常缩写为BCE,是另一种受欢迎的损失函数。当输入数据(以及目标输出)可以被视为概率,或者数据是二元(只包含0或1两个值)时,它特别适用。例如,如果你处理的是黑白图像,其中每个像素是0(黑色)或1(白色),或者如果你的输入像素值被归一化到0.0到1.0之间,并且你希望自编码器的输出也代表每个像素的概率,那么BCE是一个不错的选择。二元交叉熵的公式是:$$ L(x, \hat{x}) = - \frac{1}{n} \sum_{i=1}^{n} [x_i \log(\hat{x}_i) + (1-x_i) \log(1-\hat{x}_i)] $$我们来分析一下这个公式:$x_i$ 是输入中第 $i$ 个元素的真实值。对于BCE, $x_i$ 通常是0或1。$\hat{x}_i$ 是自编码器预测的第 $i$ 个元素为1的概率。这个值应该在0到1之间(通常由解码器最后一层的Sigmoid激活函数保证)。$\log$ 指的是自然对数。这个公式看起来稍微复杂,但其表现方式相当直观:如果真实值 $x_i$ 是 1: 求和的第二部分 $(1-x_i) \log(1-\hat{x}_i)$ 变为 $0 \cdot \log(1-\hat{x}_i) = 0$。因此,该元素的损失就是 $-x_i \log(\hat{x}_i) = -\log(\hat{x}_i)$。为了使这个值最小(使其成为一个小的正数,因为损失通常为正),我们需要 $\hat{x}_i$ 尽可能接近1。如果 $\hat{x}_i$ 接近1,则 $\log(\hat{x}_i)$ 接近0。如果 $\hat{x}_i$ 接近0(一个不好的预测),则 $\log(\hat{x}_i)$ 变为一个大的负数,而 $-\log(\hat{x}_i)$ 变为一个大的正数(高损失)。如果真实值 $x_i$ 是 0: 求和的第一部分 $x_i \log(\hat{x}_i)$ 变为 $0 \cdot \log(\hat{x}_i) = 0$。因此,该元素的损失就是 $-(1-x_i) \log(1-\hat{x}_i) = -\log(1-\hat{x}_i)$。为了使这个值最小,我们需要 $1-\hat{x}_i$ 接近1,这意味着 $\hat{x}_i$ 必须接近0。如果 $\hat{x}_i$ 接近0(一个好的预测),则 $1-\hat{x}_i$ 接近1,且 $\log(1-\hat{x}_i)$ 接近0。如果 $\hat{x}_i$ 接近1(一个不好的预测),则 $1-\hat{x}_i$ 接近0,$\log(1-\hat{x}_i)$ 变为一个大的负数,而 $-\log(1-\hat{x}_i)$ 变为一个大的正数(高损失)。开头的 $\frac{1}{n}$ 再次对所有 $n$ 个元素的损失进行平均。最前面的负号确保总损失为正,因为对数概率为负或零。何时使用BCE:当你的输入数据是二元(0和1)时。当你的输入数据被归一化到[0, 1]范围,并且可以被解释为概率时(例如,图像的像素强度,其中0是黑色,1是白色,介于两者之间的值是你想进行概率建模的灰色阴影)。它几乎总是与解码器输出层中的Sigmoid激活函数配对,因为Sigmoid将输出值压缩到[0, 1]范围,使其适合作为BCE中对数函数的输入。BCE很有效,因为它严厉惩罚那些确信地错误的预测(例如,当真实值为1时预测概率接近0,反之亦然)。选择你的损失函数MSE和BCE(或其他损失函数)的选择主要取决于你数据的性质以及你希望自编码器学习什么:如果你的数据值是连续的,并且分布在一个宽泛的范围(或归一化到像[-1, 1]或[0, 1]这样的范围,但并非严格意义上的概率),那么MSE通常是一个合理的默认选项。如果你的数据是二元的,或者你的数据被归一化到[0, 1]并且你将输出视为“激活”的概率(例如像素为白色),那么BCE通常更受青睐。这通常与解码器输出层中的Sigmoid激活函数很好地匹配。了解这些损失函数是一个重要步骤,因为自编码器的整个训练过程都围绕着最小化所选损失函数计算出的值进行。在接下来的部分,我们将看到自编码器如何使用这个损失值来调整其内部参数,从而更好地进行重构。