创作背景
本菜鸡最近想学学 机器学习,这不,刚开始。 如果觉得我这篇文章写的好的话,能不能给我 点个赞 ,评论 一波。如果要点个 关注 的话也不是不可以🤗
回归与分类的区别
- 回归 要预测的结果是 具体的数值,根据训练数据预测某一输入对应的输出数据。输出的结果是 实数。
- 分类 要判断的结果是 类别,根据训练数据预测 分类正确的概率 (属于
[0, 1] ),进而输出 判断的类别 。
回归向分类的转变
既然都是 预测,使用相同的 x ,只是输出从原来的 实数 变成了 类别,那我们就用一个函数将结果从 实数集 映射到 [0, 1] 中,然后再转成对应分类不就行了呗。
- 举个栗子:
- 有两个类别的实例,
o 代表正例,x 代表负例 - 可以找到一个超平面
w
T
x
+
b
=
0
{w}^{T}x+b=0
wTx+b=0 将两类实例分隔开,即
正确分类 - 其中,
w
∈
R
n
w \in {\mathbb{R}}^{n}
w∈Rn 为超平面的
法向量 ,
b
∈
R
b \in \mathbb{R}
b∈R 为 偏置 - 超平面上方的点都满足
w
T
x
+
b
>
0
{w}^{T}x+b>0
wTx+b>0
- 超平面下方的点都满足
w
T
x
+
b
<
0
{w}^{T}x+b<0
wTx+b<0
- 可以根据以下
x 的线性函数值(与 0 的比较结果)判断实例类别:
z
=
g
(
x
)
=
w
T
x
+
b
z=g(x)={w}^{T}x+b
z=g(x)=wTx+b - 分类函数以
z 为输入,输出预测的类别:
c
=
H
(
z
)
=
H
(
g
(
x
)
)
c=H(z)=H(g(x))
c=H(z)=H(g(x))
- 以上是 线性分类器 的基本模型。
有个方法可以实现 线性分类器 ,那就是 Logistic 回归。
Logistic 回归是一种 广义线性 模型,使用 线性判别式函数 对实例进行分类。
而一般实现这种分类方法的函数是 sigmoid 函数。(因为其中最为出名的是 logistic 函数,所以也被称为 logistic 函数)。
饱和函数
先看一下 饱和函数,至于为什么要看这个函数,因为 Sigmoid 函数都需要满足这个函数,具体见下述 sigmoid (也即 logistic ) 函数。
x < 0 时,导数值 ↑ ,x ≥ 0 时,导数值 ↓ ,即,将导函数为 正态分布 的分布函数称为 饱和函数 。- 看一下图像。
一些饱和函数
- 单位阶跃函数
δ -
e
r
f
(
π
2
x
)
erf(\frac{\sqrt {\pi}}{2}x)
erf(2π
??x)
-
2
π
arctan
?
(
π
2
x
)
\frac{2}{\pi} \arctan {(\frac{\pi}{2}x)}
π2?arctan(2π?x)
-
2
π
g
d
(
π
2
x
)
\frac{2}{\pi} gd(\frac{\pi}{2}x)
π2?gd(2π?x)
-
x
1
+
∣
x
∣
\frac{x}{1+|x|}
1+∣x∣x?
图像如下 它们的导函数是服从 正态分布 的,图像如下 所以,最理想的分类函数为 单位阶跃函数 ,直上直下的,是 饱和函数 的一种。如下图
也就是
H
(
z
)
=
{
0
,
x
<
0
0.5
,
x
=
0
1
,
x
>
0
H(z)= \begin{cases} 0, x<0 \\ 0.5, x=0 \\ 1, x>0 \end{cases}
H(z)=??????0,x<00.5,x=01,x>0?
- 但单位阶跃函数作为分类函数有一个严重缺点,不连续,所以 不是处处可微,使得一些算法不可用(如 梯度下降)。
- 找一个 输入输出特性与单位阶跃函数类似,并且 单调可微的函数 来代替阶跃函数,
sigmoid 函数是一种常用替代函数。
sigmoid 函数(logistic 函数)
sigmoid 函数是一类函数,满足以下函数特征即可:
- 有极限
- 单调 增 函数
- 满足 饱和函数 (知道我为什么要提到 饱和函数 了吧(●’?’●))
函数定义
σ
(
x
)
=
1
1
+
e
?
z
\sigma(x)=\frac{1}{1+{e}^{-z}}
σ(x)=1+e?z1?
- 一般
σ
\sigma
σ 函数就指
logistic 函数
logistic 函数的值域在 (0,1) 之间连续,函数的输出可视为 x 条件下实例为正例的条件概率 ,即
P
(
y
=
1
∣
x
)
=
σ
(
g
(
x
)
)
=
1
1
+
e
?
(
w
T
x
+
b
)
P(y=1|x)=\sigma (g(x))=\frac{1}{1+{e}^{-({w}^{T}x+b)}}
P(y=1∣x)=σ(g(x))=1+e?(wTx+b)1? x 条件下实例为负例的条件概率为
P
(
y
=
0
∣
x
)
=
1
?
σ
(
g
(
x
)
)
=
1
1
+
e
(
w
T
x
+
b
)
P(y=0|x)=1-\sigma (g(x))=\frac{1}{1+{e}^{({w}^{T}x+b)}}
P(y=0∣x)=1?σ(g(x))=1+e(wTx+b)1?
logistic 函数是 对数概率函数 的 反函数,一个事件的概率指该事件发生的概率 p 与该事件不发生的概率 1-p 的比值。
- 对数概率为
log
?
p
1
?
p
\log{\frac{p}{1-p}}
log1?pp? - 对数概率大于 0 表明 正例 的概率大,反之,则 负例 的概率大。
Logistic 回归模型假设一个实例为正例的对数概率是输入 x 的 线性函数,即:
log
?
p
1
?
p
=
w
T
x
+
b
\log {\frac{p}{1-p}}={w}^{T}x+b
log1?pp?=wTx+b 反求 p ,即:
p
=
σ
(
g
(
x
)
)
=
1
1
+
e
?
(
w
T
x
+
b
)
p = \sigma(g(x))=\frac{1}{1+{e}^{-({w}^{T}x+b)}}
p=σ(g(x))=1+e?(wTx+b)1? logistic 函数有个很好的数学特性,
σ
(
z
)
\sigma(z)
σ(z) 一阶导数形式简单,并且关于其本身的函数:
d
σ
(
z
)
d
z
=
σ
(
z
)
(
1
?
σ
(
z
)
)
\frac{d \sigma(z)}{dz} = \sigma(z) (1-\sigma(z))
dzdσ(z)?=σ(z)(1?σ(z)) Logistic 回归模型假设函数为
h
w
,
b
(
x
)
=
σ
(
g
(
x
)
)
=
1
1
+
e
?
(
w
T
x
+
b
)
{h}_{w,b}(x) = \sigma (g(x)) = \frac{1}{1+{e}^{-({w}^{T}x+b)}}
hw,b?(x)=σ(g(x))=1+e?(wTx+b)1? 将 b 纳入权向量 w ,假设函数更改为
h
w
(
x
)
=
1
1
+
e
?
(
w
T
x
)
{h}_{w}(x) = \frac{1}{1+{e}^{-({w}^{T}x)}}
hw?(x)=1+e?(wTx)1?
极大似然估计
- 根据
h
w
(
x
)
{h}_{w}(x)
hw?(x) 的概率意义,有
P
(
y
=
1
∣
x
)
=
h
w
(
x
)
P
(
y
=
0
∣
x
)
=
1
?
h
w
(
x
)
P(y=1|x)={h}_{w}(x) \\ P(y=0|x)=1-{h}_{w}(x)
P(y=1∣x)=hw?(x)P(y=0∣x)=1?hw?(x)
- 由此可得,训练集
D 中的某样本
(
x
i
,
y
i
)
({x}_{i}, {y}_{i})
(xi?,yi?) ,模型将输入实例
x
i
{x}_{i}
xi? 预测为类别
y
i
{y}_{i}
yi? 的概率为
P
(
y
=
y
i
∣
x
i
;
w
)
=
h
w
(
x
i
)
y
i
(
1
?
h
w
(
x
i
)
)
1
?
y
i
P(y={y}_{i}|{x}_{i};w)={h}_{w}({x}_{i})^{{y}_{i}}(1-{h}_{w}({x}_{i}))^{1-{y}_{i}}
P(y=yi?∣xi?;w)=hw?(xi?)yi?(1?hw?(xi?))1?yi?
- 训练集
D 各样本独立同分布,定义似然函数 L(w) 描述训练集中 m 个样本同时出现的概率,公式如下:
L
(
w
)
=
Π
i
=
1
m
P
(
y
=
y
i
∣
x
i
;
w
)
=
∏
i
=
1
m
h
w
(
x
i
)
y
i
(
1
?
h
w
(
x
i
)
)
1
?
y
i
L(w)=\Pi^{m}_{i=1}{P(y={y}_{i}|{x}_{i};w)} \\ =\prod \limits_{i=1}^{m}{h}_{w}({x}_{i})^{{y}_{i}}(1-{h}_{w}({x}_{i}))^{1-{y}_{i}}
L(w)=Πi=1m?P(y=yi?∣xi?;w)=i=1∏m?hw?(xi?)yi?(1?hw?(xi?))1?yi?
用 极大似然法 估计参数 w 的核心思想是
- 选择参数
w ,使得当前已经观测到的数据(训练集中的 m 个样本)最有可能出现(概率最大),即:
w
^
=
a
r
g
w
m
a
x
?
L
(
w
)
\hat{w}={arg}_{w}max \, L(w)
w^=argw?maxL(w)
- 为了 方便求极值点 ,可将找
L(w) 的极值点转化为找其对数似然函数 ln(L(w)) 的最大值点,即:
w
^
=
a
r
g
w
m
a
x
?
l
n
(
L
(
w
)
)
\hat{w} = {arg}_{w}max \, ln(L(w))
w^=argw?maxln(L(w))
l
(
w
)
=
l
n
(
L
(
w
)
)
=
∑
i
=
1
m
y
i
l
n
(
h
w
(
x
i
)
)
+
(
1
?
y
i
)
l
n
(
1
?
h
w
(
x
i
)
)
l(w)=ln(L(w))=\displaystyle \sum ^{m}_{i=1}{{y}_{i}ln({h}_{w}({x}_{i}))}+(1-{y}_{i})ln(1-{h}_{w}({x}_{i}))
l(w)=ln(L(w))=i=1∑m?yi?ln(hw?(xi?))+(1?yi?)ln(1?hw?(xi?))
梯度下降更新公式
对于 Logistic 回归模型,可以定义其损失为:
J
(
w
)
=
?
1
m
?
l
(
w
)
=
?
1
m
∑
i
=
1
m
y
i
?
l
n
(
h
w
(
x
i
)
)
+
(
1
?
y
i
)
?
l
n
(
1
?
h
w
(
x
i
)
)
J(w)=-\frac{1}{m} \ l(w)=-\frac{1}{m} \displaystyle \sum ^{m}_{i=1}{{y}_{i} \ ln({h}_{w}({x}_{i}))+(1-{y}_{i}) \ ln(1-{h}_{w}({x}_{i}))}
J(w)=?m1??l(w)=?m1?i=1∑m?yi??ln(hw?(xi?))+(1?yi?)?ln(1?hw?(xi?))
- 此时,求出损失函数 最小值 与求出对数似然函数 最大值
等价 ,求损失函数最小值依然可以使用 梯度下降算法 ,最终估计出模型参数
w
^
\hat{w}
w^
计算 J(w) 对分量
w
j
{w}_{j}
wj? 的偏导数(就对上边的公式 求导)
?
?
w
j
J
(
w
)
=
?
1
m
∑
i
=
1
m
y
i
l
n
h
w
(
x
i
)
+
(
1
?
y
i
)
l
n
(
1
?
h
w
(
x
i
)
)
\frac{\partial}{\partial {w}_{j}}J(w)=-\frac{1}{m}\displaystyle \sum^{m}_{i=1}{{y}_{i}ln{h}_{w}({x}_{i})+(1-{y}_{i})ln(1-{h}_{w}({x}_{i}))}
?wj???J(w)=?m1?i=1∑m?yi?lnhw?(xi?)+(1?yi?)ln(1?hw?(xi?))
=
?
1
m
∑
i
=
1
m
y
i
?
?
w
j
l
n
h
w
(
x
i
)
+
(
1
?
y
i
)
?
?
w
j
l
n
(
1
?
h
w
(
x
i
)
)
=-\frac{1}{m}\displaystyle \sum^{m}_{i=1}{{y}_{i}\frac{\partial }{\partial {w}_{j}}ln{h}_{w}({x}_{i})+(1-{y}_{i})\frac{\partial}{\partial {w}_{j}}ln(1-{h}_{w}({x}_{i}))}
=?m1?i=1∑m?yi??wj???lnhw?(xi?)+(1?yi?)?wj???ln(1?hw?(xi?))
=
?
1
m
∑
i
=
1
m
y
i
?
1
h
w
(
x
i
)
?
h
w
(
x
i
)
?
z
i
?
z
i
w
j
+
(
1
?
y
i
)
1
1
?
h
w
(
x
i
)
(
?
?
h
w
(
x
i
)
?
z
i
)
?
z
i
w
j
=- \frac{1}{m} \displaystyle \sum^{m}_{i=1}{{y}_{i} \ \frac{1}{{h}_{w}({x}_{i})} \frac{\partial {h}_{w}({x}_{i})}{\partial {z}_{i}} \frac{\partial {z}_{i}}{{w}_{j}} + (1-{y}_{i}) \frac{1}{1-{h}_{w}({x}_{i})} (-\frac{\partial {h}_{w}({x}_{i})}{\partial {z}_{i}}) \frac{\partial {z}_{i}}{{w}_{j}}}
=?m1?i=1∑m?yi??hw?(xi?)1??zi??hw?(xi?)?wj??zi??+(1?yi?)1?hw?(xi?)1?(??zi??hw?(xi?)?)wj??zi??
=
?
1
m
∑
i
=
1
m
(
y
i
h
w
(
x
i
)
?
(
1
?
h
w
(
x
i
)
h
w
(
x
i
)
?
(
1
?
y
i
)
h
w
(
x
i
)
?
(
1
?
h
w
(
x
i
)
)
(
1
?
h
w
(
x
i
)
)
)
?
z
i
w
j
=-\frac{1}{m} \displaystyle \sum^{m}_{i=1}({y}_{i} \frac{{h}_{w}({x}_{i}) \cdot (1-{h}_{w}({x}_{i})}{{h}_{w}({x}_{i})} -(1-{y}_{i}) \frac{{h}_{w}({x}_{i}) \cdot (1-{h}_{w}({x}_{i}))}{(1-{h}_{w}({x}_{i}))}) \frac{\partial {z}_{i}}{{w}_{j}}
=?m1?i=1∑m?(yi?hw?(xi?)hw?(xi?)?(1?hw?(xi?)??(1?yi?)(1?hw?(xi?))hw?(xi?)?(1?hw?(xi?))?)wj??zi??
=
?
1
m
∑
i
=
1
m
(
y
i
?
h
w
(
x
i
)
)
?
z
i
w
j
=- \frac{1}{m} \displaystyle \sum^{m}_{i=1}({y}_{i}-{h}_{w}({x}_{i})) \frac{\partial {z}_{i}}{{w}_{j}}
=?m1?i=1∑m?(yi??hw?(xi?))wj??zi??
=
1
m
∑
i
=
1
m
(
h
w
(
x
i
)
?
y
i
)
x
i
j
=\frac{1}{m} \displaystyle \sum^{m}_{i=1}({h}_{w}({x}_{i})-{y}_{i}){x}_{ij}
=m1?i=1∑m?(hw?(xi?)?yi?)xij?
- 其中,
h
w
(
x
i
)
?
y
i
{h}_{w}({x}_{i})-{y}_{i}
hw?(xi?)?yi? 可解释为模型预测
x
i
{x}_{i}
xi? 为正例的概率与其实际类别之间的 误差 。
由此可推出梯度
?
J
(
w
)
\nabla J(w)
?J(w) 计算公式为
?
J
(
w
)
=
1
m
∑
i
=
1
m
(
h
w
(
x
i
)
?
y
i
)
x
i
\nabla J(w)=\frac{1}{m} \displaystyle \sum^{m}_{i=1}({h}_{w}({x}_{i})-{y}_{i}){x}_{i}
?J(w)=m1?i=1∑m?(hw?(xi?)?yi?)xi?
对于随机梯度下降,即 m = 1 时,相应梯度计算公式为
?
J
(
w
)
=
(
h
w
(
x
i
)
?
y
i
)
x
i
\nabla J(w)=({h}_{w}({x}_{i})-{y}_{i}){x}_{i}
?J(w)=(hw?(xi?)?yi?)xi? 设学习率为
η
\eta
η ,模型参数 w 的更新公式为
w
=
w
?
η
?
?
J
(
w
)
w = w - \eta \ \nabla J(w)
w=w?η??J(w)
代码实现
自己实现
既然我们已经了解了 Logistic 模型的数学原理,那现在我们就使用 Python 实现吧!
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
class LogisticRegression:
def __init__(self, w_init=0.0, steps=10000, eta=0.01):
self.steps = steps
self.eta = eta
self.w_init = w_init
self.w = None
def __z(self, X):
'''
计算 x 与 w 的内积
'''
return np.dot(self.w, X.T)
def __sigmoid(self, z):
'''
Sigmoid 函数
'''
return 1. / (1. + np.exp(-z))
def __predict_proba(self, X):
'''
预测为正例的概率
'''
z = self.__z(X)
return self.__sigmoid(z)
def __loss(self, y, y_pred):
'''
求损失
'''
return -np.sum(y * np.log(y_pred) + (1-y)* np.log(1-y_pred)) / y.size
def __preprocess(self, X):
'''
预处理 x,x0 = 1
'''
m, n = X.shape
X_ = np.zeros((m, n+1))
X_[:, 0] = 1
X_[:, 1:] = X
return X_
def __gradient(self, X, y, y_pred):
'''
求梯度
'''
return np.matmul(y_pred-y, X) / y.size
def train(self, X, y):
X = self.__preprocess(X)
m, n = X.shape
self.w = np.full((1, n), self.w_init)
plot_loss = pd.DataFrame(columns=['step', 'loss'])
for step in range(1, self.steps+1):
y_pred = self.__predict_proba(X)
loss = self.__loss(y, y_pred)
plot_loss.loc[plot_loss.shape[0]+1] = [step, loss]
print('\rEpoch: {} {:>.2f}%: [{}{}] loss={:>.2f}'.format(
step, step / self.steps * 100,
'■' * int(step / self.steps * 20),
'□' * (20 - int(step/self.steps*20)),
loss
), end='')
grad = self.__gradient(X, y, y_pred)
self.w -= self.eta * grad
plt.plot(plot_loss['step'], plot_loss['loss'])
plt.xlabel('step')
plt.ylabel('loss')
plt.show()
def predict(self, X):
X = self.__preprocess(X)
y_pred = self.__predict_proba(X)
return np.where(y_pred >= 0.5, 1, 0)
测试一下,训练集就取
x
∈
[
0
,
10
]
x \in [0, 10]
x∈[0,10],0.1 为步长的 等差数列,
y
∈
0
,
1
y \in {0, 1}
y∈0,1 的二分类数组,将
x
≥
5
x \geq 5
x≥5 的数据对应的标签设置为 1 ,其余为 0 ,弄好以后画个图瞅瞅。代码如下:
train_x = np.arange(0, 11, 0.1).reshape(-1, 1)
train_y = np.where(train_x > 5, 1, 0).reshape(1, -1)
plt.grid()
plt.plot(train_x, train_y[0])
plt.show()
折线图如下 下边就用我们的模型试一试效果
model = LogisticRegression()
model.train(train_x, train_y)
可以看到,损失是逐渐 下降 的。
让我们来预测一波试试。
In[]: model.predict(np.array([[2], [3], [4], [5], [6]]))
-------------------------------------------------------------
Out[]: array([[0, 0, 0, 1, 1]])
看起来结果还是不错的。
利用 sklearn 实现
不得不佩服强大的 Python 生态,有好多大佬们写好的库,我们直接调用其中的 API 即可,sklearn 就是 Python 机器学习 一个常用的库,用它实现 Logistic 回归,代码如下(数据还是上边的数据):
In[]: from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
lr.fit(train_x, train_y.reshape(-1, 1))
lr.predict(np.array([[2], [3], [4], [5], [6]]))
---------------------------------------------------------------
Out[]: array([0, 0, 0, 1, 1])
成功咯!!!
参考资料
这可不能忘
[1]刘硕.Python机器学习算法原理、实现与案例[M].北京:清华大学出版社,2019
结尾
有想要一起学习 python 的小伙伴可以扫码进群哦。 以上就是我要分享的内容,因为学识尚浅,会有不足,还请各位大佬指正。 有什么问题也可在评论区留言。
|