损失函数(loss function)是用来估量你模型的预测值f(x)与真实值Y的不一致程度,它是一个非负实值函数,通常使用L(Y, f(x))来表示,损失函数越小,模型的鲁棒性就越好。损失函数是经验风险函数的核心部分,也是结构风险函数重要组成部分。模型的结构风险函数包括了经验风险项和正则项,通常可以表示成如下式子:
$$\\theta^* = \\arg \\min_\\theta \\frac{1}{N}{}\\sum_{i=1}^{N} L(y_i, f(x_i; \\theta)) + \\lambda\\ \\Phi(\\theta)$$
其中,前面的均值函数表示的是经验风险函数,L代表的是损失函数,后面的$\\Phi$是正则化项(regularizer)或者叫惩罚项(penalty term),它可以是L1,也可以是L2,或者其他的正则函数。整个式子表示的意思是找到使目标函数最小时的$\\theta$值。下面主要列出几种常见的损失函数。
一、log对数损失函数(逻辑回归)
有些人可能觉得逻辑回归的损失函数就是平方损失,其实并不是。平方损失函数可以通过线性回归在假设样本是高斯分布的条件下推导得到,而逻辑回归得到的并不是平方损失。在逻辑回归的推导中,它假设样本服从伯努利分布(0-1分布),然后求得满足该分布的似然函数,接着取对数求极值等等。而逻辑回归并没有求似然函数的极值,而是把极大化当做是一种思想,进而推导出它的经验风险函数为:最小化负的似然函数(即max F(y, f(x)) —-> min -F(y, f(x)))。从损失函数的视角来看,它就成了log损失函数了。
log损失函数的标准形式:
$$L(Y,P(Y|X)) = -\\log P(Y|X)$$
刚刚说到,取对数是为了方便计算极大似然估计,因为在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,下面将表达式分开表示):
将它带入到上式,通过推导可以得到logistic的损失函数表达式,如下:
逻辑回归最后得到的目标式子如下:
$$J(\\theta) = - \\frac{1}{m} \\sum_{i=1}^m \\left [ y^{(i)} \\log h_{\\theta}(x^{(i)}) + (1-y^{(i)}) \\log(1-h_{\\theta}(x^{(i)})) \\right ]$$
上面是针对二分类而言的。这里需要解释一下:之所以有人认为逻辑回归是平方损失,是因为在使用梯度下降来求最优解的时候,它的迭代式子与平方损失求导后的式子非常相似,从而给人一种直观上的错觉。
这里有个PDF可以参考一下:Lecture 6: logistic regression.pdf.
二、平方损失函数(最小二乘法, Ordinary Least Squares )
最小二乘法是线性回归的一种,OLS将问题转化成了一个凸优化问题。在线性回归中,它假设样本和噪声都服从高斯分布(为什么假设成高斯分布呢?其实这里隐藏了一个小知识点,就是中心极限定理,可以参考【central limit theorem】),最后通过极大似然估计(MLE)可以推导出最小二乘式子。最小二乘的基本原则是:最优拟合直线应该是使各点到回归直线的距离和最小的直线,即平方和最小。换言之,OLS是基于距离的,而这个距离就是我们用的最多的欧几里得距离。为什么它会选择使用欧式距离作为误差度量呢(即Mean squared error, MSE),主要有以下几个原因:
- 简单,计算方便;
- 欧氏距离是一种很好的相似性度量标准;
- 在不同的表示域变换后特征性质不变。
平方损失(Square loss)的标准形式如下:
$$ L(Y, f(X)) = (Y - f(X))^2 $$
当样本个数为n时,此时的损失函数变为:Y-f(X)
表示的是残差,整个式子表示的是残差的平方和,而我们的目的就是最小化这个目标函数值(注:该式子未加入正则项),也就是最小化残差的平方和(residual sum of squares,RSS)。
而在实际应用中,通常会使用均方差(MSE)作为一项衡量指标,公式如下:
$$MSE = \\frac{1}{n} \\sum_{i=1} ^{n} (\\tilde{Y_i} - Y_i )^2$$
上面提到了线性回归,这里额外补充一句,我们通常说的线性有两种情况,一种是因变量y是自变量x的线性函数,一种是因变量y是参数$\\alpha$的线性函数。在机器学习中,通常指的都是后一种情况。
三、指数损失函数(Adaboost)
学过Adaboost算法的人都知道,它是前向分步加法算法的特例,是一个加和模型,损失函数就是指数函数。在Adaboost中,经过m此迭代之后,可以得到$f_{m} (x)$:
Adaboost每次迭代时的目的是为了找到最小化下列式子时的参数$\\alpha$ 和G:
而指数损失函数(exp-loss)的标准形式如下
可以看出,Adaboost的目标式子就是指数损失,在给定n个样本的情况下,Adaboost的损失函数为:
关于Adaboost的推导,可以参考Wikipedia:AdaBoost或者《统计学习方法》P145.
四、Hinge损失函数(SVM)
在机器学习算法中,hinge损失函数和SVM是息息相关的。在线性支持向量机中,最优化问题可以等价于下列式子:
下面来对式子做个变形,令:
于是,原式就变成了:
如若取$\\lambda=\\frac{1}{2C}$,式子就可以表示成:
可以看出,该式子与下式非常相似:
前半部分中的$l$就是hinge损失函数,而后面相当于L2正则项。
Hinge 损失函数的标准形式
$$L(y) = \\max(0, 1-y\\tilde{y}), y=\\pm 1$$
可以看出,当|y|>=1时,L(y)=0。
更多内容,参考Hinge-loss。
补充一下:在libsvm中一共有4中核函数可以选择,对应的是-t
参数分别是:
- 0-线性核;
- 1-多项式核;
- 2-RBF核;
- 3-sigmoid核。
五、其它损失函数
除了以上这几种损失函数,常用的还有:
0-1损失函数
绝对值损失函数
下面来看看几种损失函数的可视化图像,对着图看看横坐标,看看纵坐标,再看看每条线都表示什么损失函数,多看几次好好消化消化。
OK,暂时先写到这里,休息下。最后,需要记住的是:参数越多,模型越复杂,而越复杂的模型越容易过拟合。过拟合就是说模型在训练数据上的效果远远好于在测试集上的性能。此时可以考虑正则化,通过设置正则项前面的hyper parameter,来权衡损失函数和正则项,减小参数规模,达到模型简化的目的,从而使模型具有更好的泛化能力。
六、示例分析
0/1损失函数是最理想的损失函数,如果分类错误(只要有一个错误)就是1,全部正确就是0。不过这个函数有凸函数,不连续等性质,在实际应用中很难实现,所以才有了几种替代的损失函数,他们都是连续,凸函数。其他的三个损失函数的0/1损失函数的上界,如果可以让其他的三个损失函数比较小,也就可以近似的让0/1损失函数比较小。hinge损失函数只要分类正确就不在要求,而其他的另个函数即使分类正确,也要追求更加正确,也就是说,如果你考60分几个,hinge损失函数知道你得到60分就满意。但是另外两个就不会满足于此,还会继续让你考80分,就是继续让你超更加好的方面更新,所以hinge损失函数是及格就好。要是不断追求完美,这就会容易导致过拟合。这几个函数的更新速度就是在分类效果差的时候,指数下降最快,慢慢变得分类效果好的时候,就是hinge下降最快。不过平方误差函数分类很正确和分类错误很严重都会导致很大的误差,模型会出问题,所以在分类的时候不用这个函数,只有在拟合的时候用这个损失函数。
我们来看下下面这个示例:
1 import numpy as np; 2 import matplotlib.pyplot as plt; 3 4 x = np.linspace(-2, 2, 300) 5 6 hinge_loss_function = [] 7 for i in (1-x): 8 if i > 0: 9 hinge_loss_function.append(i) 10 else: 11 hinge_loss_function.append(0) 12 exponential_loss_function = np.exp(-x) 13 logistic_loss_function = np.log(1+np.exp(-x))/np.log(2) 14 15 l0_1_loss_function = [] 16 for j in x: 17 if j < 0: 18 l0_1_loss_function.append(1) 19 else: 20 l0_1_loss_function.append(0) 21 22 pingfang_loss_function = (x-1) ** 2 23 24 plt.plot(x, hinge_loss_function, ‘r-‘) 25 plt.plot(x, exponential_loss_function, ‘b-‘) 26 plt.plot(x, logistic_loss_function, ‘g-‘) 27 plt.plot(x, l0_1_loss_function, ‘k-‘) 28 plt.plot(x, pingfang_loss_function, ‘c-‘) 29 plt.legend([‘hinge_loss_function‘, ‘exponential_loss_function‘, ‘logistic_loss_function‘, ‘l0_1_loss_function‘, ‘pingfang_loss_function‘]) 30 plt.show()
结果如下: