刚开始学习回归的时候一头雾水——线性回归linear regression,逻辑回归logistic regression和Softmax regression?线性回归是回归算法,而逻辑回归和softmax本质上是分类算法。
我从分类学起的,所以首先接触的是logistic regression,这篇博客就是对logistic regression详解以及如何应用在实际案例中。
logistic regression使用Sigmoid函数分类,为什么使用这个公式进行分类?例如在两个分类的情况下,我们要得到的是要么是1,要么是0。对于这种函数称为单位阶跃函数,由于Sigmoid函数有这种性质(输出0或者1),就用这个公式作为分类标准,其中X代表数据中各个特征的加权和,得到的y表示结果是1的概率。
由Sigmoid函数可以得到一个公式,当真实值是1的时候,这个函数预测值为1的概率就是Sigmoid概率,当真实值y为0时,这个函数预测值为0的概率为1-Sigmoid概率。于是这个函数代表了Sigmoid函数预测的准确程度。当我们有N个样本点时,似然函数就是这N个概率的乘积,我们的目标就是使预测的准确程度最大,也就是求使上述公式乘积最大的时候的变量值,这里使用了最大似然函数
因为我们是要求最大值,所以要沿着梯度增加的方向计算(先初始化一个权重向量),因此权重的迭代更新式为,:
可以使用批量梯度算法,每次迭代计算所有训练样本,精度高,但是复杂,也可以使用随机梯度算法(每计算一个样本就进行一次更新),这篇文章实现的代码包括了这两种算法,推荐使用随机梯度算法。
这里的代码实现的是从疝气病症预测病马的死亡率,数据集百度下载,代码如下:
from numpy import *
def loadDataSet():
dataMat=[]
labelMat=[]
fr=open()
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
def sigmoid(inX): #Sigmoid函数
return 1.0/(1+exp(-inX))
def gradAscent(dataMatIn,classLabels): #批量梯度算法
dataMatrix=mat(dataMatIn)
labelMat=mat(classLabels).transpose()
m,n=shape(dataMatrix)
alpha=0.001
weights=ones((n,1))
for k in range(500):
h=sigmoid(dataMatrix*weights)
error=labelMat-h
weights=weights+alpha*dataMatrix.transpose()*error
return weights
def stocGradAscent(dataMatIn,classLabels): #随机梯度算法
m,n=shape(dataMatIn)
alpha=0.01
weights=ones(n)
for i in range(m):
h=sigmoid(dataMatIn[i]*weights)
error=(classLabels[i]-h)
weights=weights+alpha*dataMatIn[i]*error
return weights
def classifyVector(inX,weights): #根据概率分类
prob=sigmoid(sum(inX*weights))
if prob>0.5:
return 1.0
else:
return 0.0
def colicTest():
frTrain=open('data/horseColicTraining.txt')
frTest=open('data/horseColicTest.txt')
trainingSet=[]
trainingLabels=[]
for line in frTrain.readlines():
currLine=line.strip().split('\t')
lineArr=[]
for i in range(21):
lineArr.append(float(currLine[i]))
trainingSet.append(lineArr)
trainingLabels.append(float(currLine[21]))
trainWeights=gradAscent(array(trainingSet),trainingLabels)
errotcount=0
numtestvec=0.0
for line in frTest.readlines():
numtestvec+=1.0
currLine=line.strip().split('\t')
lineArr=[]
for i in range(21):
lineArr.append(float(currLine[i]))
if int(classifyVector(array(lineArr),trainWeights))!=int(currLine[21]):
errotcount+=1
errorRate=errotcount/numtestvec
print("error rate--%f"%(float(errorRate)))
return errorRate
colicTest()
注:Logistic回归算法理解起来比较吃力,建议先自行学习相关概率知识,比如最大似然估计,以及求导等