sigmoid函数
sigmoid函数不是臆想的,而是通过假设推出来的函数。
对于多分类,假设似然率的对数为线性判别函数:
log
(
p
(
x
∣
ω
i
)
p
(
x
∣
ω
M
)
)
=
β
i
,
0
+
β
i
T
x
,
i
=
1
,
2
,
.
.
.
,
M
\log(\frac{p(x|\omega_{i})}{p(x|\omega_{M})})=\beta_{i,0}+\beta_{i}^{T}x,i=1,2,...,M
log(p(x∣ωM)p(x∣ωi))=βi,0+βiTx,i=1,2,...,M
⇒
log
(
p
(
ω
i
∣
x
)
p
(
ω
M
∣
x
)
)
=
w
i
,
0
+
w
i
T
x
,
i
=
1
,
2
,
.
.
.
,
M
\Rightarrow \log(\frac{p(\omega_{i}|x)}{p(\omega_{M}|x)})=w_{i,0}+w_{i}^{T}x,i=1,2,...,M
⇒log(p(ωM∣x)p(ωi∣x))=wi,0+wiTx,i=1,2,...,M
针对如上结果,二分类问题的概率为:
p
(
ω
2
∣
x
)
=
1
1
+
e
x
p
(
w
0
+
w
T
x
)
p(\omega_{2}|x)=\frac{1}{1+exp(w_{0}+w^{T}x)}
p(ω2∣x)=1+exp(w0+wTx)1
p
(
ω
1
∣
x
)
=
e
x
p
(
w
0
+
w
T
x
)
1
+
e
x
p
(
w
0
+
w
T
x
)
=
1
1
+
e
x
p
(
−
(
w
0
+
w
T
x
)
)
p(\omega_{1}|x)=\frac{exp(w_{0}+w^{T}x)}{1+exp(w_{0}+w^{T}x)}=\frac{1}{1+exp(-(w_{0}+w^{T}x))}
p(ω1∣x)=1+exp(w0+wTx)exp(w0+wTx)=1+exp(−(w0+wTx))1
理论讲解
对于二分类问题,输出标记为
y
∈
{
0
,
1
}
y \in \{0, 1 \}
y∈{0,1},0表示负向类,1表示正向类。logistic regression不是一个回归问题,而是一个分类问题。需要通过一个函数将线性回归模型
w
T
x
+
b
w^{T}x+b
wTx+b的输出值映射到
[
0
,
1
]
[0,1]
[0,1]范围内,这个函数就是对数几率函数(logistic function),也称为sigmoid函数:
ϕ
(
z
)
=
1
1
+
e
−
z
\phi(z)=\frac{1}{1+e^{-z}}
ϕ(z)=1+e−z1
对某个样本
x
x
x,预测概率为
y
=
1
1
+
e
−
(
w
T
x
+
b
)
y=\frac{1}{1+e^{-(w^{T}x+b)}}
y=1+e−(wTx+b)1,即
w
T
x
+
b
=
ln
y
1
−
y
w^{T}x+b=\ln\frac{y}{1-y}
wTx+b=ln1−yy,其中
y
y
y是样本正例的可能性,
1
−
y
1-y
1−y是反例可能性,
y
1
−
y
\frac{y}{1-y}
1−yy作为正例的相对可能性,成为几率。对几率取对数则得到了对数几率
ln
y
1
−
y
\ln\frac{y}{1-y}
ln1−yy
对于线性回归问题,定义的函数为所有模型误差的平方和。但是对于逻辑回归来说,这样定义所得的代价函数为非凸函数,容易陷入局部最优。代价函数为:
J
(
w
)
=
1
m
∑
i
=
1
m
[
−
y
(
i
)
log
(
ϕ
(
z
(
i
)
)
)
−
(
1
−
y
(
i
)
)
log
(
1
−
ϕ
(
x
(
i
)
)
)
]
J(w)=\frac{1}{m} \sum_{i=1}^{m}[-y^{(i)}\log(\phi(z^{(i)}))-(1-y^{(i)})\log(1-\phi(x^{(i)}))]
J(w)=m1i=1∑m[−y(i)log(ϕ(z(i)))−(1−y(i))log(1−ϕ(x(i)))]
J
(
ϕ
(
z
)
,
y
)
{
−
log
(
ϕ
(
z
)
)
i
f
y
=
1
−
log
(
1
−
ϕ
(
z
)
)
i
f
y
=
0
J(\phi(z),y)\left\{\begin{matrix} -\log(\phi(z)) \ \ \ if\ y=1\\ -\log(1-\phi(z)) \ \ \ if \ y=0 \end{matrix}\right.
J(ϕ(z),y){−log(ϕ(z)) if y=1−log(1−ϕ(z)) if y=0
如图所示。若样本正确被划分为类别1中,代价将趋向于0;若样本正确被划分为类别0中,代价将趋向于0;反正将趋向于无穷大
代价函数的推导:
在构建模型时,定义最大似然函数
L
(
w
)
L(w)
L(w),最大似然函数的入门参照:https://blog.csdn.net/winycg/article/details/80294225,公式如下:
L
(
w
)
=
∏
i
=
1
n
p
(
y
(
i
)
∣
x
(
i
)
;
w
)
=
∏
i
=
1
n
(
ϕ
(
z
(
i
)
)
)
y
(
i
)
(
1
−
ϕ
(
z
(
i
)
)
)
)
1
−
y
(
i
)
L(w)=\prod_{i=1}^{n}p(y^{(i)}|x^{(i)};w)=\prod_{i=1}^{n}(\phi(z^{(i)}))^{y^{(i)}}(1-\phi(z^{(i)})))^{1-y^{(i)}}
L(w)=i=1∏np(y(i)∣x(i);w)=i=1∏n(ϕ(z(i)))y(i)(1−ϕ(z(i))))1−y(i)
将其取对数似然方程:
log
L
(
w
)
=
∑
i
=
1
n
[
y
(
i
)
log
(
ϕ
(
z
(
i
)
)
)
+
(
1
−
y
(
i
)
)
log
(
1
−
ϕ
(
z
(
i
)
)
)
]
\log L(w)=\sum_{i=1}^{n}[y^{(i)}\log(\phi(z^{(i)}))+(1-y^{(i)})\log(1-\phi(z^{(i)}))]
logL(w)=i=1∑n[y(i)log(ϕ(z(i)))+(1−y(i))log(1−ϕ(z(i)))]
样本的最大似然函数值
log
L
(
θ
)
\log L(\theta)
logL(θ)越大,表明预测越准确。在似然函数值非常小的时候,使用对数函数可以避免数值溢出;其次可以将各因子的连乘转换为和的形式,便于求导。将
L
(
w
)
L(w)
L(w)取反,就可以得到误差函数
J
(
θ
)
=
−
1
n
log
L
(
w
)
J(\theta)=-\frac{1}{n}\log L(w)
J(θ)=−n1logL(w)
梯度下降更新公式推导:
首先计算sigmoid函数的偏导:
∂
∂
z
ϕ
(
z
)
=
e
−
z
(
1
+
e
−
z
)
2
=
1
1
+
e
−
z
(
1
−
1
1
+
e
−
z
)
=
ϕ
(
z
)
(
1
−
ϕ
(
z
)
)
\frac{\partial }{\partial z}\phi(z)=\frac{e^{-z}}{(1+e^{-z})^{2}}=\frac{1}{1+e^{-z}}(1-\frac{1}{1+e^{-z}})=\phi(z)(1-\phi(z))
∂z∂ϕ(z)=(1+e−z)2e−z=1+e−z1(1−1+e−z1)=ϕ(z)(1−ϕ(z))
计算对数似然函数对第
j
j
j个权重的偏导:
∂
∂
w
j
J
(
w
)
=
−
1
n
∑
i
=
1
n
[
y
(
i
)
1
ϕ
(
z
(
i
)
)
ϕ
(
z
(
i
)
)
(
1
−
ϕ
(
z
(
i
)
)
)
x
j
i
−
(
1
−
y
(
i
)
)
1
1
−
ϕ
(
z
(
i
)
)
ϕ
(
z
(
i
)
)
(
1
−
ϕ
(
z
(
i
)
)
)
x
j
i
]
=
−
1
n
∑
i
=
1
n
[
y
(
i
)
(
1
−
ϕ
(
z
(
i
)
)
)
x
j
i
−
(
1
−
y
(
i
)
)
ϕ
(
z
(
i
)
)
x
j
i
]
=
1
n
∑
i
=
1
n
[
ϕ
(
z
(
i
)
)
−
y
(
i
)
]
x
j
i
\frac{\partial }{\partial w_{j}}J(w) \\ =-\frac{1}{n}\sum_{i=1}^{n}[y^{(i)}\frac{1}{\phi(z^{(i)}) }\phi(z^{(i)})(1-\phi(z^{(i)}))x_{j}^{i} - (1-y^{(i)})\frac{1}{1-\phi(z^{(i)})}\phi(z^{(i)})(1-\phi(z^{(i)}))x_{j}^{i}] \\ =-\frac{1}{n}\sum_{i=1}^{n}[y^{(i)}(1-\phi(z^{(i)}))x_{j}^{i} - (1-y^{(i)})\phi(z^{(i)})x_{j}^{i}] \\ =\frac{1}{n}\sum_{i=1}^{n}[\phi(z^{(i)})-y^{(i)}] x_{j}^{i}
∂wj∂J(w)=−n1i=1∑n[y(i)ϕ(z(i))1ϕ(z(i))(1−ϕ(z(i)))xji−(1−y(i))1−ϕ(z(i))1ϕ(z(i))(1−ϕ(z(i)))xji]=−n1i=1∑n[y(i)(1−ϕ(z(i)))xji−(1−y(i))ϕ(z(i))xji]=n1i=1∑n[ϕ(z(i))−y(i)]xji
w
j
:
=
w
j
−
η
∂
J
(
w
)
∂
w
j
=
w
j
−
η
∑
i
=
1
n
[
ϕ
(
z
(
i
)
)
−
y
(
i
)
]
x
j
i
w_{j}:=w_{j}-\eta \frac{\partial J(w)}{\partial w_{j}}=w_{j}-\eta \sum_{i=1}^{n}[\phi(z^{(i)})-y^{(i)}] x_{j}^{i}
wj:=wj−η∂wj∂J(w)=wj−ηi=1∑n[ϕ(z(i))−y(i)]xji
多类别分类
现在我们有一个训练集, 好比上图表示的有三个类别, 我们用三角形表示 y=1, 方框表示 y=2, 叉叉表示 y=3。 我们下面要做的就是使用一个训练集, 将其分成三个二元分类问题。
先从用三角形代表的类别 1 开始, 实际上我们可以创建一个, 新的"伪"训练集, 类型 2 和类型 3 定为负类, 类型 1 设定为正类, 我们创建一个新的训练集, 如下图所示的那样, 我们要拟合出一个合适的分类器。
这里的三角形是正样本, 而圆形代表负样本。 可以这样想, 设置三角形的值为 1, 圆形的值为 0, 下面我们来训练一个标准的逻辑回归分类器, 这样我们就得到一个正边界。
为了实现这样的转变,将多个类中的一个类标记为正向类(
y
=
1
y=1
y=1),然后将其他所有类都标记为负向类,此模型记为
ϕ
(
1
)
(
z
)
\phi^{(1)}(z)
ϕ(1)(z)。类似地第我们选择另一个类标记为正向类
y
=
2
y=2
y=2,再将其它类都标记为负向类,将这个模型记作
ϕ
(
2
)
(
z
)
\phi^{(2)}(z)
ϕ(2)(z),依次类推
最后得到的一系列模型记为:
ϕ
(
k
)
(
z
)
=
p
(
y
=
k
∣
x
;
w
)
,
k
=
1
,
2
,
3
,
⋯
\phi^{(k)}(z)=p(y=k|x;w),k=1,2,3,\cdots
ϕ(k)(z)=p(y=k∣x;w),k=1,2,3,⋯
需要做预测时,我们将所有的分类机都运行一遍,然后对每一个输入变量,都选择最高可能性的输出变量。即让3个分类器都输入
x
x
x,选择一个使得
ϕ
(
k
)
(
z
)
\phi^{(k)}(z)
ϕ(k)(z)最大的
k
k
k,即
max
k
ϕ
(
k
)
(
z
)
\max_{k} \phi^{(k)}(z)
kmaxϕ(k)(z)
#利用scikit-learn实现逻辑回归
在模型中,使用了L2正则化防止过拟合并减少模型复杂度,即误差函数为:
J
(
w
)
=
−
1
n
∑
i
=
1
n
[
y
(
i
)
log
(
ϕ
(
z
(
i
)
)
)
+
(
1
−
y
(
i
)
)
log
(
1
−
ϕ
(
z
(
i
)
)
)
]
+
λ
2
n
∑
j
=
1
n
w
j
J(w)=-\frac{1}{n}\sum_{i=1}^{n}[y^{(i)}\log(\phi(z^{(i)}))+(1-y^{(i)})\log(1-\phi(z^{(i)}))]+\frac{ \lambda}{2n}\sum_{j=1}^{n}w_{j}
J(w)=−n1i=1∑n[y(i)log(ϕ(z(i)))+(1−y(i))log(1−ϕ(z(i)))]+2nλj=1∑nwj,一般偏置项
w
0
w_{0}
w0不做正则化处理,
λ
\lambda
λ为正则化系数。Logistic regression模型中的
C
C
C为正则化系数的倒数:
C
=
1
λ
C=\frac{1}{\lambda}
C=λ1
在多类别分类数据集上使用Logistic Regression对象,默认使用一对多(One-vs-Rest, OvR)的方法。一共有3个截距项,其中第一个截距项为类别0相对于类别1,2的匹配结果,第二个截距项为类别1相对于类别0,2的匹配结果,第三个截距项为类别2相对于类别0,1的匹配结果。
权重数组包含三个权重系数向量,每一个权重向量对应一个分类。由于样本包含2个特征值,所以每个向量包括2个权重值,通过与数据集中的特征数据相乘来计算模型的净输入:
z
=
w
1
x
1
+
w
2
x
2
+
b
z=w_{1}x_{1}+w_{2}x_{2}+b
z=w1x1+w2x2+b
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
# test_idx为测试数据编号
def plot_decision_regions(X, y, classifier, test_idx=None):
# setup marker generator and color map
markers = ('s', 'x', 'o', '^', 'v')
colors = ('red', 'blue', 'lightgreen', 'grey', 'cyan')
cmap = ListedColormap(colors[:len(np.unique(y))])
# plot the decision region
x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, 0.02), np.arange(x2_min, x2_max, 0.02))
z = classifier.predict(np.array([xx1.flatten(), xx2.flatten()]).T)
z = z.reshape(xx1.shape)
plt.contourf(xx1, xx2, z, cmap=cmap, alpha=0.3)
plt.xlim(x1_min, x1_max)
plt.ylim(x2_min, x2_max)
# plot class samples
for idx, cl in enumerate(np.unique(y)):
plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1], cmap=cmap(idx), marker=markers[idx], label=cl, alpha=1)
if test_idx:
X_test, y_test = X[test_idx, :], y[test_idx]
plt.scatter(X_test[:, 0], X_test[:, 1], c='cyan', alpha=1.0,
linewidth=1, marker='^', s=55, label='test set')
plt.legend(loc='best')
plt.title('Adaline-梯度下降法', fontproperties='SimHei')
plt.xlabel('经标准化处理的萼片宽度', fontproperties='SimHei')
plt.ylabel('经标准化处理的花瓣宽度', fontproperties='SimHei')
iris = datasets.load_iris()
X = iris.data[:, [2, 3]] # 维度:(150,2)
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=0)
sc = StandardScaler()
sc.fit(X_train) # 计算训练数据的均值和标准差
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)
X_combined_std = np.vstack((X_train_std, X_test_std))
y_combined = np.hstack((y_train, y_test))
LR = LogisticRegression(C=1000.0, random_state=0)
LR.fit(X_train_std, y_train)
plot_decision_regions(X=X_combined_std,
y=y_combined,
classifier=LR,
test_idx=range(105, 150))
print(LR.predict_proba(X_test_std[0:2, :]))
'''
展示2个样本对于3个类别的准确率:
[[2.05743774e-11 6.31620264e-02 9.36837974e-01]
[6.08753106e-04 9.99285569e-01 1.05678028e-04]]
'''
print(LR.coef_)
'''
权重向量:
[[-7.34015187 -6.64685581]
[ 2.54373335 -2.3421979 ]
[ 9.46617627 6.44380858]]
'''
print(LR.intercept_)
'''
截距项:
[-9.31757401 -0.89462847 -8.85765974]
'''
print('Test Accuracy:', LR.score(X_test_std, y_test))
# Test Accuracy: 0.9777777777777777
plt.show()