基于逻辑回归的二分类问题
分类问题是机器学习的一个基础。一般地说,通过给定的特征集,给出对应的类别标签,即学习一个从
Rn→{0,1,…}
R
n
→
{
0
,
1
,
…
}
的映射。我们将特征集记作
X={x(1),x(2),…,x(m)}
X
=
{
x
(
1
)
,
x
(
2
)
,
…
,
x
(
m
)
}
,其中每一个样本代表一个n维向量;标签集记作
y={0,1,…}
y
=
{
0
,
1
,
…
}
。对于二分类问题,
y={0,1}
y
=
{
0
,
1
}
。
逻辑回归的思想来自于线性回归。线性回归的目的是用n维空间的超平面来拟合具有线性相关性的一组数据,如下图所示。
而对于分类问题,我们会考虑特征
x
x
属于类别的概率
P(y|x)
P
(
y
|
x
)
。它的概率分布函数如下:
将这个函数写成一个统一的式子: P(y|x)=y^y(1−y^)(1−y) P ( y | x ) = y ^ y ( 1 − y ^ ) ( 1 − y ) 。为了处理的方便,对该式取对数,不改变函数的单调性: a=ylogy^+(1−y)log(1−y^) a = y log y ^ + ( 1 − y ) log ( 1 − y ^ ) 。我们的目标是调整参数最大化这个函数。
由于这里假设数据是线性可分的,则 y^=σ(wTx+b) y ^ = σ ( w T x + b ) 。其中, σ(z) σ ( z ) 称为sigmoid函数,目的是将大范围内的数据压缩回(0,1)这个区间范围。而这正好属于概率的范围。
在包含有m个训练样本的数据集上进行训练时,假设所有样本都是独立同分布的。这样,使用最大似然估计,取似然函数为 L(w,b)=∑i=1my(i)logy^(i)+(1−y(i))log(1−y^(i)) L ( w , b ) = ∑ i = 1 m y ( i ) log y ^ ( i ) + ( 1 − y ( i ) ) log ( 1 − y ^ ( i ) ) 。其中使用 (i) ( i ) 上标表示第 i i 个样本
在机器学习中最常用的优化算法是梯度下降法。它通过调整参数使得当前误差向着局部误差最小点最快的方向调整。为了适应梯度下降的需要,我们对上述的似然函数求相反数并缩放背,从而使用梯度下降求出取的最小值时的参数 w w 和: J(w,b)=−1m∑i=1m[y(i)logy^(i)+(1−y(i))log(1−y^(i))] J ( w , b ) = − 1 m ∑ i = 1 m [ y ( i ) log y ^ ( i ) + ( 1 − y ( i ) ) log ( 1 − y ^ ( i ) ) ] 。
训练
使用梯度下降对逻辑回归的参数优化步骤如下所示:
random initialize w,b
repeat:
wj−=α×∂∂wjJ(w,b) w j − = α × ∂ ∂ w j J ( w , b )
b−=α×∂∂bJ(w,b) b − = α × ∂ ∂ b J ( w , b )
end repeat
其中,
∂∂wjJ(w,b)=1m∑i=1m(a(i)−y(i))x(i)j
∂
∂
w
j
J
(
w
,
b
)
=
1
m
∑
i
=
1
m
(
a
(
i
)
−
y
(
i
)
)
x
j
(
i
)
∂∂bJ(w,b)=1m∑i=1m(a(i)−y(i))
∂
∂
b
J
(
w
,
b
)
=
1
m
∑
i
=
1
m
(
a
(
i
)
−
y
(
i
)
)
由于这里的算法使用了多重的循环,会导致算法的效率低下。在Python中,使用了单指令多数据(SIMD)的技术,可以大大地加快算法的执行速度。
random initialize w,b w , b
repeat:
z=wTX+b z = w T X + b
a=σ(z) a = σ ( z )
dz=a−y d z = a − y
dw=X(dz)T/m d w = X ( d z ) T / m
db=∑dz/m d b = ∑ d z / m
w−=αdw w − = α d w
b−=αdb b − = α d b
以下是python实现的一个简单的逻辑回归算法:
import numpy as np
from numpy import loadtxt,where
import matplotlib.pyplot as plt
def sigmoid(z):
return 1/(1+np.exp(-z))
def logistic_regression(X,y, lr=0.1, repeat=2000):
w = np.zeros((X.shape[0],1))
b = 0
for i in range(repeat):
z = np.dot(w.T, X) + b
a = sigmoid(z)
dz = a - y
dw = np.dot(X, dz.T) / X.shape[1]
db = np.sum(dz) / X.shape[1]
w -= lr * dw
b -= lr * db
return w, b
if __name__ == '__main__':
data = loadtxt('data1.txt', delimiter=',')
X = data[:,0:2]
y = data[:,2]#.reshape(1,X.shape[1])
pos = where(y == 1)
neg = where(y == 0)
plt.scatter(X[pos, 0], X[pos, 1], marker='o', c='b')
plt.scatter(X[neg, 0], X[neg, 1], marker='x', c='r')
w,b = logistic_regression(X.T,y.T,lr=0.001, repeat=200000)
print(w,b)
k1 = -w[0][0]/w[1][0]
k2 = -b / w[1][0]
xx = np.arange(20,110,1)
yy = k1 * xx + k2
plt.plot(xx,yy)
plt.show()
以上代码的运行结果如下:
w= [[ 0.06550395]
[ 0.05898701]]
b= -7.45017821751
感谢寒小阳大大提供的数据集,大家可以在这个链接下载数据集进行训练。