注:代价函数(有的地方也叫损失函数,Loss Function)在机器学习中的每一种算法中都很重要,由于训练模型的过程就是优化代价函数的过程,代价函数对每一个参数的偏导数就是梯度降低中提到的梯度,防止过拟合时添加的正则化项也是加在代价函数后面的。在学习相关算法的过程当中,对代价函数的理解也在不断的加深,在此作一个小结。html
假设有训练样本(x, y),模型为h,参数为θ。h(θ) = θTx(θT表示θ的转置)。git
(1)概况来说,任何可以衡量模型预测出来的值h(θ)与真实值y之间的差别的函数均可以叫作代价函数C(θ),若是有多个样本,则能够将全部代价函数的取值求均值,记作J(θ)。所以很容易就能够得出如下关于代价函数的性质:算法
(2)当咱们肯定了模型h,后面作的全部事情就是训练模型的参数θ。那么何时模型的训练才能结束呢?这时候也涉及到代价函数,因为代价函数是用来衡量模型好坏的,咱们的目标固然是获得最好的模型(也就是最符合训练样本(x, y)的模型)。所以训练参数的过程就是不断改变θ,从而获得更小的J(θ)的过程。理想状况下,当咱们取到代价函数J的最小值时,就获得了最优的参数θ,记为:网络
$$\displaystyle \min_{ \theta } J(\theta)$$app
例如,J(θ) = 0,表示咱们的模型完美的拟合了观察的数据,没有任何偏差。机器学习
(3)在优化参数θ的过程当中,最经常使用的方法是梯度降低,这里的梯度就是代价函数J(θ)对θ1, θ2, ..., θn的偏导数。因为须要求偏导,咱们能够获得另外一个关于代价函数的性质:ide
通过上面的描述,一个好的代价函数须要知足两个最基本的要求:可以评价模型的准确性,对参数θ可微。 函数
2.1 均方偏差学习
在线性回归中,最经常使用的是均方偏差(Mean squared error),具体形式为:优化
$$J(\theta_0, \theta_1) = \frac{ 1 }{ 2m } \displaystyle \sum_{ i = 1 }^{ m } (\hat{ y }^{(i)} - y^{(i)})^2 = \frac{ 1 }{ 2m } \displaystyle \sum_{ i = 1 }^{ m } (h_\theta(x^{(i)}) - y^{(i)})^2 $$
m:训练样本的个数;
hθ(x):用参数θ和x预测出来的y值;
y:原训练样本中的y值,也就是标准答案
上角标(i):第i个样本
2.2 交叉熵
在逻辑回归中,最经常使用的是代价函数是交叉熵(Cross Entropy),交叉熵是一个常见的代价函数,在神经网络中也会用到。下面是《神经网络与深度学习》一书对交叉熵的解释:
交叉熵是对「出乎意料」(译者注:原文使用suprise)的度量。神经元的目标是去计算函数y, 且y=y(x)。可是咱们让它取而代之计算函数a, 且a=a(x)。假设咱们把a看成y等于1的几率,1−a是y等于0的几率。那么,交叉熵衡量的是咱们在知道y的真实值时的平均「出乎意料」程度。当输出是咱们指望的值,咱们的「出乎意料」程度比较低;当输出不是咱们指望的,咱们的「出乎意料」程度就比较高。
在1948年,克劳德·艾尔伍德·香农将热力学的熵,引入到信息论,所以它又被称为香农熵(Shannon Entropy),它是香农信息量(Shannon Information Content, SIC)的指望。香农信息量用来度量不肯定性的大小:一个事件的香农信息量等于0,表示该事件的发生不会给咱们提供任何新的信息,例如肯定性的事件,发生的几率是1,发生了也不会引发任何惊讶;当不可能事件发生时,香农信息量为无穷大,这表示给咱们提供了无穷多的新信息,而且使咱们无限的惊讶。更多解释能够看这里。
$$J(\theta) = -\frac{ 1 }{ m }[\sum_{ i=1 }^{ m } ({y^{(i)} \log h_\theta(x^{(i)}) + (1-y^{(i)}) \log (1-h_\theta(x^{(i)})})]$$
符号说明同上
2.3 神经网络中的代价函数
学习过神经网络后,发现逻辑回归实际上是神经网络的一种特例(没有隐藏层的神经网络)。所以神经网络中的代价函数与逻辑回归中的代价函数很是类似:
$$J(\theta) = -\frac{ 1 }{ m }[\sum_{ i=1 }^{ m } \sum_{ k=1 }^{ K } ({y_k^{(i)} \log h_\theta(x^{(i)}) + (1 - y_k^{(i)}) \log (1 - (h_\theta(x^{(i)}))_k})]$$
这里之因此多了一层求和项,是由于神经网络的输出通常都不是单一的值,K表示在多分类中的类型数。
例如在数字识别中,K=10,表示分了10类。此时对于某一个样原本说,输出的结果以下:
1.1266e-004 1.7413e-003 2.5270e-003 1.8403e-005 9.3626e-003 3.9927e-003 5.5152e-003 4.0147e-004 6.4807e-003 9.9573e-001
一个10维的列向量,预测的结果表示输入的数字是0~9中的某一个的几率,几率最大的就被当作是预测结果。例如上面的预测结果是9。理想状况下的预测结果应该以下(9的几率是1,其余都是0):
0 0 0 0 0 0 0 0 0 1
比较预测结果和理想状况下的结果,能够看到这两个向量的对应元素之间都存在差别,共有10组,这里的10就表示代价函数里的K,至关于把每一种类型的差别都累加起来了。
代价函数衡量的是模型预测值h(θ) 与标准答案y之间的差别,因此总的代价函数J是h(θ)和y的函数,即J=f(h(θ), y)。又由于y都是训练样本中给定的,h(θ)由θ决定,因此,最终仍是模型参数θ的改变致使了J的改变。对于不一样的θ,对应不一样的预测值h(θ),也就对应着不一样的代价函数J的取值。变化过程为:
$$\theta --> h(\theta) --> J(\theta)$$
θ引发了h(θ)的改变,进而改变了J(θ)的取值。为了更直观的看到参数对代价函数的影响,举个简单的例子:
有训练样本{(0, 0), (1, 1), (2, 2), (4, 4)},即4对训练样本,每一个样本对中第1个数表示x的值,第2个数表示y的值。这几个点很明显都是y=x这条直线上的点。以下图:
图1:不一样参数能够拟合出不一样的直线
""" Spyder Editor Python 3.6, Belter, 20170401 """ import matplotlib.pyplot as plt import numpy as np X = np.array([[0, 1, 2, 4]]).T # 都转换成列向量 y = np.array([[0, 1, 2, 4]]).T theta1 = np.array([[0, 0]]).T # 三个不一样的theta_1值 theta2 = np.array([[0, 0.5]]).T theta3 = np.array([[0, 1]]).T X_size = X.shape X_0 = np.ones((X_size[0],1)) # 添加x_0 X_with_x0 = np.concatenate((X_0, X), axis=1) h1 = np.dot(X_with_x0, theta1) h2 = np.dot(X_with_x0, theta2) h3 = np.dot(X_with_x0, theta3) plt.plot(X, y, 'rx', label='y') plt.plot(X, h1, 'b', label='h1, theta_1=0') plt.plot(X, h2, 'm', label='h2, theta_1=0.5') plt.plot(X, h3, 'g', label='h3, theta_1=1') plt.xlabel('X') plt.ylabel('y/h') plt.axis([-0.1, 4.5, -0.1, 4.5]) plt.legend(loc='upper left') plt.savefig('liner_gression_error.png', dpi=200)
常数项为0,因此能够取θ0=0,而后取不一样的θ1,能够获得不一样的拟合直线。当θ1=0时,拟合的直线是y=0,即蓝色线段,此时距离样本点最远,代价函数的值(偏差)也最大;当θ1=1时,拟合的直线是y=x,即绿色线段,此时拟合的直线通过每个样本点,代价函数的值为0。
经过下图能够查看随着θ1的变化,J(θ)的变化状况:
图2:代价函数J(θ)随参数的变化而变化
""" Spyder Editor Python 3.6, Belter, 20170401 """ # 计算代价函数的值 def calcu_cost(theta, X, y): m = X.shape[0] # sample size X_0 = np.ones((m,1)) X_with_x0 = np.concatenate((X_0, X), axis=1) h = np.dot(X_with_x0, theta) return(np.dot((h-y).T, (h-y))/(2*m)) X = np.array([[0, 1, 2, 4]]).T y = np.array([[0, 1, 2, 4]]).T theta_0 = np.zeros((101, 1)) theta_1 = np.array([np.linspace(-2, 4, 101)]).T theta = np.concatenate((theta_0, theta_1), axis=1) # 101组不一样的参数 J_list = [] for i in range(101): current_theta = theta[i:i+1].T cost = calcu_cost(current_theta, X, y) J_list.append(cost[0,0]) plt.plot(theta_1, J_list) plt.xlabel('theta_1') plt.ylabel('J(theta)') plt.savefig('cost_theta.png', dpi=200)
从图中能够很直观的看到θ对代价函数的影响,当θ1=1时,代价函数J(θ)取到最小值。由于线性回归模型的代价函数(均方偏差)的性质很是好,所以也能够直接使用代数的方法,求J(θ)的一阶导数为0的点,就能够直接求出最优的θ值(正规方程法)。
梯度降低中的梯度指的是代价函数对各个参数的偏导数,偏导数的方向决定了在学习过程当中参数降低的方向,学习率(一般用α表示)决定了每步变化的步长,有了导数和学习率就可使用梯度降低算法(Gradient Descent Algorithm)更新参数了。下图中展现了只有两个参数的模型运用梯度降低算法的过程。
4.1 线性回归模型的代价函数对参数的偏导数
仍是以两个参数为例,每一个参数都有一个偏导数,且综合了全部样本的信息。
4.2 逻辑回归模型的代价函数对参数的偏导数
根据逻辑回归模型的代价函数以及sigmoid函数
$$h_{\theta}(x)=g(\theta^{T}x)$$
$$g(z)=\frac{1}{1+e^{-z}}$$
获得对每一个参数的偏导数为
$$\frac{\partial}{\partial\theta_{j}}J(\theta) =\sum_{i=1}^{m}(h_\theta(x^{i})-y^i)x_j^i$$
详细推导过程能够看这里-逻辑回归代价函数的导数
4.3 神经网络中的代价函数对参数的偏导数
这里的计算过程与前面都不同,后面再补充。
重大修订:
2017.8.14 修改排版,补充对交叉熵的解释
https://www.quora.com/How-are-the-cost-functions-for-Neural-Networks-derived/answer/Daniel-Watson-22?srid=uIoGQ
https://www.zhihu.com/question/23468713
https://zh.wikipedia.org/wiki/%E7%86%B5_(%E4%BF%A1%E6%81%AF%E8%AE%BA)
https://hit-scir.gitbooks.io/neural-networks-and-deep-learning-zh_cn/content/chap3/c3s3.html
Coursera, Andrew Ng 公开课第一周,第三周,第五周
http://math.stackexchange.com/questions/477207/derivative-of-cost-function-for-logistic-regression
http://math.stackexchange.com/questions/947604/gradient-tangents-planes-and-steepest-direction