您的位置:首页 > 其它

机器学习之十一:逻辑回归

2018-03-31 12:02 561 查看
1、逻辑斯谛分布

设XX是连续随机变量,XX服从逻辑斯蒂分布是指XX具有下列分布函数和概率密度:

F(x)=P(X≤x)=11+e−(x−μ)/γf(x)=F′(x)=1+e−(x−μ)/γγ(1+e−(x−μ)/γ)2F(x)=P(X≤x)=11+e−(x−μ)/γf(x)=F′(x)=1+e−(x−μ)/γγ(1+e−(x−μ)/γ)2

其中μμ为位置参数,γγ为形状参数。

逻辑斯谛分布的密度函数和分布函数的图形如下所示,分布函数属于逻辑斯谛函数,其图形是一条S形曲线,该曲线以点(μ,1/2)(μ,1/2)为中心点,曲线在中心附近增长速度较快,在两端增长速度较慢,形状参数γγ值越小,曲线在中心附近增长的越快:



2、二项逻辑斯谛回归模型

二项逻辑斯谛回归模型是一种分类模型,由条件概率分布P(Y|X)P(Y|X)表示,形式为参数化的逻辑斯蒂分布。二项逻辑斯谛回归模型是如下条件概率:

P(Y=1|x)=exp(w⋅x+b)1+exp(w⋅x+b)P(Y=0|x)=11+exp(w⋅x+b)P(Y=1|x)=exp⁡(w⋅x+b)1+exp⁡(w⋅x+b)P(Y=0|x)=11+exp⁡(w⋅x+b)

其中x∈Rnx∈Rn,Y∈0,1Y∈0,1,w∈Rnw∈Rn和b∈Rb∈R是参数,ww称为权值向量,bb称为偏置,w⋅xw⋅x为ww和xx的内积。

对于给定的输入实例xx,按照上述两个公式可以求得P(Y=1|x)P(Y=1|x)和P(Y=0|x)P(Y=0|x),逻辑斯谛回归比较两个条件概率值大小,将实例xx分到概率值比较大的那一类。

有时为了方便,将权值向量和输入向量加以扩充,仍记做w,xw,x,即w=(w(1),w(2),...,w(n),b)w=(w(1),w(2),...,w(n),b),x=(x(1),(x(2),...(x(n),1)x=(x(1),(x(2),...(x(n),1),这时逻辑斯谛回归模型如下:

P(Y=1|x)=exp(w⋅x)1+exp(w⋅x)P(Y=0|x)=11+exp(w⋅x)P(Y=1|x)=exp⁡(w⋅x)1+exp⁡(w⋅x)P(Y=0|x)=11+exp⁡(w⋅x)

3、模型参数估计:

逻辑斯谛回归模型学习,对于给定的训练数据集T={(x1,y1),(x2,y2),...,(xN,yN)}T={(x1,y1),(x2,y2),...,(xN,yN)},xi∈Rnxi∈Rn,yi∈{0,1}yi∈{0,1},可以用极大似然估计法估计模型参数,从而得到逻辑斯谛回归模型。设:

P(Y=1|x)=π(x)P(Y=0|x)=1−π(x)⇒P(Y|x)=[π(x)]y[1−π(x)](1−y)P(Y=1|x)=π(x)P(Y=0|x)=1−π(x)⇒P(Y|x)=[π(x)]y[1−π(x)](1−y)

似然函数为:

∏i=1N=[π(xi)]yi[1−π(xi)](1−yi)∏i=1N=[π(xi)]yi[1−π(xi)](1−yi)

对数似然函数为:

L(w)=∑i=1N[yilogπ(xi)+(1−yi)log(1−π(xi))]=∑i=1N[yilogπ(xi)1−π(xi)+log(1−π(xi))]=∑i=1N[yi(w⋅xi)−log(1+exp(w⋅xi))]L(w)=∑i=1N[yilog⁡π(xi)+(1−yi)log⁡(1−π(xi))]=∑i=1N[yilog⁡π(xi)1−π(xi)+log⁡(1−π(xi))]=∑i=1N[yi(w⋅xi)−log⁡(1+exp⁡(w⋅xi))]

对L(w)L(w)求极大值,得到ww的估计值。问题就变成了以对数似然函数为目标函数的最优化问题,逻辑斯谛回归学习中通常采用的方法是梯度下降法或者随机梯度下降法以及拟牛顿法。

∂L(w)∂w=∑i=1N[(yi−exp(w⋅xi)1+exp(w⋅xi))xi]w=w+α∂L(w)∂w∂L(w)∂w=∑i=1N[(yi−exp⁡(w⋅xi)1+exp⁡(w⋅xi))xi]w=w+α∂L(w)∂w

4、优缺点:

逻辑回归优点:

  1)、实现简单;

  2)、分类时计算量非常小,速度很快,存储资源低;

缺点:

  1)、容易欠拟合,一般准确度不太高

  2)、只能处理两分类问题(在此基础上衍生出来的softmax可以用于多分类),且必须线性可分;

  

