在分类问题中,你要预测的变量 y y y 是离散的值,我们将学习一种叫做逻辑回归 (Logistic Regression) 的算法,这是目前使用最广泛的学习算法之一。
在分类问题中,我们尝试预测的是结果是否属于某一个分类(例如正确或错误)。分类问题的例子有:判断一封电子邮件是否是垃圾邮件;判断一次金融交易是否是欺诈;区别一个肿瘤是恶性的还是良性的等等。
我们从二元的分类问题开始讨论。
我们将因变量( dependent variable
)可能属于的两个类分别称为负向类( negative class
)和正向类( positive class
),则因变量 y ∈ 0 , 1 y \in 0, 1 y∈0,1 ,其中 0
表示负向类,1
表示正向类。
如果我们要用线性回归算法来解决一个分类问题,对于分类, 取值为 0
或者 1
,但如果你使用的是线性回归,即使所有训练样本的标签 都等于 0
或 1
,函数的输出值可能远大于 1
,或者远小于 0
(线性回归的输出值的值域为 ( − ∞ , + ∞ ) (-\infty, +\infty) (−∞,+∞))。尽管我们知道标签应该取值 0
或者 1
,但是如果算法得到的值远大于 1
或者远小于 0
的话,就会感觉很奇怪。所以我们在接下来的要研究的算法就叫做逻辑回归算法,这个算法的性质是:它的输出值的取值范围永远在 0
到 1
之间。
顺便说一下,逻辑回归算法是分类算法,我们将它作为分类算法使用。有时候可能因为这个算法的名字中出现了“回归”使你感到困惑,但逻辑回归算法实际上是一种分类算法,它适用于标签 取值离散的情况,如:1 0 0 1
。
接下来我们要搞清楚,在分类问题中,要用什么样的函数来表示我们的假设。此前我们说过,希望我们的分类器的输出值在 0
和 1
之间,因此,我们希望想出一个满足某个性质的假设函数,这个性质是它的预测值要在 0
和 1
之间。
回顾在一开始提到的乳腺癌分类问题,我们可以用线性回归的方法求出适合数据的一条直线:
根据线性回归模型我们只能预测连续的值,然而对于分类问题,我们需要输出 0
或 1
,我们可以预测:
当 h θ ( x ) ≥ 0.5 h_{\theta}(x) \geq 0.5 hθ(x)≥0.5 时,预测 y = 1 y = 1 y=1 ;
当 h θ ( x ) < 0.5 h_{\theta}(x) \lt 0.5 hθ(x)<0.5 时,预测 y = 0 y = 0 y=0 。
对于上图所示的数据,这样的一个线性模型似乎能很好地完成分类任务。假使我们又观测到一个非常大尺寸的恶性肿瘤,将其作为实例加入到我们的训练集中来,这将使得我们获得一条新的直线。
这时,再使用 0.5
作为阀值来预测肿瘤是良性还是恶性便不合适了。可以看出,线性回归模型,因为其预测的值可以超越 [0,1]
的范围,并不适合解决这样的分类问题。
我们引入一个新的模型,逻辑回归,该模型的输出变量范围始终在 0
和 1
之间。逻辑回归模型的假设是: h θ ( x ) = g ( θ T X ) h_{\theta}(x) = g(\theta^T X) hθ(x)=g(θTX) 其中: X X X 代表特征向量, g g g 代表逻辑函数(logistic function)是一个常用的 S
形函数(Sigmoid function),公式为: g ( z ) = 1 / ( 1 + e − z ) g(z) = 1/(1 + e^{-z}) g(z)=1/(1+e−z) 。
使用Python代码实现这个函数:
import numpy as np
def fn_sigmoid(z):
return 1 / (1 + np.exp(-z))
# test
print(fn_sigmoid(0))
# result
0.5
import matplotlib.pyplot as plt
plt.figure(figsize=(20, 8), dpi=80)
x = np.linspace(-10, 10, 10000)
y = 1 / (1 + np.exp(-x))
plt.grid()
plt.plot(x, y, 'r')
plt.show()
合起来,我们得到逻辑回归模型的假设:
对模型 g ( z ) = 1 / ( 1 + e − z ) g(z) = 1/(1 + e^{-z}) g(z)=1/(1+e−z) 的理解:
h θ ( x ) = g ( θ T X ) = 1 / ( 1 + e − θ T X ) h_{\theta}(x) = g(\theta^TX) = 1/(1 + e^{-\theta^TX}) hθ(x)=g(θTX)=1/(1+e−θTX) 的作用是,对于给定的输入变量,根据选择的参数计算 输出变量 = 1
的可能性(estimated probablity)即 h θ ( x ) = P ( y = 1 ∣ x ; θ ) h_{\theta}(x) = P(y=1| x; \theta) hθ(x)=P(y=1∣x;θ) 。例如,如果对于给定的 x x x ,通过已经确定的参数计算得出 h θ ( x ) = 0.7 h_{\theta}(x) = 0.7 hθ(x)=0.7 ,则表示有 70%
的几率 y y y 为正向类,相应地 y y y 为负向类的几率为 1-0.7=0.3
。
现在讲下决策边界(decision boundary
)的概念。这个概念能更好地帮助我们理解逻辑回归的假设函数在计算什么。
在逻辑回归中,我们预测:
当 h θ ( x ) ≥ 0.5 h_{\theta}(x) \geq 0.5 hθ(x)≥0.5 时,预测 y = 1 y = 1 y=1 ;
当 h θ ( x ) < 0.5 h_{\theta}(x) \lt 0.5 hθ(x)<0.5 时,预测 y = 0 y = 0 y=0 。
根据上面绘制出的 S 形函数图像,我们知道当:
又 z = θ T X z = \theta^TX z=θTX ,即: θ T X ≥ 0 \theta^TX \geq 0 θTX≥0 时,预测 y = 1 y = 1 y=1 , θ T X < 0 \theta^TX \lt 0 θTX<0 时,预测 y = 0 y = 0 y=0 。
现在假设我们有一个模型:
并且参数 θ \theta θ 是向量 [-3 1 1]
。则当 − 3 + x 1 + x 2 ≥ 0 -3 + x_1 + x_2 \geq 0 −3+x1+x2≥0 ,即 x 1 + x 2 ≥ 3 x_1 + x_2 \geq 3 x1+x2≥3 时,模型将预测 y = 1 y = 1 y=1 。我们可以绘制直线 x 1 + x 2 = 3 x_1 + x_2 = 3 x1+x2=3 ,这条线便是我们模型的分界线,将预测为 1
的区域和预测为 0
的区域分隔开。
假使我们的数据呈现这样的分布情况,怎样的模型才能适合呢?
因为需要用曲线才能分隔 y = 1 y = 1 y=1 的区域和 y = 0 y = 0 y=0 的区域,我们需要二次方特征:
函数 h θ ( x ) = g ( θ 0 + θ 1 x 1 + θ 2 x 2 + θ 3 x 1 2 + θ 4 x 2 2 ) h_{\theta}(x) = g(\theta_0 + \theta_1 x_1 + \theta_2 x_2 + \theta_3 x_1^2 + \theta_4 x_2^2) hθ(x)=g(θ0+θ1x1+θ2x2+θ3x12+θ4x22) 的系数分别是 [-1 0 0 1 1]
,则我们得到的判定边界恰好是圆点在原点且半径为 1
的圆形。
我们还可以用非常复杂的模型来适应非常复杂形状的判定边界。
接下来我们介绍如何拟合逻辑回归模型的参数 θ \theta θ 。具体来说,我要定义用来拟合参数的优化目标叫代价函数(或者损失函数),这便是监督学习问题中的逻辑回归模型的拟合问题。
对于线性回归模型,我们定义的代价函数是所有模型误差的平方和。理论上来说,我们也可以对逻辑回归模型沿用这个定义,但是问题在于,当我们将 h θ ( x ) = 1 / ( 1 + e − θ T x ) h_{\theta}(x) = 1/(1 + e^{-\theta^Tx}) hθ(x)=1/(1+e−θTx) 带入到这样定义了的代价函数中时,我们得到的代价函数将是一个非凸函数(non-convexfunction
)。
关于凸函数的概念,首先了解一下凸集:
在欧氏空间中,凸集是对于集合内的每两个点,连接这两个点的直线段上的每个点也在该集合内。例如,立方体是凸集,但是任何中空的或具有凹痕的例如月牙形都不是凸集。
特别的,若在实数 R R R 上(或复数 C C C 上)的向量空间中,如果集合 S S S 中任两点的连线上的点都在 S S S 内,则称集合 S S S 为凸集。
而凸函数则是一个定义在某个实数空间的凸子集 C C C 上的实值函数 f f f ,而且对于凸子集 C C C 中任意两个点 x 1 , x 2 x_1, x_2 x1,x2 有 f ( ( x 1 + x 2 ) / 2 ) ≤ ( f ( x 1 ) + f ( x 2 ) ) / 2 f((x_1 + x_2) / 2) \leq (f(x_1) + f(x_2)) / 2 f((x1+x2)/2)≤(f(x1)+f(x2))/2 成立。
判定函数是否是凸函数,可以利用定义法、已知结论法以及函数的二阶导数,对于实数集上的凸函数,一般的判别方法是求它的二阶导数,如果其二阶导数在区间上非负,就称为凸函数。如果其二阶导数在区间上恒大于 0
,就称为严格凸函数。
很明显,上 图1
是非凸函数,上 图2
是凸函数。
这意味着我们的代价函数有许多局部最小值,这将影响梯度下降算法寻找全局最小值。
线性回归的代价函数为: J ( θ ) = 1 m ∑ i = 1 m 1 2 ( h θ ( x ( i ) ) − y ( i ) ) 2 J(\theta) = \frac{1}{m} \sum_{i=1}^m \frac{1}{2} (h_{\theta}(x^{(i)}) - y^{(i)})^2 J(θ)=m1∑i=1m21(hθ(x(i))−y(i))2 。我们重新定义逻辑回归的代价函数为: J ( θ ) = 1 m ∑ i = 1 m C o s t ( h θ ( x ( i ) ) − y ( i ) ) J(\theta) = \frac{1}{m} \sum_{i=1}^m Cost (h_{\theta}(x^{(i)}) - y^{(i)}) J(θ)=m1∑i=1mCost(hθ(x(i))−y(i)) ,其中:
C o s t ( h θ ( x ) − y ) = { − l o g ( h θ ( x ) ) , if y = 1 − l o g ( 1 − h θ ( x ) ) , if y = 0 Cost (h_{\theta}(x) - y) = \begin{cases} -log(h_{\theta}(x)), \quad \text{if $y = 1$} \\ -log(1 - h_{\theta}(x)), \quad \text{if $y = 0$} \end{cases} Cost(hθ(x)−y)={−log(hθ(x)),if y=1−log(1−hθ(x)),if y=0
h θ ( x ) h_{\theta}(x) hθ(x) 与 C o s t ( h θ ( x ) − y ) Cost (h_{\theta}(x) - y) Cost(hθ(x)−y) 之间的关系如下图所示:
图像绘制Python代码:
fig, axes = plt.subplots(ncols=2, nrows=1, figsize=(20, 8), dpi=80)
x = np.linspace(0, 1, 10000)
y1 = -np.log(x)
y2 = -np.log(1 - x)
axes[0].plot(x, y1)
axes[1].plot(x, y2)
axes[0].set_xlabel("$h_{θ}(x)$", fontsize=18)
axes[0].set_ylabel("$Cost(h_{θ}(x), y)$", fontsize=18)
axes[1].set_xlabel("$h_{θ}(x)$", fontsize=18)
axes[1].set_ylabel("$Cost(h_{θ}(x), y)$", fontsize=18)
axes[0].annotate("if y = 1", (0.4, 8), fontsize=18)
axes[1].annotate("if y = 0", (0.4, 8), fontsize=18)
axes[0].grid()
axes[1].grid()
plt.show()
这样构建的 C o s t ( h θ ( x ) − y ) Cost (h_{\theta}(x) - y) Cost(hθ(x)−y) 函数的特点是:当实际的 y = 1 y = 1 y=1 且 h θ ( x ) h_{\theta}(x) hθ(x) 也为 1
时误差为 0
,当 y = 1 y = 1 y=1 但 h θ ( x ) h_{\theta}(x) hθ(x) 不为 1
时误差随着 h θ ( x ) h_{\theta}(x) hθ(x) 变小而变大;当实际的 y = 0 y = 0 y=0 且 h θ ( x ) h_{\theta}(x) hθ(x) 也为 0
时代价为 0
,当 y = 0 y = 0 y=0 但 h θ ( x ) h_{\theta}(x) hθ(x) 不为 0
时误差随着 h θ ( x ) h_{\theta}(x) hθ(x) 的变大而变大。将构建的 C o s t ( h θ ( x ) − y ) Cost (h_{\theta}(x) - y) Cost(hθ(x)−y) 函数简化如下:
C o s t ( h θ ( x ) − y ) = − y l o g ( h θ ( x ) ) − ( 1 − y ) l o g ( 1 − h θ ( x ) ) Cost (h_{\theta}(x) - y) = - y log(h_{\theta}(x)) - (1 - y) log(1 - h_{\theta}(x)) Cost(hθ(x)−y)=−ylog(hθ(x))−(1−y)log(1−hθ(x))
带入代价函数得到:
J ( θ ) = 1 m ∑ i = 1 m [ − y ( i ) l o g ( h θ ( x ( i ) ) ) − ( 1 − y ( i ) ) l o g ( 1 − h θ ( x ( i ) ) ) ] 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)}))] J(θ)=m1i=1∑m[−y(i)log(hθ(x(i)))−(1−y(i))log(1−hθ(x(i)))]
即:
J ( θ ) = − 1 m ∑ i = 1 m [ y ( i ) l o g ( h θ ( x ( i ) ) ) + ( 1 − y ( i ) ) l o g ( 1 − h θ ( x ( i ) ) ) ] 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)}))] J(θ)=−m1i=1∑m[y(i)log(hθ(x(i)))+(1−y(i))log(1−hθ(x(i)))]
使用Python代码实现损失函数:
def LR_cost(theta, X, y):
theta = np.matrix(theta)
X = np.matrix(X)
y = np.matrix(y)
y0 = np.mutiply(-y, np.log(fn_sigmoid(X * theta.T)))
y1 = np.mutiply(-(1 - y), np.log(1 - fn_sigmoid(X * theta.T)))
return (np.sum(y0 + y1))/len(X)
在得到这样一个代价函数以后,我们便可以用梯度下降算法来求得能使代价函数最小的参数了。算法为:
repeat { θ j : = θ j − α ∂ ∂ θ j J ( θ ) ( s i m u l t a n e o u s l y u p d a t e a l l ) } \text{repeat \{$\theta_j := \theta_j - \alpha \frac{\partial}{\partial \theta_j} J(\theta) \quad (simultaneously \; update \; all) $\}} repeat {θj:=θj−α∂θj∂J(θ)(simultaneouslyupdateall)}
我们将 ∂ ∂ θ j J ( θ ) \frac{\partial}{\partial \theta_j} J(\theta) ∂θj∂J(θ) 项替换成求导后的公式,即:
repeat { θ j : = θ j − α 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) ( s i m u l t a n e o u s l y u p d a t e a l l ) } \text{repeat \{$\theta_j := \theta_j - \alpha \frac{1}{m} \sum_{i=1}^m \bigg(h_{\theta}(x^{(i)}) - y^{(i)}\bigg)x_{j}^{(i)} \quad (simultaneously \; update \; all) $\}} repeat {θj:=θj−αm1∑i=1m(hθ(x(i))−y(i))xj(i)(simultaneouslyupdateall)}
这里我们可以证明这个代价函数是一个凸函数,并且没有局部最优值,通过优化这个代价函数我们得到的一定是一个全局最优解。
推导过程:
J ( θ ) = − 1 m ∑ i = 1 m [ y ( i ) l o g ( h θ ( x ( i ) ) ) + ( 1 − y ( i ) ) l o g ( 1 − h θ ( x ( i ) ) ) ] 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)}))] J(θ)=−m1i=1∑m[y(i)log(hθ(x(i)))+(1−y(i))log(1−hθ(x(i)))]
考虑:
h θ ( x ( i ) ) = 1 1 + e − θ T x ( i ) h_{\theta}(x^{(i)}) = \frac{1}{1 + e^{-\theta^Tx^{(i)}}} hθ(x(i))=1+e−θTx(i)1
则有:
y ( i ) l o g ( h θ ( x ( i ) ) ) + ( 1 − y ( i ) ) l o g ( 1 − h θ ( x ( i ) ) ) y^{(i)} log(h_{\theta}(x^{(i)})) + (1 - y^{(i)}) log(1 - h_{\theta}(x^{(i)})) y(i)log(hθ(x(i)))+(1−y(i))log(1−hθ(x(i)))
= y ( i ) l o g ( 1 1 + e − θ T x ( i ) ) + ( 1 − y ( i ) ) l o g ( 1 − 1 1 + e − θ T x ( i ) ) = y^{(i)} log \bigg(\frac{1}{1 + e^{-\theta^Tx^{(i)}}} \bigg) + (1 - y^{(i)}) log \bigg(1 - \frac{1}{1 + e^{-\theta^Tx^{(i)}}} \bigg) =y(i)log(1+e−θTx(i)1)+(1−y(i))log(1−1+e−θTx(i)1)
= − y ( i ) l o g ( 1 + e − θ T x ( i ) ) − ( 1 − y ( i ) ) l o g ( 1 + e θ T x ( i ) ) = -y^{(i)} log \bigg(1 + e^{-\theta^Tx^{(i)}} \bigg) - (1 - y^{(i)}) log \bigg(1 + e^{\theta^Tx^{(i)}} \bigg) =−y(i)log(1+e−θTx(i))−(1−y(i))log(1+eθTx(i))
所以:
∂ ∂ θ j J ( θ ) = ∂ ∂ θ j [ − 1 m ∑ i = 1 m ( − y ( i ) l o g ( 1 + e − θ T x ( i ) ) − ( 1 − y ( i ) ) l o g ( 1 + e θ T x ( i ) ) ) ] \frac{\partial}{\partial \theta_j} J(\theta) = \frac{\partial}{\partial \theta_j} \bigg[-\frac{1}{m} \sum_{i=1}^m \bigg(-y^{(i)} log(1 + e^{-\theta^Tx^{(i)}}) - (1 - y^{(i)}) log(1 + e^{\theta^Tx^{(i)}}) \bigg) \bigg] ∂θj∂J(θ)=∂θj∂[−m1i=1∑m(−y(i)log(1+e−θTx(i))−(1−y(i))log(1+eθTx(i)))]
= − 1 m ∑ i = 1 m ( − y ( i ) − x j ( i ) e − θ T x ( i ) 1 + e − θ T x ( i ) − ( 1 − y ( i ) ) x j ( i ) e θ T x ( i ) 1 + e θ T x ( i ) ) = -\frac{1}{m} \sum_{i=1}^m \bigg(-y^{(i)} \frac{-x_{j}^{(i)}e^{-\theta^Tx^{(i)}}}{1 + e^{-\theta^Tx^{(i)}}} - (1 - y^{(i)}) \frac{x_{j}^{(i)}e^{\theta^Tx^{(i)}}}{1 + e^{\theta^Tx^{(i)}}} \bigg) =−m1i=1∑m(−y(i)1+e−θTx(i)−xj(i)e−θTx(i)−(1−y(i))1+eθTx(i)xj(i)eθTx(i))
= − 1 m ∑ i = 1 m ( y ( i ) x j ( i ) 1 + e θ T x ( i ) − ( 1 − y ( i ) ) x j ( i ) e θ T x ( i ) 1 + e θ T x ( i ) ) = -\frac{1}{m} \sum_{i=1}^m \bigg(y^{(i)} \frac{x_{j}^{(i)}}{1 + e^{\theta^Tx^{(i)}}} - (1 - y^{(i)}) \frac{x_{j}^{(i)}e^{\theta^Tx^{(i)}}}{1 + e^{\theta^Tx^{(i)}}} \bigg) =−m1i=1∑m(y(i)1+eθTx(i)xj(i)−(1−y(i))1+eθTx(i)xj(i)eθTx(i))
= − 1 m ∑ i = 1 m x j ( i ) y ( i ) − x j ( i ) e θ T x ( i ) + x j ( i ) y ( i ) e θ T x ( i ) 1 + e θ T x ( i ) = -\frac{1}{m} \sum_{i=1}^m \frac{x_{j}^{(i)}y^{(i)} - x_{j}^{(i)}e^{\theta^Tx^{(i)}} + x_{j}^{(i)}y^{(i)}e^{\theta^Tx^{(i)}}}{1 + e^{\theta^Tx^{(i)}}} =−m1i=1∑m1+eθTx(i)xj(i)y(i)−xj(i)eθTx(i)+xj(i)y(i)eθTx(i)
= − 1 m ∑ i = 1 m y ( i ) ( 1 + e θ T x ( i ) ) − e θ T x ( i ) 1 + e θ T x ( i ) x j ( i ) = -\frac{1}{m} \sum_{i=1}^m \frac{y^{(i)} (1 + e^{\theta^Tx^{(i)}}) - e^{\theta^Tx^{(i)}}}{1 + e^{\theta^Tx^{(i)}}} x_{j}^{(i)} =−m1i=1∑m1+eθTx(i)y(i)(1+eθTx(i))−eθTx(i)xj(i)
= − 1 m ∑ i = 1 m ( y ( i ) − e θ T x ( i ) 1 + e θ T x ( i ) ) x j ( i ) = − 1 m ∑ i = 1 m ( y ( i ) − 1 1 + e − θ T x ( i ) ) x j ( i ) = -\frac{1}{m} \sum_{i=1}^m \bigg(y^{(i)} - \frac{e^{\theta^Tx^{(i)}}}{1 + e^{\theta^Tx^{(i)}}} \bigg) x_{j}^{(i)} = -\frac{1}{m} \sum_{i=1}^m \bigg(y^{(i)} - \frac{1}{1 + e^{-\theta^Tx^{(i)}}} \bigg) x_{j}^{(i)} =−m1i=1∑m(y(i)−1+eθTx(i)eθTx(i))xj(i)=−m1i=1∑m(y(i)−1+e−θTx(i)1)xj(i)
= − 1 m ∑ i = 1 m ( y ( i ) − h θ ( x ( i ) ) ) x j ( i ) = 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) = -\frac{1}{m} \sum_{i=1}^m \bigg(y^{(i)} - h_{\theta}(x^{(i)}) \bigg) x_{j}^{(i)} = \frac{1}{m} \sum_{i=1}^m \bigg(h_{\theta}(x^{(i)}) - y^{(i)} \bigg) x_{j}^{(i)} =−m1i=1∑m(y(i)−hθ(x(i)))xj(i)=m1i=1∑m(hθ(x(i))−y(i))xj(i)
注:虽然得到的梯度下降算法表面上看上去与线性回归的梯度下降算法一样,但是这里的 h θ ( x ) = g ( θ T X ) h_{\theta}(x) = g(\theta^TX) hθ(x)=g(θTX) 与线性回归中不同,所以实际上是不一样的。另外,在运行梯度下降算法之前,进行特征缩放依旧是非常必要的。
一些梯度下降算法之外的选择:除了梯度下降算法以外,还有一些常被用来使代价函数最小的算法,这些算法更加复杂和优越,而且通常不需要人工选择学习率,通常比梯度下降算法要更加快速。这些算法有:共轭梯度( Conjugate Gradient
),局部优化法(Broyden fletcher goldfarb shann
, BFGS
)和有限内存局部优化法( LBFGS
) 。
接下来我们将会找出一种稍微简单一点的方法来写代价函数,替换我们现在用的方法。同时我们还要弄清楚如何运用梯度下降法,来拟合出逻辑回归的参数。因此,看了这节内容,你就应该知道如何实现一个完整的逻辑回归算法。
那么根据上一小节的推导,我们可以将原始梯度下降的公式:
θ j : = θ j − α ∂ ∂ θ j J ( θ ) \theta_j := \theta_j - \alpha \frac{\partial}{\partial \theta_j} J(\theta) θj:=θj−α∂θj∂J(θ)
变成:
θ j : = θ j − α 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) \theta_j := \theta_j - \alpha \frac{1}{m} \sum_{i=1}^m \bigg(h_{\theta}(x^{(i)}) - y^{(i)}\bigg)x_{j}^{(i)} θj:=θj−αm1i=1∑m(hθ(x(i))−y(i))xj(i)
其中, ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) \sum_{i=1}^m \bigg(h_{\theta}(x^{(i)}) - y^{(i)}\bigg)x_{j}^{(i)} ∑i=1m(hθ(x(i))−y(i))xj(i) 代表的意义为:计算每个样本的测试误差与当前样本第 j j j 个特征的乘积,然后将 m m m个样本的结果求和。
所以,如果你有 n n n 个特征,也就是说: θ = [ θ 0 θ 1 ⋮ θ n ] \theta = \begin{bmatrix}\theta_0 \\ \theta_1 \\ \vdots \\ \theta_n\end{bmatrix} θ=⎣⎢⎢⎢⎡θ0θ1⋮θn⎦⎥⎥⎥⎤ ,那么你就需要用上述式子来同时更新所有的参数 θ \theta θ 值。
现在,如果你把这个更新规则和我们之前用在线性回归上的进行比较的话,你会惊讶地发现,这个式子正是我们用来做线性回归梯度下降的式子。
那么,线性回归和逻辑回归是同一个算法吗?要回答这个问题,我们要观察逻辑回归看看发生了哪些变化。实际上,假设的定义发生了变化。
对于线性回归假设函数:
h θ ( x ) = θ T X = θ 0 x 0 + θ 1 x 1 + . . . + θ n x n h_{\theta}(x) = \theta^TX = \theta_0 x_0 + \theta_1 x_1 + ... + \theta_n x_n hθ(x)=θTX=θ0x0+θ1x1+...+θnxn
而现在逻辑函数的假设函数:
h θ ( x ) = 1 1 + e − θ T X h_{\theta}(x) = \frac{1}{1 + e^{-\theta^TX}} hθ(x)=1+e−θTX1
因此,即使更新参数的规则看起来基本相同,但由于假设的定义发生了变化,所以逻辑函数的梯度下降,跟线性回归的梯度下降实际上是两个完全不同的东西。
当我们在谈论线性回归的梯度下降法时,我们谈到了如何监控梯度下降法以确保其收敛,我们通常也把同样的方法用在逻辑回归中,来监测梯度下降,以确保它正常收敛。
当使用梯度下降法来实现逻辑回归时,我们有这些不同的参数 θ = [ θ 0 θ 1 ⋮ θ n ] \theta = \begin{bmatrix}\theta_0 \\ \theta_1 \\ \vdots \\ \theta_n\end{bmatrix} θ=⎣⎢⎢⎢⎡θ0θ1⋮θn⎦⎥⎥⎥⎤ ,我们需要用这个表达式来更新这些参数。我们还可以使用 for
循环来更新这些参数值,用 for i=1 to n
,或者 for i=1 to n+1
。当然,不用 for
循环也是可以的,理想情况下,我们更提倡使用向量化的实现,可以把所有这些 n n n 个参数同时更新。
最后还有一点,我们在谈线性回归时讲到的特征缩放,我们看到了特征缩放是如何提高梯度下降的收敛速度的,这个特征缩放的方法,也适用于逻辑回归。如果你的特征范围差距很大的话,那么应用特征缩放的方法,同样也可以让逻辑回归的梯度下降收敛更快。
现在你应该知道如何实现逻辑回归了,这是一种非常强大,甚至可能世界上使用最广泛的一种分类算法。
上一节我们讨论了用梯度下降的方法最小化逻辑回归中的代价函数 J ( θ ) J(\theta) J(θ) 。在本小节,我们会用一些高级优化算法和一些高级的优化概念,利用这些方法,我们就能够让通过梯度下降进行逻辑回归的速度大大提高,而这也将使算法更加适合解决大型的机器学习问题,比如,我们有数目庞大的特征数量。现在我们换个角度来看什么是梯度下降,我们有个代价函数 J ( θ ) J(\theta) J(θ) ,而我们想要使其最小化,那么我们需要做的是编写代码,当输入参数 θ \theta θ 时,它们会计算出两样东西: J ( θ ) J(\theta) J(θ) 以及 j j j 等于 0
、1
直到 n
时的偏导数项。
假设我们已经完成了可以实现这两件事的代码,那么梯度下降所做的就是反复执行这些更新。另一种考虑梯度下降的思路是:我们需要写出代码来计算 J ( θ ) J(\theta) J(θ) 和这些偏导数,然后把这些插入到梯度下降中,然后它就可以为我们最小化这个函数。对于梯度下降来说,我认为从技术上讲,你实际并不需要编写代码来计算代价函数 J ( θ ) J(\theta) J(θ) 。你只需要编写代码来计算导数项,但是,如果你希望代码还要能够监控这些 J ( θ ) J(\theta) J(θ) 的收敛性,那么我们就需要自己编写代码来计算代价函数 J ( θ ) J(\theta) J(θ) 和偏导数项 ∂ ∂ θ j J ( θ ) \frac{\partial}{\partial \theta_j} J(\theta) ∂θj∂J(θ) 。所以,在写完能够计算这两者的代码之后,我们就可以使用梯度下降。然而梯度下降并不是我们可以使用的唯一算法,还有其他一些算法,更高级、更复杂。共轭梯度法 BFGS
(变尺度法) 和 L-BFGS
(限制变尺度法) 就是其中一些更高级的优化算法,它们需要有一种方法来计算 J ( θ ) J(\theta) J(θ) ,以及需要一种方法计算导数项 ∂ ∂ θ j J ( θ ) \frac{\partial}{\partial \theta_j} J(\theta) ∂θj∂J(θ) ,然后使用比梯度下降更复杂的算法来最小化代价函数。这三种算法的具体细节本小节不做研究。实际上你最后通常会花费很多天,或几周时间研究这些算法,你可以专门学一门课来提高数值计算能力,不过让我来告诉你他们的一些特性:
这三种算法有许多优点:
一个是使用这其中任何一个算法,你通常不需要手动选择学习率 α \alpha α , 所以对于这些算法的一种思路是,给出计算导数项和代价函数的方法,你可以认为算法有一个智能的内部循环,而且,事实上,他们确实有一个智能的内部循环, 称为线性搜索( line search
)算法,它可以自动尝试不同的学习速率 α \alpha α ,并自动选择一个最好的学习速率 ,因此它甚至可以为每次迭代选择不同的学习速率,那么你就不需要自己选择。这些算法实际上在做更复杂的事情,不仅仅是选择一个好的学习速率,所以它们往往最终比梯度下降收敛要快得多。
有了这些算法,你就可以使用一个复杂的优化库,它让算法使用起来更模糊一点。因此也许稍微有点难调试,不过由于这些算法的运行速度通常远远超过梯度下降。
所以当我有一个很大的机器学习问题时,我会选择这些高级算法,而不是梯度下降。
在本小节,我们将谈到如何使用逻辑回归 (logistic regression
)来解决多类别分类问题,具体来说通过一个叫做"一对多" ( one-vs-all
) 的分类算法来实现。
先看这样一些例子。
第一个例子:假如说你现在需要一个学习算法能自动地将邮件归类到不同的文件夹里,或者说可以自动地加上标签,那么,你也许需要一些不同的文件夹,或者不同的标签来完成这件事,来区分开来自工作的邮件、朋友的邮件、家人的邮件或者是有关兴趣爱好的邮件,那么,我们就有了这样一个分类问题:其类别有四个,分别用 y = 1 y=1 y=1 、 y = 2 y=2 y=2 、 y = 3 y=3 y=3 、 y = 4 y=4 y=4 来代表。
第二个例子是有关药物诊断的,如果一个病人因为鼻塞来到你的诊所,他可能并没有生病,用 y = 1 y=1 y=1 这个类别来代表;或者患了感冒,用 y = 2 y=2 y=2 来代表;或者得了流感用 y = 3 y=3 y=3 来代表。
第三个例子:如果你正在做有关天气的机器学习分类问题,那么你可能想要区分哪些天是晴天、多云、雨天、或者下雪天,对上述所有的例子, y y y 可以取一个很小的数值,一个相对"谨慎"的数值,比如 1
到 3
、1
到 4
或者其它数值,以上说的都是多分类问题,顺便提一下,对于下标是 0 1 2 3
,还是 1 2 3 4
都不重要,我们更喜欢将分类从 1
开始标注而不是 0
,其实怎样标注都不会影响最后的结果。
然而对于之前的二分类问题,我们的数据看起来可能是像这样的:
对于一个多分类问题,我们的数据集或许看起来像这样的:
我用 3
种不同的符号来代表 3
个类别,问题就是给出 3
个类型的数据集,我们如何得到一个学习算法来进行分类呢?
我们现在已经知道如何进行二分类,可以使用逻辑回归,对于直线或许你也知道,可以将数据集一分为二成正类和负类。用一对多的分类思想,我们可以将其用在多分类问题上。
下面将介绍如何进行一对多的分类工作,有时这个方法也被称为"一对剩余"( one-vs-rest
) 方法。
现在我们有一个训练集,好比上图表示的有 3
个类别,我们用三角形表示 y = 1 y=1 y=1 ,方框表示 y = 2 y=2 y=2 ,叉叉表示 y = 3 y=3 y=3 。我们下面要做的就是使用一个训练集,将其分成 3
个二分类问题。
我们先从用三角形代表的类别 1 1 1 开始,实际上我们可以创建一个新的"伪"训练集,类型 2 2 2 和类型 3 3 3 定为负类,类型 1 1 1 设定为正类,我们创建一个新的训练集,如下图所示的那样,我们要拟合出一个合适的分类器。
这里的三角形是正样本,而圆形代表负样本。可以这样想,设置三角形的值为 1 1 1,圆形的值为 0 0 0,下面我们来训练一个标准的逻辑回归分类器,这样我们就得到一个正边界。
为了能实现这样的转变,我们将多个类中的一个类标记为正向类( y = 1 y = 1 y=1 ),然后将其他所有类都标记为负向类,这个模型记作 h θ ( 1 ) ( x ) h_{\theta}^{(1)} (x) hθ(1)(x) 。接着,类似地我们选择另一个类标记为正向类( y = 2 y = 2 y=2 ),再将其它类都标记为负向类,将这个模型记作 h θ ( 2 ) ( x ) h_{\theta}^{(2)} (x) hθ(2)(x) ,依此类推。最后我们得到一系列的模型简记为: h θ ( i ) ( x ) = P ( y = i ∣ x , θ ) h_{\theta}^{(i)} (x) = P(y = i | x, \theta) hθ(i)(x)=P(y=i∣x,θ) ,其中: i = { 1 , 2 , . . . , k } i = \{1, 2, ..., k\} i={1,2,...,k} 。
最后,在我们需要做预测时,我们将所有的分类器都运行一遍,然后对每一个输入变量,都选择最高可能性的输出变量。
总之,我们已经把要做的做完了,现在要做的就是训练这个逻辑回归分类器: h θ ( i ) ( x ) h_{\theta}^{(i)} (x) hθ(i)(x) , 其中 i i i 对应每一个可能的 y = i y = i y=i ,最后,为了做出预测,我们输入一个新的 x x x 值,用这个做预测。我们要做的就是在我们三个分类器里面输入 x x x ,然后我们选择一个让 h θ ( i ) ( x ) h_{\theta}^{(i)} (x) hθ(i)(x) 最大的 i i i ,即: max i h θ ( i ) ( x ) \max_i h_{\theta}^{(i)} (x) maxihθ(i)(x) 。
现在我们知道了基本的挑选分类器的方法,选择出哪一个分类器是可信度最高效果最好的,那么我们就可认为得到一个正确的分类,无论 i i i 值是多少,我们都有最高的概率值 y y y 。这就是多分类问题,以及一对多的方法,通过这个小方法,你现在也可以将逻辑回归分类器用在多分类的问题上。