吴恩达机器学习笔记(5)—逻辑回归(附代码)

前文介绍了基本的线性回归问题,尝试预测一系列连续值属性。现在我们将介绍的分类问题则关注离散值属性的预测。

在分类问题中,我们尝试预测的结果是否属于某一个类,最基础的就是二元的分类问题(例如预测垃圾邮件、恶性肿瘤),更为复杂的则是预测多元的分类问题。

一、分类问题

分类问题的样本与回归问题类似,由特征和目标构成,给定数据集:
{ ( x ( i ) , y ( i ) ) , i = 1 , 2 , . . . , m } \{(x^{(i)},y^{(i)}),i=1,2,...,m\} {(x(i),y(i)),i=1,2,...,m}

x ( i ) x^{(i)} x(i) 代表第 i i i 个观察实例的 n + 1 n+1 n+1特征向量 ( x 0 ( i ) , . . . , x n ( i ) ) T (x_{0}^{(i)},...,x_{n}^{(i)})^T (x0(i),...,xn(i))T y ( i ) ∈ { 0 , 1 } y^{(i)} \in \{0,1\} y(i){0,1} 代表第 i i i 个观察实例的目标变量,在这里有 0 或 1 两类结果。

即对于输入的自变量 x ( i ) x^{(i)} x(i) ,因变量 y ( i ) y^{(i)} y(i) 可能为 0 或 1。其中 0 表示负向类,1 表示正向类

我们不对「正向」和「负向」加以特殊区分,但在实际应用中「正向」通常表示「具有我们要寻找的东西」,如垃圾邮件、恶性肿瘤等。

把线性回归算法应用到下图的数据集,用直线拟合结果,当预测值大于 0.5 时归为正向类,反之归为负向类。这看似合理,然而线性回归保留了 y ( i ) y^{(i)} y(i) 太多的「信息量」。对于某些「反常样本」,我们可能预测出一个远大于 1 或者远小于 0 的结果。同理,这些「反常样本」用于拟合直线时也会对其造成一定偏移,以至于正常样本被归为错误类别。下图反常样本使得蓝线偏移。
在这里插入图片描述

反常样本使得蓝线偏移

如果我们要用线性回归算法来解决一个分类问题,对于分类, 取值为 0 或者1,但如果你使用的是线性回归,那么假设函数的输出值可能远大于 1,或者远小于0,即使所有训练样本的标签 都等于 0 或 1。尽管我们知道标签应该取值0 或者1,但是如果算法得到的值远大于1或者远小于0的话,就会感觉很奇怪。

逻辑回归算法的特点在于,算法的输出或者预测值一直介于0和1之间。顺便说以下,线性回归和逻辑回归都属于「广义线性模型」的特殊形式,线性模型都可用于回归问题的求解。但由于「逻辑函数」将结果映射到「伯努利分布」,因此逻辑回归更常用于分类问题。

二、假设表示

我们在线性回归的假设函数: h θ ( x ) = θ T x h_\theta(x)=\theta^Tx hθ(x)=θTx ,其外套上 sigmoid 函数,构造逻辑回归的假设函数为:
h θ ( x ) = g ( θ T x ) = 1 1 + e − θ T x h_\theta(x)=g(\theta^Tx)=\frac{1}{1 + e^{-\theta^Tx}} hθ(x)=g(θTx)=1+eθTx1

所谓 sigmoid 函数(也即前面提到的逻辑函数),是一个介于 (0,1) 之间的单增 S 形函数:
g ( z ) = 1 1 + e − z g(z)=\frac{1}{1 + e^{-z}} g(z)=1+ez1
在这里插入图片描述

也就是说,对于一个参数为 θ \theta θ 的逻辑回归模型,输入 x x x,得到 h θ ( x ) = 1 1 + e − θ T x h_\theta(x)=\frac{1}{1 + e^{-\theta^Tx}} hθ(x)=1+eθTx1 的预测值。我们可以把这个输出值视为 x x x 这个样本对应的 y y y 等于 1 的概率,即 h θ ( x ) = P ( y = 1 ∣ x ; θ ) h_\theta(x)=P(y=1|x;\theta) hθ(x)=P(y=1∣x;θ) 。针对分类情形,我们可以认为如果概率 ⩾ 0.5 ⩾0.5 0.5,则分类为 1,否则分类为 0。例如如果对于给定的 x x x,通过已经确定的参数计算得出 h θ ( x ) = 0.7 h_\theta(x)=0.7 hθ(x)=0.7,则表示有 70% 的几率为正向类,相应地为负向类的几率为 1 − 0.7 = 0.3 1-0.7=0.3 10.7=0.3

