参考博文:https://blog.csdn.net/App_12062011/article/details/56276228
一、损失函数
损失函数和代价函数是同一个东西,目标函数是一个与他们相关但更广的概念,对于目标函数来说在有约束条件下的最小化就是损失函数(loss function)。度量模型,指导模型训练,因此损失函数的设计和模型结构设计一样的重要,损失函数用来评价预测值和真实值间的关系。
经验风险==》期望风险(大数定律) 经验风险+结构风险
经验风险最小化:最优模型 结构风险最小化:等价于正则化(regularization)防止过拟合,结构风险在经验风险的基础上加上表示模型复杂度的正则化项/罚项
损失函数(loss function)是用来估量模型的预测值f(x)与真实值Y的不一致程度,它是一个非负实值函数,通常使用L(Y, f(x))来表示,损失函数越小,模型的鲁棒性就越好。损失函数是经验风险函数的核心部分,也是结构风险函数重要组成部分。模型的结构风险函数包括了经验风险项和正则项,通常可以表示成如下式子:
其中,前面的均值函数表示的是经验风险函数,L代表的是损失函数,后面的Φ是正则化项(regularizer)或者叫惩罚项(penalty term),它可以是L1,也可以是L2,或者其他的正则函数。整个式子表示的意思是找到使目标函数最小时的θ值。
理解:损失函数旨在表示出logit和label的差异程度,不同的损失函数有不同的表示意义,也就是在最小化损失函数过程中,logit逼近label的方式不同,得到的结果可能也不同。一般情况下,softmax和sigmoid使用交叉熵损失(logloss),hingeloss是SVM推导出的,hingeloss的输入使用原始logit即可。
二、LogLoss对数损失函数(逻辑回归,交叉熵损失) 分类问题
它描述了两个概率分布之间的距离,当交叉熵越小说明二者之间越接近。它是分类问题中使用比较广的一种损失函数。
有些人可能觉得逻辑回归的损失函数就是平方损失,其实并不是。平方损失函数可以通过线性回归在假设样本是高斯分布的条件下推导得到,而逻辑回归得到的并不是平方损失。在逻辑回归的推导中,它假设样本服从伯努利分布(0-1分布),然后求得满足该分布的似然函数,接着取对数求极值等等。而逻辑回归并没有求似然函数的极值,而是把极大化当做是一种思想,进而推导出它的经验风险函数为:最小化负的似然函数(即max F(y, f(x)) —> min -F(y, f(x)))。从损失函数的视角来看,它就成了log损失函数了。
log损失函数的标准形式:
取对数是为了方便计算极大似然估计,因为在MLE(最大似然估计)中,直接求导比较困难,所以通常都是先取对数再求导找极值点。损失函数L(Y, P(Y|X))表达的是样本X在分类Y的情况下,使概率P(Y|X)达到最大值(换言之,就是利用已知的样本分布,找到最有可能(即最大概率)导致这种分布的参数值;或者说什么样的参数才能使我们观测到目前这组数据的概率最大)。因为log函数是单调递增的,所以logP(Y|X)也会达到最大值,因此在前面加上负号之后,最大化P(Y|X)就等价于最小化L了。(极大似然:已知模型,求取参数)
逻辑回归的P(Y=y|x)表达式如下(为了将类别标签y统一为1和0,下面将表达式分开表示)
逻辑回归最后得到的目标式子如下:
上面是针对二分类而言的。这里需要解释一下:之所以有人认为逻辑回归是平方损失,是因为在使用梯度下降来求最优解的时候,它的迭代式子与平方损失求导后的式子非常相似,从而给人一种直观上的错觉。
这里有个PDF可以参考一下:Lecture 6: logistic regression.pdf.
注意:softmax使用的即为交叉熵损失函数,binary_cossentropy为二分类交叉熵损失,categorical_crossentropy为多分类交叉熵损失,当使用多分类交叉熵损失函数时,标签应该为多分类模式,即使用one-hot编码的向量。
1、自定义交叉熵:cross_entropy1=tf.reduce_mean(y_*tf.log(tf.clip_by_value(y1,le-10,1.0)))
tf.clip_by_value()函数可将一个tensor的元素数值限制在指定范围内,这样可防止一些错误运算,起到数值检查作用。
* 乘法操作符是元素之间直接相乘,tensor中是每个元素对应相乘,要区别去tf.matmul()函数的矩阵相乘
2、Tf.集成交叉熵 Tf.nn.softmax_cross_entropy_with_logits(label=y, logits=y_) // 在未经过softmax处理的logits 上否则会产生错误。
交叉熵和方差代价函数的区别:sigmoid 正无穷和负无穷 趋于平坦,更新缓慢,克服这个缺点引入交叉熵
交叉熵:非负性,当真实与期望y接近的时候,代价函数接近于0,(比如y=0,a~0;y=1,a~1时,代价函数都接近0)
克服方差代价更新权重过慢的问题 ,看导数。
当我们用sigmoid函数作为神经元的激活函数时,最好使用交叉熵代价函数来替代方差代价函数,以避免训练过程太慢。
不过,你也许会问,为什么是交叉熵函数?导数中不带σ′(z)项的函数有无数种,怎么就想到用交叉熵函数?这自然是有来头的,更深入的讨论就不写了,少年请自行了解。
另外,交叉熵函数的形式是−[ylna+(1−y)ln(1−a)]而不是 −[alny+(1−a)ln(1−y)],为什么?因为当期望输出的y=0时,lny没有意义;当期望y=1时,ln(1-y)没有意义。而因为a是sigmoid函数的实际输出,永远不会等于0或1,只会无限接近于0或者1,因此不存在这个问题。
参考博文 : https://blog.csdn.net/liweibin1994/article/details/79510237
如果sigmoid 输出是1 的时候 曲线平缓,导/斜率很小,所以对参数的偏导结果就很小,所以一开始cost曲线没有下降
交叉熵:
从这里我们就可以看到,权重参数的偏导数由σ(z)−yσ(z)−y控制,模型的输出与标签y之间的偏差越大,也就是σ(z)−yσ(z)−y的值越大,那么偏导数就会越大,学习就会越快。这正是我们想要的结果。我们用一开始那个例子,不错这一次cost函数使用交叉熵代价函数了,可以得到下面的曲线:
可以看到,这一次,在一开始的时候,曲线下降的速度变快了。这就是为什么我们在大部分的机器学习模型中,经常使用交叉熵函数作为代价函数的原因了。
平方误差函数和交叉熵损失函数分别适合什么场景?
平方损失适合输出为连续,最后一层不含sigmoid或者 softmax的激活函数的神经网络,交叉熵损失更适合二分类或者多分类的场景,sigmoid 当接近于1或者0导数趋于平缓,基于梯度学习速度特别缓慢,使用交叉熵,相对于输出层的导数(残差)是导数线性的,因此不会存在刚开始学习速度过慢的问题。
二、平方损失函数(最小二乘法, Ordinary Least Squares ) 回归损失函数
最小二乘法是线性回归的一种,最小二乘法(OLS)将问题转化成了一个凸优化问题。在线性回归中,它假设样本和噪声都服从高斯分布(为什么假设成高斯分布呢?其实这里隐藏了一个小知识点,就是中心极限定理,可以参考【central limit theorem】),最后通过极大似然估计(MLE)可以推导出最小二乘式子。最小二乘的基本原则是:最优拟合直线应该是使各点到回归直线的距离和最小的直线,即平方和最小。换言之,OLS是基于距离的,而这个距离就是我们用的最多的欧几里得距离。为什么它会选择使用欧式距离作为误差度量呢(即Mean squared error, MSE),主要有以下几个原因:
平方损失(Square loss)的标准形式如下:
当样本个数为n时,此时的损失函数变为:
Y-f(X)表示的是残差,整个式子表示的是残差的平方和,而我们的目的就是最小化这个目标函数值(注:该式子未加入正则项),也就是最小化残差的平方和(residual sum of squares,RSS)。
而在实际应用中,通常会使用均方差(MSE)作为一项衡量指标,公式如下:
上面提到了线性回归,这里额外补充一句,我们通常说的线性有两种情况,一种是因变量y是自变量x的线性函数,一种是因变量y是参数α的线性函数。在机器学习中,通常指的都是后一种情况。
代码实现:
loss= tf.reduce_sum(tf.square(y_-y)
tf.greater(x,y),返回x>y的判断结果的bool型tensor,当tensor x, y的维度不一致时,采取广播(broadcasting)机制。
tf.where(condition,x=None, y=None, name=None),根据condition选择x (if true) or y (if false)。
v1=tf.constant([1.0,2.0,3.0,4.0])
v2=tf.constant([4.0,3.0,2.0,1.0])
sess=tf.InteractiveSession()
print(tf.greater(v1,v2).eval())
print(tf.where(tf.greater(v1,v2),v1,v2).eval())
三、指数损失函数(Adaboost)
学过Adaboost算法的人都知道,它是前向分步加法算法的特例,是一个加和模型,损失函数就是指数函数。在Adaboost中,经过m此迭代之后,可以得到fm(x):
Adaboost每次迭代时的目的是为了找到最小化下列式子时的参数α 和G:
而指数损失函数(exp-loss)的标准形式如下
可以看出,Adaboost的目标式子就是指数损失,在给定n个样本的情况下,Adaboost的损失函数为:
关于Adaboost的推导,可以参考Wikipedia:AdaBoost或者《统计学习方法》P145.
四、Hinge损失函数(SVM)
在机器学习算法中,hinge损失函数和SVM是息息相关的。在线性支持向量机中,最优化问题可以等价于下列式子:
下面来对式子做个变形,令:
于是,原式就变成了:
如若取λ=1/(2C),式子就可以表示成:
可以看出,该式子与下式非常相似:
前半部分中的 l 就是hinge损失函数,而后面相当于L2正则项。
Hinge 损失函数的标准形式
可以看出,当|y|>=1时,L(y)=0。
更多内容,参考Hinge-loss。
补充一下:在libsvm中一共有4中核函数可以选择,对应的是-t参数分别是:
五、其它损失函数
除了以上这几种损失函数,常用的还有:
0-1损失函数
绝对值损失函数
下面来看看几种损失函数的可视化图像,对着图看看横坐标,看看纵坐标,再看看每条线都表示什么损失函数,多看几次好好消化消化。
六、Keras / TensorFlow 中常用 Cost Function 总结
需要记住的是:参数越多,模型越复杂,而越复杂的模型越容易过拟合。过拟合就是说模型在训练数据上的效果远远好于在测试集上的性能。此时可以考虑正则化,通过设置正则项前面的hyper parameter,来权衡损失函数和正则项,减小参数规模,达到模型简化的目的,从而使模型具有更好的泛化能力。
1、自定义交叉熵:cross_entropy1=tf.reduce_mean(y_*tf.log(tf.clip_by_value(y1,le-10,1.0)))
tf.clip_by_value()函数可将一个tensor的元素数值限制在指定范围内,这样可防止一些错误运算,起到数值检查作用。
* 乘法操作符是元素之间直接相乘,tensor中是每个元素对应相乘,要区别去tf.matmul()函数的矩阵相乘
2、Tf.集成交叉熵 Tf.nn.softmax_cross_entropy_with_logits(label=y, logits=y_) // 在未经过softmax处理的logits 上否则会产生错误,最后一层是one-hot 形式标签,在计算loss的时候,输出Tensor要加上tf.reduce_mean(Tensor)或者tf.reduce_sum(Tensor),作为tensorflow优化器(optimizer)的输入。
Softmax :
Cross_entropy:
注意!!!这个函数的返回值并不是一个数,而是一个向量,如果要求交叉熵,我们要再做一步tf.reduce_sum操作,就是对向量里面所有元素求和,最后才得到交叉熵,如果求loss,则要做一步tf.reduce_mean操作,对向量求均值!
3、
tf.nn.sparse_softmax_cross_entropy_with_logits(_sentinel=None,labels=None, logits=None, name=None)
该函数与tf.nn.softmax_cross_entropy_with_logits(_sentinel=None,labels=None, logits=None, dim=-1, name=None)十分相似,唯一的区别在于labels,该函数的标签labels要求是排他性的即只有一个正确类别,labels的形状要求是[batch_size] 而值必须是从0开始编码的int32或int64,而且值范围是[0, num_class),对比于tf.nn.softmax_cross_entropy_with_logits的[batchsize,num_classes]格式的得分编码。
这个函数和上面的区别就是labels参数应该是没有经过onehot的标签,其余的都是一样的。另外加了sparse的loss还有一个特性就是标签可以出现-1,如果标签是-1代表这个数据不再进行梯度回传。
4、
tf.nn.sigmoid_cross_entropy_with_logits(_sentinel=None,labels=None, logits=None, name=None)
sigmoid_cross_entropy_with_logits是TensorFlow最早实现的交叉熵算法。这个函数的输入是logits和labels,logits就是神经网络模型中的 W * X矩阵,注意不需要经过sigmoid,而labels的shape和logits相同,就是正确的标签值,例如这个模型一次要判断100张图是否包含10种动物,这两个输入的shape都是[100, 10]。注释中还提到这10个分类之间是独立的、不要求是互斥,这种问题我们称为多目标(多标签)分类,例如判断图片中是否包含10种动物中的一种或几种,标签值可以包含多个1或0个1。
sigmoid交叉熵loss,与softmax不同的是,该函数首先进行sigmoid操作之后计算交叉熵的损失函数,其余的特性与tf.nn.softmax_cross_entropy_with_logits一致。
5、
tf.nn.weighted_cross_entropy_with_logits(targets, logits, pos_weight, name=None)
weighted_sigmoid_cross_entropy_with_logits是sigmoid_cross_entropy_with_logits的拓展版,多支持一个pos_weight参数,在传统基于sigmoid的交叉熵算法上,正样本算出的值乘以某个系数
这个loss与众不同的地方就是加入了一个权重的系数,其余的地方与tf.nn. sigmoid_cross_entropy_with_logits这个损失函数是一致的,加入的pos_weight函数可以适当的增大或者缩小正样本的loss,可以一定程度上解决正负样本数量差距过大的问题。对比下面两个公式我们可以更加清晰的看到,他和sigmoid的损失函数的区别,对于普通的sigmoid来说计算的形式如下:
targets * -log(sigmoid(logits)) + (1 - targets) * -log(1 - sigmoid(logits))
加入了pos_weight之后的计算形式如下:
targets * -log(sigmoid(logits)) * pos_weight + (1 - targets) * -log(1 - sigmoid(logits))
参考博文: https://blog.csdn.net/hongxue8888/article/details/77159772
参考博文:https://blog.csdn.net/limiyudianzi/article/details/80693695