写这篇博文用了很多时间和精力,如果这篇博文对你有帮助,希望您可以打赏给博主相国大人。哪怕只捐1毛钱,也是一种心意。通过这样的方式,也可以培养整个行业的知识产权意识。我可以和您建立更多的联系,并且在相关领域提供给您更多的资料和技术支持。
手机扫一扫,即可:
主要内容:
深入浅出Logistic回归
一些实验和实战
我的其他博文
softmax回归及其实现(TensorFlow)
感知机实现:python
1,logistic“回归”
本节主要内容为:线性判别模型与感知机,广义线性模型,训练算法,python实现。
下面这个是一个感知机的示意图,也可以看成是一个分类器示意图。
SUM模块将输入数据按照各个维度进行加权求和,得到的结果送入 f f 模块。
SUM模块可以写成:,为了后面的处理更加方便。我们将 ω ω 和 x x 进行增广,这样SUM模块可以写成:
f f 模块是判别函数。他将SUM得到的结果进行处理,从而进行类别的判断。
对于常见的有两种,一种是阶跃函数,另一种叫做sigmod函数。由于阶跃函数存在不连续点,不容易处理。因此更常用的是sigmod函数:
y=11+exp(−ωTx)
y
=
1
1
+
e
x
p
(
−
ω
T
x
)
函数图像为:
这个函数的输出是介于0和1之间的数。我们一般用它来模拟概率。并且当输出大于0.5时,认为是正例。反之为负例。
这个函数本身并不是线性的。因此我们考虑,能够通过某种变换,得到一个线性函数?考虑如下的变化:
lny1−y=ωTx
l
n
y
1
−
y
=
ω
T
x
可以看到,通过变换
lny1−y
l
n
y
1
−
y
我们得到了一个线性函数。
因此,我们说logistic回归,是(广义)线性的。由他得到的图1.1叫做logistic分类器。sigmod函数在这里也别叫做logistic函数。现在我们有一批训练数据,我们希望通过训练得到比较好的 ω ω ,这样再给我们一个输入时,就可以据此来预测分类了。下面我们介绍训练算法。
其中 M M 为误分类点的集合。这是一个损失函数,我们希望它取得最小值。对于这个函数,可以采用梯度下降法。具体可以见我的另一篇博文《感知机实现python》
对于logistic回归,我们刚才说到,logistic函数给出的是一个类概率。因此这里我们采用似然函数作为优化目标。logistic函数的输出,可以看做是 P(y=1|x) P ( y = 1 | x ) ,因此我们的似然函数可以写为:
l(ω)=Πni=1(P(Y=1|xi)yi(1−P(Y=1|xi))1−yi)
l
(
ω
)
=
Π
i
=
1
n
(
P
(
Y
=
1
|
x
i
)
y
i
(
1
−
P
(
Y
=
1
|
x
i
)
)
1
−
y
i
)
这里
y
y
取值为0或1,相应的对数似然为:对此求关于 ω ω 的偏导数。得到:
∂L(ω)∂ω=▽ωL(ω)=∑i=1n(yi−11+exp(−ωTxi))xi=XTErrors
∂
L
(
ω
)
∂
ω
=
▽
ω
L
(
ω
)
=
∑
i
=
1
n
(
y
i
−
1
1
+
e
x
p
(
−
ω
T
x
i
)
)
x
i
=
X
T
E
r
r
o
r
s
其中 Errors E r r o r s 是由一些列的
yi−11+exp(−ωTxi)=yi−logistic(ωTxi)
y
i
−
1
1
+
e
x
p
(
−
ω
T
x
i
)
=
y
i
−
l
o
g
i
s
t
i
c
(
ω
T
x
i
)
构成的误差向量。
我们的目标是对似然函数做极大似然估计,你可以另导数为0,然而我们发现这样得不到解析解。所以我们转而采用梯度上升法。可以看到,这里的梯度就是误差向量与输入矩阵的乘积。关于梯度上升法,我已经在《感知机实现python》中做了详细的实现和讲解。此处不再赘述。
代码实现:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@author: XiangguoSun
@contact: sunxiangguodut@qq.com
@file: logistic.py
@time: 2017/3/5 9:58
@software: PyCharm
"""
import numpy as np
from numpy import *
import matplotlib.pyplot as plt
def drawSamples(plt,Input):
m, n=shape(Input)
target = Input[:,-1]
for i in xrange(m):
if target[i]==0:
plt.scatter(Input[i,0],Input[i,1],c='blue',marker='o')
else:
plt.scatter(Input[i,0],Input[i,1],c='red',marker='s')
def buildMat(dataSet):
m, n = shape(dataSet)
dataMat = zeros((m, n))
dataMat[:, 0] = 1
dataMat[:, 1:] = dataSet[:, :-1]
return dataMat
# Logistic函数
def logistic(wTx):
return 1.0/(1.0+exp(-wTx))
if __name__ == '__main__':
#导入数据
path = './testSet.txt' # 数据文件路径
Input = mat(np.loadtxt(path, dtype=float))
target = Input[:,-1] #获取分类标签列表
[m,n] = shape(Input)
#构建b+x 系数矩阵:b这里默认为1
dataMat = buildMat(Input)
#定义步长和迭代次数
alpha = 0.001 # 步长
steps = 500 # 迭代次数
weights = ones((n,1))# 初始化权重向量
weightlist=[]
#主程序
for k in xrange(steps):
gradient = dataMat*mat(weights) # 梯度
output = logistic(gradient) # logistic函数
errors = target-output # 计算误差
weights = weights + alpha*dataMat.T*errors
weightlist.append(weights)#这个作用时候为了日后分析各个参数变化
print weights#输出训练后的权重
#按分类绘制散点图
drawSamples(plt, Input)
#绘制训练后超平面
X = np.linspace(-7,7,100)
Y = -(double(weights[0])+X*(double(weights[1])))/double(weights[2])
plt.plot(X,Y)
plt.show()
实验结果
训练好之后,我们就可以用来分类了,分类器非常简单:
def classifier(testData,weights):
m,n=shape(testData)
test=zeros((m,n+1))
test[:,0]=1
test[:,1:]=testData
pro=logistic(sum(test*weights))
if pro > 0.5:
return 1.0
else:
return 0.0
需要说明的是,logistic回归是一个二分类的模型(虽然名字叫回归,其实是分类模型)。那么如果我们希望进行多分类,就可以将logistic的思想推广到多分类中,也就是我们另一篇博文将要介绍的softmax 回归。softmax回归是神经网络和深度学习的最基本的概念。关于softmax回归,请见博主的这篇博文
《softmax回归及其实现(TensorFlow)》