赞
踩
假设现在有一些数据点,我们用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称作回归。利用Logistic回归进行分类的主要思想是:根据现有数据对分类边界线建立回归公式,以此进行分类。这里的“回归”一词源于最佳拟合,表示要找到最佳拟合参数集。训练分类器时的做法就是寻找最佳拟合参数,使用的是最优化算法。
线性模型一般形式:
其中x=(x1, x2, …, xd)是由d维属性描述的样本,其中 xi是 x 在 第 i 个属性上的取值。
向量形式可记为:
其中w=(w1, w2, …, wd)为待求解系数
线性模型可以衍生出一般形式:
g(∙)称为联系函数(link function),该函数一般为单调可微函数。
对数线性回归是 g(∙)=ln(∙) 时广义/多维线性模型的特例。
预测值与输出标记
寻找函数将分类标记与线性回归模型输出联系起来。
单位阶跃函数:
单位阶跃函数缺点:不连续
替代函数——逻辑斯蒂函数(logistic/sigmoid function) – 单调可微、任意阶可导
Sigmoid函数是一种阶跃函数( step function )。在数学中,如果实数域上的某个函数可以用半开区间上的指示函数的有限次线性组合来表示,那么这个函数就是阶跃函数。而数学中指示函数(indicator function)是定义在某集合X上的函数,表示其中有哪些元素属于某一子集A。
逻辑回归是拟合“y的sigmoid函数”
运用Sigmoid函数
整合成一个公式,就变成了如下公式:
对数几率(log odds) – 样本作为正例的相对可能性的对数
为了实现Logistic回归分类器,我们在每个特征上都乘以一个回归系数,然后把所有的结果值相加,将这个总和代人Sigmoid函数中,进而得到一个范围在0~1之间的数值。任何大于0.5的数据被分入1类,小于0.5即被归入0类。所以,Logistic回归也可以被看成是一种概率估计。
梯度上升算法到达每个点后都会重新估计移动的方向。从P0开始,计算完该点的梯度,函数就根据梯度移动到下一点P1。在P1点,梯度再次被重新计算,并沿新的梯度方向移动到P2.如此循环迭代,知道满足通知条件。迭代的过程中,梯度算子总是保证我们能选取到最佳的移动方向
按梯度上升的反方向迭代公式即可
梯度上升算法用来求函数的最大值,而梯度下降算法用来求函数的最小值。
对课本中的例子进行实现,有100个样本点,这些数据有两维特征,因此可以将数据在一个二维平面上展示出来。我们可以将第一列数据(X1)看作x轴上的值,第二列数据(X2)看作y轴上的值。而最后一列数据即为分类标签。根据标签的不同,对这些点进行分类。
# 加载数据 def loadDataSet(): dataMat = [] labelMat = [] fr = open('testSet.txt') for line in fr.readlines(): lineArr = line.strip().split() dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])]) labelMat.append(int(lineArr[2])) fr.close() return dataMat, labelMat # 绘制数据集 def plotDataSet(): dataMat, labelMat = loadDataSet()#加载数据集 dataArr = np.array(dataMat) #转换成numpy的array数组 n = np.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]) #1为正样本 else: xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2]) #0为负样本 fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(xcord1, ycord1, s = 20, c = 'red', marker = 's',alpha=.5) ax.scatter(xcord2, ycord2, s = 20, c = 'green',alpha=.5) plt.title('DataSet') plt.xlabel('x'); plt.ylabel('y') plt.show() if __name__ == '__main__': plotDataSet()
sigmoid函数
def sigmoid(inX):
return 1.0 / (1 + np.exp(-inX))
梯度上升算法
def gradAscent(dataMatIn,classLabels):
dataMatrix = np.mat(dataMatIn) #转换成numpy的mat
labelMat = np.mat(classLabels).transpose() #转换后进行转置
m,n = np.shape(dataMatrix) #返回dataMatrix的大小,m为函数,n为列数
alpha = 0.001 #移动步长
maxCycles = 500 #最大迭代次数
weights = np.ones((n,1))
for k in range(maxCycles):
h = sigmoid(dataMatrix * weights)
error = labelMat - h
weights = weights + alpha * dataMatrix.transpose() * error
return weights.getA()
梯度上升算哒在每次更新回归系数时都需要遍历整个数据集(批处理),该方法的计算复杂度随着样本和特征的数量的增多而加大。因此我们使用随机梯度上升算法来改进。随机梯度算法是一个在线学习算法
在随机梯度上升算法中一些系数需要的迭代次数更多,并且大的波动停止后会产生一些小的周期性的波动。产生这种现象的原因是存在一些不能正确分类的样本点,在每次迭代时会引法系数的剧烈改变。而改进的随机梯度上升能解决这一问题
def stocGradAscent1(dataMatrix,classLabels,numIter = 150):
m,n = np.shape(dataMatrix)
weights = np.ones(n) #参数初始化
for j in range(numIter):
dataIndex = list(range(m))
for i in range(m):
alpha = 4/(1.0+j+i)+0.01 #降低alpha的大小
randIndex = int(random.uniform(0,len(dataIndex))) #随机抽取样本
h = sigmoid(sum(dataMatrix[dataIndex[randIndex]]*weights)) #计算h
error = classLabels[dataIndex[randIndex]] - h #计算误差
weights = weights+alpha * error * dataMatrix[dataIndex[randIndex]]#更新回归函数
del(dataIndex[randIndex]) #删除已使用的样本
return weights
本节将使用 Logistic回归来预测患有疝病的马的存活问题。这里的数据包含368个样本和28个特征。我并非育马专家,从一些文献中了解到,疝病是描述马胃肠痛的术语。然而,这种病不定源自马的胃肠问题,其他问题也可能引发马疝病。该数据集中包含了医院检测马疝病的一些指标,有的指标比较主观,有的指标难以测量,例如马的疼痛级别。
import random import matplotlib.pyplot as plt import numpy as np def sigmoid(inX): return 1.0/(1+np.exp(-inX)) def stocGradAscent1(dataMatrix,classLabels,numIter = 150): m,n = np.shape(dataMatrix) weights = np.ones(n) #参数初始化 for j in range(numIter): dataIndex = list(range(m)) for i in range(m): alpha = 4/(1.0+j+i)+0.01 #降低alpha的大小 randIndex = int(random.uniform(0,len(dataIndex))) #随机抽取样本 h = sigmoid(sum(dataMatrix[dataIndex[randIndex]]*weights)) #计算h error = classLabels[dataIndex[randIndex]] - h #计算误差 weights = weights+alpha * error * dataMatrix[dataIndex[randIndex]]#更新回归函数 del(dataIndex[randIndex]) #删除已使用的样本 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('horseColicTraining.txt') frTest = open('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(lineArr) trainWeights = stocGradAscent1(np.array(trainingSet),trainingLabels,1000) errorCount = 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(np.array(lineArr),trainWeights))!= int(currLine[21]): errorCount +=1 errorRata = (float(errorCount)/numTestVec) print("the error rate of this test is:%f" % errorRata) return errorRata
Logistic回归的目的是寻找一个非线性函数Sigmoid的最佳拟合参数,求解过程可以由最优化算法来完成。在最优化算法中,最常用的就是梯度上升算法,而梯度上升算法又可以简化为随机梯度上升算法。
随机梯度上升算法与梯度上升算法的效果相当,但占用更少的计算资源。此外,随机梯度上升是一个在线算法,它可以在新数据到来时就完成参数更新,而不需要重新读取整个数据集来进行批处理运算。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。