5、代码实现逻辑回归

#coding=utf-8
from numpy import *
import matplotlib.pyplot as plt

# 载入数据
def loadDataSet():
dataMat = []
labelMat = []
fr = open('testSet.txt')
# 逐行读入数据,然后strip去头去尾,用split分组
for line in fr.readlines():
lineArr = line.strip().split('    ')
dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])  # 对输入向量进行扩充
labelMat.append(int(lineArr[2]))
return dataMat,labelMat

# 定义sigmoid函数
def sigmoid(inX):
return 1.0/(1+exp(-inX))

# 梯度下降法
def gardDescent(dataMatIn,classLabels):
dataMatrix = mat(dataMatIn)
labelMatrix = mat(classLabels).T  # 真实值
m,n = shape(dataMatrix)     # 得到数据规模,m为样本点个数,n为特征个数
# 迭代步长
alpha = 0.01
# 迭代次数
maxCycles = 5000            #最大迭代次数
weights = ones((n,1))       # 初始化权重向量
# 设定初始参数,全为1
for k in range(maxCycles):
h = sigmoid(dataMatrix * weights)  # sigmoid函数已定义
E = (h - labelMatrix)
weights = weights - alpha * dataMatrix.T * E
return weights

# 随机梯度上升算法
# 每次对参数的更新都只用一个样本值,属于在线算法
def stocGradAscent0(dataMatrix,classLabels):
dataMatrix = array(dataMatrix)
m,n = shape(dataMatrix)
alpha = 0.01
weights = ones(n)
for i in range(m):
h = sigmoid(sum(dataMatrix[i] * weights))
E = classLabels[i] - h
weights = weights + alpha * E * dataMatrix[i]
return weights

# 改进的随机梯度上升算法
def stocGradAscent0(dataMatrix,classLabels):
dataMatrix = array(dataMatrix)
m,n = shape(dataMatrix)
alpha = 0.01
weights = ones(n)
# 在所有样本点上迭代500次
for j in range(500):
for i in range(m):
h = sigmoid(sum(dataMatrix[i] * weights))
E = classLabels[i] - h
weights = weights + alpha * E * dataMatrix[i]
return weights

# 画图函数,传入参数为两种不同算法得到的参数矩阵
def plotBestFit(weights_1,weights_2):
weights_1 = weights_1.getA()      # numpy.matrix.getA():
# Return `self` as an `ndarray` object.
# weights_2 = weights_2.getA()
dataMat,labelMatrix = loadDataSet()
dataArr = array(dataMat)
n = shape(dataArr)[0]

# 使用如下矩阵表示标签不同的两类训练样本
xcord1 = []; ycord1 = []
xcord2 = []; ycord2 = []

# 将训练样本按照标记不同,分为两类不同的点
for i in range(n):
if int(labelMat[i]) == 1:
xcord1.append(dataArr[i,1])
ycord1.append(dataArr[i,2])
else:
xcord2.append(dataArr[i,1])
ycord2.append(dataArr[i,2])

fig = plt.figure(figsize=(14,6))

####################### 图1 ####################
ax = fig.add_subplot(121)
# 画散点图,不同的样本点用不同颜色表示
ax.scatter(xcord1,ycord1,s=30,c='red',marker='s')
ax.scatter(xcord2,ycord2,s=30,c='blue',)

x = arange(-3.0,3.0,0.1)
y_1 = (-weights_1[0]-weights_1[1]*x)/(weights_1[2])
ax.plot(x,y_1,'k--',color = 'yellow',linewidth=2)
plt.xlabel('Logistics Regression GradDescent')

# 去掉坐标系右边和上边的边界,美观
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')

####################### 图2 ####################
ax = fig.add_subplot(122)
ax.scatter(xcord1,ycord1,s=30,c='red',marker='s')
ax.scatter(xcord2,ycord2,s=30,c='blue',)
x = arange(-3.0,3.0,0.1)
y_2 = (-weights_2[0]-weights_2[1]*x)/(weights_2[2])
ax.plot(x,y_2,'k--',color = 'yellow',linewidth=2)
plt.xlabel('Logistics Regression StocGradDescent')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
plt.show()

