以前在新浪上写博客的,研一开学一直忙,博客没更,考虑到CSDN是专业的技术平台,把博客搬家到这里。进入正题:
算法思想:
二项logistic回归模型是一种分类模型,服从如下的条件概率分布:
P(Y=1|x)=exp(w.x)/(1+exp(w.x)) P(Y=0|x)=1/(1+exp(w.x)) w.x是w和x的内积
对于给定的输入实例x,比较两个条件概率P(Y=1|x)和P(Y=0|x)的概率值大小,将实例x分到概率值较大的那一类。
一个事件的几率(odds)是该事件发生的概率与不发生的概率的比值,如果事件发生的概率是p,那么事件发生的概率是p/(1-p),事件的对数几率logit(p)=log(p/(1+p)),所以对Logistic回归而言,P(Y=1|x))/(1-P(Y=0|x))的对数值是w与x的内积,也就是说,在该模型中,输出Y=1的几率是输入x的线性函数。我们可以把线性函数w.x转换成概率:P(Y=1|x)=1/(1+exp(-w.x))
对于模型参数,我们应用极大似然估计法估计,对似然函数求极值,将问题转换成最优化问题。
实现:
def loadset(filename):
fr=open(filename)
lines=fr.readlines()
dataMat=[]
classlabels=[]
for line in lines:
list=line.strip().split('\t')
dataMat.append([1.0,float(list[0]),float(list[1])]) #由于logit(x)=w0+w1*x1+w2*x2.....
classlabels.append(int(list[-1]))
return dataMat,classlabels
#构造sigmoid函数
def sigmoid(inX):
return 1.0/(1+exp(-inX))
#梯度上升法,随机梯度上升以及改进的随机梯度上升
def gradAscent(dataMatIn,classlabels,opts):
dataMat=mat(dataMatIn) #将数组转换成矩阵
labelMat=mat(classlabels).transpose() #将标签矩阵转秩
m,n=shape(dataMat) #求矩阵的维度大小,即矩阵的行数和列数
alpha=0.0001 #沿着梯度方向移动一步的步长
weights=ones((n,1)) #权重值初始化为1
maxcycles=500 #设置最大循环次数
for k in range(maxcycles):
if opts[optimaize]='ascent': #梯度上升
h=sigmoid(dataMat*weights)
err=(labelMat-h) #计算偏差
weights=weights+alpha*dataMat.transpose()*err #连乘的前一项是步长,后两项是梯度
elif opts[optimize]='randomAscent': #随机梯度上升算法
for i in range(m): #每用一个样本就更新一次权值
h=sigmoid(dataMat[i,:]*weights)
err=labelMat[i,0]-h
weights=weights+alpha*dataMat[i,:].transpose()*err
elif opts[optimize]='modifyAscent': #改进的随机梯度上升
index=range(m)
for i in range(m): #并不是按样本集从上到下计算权值,而是随机地从样本集中取样,这样可以减少周期性波动
alpha=4/(1+k+i)+0.01 #每循环一次都逐步减小步长,以防在最佳点附近徘徊
randindex=int(random.uniform(0,len(index)))
h=sigmoid(dataMat[randindex,:]*weights)
err=labelMat[randindex,:]-h
weights=weights+alpha*dataMat[randindex,:].transpose().err
return weights