逻辑回归的输出变量范围始终在0和1之间,回归模型的假设是:
h θ = g ( θ T X ) h_\theta = g(\theta^TX) hθ=g(θTX)
其中X代表特征向量,g表示逻辑函数,逻辑函数我们采用sigmoid激活函数
g ( z ) = 1 / ( 1 + e − z ) g(z) = 1/(1+e^{-z}) g(z)=1/(1+e−z)
整合上式可得
h θ ( x ) = 1 / ( 1 + e − θ T X ) h_\theta(x) = 1 / (1 + e^{-\theta^TX}) hθ(x)=1/(1+e−θTX)
python代码如下:
import numpy as np
def sigmoid(z):
return 1 / (1 + np.exp(-z))
h θ ( x ) 的作用,给定输入变量,计算输出变量 = 1 的可能性,即 h θ ( x ) = P ( y = 1 ∣ x ; θ ) 例如:对于一个肿瘤样本,计算得到 h θ ( x ) = 0.7 ,也就是有 70 % 的可能是恶性的 h_\theta(x)的作用,给定输入变量,计算输出变量=1的可能性,即h_\theta(x) = P(y = 1 | x;\theta)\\ 例如:对于一个肿瘤样本,计算得到h_\theta(x) = 0.7,也就是有70\%的可能是恶性的 hθ(x)的作用,给定输入变量,计算输出变量=1的可能性,即hθ(x)=P(y=1∣x;θ)例如:对于一个肿瘤样本,计算得到hθ(x)=0.7,也就是有70%的可能是恶性的
可以总结为:当 θTx >= 0 时,预测 y=1 ,θTx < 0 时,预测 y=0
所以我们可以通过 θTx == 0 来构建边界,例如:
对于线性回归模型,我们定义的代价函数是所有模型误差的平方和( J(θ)=1/(2m) Σ (hθ(x(i))-y(i))2 )。理论上来说,我们也可以对逻辑回归模型沿用这个定义,但是问题在于,当我们将 hθ(x)=(1+e-θTx)-1 带入到这样定义了的代价函数中时,我们得到的代价函数将是一个非凸函数
凸函数和非凸函数的示意图如下:
我们需要寻找的代价函数J应该为一个非凸函数,这样方便梯度下降算法寻找一个全局最小值。
因此我们重新定义代价函数为:
J ( θ ) = 1 m ∑ i = 1 m C o s t ( h θ ( x ( i ) ) , y ( i ) ) J(\theta) = \frac{1}{m}\sum_{i=1}^mCost\left(h_\theta(x^{(i)}),y^{(i)} \right) J(θ)=m1i=1∑mCost(hθ(x(i)),y(i))
其中cost函数为:
C o s t ( h θ ( x ) , y ) = { − l o g ( h θ ( x ) ) , i f y = 1 − l o g ( 1 − h θ ( x ) ) i f y = 0 \begin{align} Cost\left(h_\theta(x),y \right) = {\begin{cases}-log(h_\theta(x)), \,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,if\,\,y = 1\\ -log(1-h_\theta(x)) \,\,\,\,\,\,\,\,if\,\,y = 0\end{cases}} \end{align} Cost(hθ(x),y)={−log(hθ(x)),ify=1−log(1−hθ(x))ify=0
hθ(x) 与 Cost(hθ(x),y) 之间的关系如下图所示:
这样构建的 Cost(hθ(x),y) 函数的特点是:当实际的 y=1 且 hθ(x) 也为1时误差为0,当 y=1 但 hθ(x) 不为1时误差随着 hθ(x) 变小而变大;当实际的 y=0 且 hθ(x) 也为0时代价为0,当 y=0 但 hθ(x) 不为0时误差随着 hθ(x) 的变大而变大。
将上式整合后如下:
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) = -ylog(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 ) ) ) ] = − 1 m ∑ i = 1 m [ y ( i ) l o g ( h θ ( x ( i ) ) ) + ( 1 − y ( i ) ) l o g ( 1 − h θ ( x ( i ) ) ) ] \begin{align} 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]\\ &=-\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] \end{align} J(θ)=m1i=1∑m[−y(i)log(hθ(x(i)))−(1−y(i))log(1−hθ(x(i)))]=−m1i=1∑m[y(i)log(hθ(x(i)))+(1−y(i))log(1−hθ(x(i)))]
def cost(theta, X, y):
"""
代价函数\n
:param theta: θ
:param X: 特征
:param y: 标签
:return: 代价函数值
"""
inner = -y * np.log(sigmoid(X @ theta.T)) - (1 - y) * np.log(1 - sigmoid(X @ theta.T))
return np.mean(inner)
Repeat { θ j : = θ j − α 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) (simultaneously update all) } \begin{align*} \text{Repeat \{} & \\ &\theta_j := \theta_j - \alpha \frac{1}{m}\sum\limits_{i=1}^{m} \left( h_\theta \left( x^{\left( i \right)} \right) - y^{\left( i \right)} \right) x_{j}^{(i)} \\ &\text{(simultaneously update all)} \\ \mathbf{\}} \end{align*} Repeat {}θj:=θj−αm1i=1∑m(hθ(x(i))−y(i))xj(i)(simultaneously update all)
def gradient(theta, X, y):
"""
梯度下降算法, 转化为矩阵化运算:(1/m)X^T(sigmoid(Xθ) - y)\n
:param theta: θ
:param X: 特征
:param y: 标签
:return:
"""
# 矩阵化实现
'''注意,我们实际上没有在这个函数中执行梯度下降,我们仅仅在计算一个梯度步长。
在练习中,一个称为“fminunc”的Octave函数是用来优化函数来计算成本和梯度参数。
使用Python中的SciPy的“optimize”命名空间来做同样的事情。'''
grad = (1 / len(X)) * X.T @ (sigmoid(X @ theta.T) - y)
return grad
在进行梯度下降之前,我们要对特性进行缩放来构建合适的多项式,如下:
def feature_mapping(x, y, power, as_ndarray=False):
"""
创建一组多项式特征,扩展原先的特征维度
:param x: 第一个特征
:param y: 第二个特征
:param power: 多项式的最高次数
:param as_ndarray: 是否返回ndarray
:return: 返回映射的特征为ndarray或dataframe
"""
data = {}
for i in np.arange(power + 1):
for p in np.arange(i + 1):
data[f"f{i - p}{p}"] = np.power(x, i - p) * np.power(y, p)
if as_ndarray:
return pd.DataFrame(data).values
else:
return pd.DataFrame(data)
正则化的作用:防止过拟合,使得模型能够具有更好的推广
分类问题中存在这样的问题:(分别为欠拟合,合适效果,过拟合)
我们拿特征多项式来理解的话,特征x的次数越高,拟合效果越好,但是相应的预测能力就可能变差,正则化可以在保留所有的特征的前提下,通过减少参数的大小(权重)来防止过拟合
假设我们的线性回归模型假设为:
h θ ( x ) = θ 0 + θ 1 x 1 + θ 2 x 2 2 + θ 3 x 3 3 + θ 4 x 4 4 h_\theta(x)=\theta_0 + \theta_1x_1 + \theta_2x_2^2 + \theta_3x_3^3 + \theta_4x_4^4 hθ(x)=θ0+θ1x1+θ2x22+θ3x33+θ4x44
由于是最高次项导致过拟合,我们可以通过对最高次项进行一些惩罚来减小最高次项的权重,修改后的代价函数可以如下:
m i n θ 1 m [ ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 + 1000 θ 3 2 + 10000 θ 4 2 ] \underset\theta {min} \frac{1}{m}\left[\sum_{i=1}^m(h_\theta(x^{(i)}) - y^{(i)})^2 + 1000\theta_3^2 + 10000\theta_4^2\right] θminm1[i=1∑m(hθ(x(i))−y(i))2+1000θ32+10000θ42]
假设我们有非常多的特征,我们可以对所有的特征进行惩罚:
J ( θ ) = 1 2 m [ ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 + λ ∑ j = 1 m θ j 2 ] J(\theta)=\frac{1}{2m}\left[\sum_{i= 1}^m(h_\theta(x^{(i)}) - y^{(i)})^2 + \lambda\sum_{j=1}^m\theta_j^2\right] J(θ)=2m1[i=1∑m(hθ(x(i))−y(i))2+λj=1∑mθj2]
其中λ又叫做正则化参数 ,注:一般不对θ0进行惩罚
经过正则化处理后的模型与原模型的对比可以如下
我们推广到本文的逻辑回归中可以得到正则化后的逻辑回归的代价函数为:
J ( θ ) = 1 m ∑ i = 1 m [ − y ( i ) l o g ( h θ ( x ( i ) ) ) − ( 1 − y ( i ) ) l o g ( 1 − h θ ( x ( i ) ) ) ] + λ 2 m ∑ j = 1 m θ j 2 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] + \frac{\lambda}{2m}\sum_{j=1}^m\theta_j^2 J(θ)=m1i=1∑m[−y(i)log(hθ(x(i)))−(1−y(i))log(1−hθ(x(i)))]+2mλj=1∑mθj2
def regularized_cost(theta, X, y, l=1):
"""
正则化代价函数
:param theta: θ
:param X: 特征
:param y: 标签
:param l: 正则化参数
:return: 正则化代价函数值
"""
# 不需要对θ0进行正则化
theta_j1_to_n = theta[1:]
m = len(X)
# 正则化额外项
regularized_term = (l / (2 * m)) * np.power(theta_j1_to_n, 2).sum()
# 原先的代价函数值加上正则化项
return cost(theta, X, y) + regularized_term
因为我们不对θ进行正则化,所以正则化梯度下降分为两种情况:
θ 0 = θ 0 − a 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x 0 ( i ) θ j = θ j − a 1 m [ ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x 0 ( i ) + λ θ j ] , j = 1 , 2 , 3... , n \begin{align} \theta_0 &= \theta_0 - a\frac{1}{m}\sum_{i=1}^m\left(h_\theta(x^{(i)}) -y^{(i)}\right)x_0^{(i)}\\ \theta_j &= \theta_j - a\frac{1}{m}\left[\sum_{i=1}^m\left(h_\theta(x^{(i)}) -y^{(i)}\right)x_0^{(i)} + \lambda\theta_j\right],j=1,2,3...,n \end{align} θ0θj=θ0−am1i=1∑m(hθ(x(i))−y(i))x0(i)=θj−am1[i=1∑m(hθ(x(i))−y(i))x0(i)+λθj],j=1,2,3...,n
上式可调整为:
θ j : = θ j ( 1 − α λ m ) − a 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) {\theta_j}:={\theta_j}(1-\alpha\frac{\lambda}{m})-a\frac{1}{m}\sum\limits_{i=1}^m{\left({h_\theta}(x^{(i)})-{y^{(i)}}\right)x_j^{\left(i\right)}} θj:=θj(1−αmλ)−am1i=1∑m(hθ(x(i))−y(i))xj(i)
正则化线性回归的梯度下降算法的变化在于,每次都在原有算法更新规则的基础上令值减少了一个额外的值。
def regularized_gradient(theta, X, y, l):
"""
正则化梯度下降
:param theta: θ
:param X: 特征
:param y: 标签
:param l: 学习率
:return: 正则化梯度λ
"""
# 不需要对θ0进行正则化
theta_j1_to_n = theta[1:]
m = len(X)
# 正则化额外项
regularized_term = (l / m) * theta_j1_to_n
# 加上θ0
regularized_term = np.concatenate([np.array(theta[0]), regularized_term])
# 原先的梯度加上正则化项
return gradient(theta, X, y) + regularized_term
λ = 1时(正则化梯度下降拟合):
λ = 0时(无正则化,出现过拟合现象):
λ = 100时(出现欠拟合现象):
参考链接: https://github.com/loveunk/machine-learning-deep-learning-notes/blob/master/machine-learning/logistic-regression.md