# 定义准确度计算函数
def calAccuracyRate(dataMat,labelMat,weights):
count = 0
dataMat = mat(dataMat)
labelMat = mat(labelMat).T
m,n = shape(dataMat)
for i in range(m):
h = sigmoid(dataMat[i,:] * weights)
if ( h>0.5 and int(labelMat[i,0]) == 1) or ( h<0.5 and int(labelMat[i,0]) == 0 ):
count += 1
return count/m

if __name__ == '__main__':
dataMat,labelMat = loadDataSet()
weights_GD = gardDescent(dataMat,labelMat)              # 使用梯度下降计算参数矩阵 θ
weights_SGD = stocGradAscent0(dataMat,labelMat)         # 使用随机梯度下降计算参数矩阵 θ
print('weights_GD:\n',weights_GD)
print('weights_SGD:\n',weights_SGD)
plotBestFit(weights_GD,weights_SGD)
# 计算两种算法结果的准确度
acc_gd = calAccuracyRate(dataMat,labelMat,weights_GD)
weights_SGD = mat(weights_SGD).transpose()
acc_sgd = calAccuracyRate(dataMat,labelMat,weights_SGD)
print('\n\nacc_gd:',acc_gd)
print('acc_sgd:',acc_sgd)




算法使用的数据集:

-0.017612 14.053064 0

-1.395634 4.662541 1

-0.752157 6.538620 0

-1.322371 7.152853 0

0.423363 11.054677 0

0.406704 7.067335 1

0.667394 12.741452 0

-2.460150 6.866805 1

0.569411 9.548755 0

-0.026632 10.427743 0

0.850433 6.920334 1

1.347183 13.175500 0

1.176813 3.167020 1

-1.781871 9.097953 0

-0.566606 5.749003 1

0.931635 1.589505 1

-0.024205 6.151823 1

-0.036453 2.690988 1

-0.196949 0.444165 1

1.014459 5.754399 1

1.985298 3.230619 1

-1.693453 -0.557540 1

-0.576525 11.778922 0

-0.346811 -1.678730 1

-2.124484 2.672471 1

1.217916 9.597015 0

-0.733928 9.098687 0

-3.642001 -1.618087 1

0.315985 3.523953 1

1.416614 9.619232 0

-0.386323 3.989286 1

0.556921 8.294984 1

1.224863 11.587360 0

-1.347803 -2.406051 1

1.196604 4.951851 1

0.275221 9.543647 0

0.470575 9.332488 0

-1.889567 9.542662 0

-1.527893 12.150579 0

-1.185247 11.309318 0

-0.445678 3.297303 1

1.042222 6.105155 1

-0.618787 10.320986 0

1.152083 0.548467 1

0.828534 2.676045 1

-1.237728 10.549033 0

-0.683565 -2.166125 1

0.229456 5.921938 1

-0.959885 11.555336 0

0.492911 10.993324 0

0.184992 8.721488 0

-0.355715 10.325976 0

-0.397822 8.058397 0

0.824839 13.730343 0

1.507278 5.027866 1

0.099671 6.835839 1

-0.344008 10.717485 0

1.785928 7.718645 1

-0.918801 11.560217 0

-0.364009 4.747300 1

-0.841722 4.119083 1

0.490426 1.960539 1

-0.007194 9.075792 0

0.356107 12.447863 0

0.342578 12.281162 0

-0.810823 -1.466018 1

2.530777 6.476801 1

1.296683 11.607559 0

0.475487 12.040035 0

-0.783277 11.009725 0

0.074798 11.023650 0

-1.337472 0.468339 1

-0.102781 13.763651 0

-0.147324 2.874846 1

0.518389 9.887035 0

1.015399 7.571882 0

-1.658086 -0.027255 1

1.319944 2.171228 1

2.056216 5.019981 1

-0.851633 4.375691 1

-1.510047 6.061992 0

-1.076637 -3.181888 1

1.821096 10.283990 0

3.010150 8.401766 1

-1.099458 1.688274 1

-0.834872 -1.733869 1

-0.846637 3.849075 1

1.400102 12.628781 0

1.752842 5.468166 1

0.078557 0.059736 1

0.089392 -0.715300 1

1.825662 12.693808 0

0.197445 9.744638 0

0.126117 0.922311 1

-0.679797 1.220530 1

0.677983 2.556666 1

0.761349 10.693862 0

-2.168791 0.143632 1

1.388610 9.341997 0

0.317029 14.739025 0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: