分类问题和回归问题是监督学习的两大种类,本文将分别介绍分类问题和回归问题中使用到的经典损失函数以及根据实际情况所自定义的损失函数。
同时注意损失函数定义的是损失,所以要将利润最大化,定义损失函数应该刻画成本或者代价。在实际情况中,可以根据具体问题自定义损失函数。
一、经典损失函数
1、分类问题
1.1、交叉熵简介
机器学习中,在解决二分类的情况时,可以通过设置一个阈值,大于阈值的认为是一类,小于阈值的认为是另外一类;然而在解决多分类的问题时,虽然设置多个阈值在理论上是可行的,但在解决实际问题的时候往往是设置输出n维向量,其中n为类别的个数。
那么如何判一个输出向量和期望的向量有多接近呢。交叉熵(cross entropy) 是最经典的评判方法之一。交叉熵刻画了两个概率之间的距离,他是分类问题中使用比较广泛的一种损失函数。
M
S
E
(
y
,
y
′
)
=
∑
i
=
1
n
(
y
i
−
y
i
′
)
2
n
MSE(y, {y}') = \frac{\sum_{i=1}^{n}(y_{i}-{y_{i}}')^{2}}{n}
MSE(y,y′)=n∑i=1n(yi−yi′)2
他刻画的是通过概率分布q来表示概率分布p的困难程度。因为正确答案是希望得到的结果,所以交叉熵作为损失函数时,p代表准确答案,q代表预测答案。
1.2、softmax简介
如何将神经网络前向传播得到的结果变成概率分布呢?softmax回归 是最常用的方法。它本身可以作为一个学习算法来优化分类结果,但在TensorFlow中,softmax回归的参数被去掉了,他只是一层额外的处理层,将神经网络的输出变成一个概率分布。
假设原始神经网络输出为
y
1
,
y
2
,
y
3
,
.
.
.
,
y
n
y_{1},y_{2},y_{3}, ..., y_{n}
y1,y2,y3,...,yn,那么经过Softmax回归处理之后的输出为:
M
S
E
(
y
,
y
′
)
=
∑
i
=
1
n
(
y
i
−
y
i
′
)
2
n
MSE(y, {y}') = \frac{\sum_{i=1}^{n}(y_{i}-{y_{i}}')^{2}}{n}
MSE(y,y′)=n∑i=1n(yi−yi′)2
这样就把神经网络的输出也变成了一个概率分布了,从而可以通过交叉熵来计算预测的概率分布和只是答案分布之间的距离了。
1.3、TensorFlow实现
import tensorflow as tf
cross_entropy = -tf.reduce_mean(
y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0
)
分解如下:
with tf.Session() as sess:
v = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
# tf.clip_by_value函数将一个张量中的数值限制在一个范围内
# 小于2.5的换乘了2.5, 大于4.5的被换乘了4.5
print(tf.clip_by_value(v, 2.5, 4.5).eval())
# 输出为:[[2.5, 2.5, 3.],[4., 4.5, 4.5]]
v1 = tf.constant([[1.0, 2.0], [3.0, 4.0]])
v2 = tf.constant([[5.0, 6.0], [7.0, 8.0]])
# 元素之间对应相乘
print((v1*v2).eval())
# 矩阵成法
print(tf.matmul(v1, v2).eval())
# 对所有数值取平均数
print(tf.reduce_mean(v1).eval())
# 输出为: 2.5
因为交叉熵一般会与softmax回归一起使用,所以TensorFlow对这两个功能进行了同一封装,提供了 tf.nn.softmax_cross_entropy_with_logist() 函数。
2、回归问题
2.1、均方误差简介
与分类问题不同,回归问题解决的是对具体数值的预测,比如房价预测、销量预测等。这些问题需要预测的不是一个事先定义好的类别,而是一个任意实数。解决回归问题的神经网络一般都只有一个输出节点。对于回归问题,最经典的损失函数是均方误差(MSE, mean squared error) 它的定义如下:
M
S
E
(
y
,
y
′
)
=
∑
i
=
1
n
(
y
i
−
y
i
′
)
2
n
MSE(y, {y}') = \frac{\sum_{i=1}^{n}(y_{i}-{y_{i}}')^{2}}{n}
MSE(y,y′)=n∑i=1n(yi−yi′)2
其中
y
i
y_{i}
yi为一个batch中第i个数据的额正确答案, 而
y
i
′
{y_{i}}'
yi′为神经网络给出的预测值。
2.2、TensorFlow实现
mes = tf.reduce_mean(tf.square(y_ - y))
二、自定义损失函数
1、情景引入
TensorFlow不仅支持经典的损失函数,还可以优化任意的自定义损失函数,本小节将介绍如何通过自定义损失函数的方法,使得是经网络优化结果更加接近实际问题的需求。
例如,在预测商品销量时,如果预测多了(预测值大于实际值),商家损失的是生产商品的成本;如果预测少了(预测值小于实际值),损失的则是商品的利润,因为一般商品的成本和利润不会对等,比如:一件商品成本为1元, 利润为10元。如果损失函数是均方误差,那么很有可能此模型无法最大化利润。为了最大化利润,需要我们根据实际情况自定义损失函数,以下公式给出了一个当预测值多于实际值和少于实际值时,有不同损失系数的损失函数:
L
o
s
s
(
y
,
y
′
)
=
∑
i
=
1
n
f
(
y
i
,
y
i
′
)
,
f
(
x
)
=
{
a
(
x
−
y
)
x
>
y
b
(
y
−
x
)
x
≤
y
Loss(y, {y}')=\sum_{i=1}^{n}f(y_i, {y_i}'), f(x)=\left\{\begin{matrix} a(x-y) x>y\\ b(y-x) x\leq y \end{matrix}\right.
Loss(y,y′)=i=1∑nf(yi,yi′),f(x)={a(x−y)x>yb(y−x)x≤y
2、TensorFlow实现
loss = tf.reduce_sum(
tf.where(tf.greater(v1, v2), (v1 - v2)*a, (v2 - v1)*b
)
分解如下:
import tensorflow as tf
with tf.Session() as sess:
v1 = tf.constant([1.0, 2.0, 3.0, 4.0])
v2 = tf.constant([4.0, 3.0, 2.0, 1.0])
# tf.greater的输入是两个张量,他会比较这两个张量中每一个元素的大小
print(sess.run(tf.greater(v1, v2))
# 输出 [False, False, True, True]
# tf.where与np.where相似
print(tf.where(tf.greater(v1, v2), v1, v2).eval()
# 输出 [4., 3., 3., 4.]