开篇
这次要与大家分享的是回归损失函数,常见的损失函数有 m s e , m e , m a e mse,me,mae mse,me,mae等。我们在这里整理了keras官方给出的不同的loss函数的API,并从网上搜集了相关函数的一些特性,把他们整理在了一起。这部分的loss按照keras官方的教程分成class和function两部分,这一次讲的是class部分。
API
MeanSquaredError(mse)
$loss = \frac{\sum(y_{true} - y_{pred})^2}{n} $
计算的是标签和预测值的误差的平方的平均值,俗称均方误差。
>>> y_true = [[0., 1.], [0., 0.]]
>>> y_pred = [[1., 1.], [1., 0.]]
>>> # Using 'auto'/'sum_over_batch_size' reduction type.
>>> mse = tf.keras.losses.MeanSquaredError()
>>> mse(y_true, y_pred).numpy()
0.5
数理统计中均方误差是指参数估计值与参数值之差平方的期望值,记为MSE。MSE是衡量“平均误差”的一种较方便的方法,MSE可以评价数据的变化程度,MSE的值越小,说明预测模型描述实验数据具有更好的精确度。
在compile时的用法如下所示:
model.compile(optimizer='sgd', loss=tf.keras.losses.MeanSquaredError())
缺点
假设我们使用的激活函数为sigmod σ ( ) \sigma() σ(),则在训练过程中存在如下问题:
设 l o s s = J = 1 2 ( y i − y ^ i ) 2 loss = J = \frac{1}{2}(y_i - \hat{y}_i)^2 loss=J=21(yi−y^i)2
求反向传播所需梯度为 ∂ J ∂ W = ( y i − y ^ i ) σ ′ ( W x i + b ) x i \frac{\partial J}{\partial W} = (y_i - \hat{y}_i)\sigma'(Wx_i+b)x_i ∂W∂J=(yi−y^i)σ′(Wxi+b)xi
而
σ
′
(
Δ
)
=
(
1
1
+
e
−
Δ
)
′
=
(
1
1
+
e
−
Δ
)
2
−
1
1
+
e
−
Δ
=
(
σ
(
Δ
)
)
2
−
σ
(
Δ
)
=
σ
(
Δ
)
(
σ
(
Δ
)
−
1
)
\sigma'(\Delta) = (\frac{1}{1 + e^{-\Delta}})'\\ = (\frac{1}{1 + e^{-\Delta}})^2 - \frac{1}{1 + e^{-\Delta}}\\ = (\sigma(\Delta))^2 - \sigma(\Delta)\\ = \sigma(\Delta)(\sigma(\Delta) - 1)\\
σ′(Δ)=(1+e−Δ1)′=(1+e−Δ1)2−1+e−Δ1=(σ(Δ))2−σ(Δ)=σ(Δ)(σ(Δ)−1)
所以如果预测结果是很接近0或者1的,会导致梯度非常的小,从而训练速度也会很低。
一种解决办法是使用交叉熵作为损失函数,这在后面会讲到。
MeanAbsoluteError(mae)
l o s s = ∑ ∣ y t r u e − y p r e d ∣ n loss = \frac{\sum|y_{true} - y_{pred}|}{n} loss=n∑∣ytrue−ypred∣
计算差的绝对值的均值, 可以更好地反映预测值误差的实际情况。
俗称平均绝对值误差,也称L1损失。上面的mse时L2损失。
model.compile(optimizer='sgd', loss=tf.keras.losses.MeanAbsoluteError())
MeanAbsolutePercentageError(mape)
l o s s = ∑ 100 ∗ ∣ y t r u e − y p r e d ∣ y t r u e n loss = \frac{\sum100*\frac{|y_{true} - y_{pred}|}{y_{true}}}{n} loss=n∑100∗ytrue∣ytrue−ypred∣
这个公式更能表示预测值与标签的相对关系,乘以100的目的是为了放大loss函数。
model.compile(optimizer='sgd',
loss=tf.keras.losses.MeanAbsolutePercentageError())
MeanSquaredLogarithmicError(msle)
$loss = \frac{\sum(log(y_{true} + 1) - log(y_{pred} + 1))^2}{n} $
从形式上看是把每一项的loss缩小了,是mse的一个修改版本,这样做有什么好处呢?请看下面这个例子(引自 https://blog.csdn.net/leadai/article/details/78876511 )。
y t r u e y_{true} ytrue:[1,2,3,100] y 1 y_1 y1:[1,2,3,110] y 2 y_2 y2:[2,3,4,100]
可以计算一下如果是mse的话, y 2 y_2 y2会成为更优的预测结果,如果用msle,则是 y 1 y_1 y1,在这里显然 y 1 y_1 y1更优。
model.compile(optimizer='sgd',
loss=tf.keras.losses.MeanSquaredLogarithmicError())
CosineSimilarity
l o s s = − ∑ ( l 2 _ n o r m ( y t r u e ) ∗ l 2 _ n o r m ( y p r e d ) ) loss = -\sum(l2\_norm(y_{true}) * l2\_norm(y_{pred})) loss=−∑(l2_norm(ytrue)∗l2_norm(ypred))
请注意,它是介于-1和0之间的负数,其中0表示正交,而接近-1的值表示更大的相似性。 这使得它在尝试最大化预测值与目标值之间的接近度的设置中可用作损失函数。 如果y_true或y_pred是零向量,则余弦相似度将为0,而与预测值和目标值之间的接近程度无关。
从形式上看,是向量的点乘,从抽象的角度来看,是两个向量之间夹角的衡量,当两个向量正交时是不希望的情况,对应的cosine是0,损失函数的结果也是0,当两个向量夹角为零,cosine为1,正则化的计算结果也是1。最后在公式前面乘以-1,统一化成最小化计算。
model.compile(optimizer='sgd', loss=tf.keras.losses.CosineSimilarity(axis=1))
huber class
首先定义 x ← y _ t r u e − y _ p r e d x \gets y\_true - y\_pred x←y_true−y_pred
于是loss就如下计算
loss = 0.5 * x^2 if |x| <= d
loss = 0.5 * d^2 + d * (|x| - d) if |x| > d
一个简单的例子如下所示:
>>> y_true = [[0, 1], [0, 0]]
>>> y_pred = [[0.6, 0.4], [0.4, 0.6]]
>>> # Using 'auto'/'sum_over_batch_size' reduction type.
>>> h = tf.keras.losses.Huber()
>>> h(y_true, y_pred).numpy()
0.155
在进行编译时的例子:
model.compile(optimizer='sgd', loss=tf.keras.losses.Huber())
对于这个loss函数的理解非常简单:当预测值和真实值相差很小的时候就用平方损失函数,否则通过一定的手段降低loss。
欢迎关注公众号BBIT
让我们共同学习共同进步!