一、logistic回归基本概念
- 线性模型
一般形式:
其中x=(x1, x2, ..., xd)是由d维属性描述的样本,其中 xi 是 x 在第 i 个属性上的取值。
- 2.Logistic回归
- Logistic回归是统计学习中的经典分类方法,属于对数线性模型,所以也被称为对数几率回归。虽然是叫做回归,但其实这是一种分类算法,Logistic回归是一种线性分类器,针对的是线性可分问题。利用logistic回归进行分类的主要思想是:根据现有的数据对分类边界线建立回归公式,以此进行分类。
- 我们都知道使用线性模型可以进行回归学习,但若要做的是分类任务改如何处理?只需要找一个单调可微函数将分类任务的真实标记y与线性回归模型的预测值联系起来。考虑二分类任务,其输出标记y的取值为0和1,而线性回归模型产生的预测值是实值,于是需将实值z转换为0/1值。通过Sigmoid函数引入非线性因素,可以实现实值z转换为0/1值,处理二分类问题。
2.1Sigmoid函数
与单位阶跃函数的不连续相比Sigmoid函数则具有单调可微、任意阶可导的优点。
Sigmoid函数与单位阶跃函数比较:
- Sigmoid函数图像:
y
-
二、logistic回归算法
- 1.极大似然估计
-
极大似然估计的方法步骤:
- 确定待求解的未知参数
,如均值、方差或特定分布函数的参数等;
- 计算每个样本
的概率密度为
;
- 根据样本的概率密度累乘构造似然函数:
- 通过似然函数最大化(求导为0),求解未知参数θ,为了降低计算难度,可采用对数加法替换概率乘法,通过导数为0/极大值来求解未知参数。
-
2.梯度上升法
梯度上升法基本的思想是:要找到某函数的 最大值,最好的方法是沿着该函数的梯度方向探寻。如果梯度记为∇,则函数f(x,y)的梯度由 下式表示:
梯度上升算法到达每个点后都会重新估计移动的方向。从P0开始,计算完该点的梯度,函数就根据梯度移动到下一点P1。在P1点,梯度再次被重新计算,并沿新的梯度方向移动到P2。如此循环迭代,直到满足停止条件。迭代的过程中,梯度算子总是保证我们能选取到最佳的移动方向。
3.梯度下降法
梯度下降算法,它与上述的梯度上升算法是一样的,只是公式中的加法需要变成减法。梯度上升算法用来求函数的最大值,而梯度下降算法用来求函数的最小值。
三、算法实现
代码实现:
#coding:utf-8
from numpy import *
import matplotlib.pyplot as plt
class func:
def loadDataSet(self):
dataMat = []
labelMat = []
fr = open('testSet.txt')
for line in fr.readlines():
# 矩阵的格式【标签,X1,X2】
lineArr = line.strip().split()
#插入X1,X2,以及初始化的回归系数(权重),全部设为1.0
dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])
#插入标签,
#必须转换成int类型,因为只有两类
labelMat.append(int(lineArr[2]))
return dataMat,labelMat
# 使用sigmoid函数进行分类
def sigmoid(self,inX):
return 1.0/(1+exp(-inX))
#普通梯度上升
#使用梯度上升算法进行优化,找到最佳优化系数
#dataMatIn是训练集,三维矩阵,(-0.017612 14.053064 0)
#classLabels是类别标签,数值型行向量,需要转置为列向量,取值是0,1
def gradAscent(self,dataMatIn,classLabels):
dataMatrix = mat(dataMatIn) #转换为Numpy矩阵数据类型
labelMat = mat(classLabels).transpose() #转置矩阵,便于加权相乘
m,n = shape(dataMatrix) #得到矩阵的行列数,便于设定权重向量的维度
alpha = 0.001
maxCycles = 500
weights = ones((n,1)) #返回一个被1填满的 n * 1 矩阵,作为初始化权重
for k in range(maxCycles):
h = self.sigmoid(dataMatrix*weights)
erro = (labelMat - h) #labelMat是使用当前回归系数得到的的标签,labelMat是训练集的标签,取值是0,1
weights = weights + alpha * dataMatrix.transpose( ) * erro #根据使用当前权重计算的值与初始值的误差,更改weight,
#按照误差的方向调整回归系数
return weights
#随机梯度上升
def stocGradAscent0(dataMatrix, classLabels):
m, n = shape(dataMatrix)
alpha = 0.01
weights = ones(n)
for i in range(m):
h = sigmoid(sum(dataMatrix[i] * weights))
error = classLabels[i] - h
weights = weights + alpha * error * dataMatrix[i]
return weights
def plotBestFit(self,wei):
weights = wei.getA()
dataMat,labelMat = self.loadDataSet()
dataArr = array(dataMat)
n = shape(dataMat)[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()
ax = fig.add_subplot(111) #将画布分为一行一列的画布,并从第一块开始画
ax.scatter(xcord1,ycord1,s=30,c='red',marker = 's') #scatter散开
ax.scatter(xcord2,ycord2,s=30,c='green')
x = arange(-3.0,3.0,1)
y = (-weights[0]-weights[1]*x)/weights[2]
ax.plot(x,y)
plt.xlabel('x1')
plt.ylabel('x2')
plt.show()
if __name__=="__main__":
#普通梯度上升
logRegres = func()
dataArr,labelMat = logRegres.loadDataSet()
weights = logRegres.gradAscent(dataArr,labelMat)
logRegres.plotBestFit(weights)
#随机梯度上升
logRegres = func()
dataArr,labelMat = logRegres.loadDataSet()
weights =stocGradAscent0(array(dataArr),labelMat)
plotBestFit(weights)
结果展示:
分析:我们使用普通梯度上升法来实现,普通梯度上升在每次更新回归系数时都需要遍历整个数据集,复杂度会较高,但是准确率也会比较好。而另一种随机梯度上升算法则是一次仅用一个样本点更新回归系数,拟合效果没有普通梯度上升算法好,这是因为所用于实验的数据太少,准确率会比较低。
四、总结
通过上述原理的说明,我们知道了机器学习Logistic回归算法的概念以及如何通过Logistic回归来处理模型,还有这回归函数的的含义,并且我们通过获取数据集之后对数据进行预处理,再通过对数据集进行Logistic回归算法之后,对模型进行创建、训练与评估之后,得出最后的预测结果。我们也可以知道Logistic回归算法具有很好的数学原理。而且在数据量很小的时候我们可以通过普通梯度算法来解决问题,首先复杂度不高,且准确度好,数据量很大的时候我们可以通过随机梯度上升算法来计算,以此来减小函数的复杂度。通过学习我们也知道了 Logistic 回归原理简单,模型清晰,操作高效,背后的概率的推导过程经得住推敲,在研究中,通常以 Logistic 回归模型作为基准,再尝试使用更复杂的算法,可以在大数据场景中使用。但同时也存在容易欠拟合,精度不高的问题。