三、决策边界

根据 sigmoid 函数的性质,结合图形:
h θ ( x ) ≥ 0.5 ⟺ θ T X ≥ 0 h_{\theta}(x) \geq 0.5 \Longleftrightarrow \theta^{T}X \geq 0 hθ(x)0.5θTX0

所以只要 θ T X ≥ 0 \theta^{T}X \geq 0 θTX0 ,就会分类为 1,否则分类为 0;于是乎, θ T X = 0 \theta^{T}X = 0 θTX=0 解出的这条「线」被称作决策边界,它将整个空间划分成两块区域,各自属于一个分类。决策边界是假设函数的属性,不是数据集的属性,确定了参数 θ θ θ 也就确定了决策边界。

下面看两个二维情形的例子:
在这里插入图片描述

线性的决策边界

对于上述样本点的分布,用一条直线即可划分空间,对应的假设函数为 h θ ( x ) = g ( θ 0 + θ 1 x 1 + θ 2 x 2 ) h_{\theta}(x) = g(\theta_0+\theta_1x_1+\theta_2x_2) hθ(x)=g(θ0+θ1x1+θ2x2)。例子中的决策边界是 − 3 + x 1 + x 2 = 0 -3+x_1+x_2 = 0 3+x1+x2=0 所对应的直线。
在这里插入图片描述

多项式的决策边界

而对于这种分布,我们必须选择二维曲线来划分空间,即使用多项式特征来确定曲线的参数,对应的假设函数为 h θ ( x ) = g ( θ 0 + θ 1 x 1 + θ 2 x 2 + θ 3 x 3 2 + θ 4 x 4 2 ) h_{\theta}(x) = g(\theta_{0}+\theta_{1}x_{1}+\theta_{2}x_{2}+\theta_3x_{3}^{2}+\theta_{4}x_{4}^{2}) hθ(x)=g(θ0+θ1x1+θ2x2+θ3x32+θ4x42) 。当然,我们也可以用更复杂的多项式曲线来划分更复杂的分布。例子中的决策边界是 − 31 + x 1 2 + x 2 2 = 0 -31+x_1^2+x_2^2 = 0 31+x12+x22=0 所对应的曲线。

四、代价函数

对于线性回归模型,我们定义的代价函数是所有模型误差的平方和。理论上来说,我们也可以对逻辑回归模型沿用这个定义,但是问题在于,当我们将 h θ ( x ) = 1 1 + e − θ T x h_\theta(x)=\frac{1}{1 + e^{-\theta^Tx}} hθ(x)=1+eθTx1 带入到这样定义了的代价函数中时,我们得到的代价函数将是一个非凸函数,如下图。
在这里插入图片描述

现在,我们的任务就是从训练集中拟合逻辑回归的参数 θ θ θ。仍然采用代价函数的思想——找到使代价最小的参数即可。

广义上来讲,代价函数是这样的一个函数:
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(θ)=m1i=1mCost(hθ(x(i)),y(i))

也就是说用每个数据的估计值 h θ ( x ( i ) ) h_{\theta}(x^{(i)}) hθ(x(i)) 和真实值 y ( i ) y^{(i)} y(i) 计算一个代价 C o s t ( h θ ( x ( i ) ) , y ( i ) ) Cost (h_\theta(x^{(i)}) , y^{(i)}) Cost(hθ(x(i)),y(i)) ,比如线性回归中这个代价就是二者差值的平方。

理论上来说,我们也可以对逻辑回归模型沿用平方误差的定义,但当我们将 h θ ( x ) = 1 1 + e − θ T x h_\theta(x)=\frac{1}{1 + e^{-\theta^Tx}} hθ(x)=1+eθTx1 代入到这样的代价函数中时,我们得到的将是一个非凸函数。这意味着空间中会有许多局部最小值,使得梯度下降法难以寻找到全局最小值

因此我们重新定义逻辑回归的代价函数
C o s t ( h θ ( x ) , y ) = { − ln ⁡ ( h θ ( x ) ) y = 1 − ln ⁡ ( 1 − h θ ( x ) ) y = 0 Cost (h_\theta(x) , y) = \begin{cases} -\ln (h_{\theta}(x)) & y=1 \\ -\ln (1-h_{\theta}(x)) & y=0 \end{cases} Cost(hθ(x),y)={ln(hθ(x))ln(1hθ(x))y=1y=0

绘制出的曲线大致呈这样:
在这里插入图片描述

代价函数

观察曲线,发现当 y = 1 y=1 y=1(样本的真实值为 1)时,预测值 $h_{\theta}(x) $ 越接近 1 则代价越小,越接近 0 则代价趋于无穷。譬如在肿瘤分类中,将实际为恶性的肿瘤以百分之百的概率预测为良性,带来的后果将不可估量。

与此同时,注意到代价函数也可以简写为:
C o s t ( h θ ( x ) , y ) = − [ y ln ⁡ ( h θ ( x ) ) + ( 1 − y ) ln ⁡ ( 1 − h θ ( x ) ) ] Cost (h_\theta(x) , y) = -[y\ln(h_\theta(x)) + (1-y)\ln(1-h_\theta(x))] Cost(hθ(x),y)=[yln(hθ(x))+(1y)ln(1hθ(x))]

它还有另外一个名称——二元交叉熵代价函数(BCE)

五、代价函数的数学推导

首先明确什么是一个好的代价函数——当参数 θ θ θ 使得 J ( θ ) J(\theta) J(θ)最小值时,这个 θ θ θ 也能使模型拟合效果最好。这时我们回忆起 最大似然估计 的思想:当参数 θ θ θ 使得 L ( θ ) L(\theta) L(θ)最大值时,这个 θ θ θ 也能使得事件组最容易发生!

前文已经提到,我们用概率解释预测值
P ( y = k ) = { p k = 1 1 − p k = 0 P(y = k) = \begin{cases} p & k = 1 \\ 1 - p & k = 0 \end{cases} P(y=k)={p1pk=1k=0

利用「伯努利分布公式」故:
P ( y = k ) = [ h θ ( x ) ] k [ 1 − h θ ( x ) ] 1 − k , k ∈ { 0 , 1 } P(y = k) = \left[ h_\theta(x) \right]^k \left[ 1 - h_\theta(x) \right]^{1 - k}, \quad k \in \{0, 1\} P(y=k)=[hθ(x)]k[1hθ(x)]1k,k{0,1}

而对于数据集 { ( x ( i ) , y ( i ) ) ,   i = 1 , 2 , ⋯   , m } \left\{ (x^{(i)}, y^{(i)}), \, i = 1, 2, \cdots, m \right\} {(x(i),y(i)),i=1,2,,m} 下,将其视为已发生的一个事件组,则似然函数为:
L ( θ ) = ∏ i = 1 m P ( y = y ( i ) ) = ∏ i = 1 m [ h θ ( x ( i ) ) ] y ( i ) [ 1 − h θ ( x ( i ) ) ] 1 − y ( i ) L(\theta) = \prod_{i=1}^m P\left( y = y^{(i)} \right) = \prod_{i=1}^m \left[ h_\theta \left( x^{(i)} \right) \right]^{y^{(i)}} \left[ 1 - h_\theta \left( x^{(i)} \right) \right]^{1 - y^{(i)}} L(θ)=i=1mP(y=y(i))=i=1m[hθ(x(i))]y(i)[1hθ(x(i))]1y(i)

取对数得到:
ln ⁡ L ( θ ) = ∑ i = 1 m { y ( i ) ln ⁡ [ h θ ( x ( i ) ) ] + ( 1 − y ( i ) ) ln ⁡ [ 1 − h θ ( x ( i ) ) ] } \ln L(\theta) = \sum_{i=1}^m \left\{ y^{(i)} \ln \left[ h_\theta \left( x^{(i)} \right) \right] + \left( 1 - y^{(i)} \right) \ln \left[ 1 - h_\theta \left( x^{(i)} \right) \right] \right\} lnL(θ)=i=1m{y(i)ln[hθ(x(i))]+(1y(i))ln[1hθ(x(i))]}

注意到,最大似然估计法的目标是找到 L ( θ ) L(\theta) L(θ) ln ⁡ L ( θ ) \ln L(\theta) lnL(θ) 的最大值,而逻辑回归的目标是找到 J ( θ ) J(\theta) J(θ) 的最小值,所以自然的,我们将 ln ⁡ L ( θ ) \ln L(\theta) lnL(θ) 取反来定义 J ( θ ) J(\theta) J(θ)
J ( θ ) = − 1 m ln ⁡ L ( θ ) = − 1 m ∑ i = 1 m [ y ( i ) ln ⁡ ( h θ ( x ( i ) ) ) + ( 1 − y ( i ) ) ln ⁡ ( 1 − h θ ( x ( i ) ) ) ] \begin{aligned} J(\theta) &= -\frac{1}{m} \ln L(\theta) \\ &= -\frac{1}{m} \sum_{i=1}^m \left[ y^{(i)} \ln \left( h_\theta \left( x^{(i)} \right) \right) + \left( 1 - y^{(i)} \right) \ln \left( 1 - h_\theta \left( x^{(i)} \right) \right) \right] \end{aligned} J(θ)=m1lnL(θ)=m1i=1m[y(i)ln(hθ(x(i)))+(1y(i))ln(1hθ(x(i)))]

其中 1 m \frac{1}{m} m1 对要求的 θ θ θ 没有影响,仅是取一下平均罢了。

可以证明上述代价函数 J ( θ ) J(\theta) J(θ) 会是一个凸函数,并且没有局部最优值。凸性分析的内容不在本讲的范围,但是可以证明我们所选的代价函数会给我们带来一个凸优化问题。

六、梯度下降和高级优化

既然是凸函数,那么现在我们就可以进行梯度下降求解 arg ⁡ min ⁡ θ J ( θ ) \arg \min_{\theta} J(\theta) argminθJ(θ) ,利用 sigmoid 函数的对数性质 log ⁡ σ ( z ) = − log ⁡ ( 1 + e − z ) \log \sigma(z) = -\log(1 + e^{-z}) logσ(z)=log(1+ez) log ⁡ ( 1 − σ ( z ) ) = − log ⁡ ( 1 + e z ) \log(1 - \sigma(z)) = -\log(1 + e^{z}) log(1σ(z))=log(1+ez) 求偏导,我们先计算:
∂ ∂ θ Cost ( h θ ( x ) , y ) = ∂ ∂ θ [ − y ln ⁡ ( h θ ( x ) ) − ( 1 − y ) ln ⁡ ( 1 − h θ ( x ) ) ] = ∂ ∂ θ [ y ln ⁡ ( 1 + e − θ T x ) + ( 1 − y ) ln ⁡ ( 1 + e θ T x ) ] = − y x e − θ T x 1 + e − θ T x + ( 1 − y ) x e θ T x 1 + e θ T x = − y x + ( 1 − y ) x e θ T x 1 + e θ T x = ( − y + 1 1 + e − θ T x ) x = ( h θ ( x ) − y ) x \begin{aligned} \frac{\partial}{\partial \theta} \text{Cost} \left( h_\theta (x), y \right) &= \frac{\partial}{\partial \theta} \left[ -y \ln \left( h_\theta (x) \right) - (1 - y) \ln \left( 1 - h_\theta (x) \right) \right] \\ &= \frac{\partial}{\partial \theta} \left[ y \ln \left( 1 + e^{-\theta^T x} \right) + (1 - y) \ln \left( 1 + e^{\theta^T x} \right) \right] \\ &= \frac{ -y x e^{-\theta^T x} }{ 1 + e^{-\theta^T x} } + \frac{ (1 - y) x e^{\theta^T x} }{ 1 + e^{\theta^T x} } \\ &= \frac{ -y x + (1 - y) x e^{\theta^T x} }{ 1 + e^{\theta^T x} } \\ &= \left( -y + \frac{1}{ 1 + e^{-\theta^T x} } \right) x \\ &= \left( h_\theta (x) - y \right) x \end{aligned} θCost(hθ(x),y)=θ[yln(hθ(x))(1y)ln(1hθ(x))]=θ[yln(1+eθTx)+(1y)ln(1+eθTx)]=1+eθTxyxeθTx+1+eθTx(1y)xeθTx=1+eθTxyx+(1y)xeθTx=(y+1+eθTx1)x=(hθ(x)y)x

于是乎,
∂ J ∂ θ = 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x ( i ) \frac{\partial J}{\partial \theta} = \frac{1}{m} \sum_{i=1}^m \left( h_\theta \left( x^{(i)} \right) - y^{(i)} \right) x^{(i)} θJ=m1i=1m(hθ(x(i))y(i))x(i)

没错,这个偏导的形式和线性回归完全相同!不同的只是 h θ ( x ) = g ( θ T X ) h_\theta (x) = g \left( \theta^T X \right) hθ(x)=g(θTX) 的定义——多了一层 sigmoid 函数,正是因此,我们不能使用正规方程直接给出解析解,而必须使用梯度下降等方法
θ : = θ − α ⋅ ∂ J ∂ θ \theta := \theta - \alpha \cdot \frac{\partial J}{\partial \theta} θ:=θαθJ

现在我们对其使用梯度下降即可。另外,在运行梯度下降算法之前,进行特征缩放依旧是非常必要的。

除了梯度下降法,还有很多算法可以用来求解这个最优值:共轭梯度法(Conjugate Gradient)、局部优化法(BFGS)、有限内存局部优化法(LBFGS)等。

这些算法通常不需要手动选择学习率 α \alpha α ,而是使用一个智能的内循环(线性搜索算法)来选择一个较好的 α \alpha α ,甚至能为每次迭代选择不同的 α \alpha α因此他们有着更优越的常数和时间复杂度,在大型机器学习项目中更加适用

七、代码实现

下面以 Coursera 上的二分类数据集 ex2data1.txt 为例,首先看一下数据的分布:

import numpy as np
import matplotlib.pyplot as plt

# load data, data.shape = (100, 3)
data = np.loadtxt('ex2data1.txt', delimiter=',')
(m, n) = data.shape
X = data[:, :-1]
y = data[:, -1]

# preview data
pos = np.where(y == 1)[0]
neg = np.where(y == 0)[0]  # 返回索引
plt.scatter(X[pos, 0], X[pos, 1], marker="o", c='c')
plt.scatter(X[neg, 0], X[neg, 1], marker="x", c='r')
plt.xlabel('Exam 1 score')
plt.ylabel('Exam 2 score')
plt.show()

在这里插入图片描述

数据分布散点图

看起来用直线即可划分数据。

此外,注意到如果每次都用 n p . s u m ( ) np.sum() np.sum() 计算 ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) \sum_{i=1}^m \left( h_\theta \left( x^{(i)} \right) - y^{(i)} \right) x_j^{(i)} i=1m(hθ(x(i))y(i))xj(i) 耗时较大,因此将求和化成矩阵形式
θ : = θ − α 1 m X T ( g ( X θ ) − y ) \theta := \theta - \alpha \frac{1}{m} X^T \left( g(X\theta) - y \right) θ:=θαm1XT(g()y)

实现逻辑回归如下,矩阵化后运行时间可缩短一半:

import numpy as np
import matplotlib.pyplot as plt

# load data, data.shape = (100, 3)
data = np.loadtxt('ex2data1.txt', delimiter=',')
(m, n) = data.shape
X = data[:, :-1]
y = data[:, -1]

# normalization
X = (X - X.mean(axis=0)) / X.std(axis=0, ddof=1)
X = np.c_[np.ones(m), X] # 增加一列 1

# parameters
alpha = 0.01
num_iters = 10000
theta = np.zeros(n)

def sigmoid(z):
    g = np.zeros(z.size)
    g = 1 / (1 + np.exp(-z))
    return g

# Gradient Descent
for _ in range(0, num_iters):
	error = sigmoid(X @ theta) - y  # error.shape = (100, )
	theta -= (alpha / m) * (X.T @ error)  # X.T.shape = (2, 100)

# plot decision boundary
pos = np.where(y == 1)[0]
neg = np.where(y == 0)[0]
plt.scatter(X[pos, 1], X[pos, 2], marker="o", c='c')
plt.scatter(X[neg, 1], X[neg, 2], marker="x", c='r')

x_plot = np.array([np.min(X[:, 1]), np.max(X[:, 1])])
y_plot = (-1 / theta[2]) * (theta[1] * x_plot + theta[0])
plt.plot(x_plot, y_plot)
plt.show()

得到的 ( θ 0 , θ 1 , θ 2 ) (\theta_0, \theta_1, \theta_2) (θ0,θ1,θ2) 结果是: [ 1.2677 , 3.0555 , 2.8289 ] [1.2677, 3.0555, 2.8289] [1.2677,3.0555,2.8289],绘制出决策边界的图像为:
在这里插入图片描述

决策边界(归一化)

八、多类别分类:一对多

在实际情形中,我们还会使用逻辑回归来解决多元的分类问题。多分类的数据集和二分类相似,区别在于目标变量 y ( i ) y^{(i)} y(i)在这里不仅有 0 或 1 两类结果,还可以取 2、3 等更多的数字。
在这里插入图片描述

二分类和多分类

对于接下来要介绍的方法,标签数字的顺序、取法,都不会影响最终的结果。但在某些分类模型中,数值可能具有实际意义,这时候使用独热码(One-Hot)或许是更好的选择。

对于 N 分类问题,我们可以将其转化为 N 个二分类问题——只需创建 N 个「伪训练集」,每个训练集中仅包含一个类作为正向类,其他 N-1 个类均视为负向类。
在这里插入图片描述

一对余

接下来就可以训练 N 个标准的逻辑回归分类器,将其记为:
h θ ( i ) ( x ) = P ( y = i ∣ x ; θ ) , i = ( 1 , 2 , ⋯   , N ) h_\theta^{(i)} (x) = P(y = i \mid x; \theta), \quad i = (1, 2, \cdots, N) hθ(i)(x)=P(y=ix;θ),i=(1,2,,N)

显然,每个分类器的输出都可以视为「属于某类」的概率,在预测时,我们只需要运行一遍所有分类器,然后取其最大值作为预测结果即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值