《机器学习:公式推导与代码实践》鲁伟著读书笔记。上一章介绍了线性回归的数学推导过程以及python实现,可以知道线性回归模型就是对数据进行线性拟合或者说是回归,然后采用训练好的模型对未来数据进行预测。那能否运用线性模型对一些数据进行分类呢,这就需要运用对数几率回归模型(logistics regression,LR)这种线性分类模型。
对数几率回归的数学原理
在对数几率回归中,我们需要将线性回归模型的预测值转化为0/1值,而不是去逼近真实标签
y
y
y。而取值范围为(0,1),单调可微的Sigmoid函数便是对数几率回归的不二之选。Sigmoid函数的表达式为:
y
=
1
1
+
e
−
z
y=\frac{1}{1+e^{-z}}
y=1+e−z1。特别的是,Sigmoid函数的导数是可以由其自身来表达的:
f
′
(
x
)
=
f
(
x
)
(
1
−
f
(
x
)
)
f^{\prime}(x)=f(x)(1-f(x))
f′(x)=f(x)(1−f(x))。
我们知道了对数几率回归模型的重要函数了,下一步便将线性回归模型带入Sigmoid函数中,进行基本数学理论的推导。大致分为以下几步:
- 定义线性回归模型
我们采用上一节所讲的线性回归模型,令线性回归模型的公式为:y
=
X
ω
+
b
y=X\omega+b
- 通过Sigmoid激活函数
y
=
1
1
+
e
−
(
X
ω
+
b
)
y=\frac{1}{1+e^{-(X\omega+b)}}
- 化简后两边同时取对数
y
+
y
e
−
(
X
ω
+
b
)
=
1
y+ye^{-(X\omega+b)}=1
1
−
y
y
=
e
−
(
X
ω
+
b
)
\frac{1-y}{y} =e^{-(X\omega+b)}
l
n
1
−
y
y
=
−
(
X
ω
+
b
)
ln\frac{1-y}{y}=-(X\omega+b)
l
n
y
1
−
y
=
X
ω
+
b
ln\frac{y}{1-y}=X\omega+b
y
y
X
X
1
−
y
1-y
X
X
y
1
−
y
\frac{y}{1-y}
- 确定
ω
\omega
b
b
将y
y
p
(
y
=
1
∣
x
)
p(y=1|x)
l
n
p
(
y
=
1
∣
x
)
p
(
y
=
0
∣
x
)
=
X
ω
+
b
ln\frac{p(y=1|x)}{p(y=0|x)}=X\omega+b
- 展开上式可得
p
(
y
=
1
∣
x
)
=
1
1
+
e
−
(
X
ω
+
b
)
=
y
^
p(y=1|x)=\frac{1}{1+e^{-(X\omega+b)}}=\hat {y}
p
(
y
=
0
∣
x
)
=
e
−
(
X
ω
+
b
)
1
+
e
−
(
X
ω
+
b
)
=
1
−
y
^
p(y=0|x)=\frac{e^{-(X\omega+b)}}{1+e^{-(X\omega+b)}}=1-\hat {y}
p
(
y
∣
x
)
=
y
^
y
+
(
1
−
y
^
)
1
−
y
p(y|x)=\hat {y}^{y}+(1-\hat {y})^{1-y}
l
n
p
(
y
∣
x
)
=
y
l
n
y
^
+
(
1
−
y
)
l
n
(
1
−
y
^
)
lnp(y|x)=yln\hat {y}+(1-y)ln(1-\hat {y})
- 令
L
=
l
n
p
(
y
∣
x
)
L=lnp(y|x)
ω
\omega
b
b
L
=
y
l
n
(
1
1
+
e
−
(
X
ω
+
b
)
)
+
(
1
−
y
)
l
n
(
e
−
(
X
ω
+
b
)
1
+
e
−
(
X
ω
+
b
)
)
L=yln(\frac{1}{1+e^{-(X\omega+b)}})+(1-y)ln(\frac{e^{-(X\omega+b)}}{1+e^{-(X\omega+b)}})
L
=
y
(
−
l
n
(
1
+
e
−
(
X
ω
+
b
)
)
)
+
(
1
−
y
)
[
−
(
X
ω
+
b
)
−
l
n
(
1
+
e
−
(
X
ω
+
b
)
)
]
L=y(-ln(1+e^{-(X\omega+b)}))+(1-y)[-(X\omega+b)-ln(1+e^{-(X\omega+b)})]
L
=
−
y
l
n
(
1
+
e
−
(
X
ω
+
b
)
)
−
(
X
ω
+
b
)
−
l
n
(
1
+
e
−
(
X
ω
+
b
)
)
+
y
(
X
ω
+
b
)
+
y
l
n
(
1
+
e
−
(
X
ω
+
b
)
)
L=-yln(1+e^{-(X\omega+b)})-(X\omega+b)-ln(1+e^{-(X\omega+b)})+y(X\omega+b)+yln(1+e^{-(X\omega+b)})
L
=
−
(
X
ω
+
b
)
−
l
n
(
1
+
e
−
(
X
ω
+
b
)
)
+
y
(
X
ω
+
b
)
L=-(X\omega+b)-ln(1+e^{-(X\omega+b)})+y(X\omega+b)
∂
L
∂
ω
=
∂
−
(
X
ω
+
b
)
∂
ω
+
∂
−
l
n
(
1
+
e
−
(
X
ω
+
b
)
)
∂
ω
+
∂
y
(
X
ω
+
b
)
∂
ω
\frac{\partial L}{\partial {\omega}}=\frac{\partial -(X\omega+b)}{\partial {\omega}}+\frac{\partial -ln(1+e^{-(X\omega+b)})}{\partial {\omega}}+\frac{\partial y(X\omega+b)}{\partial {\omega}}
∂
L
∂
ω
=
−
X
T
+
X
T
1
1
+
e
−
(
X
ω
+
b
)
e
−
(
X
ω
+
b
)
+
X
T
y
\frac{\partial L}{\partial {\omega}}=-X^{T}+X^{T}\frac{1}{1+e^{-(X\omega+b)}}e^{-(X\omega+b)}+X^{T}y
∂
L
∂
ω
=
−
X
T
+
X
T
(
1
−
y
^
)
+
X
T
y
\frac{\partial L}{\partial {\omega}}=-X^{T}+X^{T}(1-\hat {y})+X^{T}y
∂
L
∂
ω
=
X
T
(
y
−
y
^
)
\frac{\partial L}{\partial {\omega}}=X^{T}(y-\hat {y})
∂
L
∂
b
=
∂
−
(
X
ω
+
b
)
∂
b
+
∂
−
l
n
(
1
+
e
−
(
X
ω
+
b
)
)
∂
b
+
∂
y
(
X
ω
+
b
)
∂
b
\frac{\partial L}{\partial {b}}=\frac{\partial -(X\omega+b)}{\partial {b}}+\frac{\partial -ln(1+e^{-(X\omega+b)})}{\partial {b}}+\frac{\partial y(X\omega+b)}{\partial {b}}
∂
L
∂
b
=
−
1
+
1
1
+
e
−
(
X
ω
+
b
)
e
−
(
X
ω
+
b
)
+
y
\frac{\partial L}{\partial {b}}=-1+\frac{1}{1+e^{-(X\omega+b)}}e^{-(X\omega+b)}+y
∂
L
∂
b
=
−
1
+
(
1
−
y
^
)
+
y
\frac{\partial L}{\partial {b}}=-1+(1-\hat {y})+y
∂
L
∂
b
=
y
−
y
^
\frac{\partial L}{\partial {b}}=y-\hat {y}
综上所述,对数几率回归算法的参数更新公式为:∂
L
∂
ω
=
X
T
(
y
−
y
^
)
\frac{\partial L}{\partial {\omega}}=X^{T}(y-\hat {y})
∂
L
∂
b
=
y
−
y
^
\frac{\partial L}{\partial {b}}=y-\hat {y}
对数几率回归的NumPy手撕代码
对数几率回归模型的算法思路是建立在线性回归算法之上的,具体过程如下。
初始化与定义Sigmoid函数
def init_params(train_dim):
w = np.zeros((train_dim,1))
b = 0
return w,b
def sigmoid(x):
z=1/(1+np.exp(-x))
return z
定义对数几率回归模型主体
def logistics(X,y,w,b):
num_train = X.shape[0]
num_feature = X.shape[1]
y_hat = sigmoid(np.dot(X,w) + b)
loss = -1/num_train * np.sum(y*np.log(y_hat)+(1-y)*np.log(1-y_hat)) # 交叉熵损失
dw = np.dot(X.T,(y_hat-y))/num_train
db = np.sum((y_hat-y))/num_train
loss = np.squeeze(loss)
return y_hat, loss, dw, db
定义训练过程
def train(X, y, learning_rate=0.01, epochs=10000):
'''
输入:
X:输入数据
y:输出标签
learning_rate:学习率
epochs:迭代次数
输出:
loss_his:每一代的误差
params:参数字典
grads:优化后的梯度
'''
loss_his = []
w, b = init_params(X.shape[1])
for i in range(epochs):
y_hat, loss, dw, db = logistics(X, y, w, b)
w += -learning_rate*dw
b += -learning_rate*db
loss_his.append(loss)
params = {'w':w, 'b':b}
grads = {'dw':dw,'db':db}
return loss_his, params, grads
定义预测函数
def predict(X, params):
'''
输入:
X:测试数据集
params:模型训练参数
输出:
y_pre:预测值
'''
w = params['w']
b = params['b']
y_pre = sigmoid(np.dot(X, w) + b)
for i in range(len(y_pre)):
if y_pre[i]>0.5:
y_pre[i]=1
else:
y_pre[i]=0
return y_pre
下一个章节进一步讲解另外一种分类方法,线性判别分析法。