最近一直在看机器学习相关的算法,今天学习logistic回归,在对算法进行了简单分析编程实现以后,经过实例进行验证。python
一 logistic概述 算法
我的理解的回归就是发现变量之间的关系,也就是求回归系数,常常用回归来预测目标值。回归和分类同属于监督学习,所不一样的是回归的目标变量必须是连续数值型。编程
今天要学习的logistic回归的主要思想是根据现有的数据对分类边界线创建回归公式,以此进行分类。主要在流行病学中应用较多,比较经常使用的情形是探索某疾病的危险因素,根据危险因素预测某疾病发生的几率等等。logistic回归的因变量能够是二分类的,也能够是多分类的,可是二分类的更为经常使用,也更加容易解释,因此实际中最为经常使用的就是二分类的logistic回归。xcode
今天咱们就二分类进行分析,咱们在回归分析中须要一个函数能够接受全部的输入而后预测出类别,假定用0和1分别表示两个类别,logistic函数曲线很像S型,故此咱们能够联系sigmoid函数:σ = 1/(1/(1+e-z))。为了实现logistic回归分类器,咱们能够在每一个特征上乘以一个回归系数,将全部的乘积相加,将和值代入sigmoid函数中,获得一个范围为0-1之间的数,若是该数值大于0.5则被纳入1类,不然被归为0类。app
基于以前的分析,须要找到回归系数,首先咱们能够将sigmoid函数的输入形式记为:z = w0x0 + w1x1 +...+wnxn,其中x为输入数据,相应的w就是咱们要求的系数,为了求得最佳系数,结合最优化理论,咱们能够选取梯度上升法优化算法。梯度上升法的基本思想是:要找到函数的最大值,最好的方法是沿着该函数的梯度方向寻找。要想更进一步的了解这个方法,建议去看Andrew Ng的机器学习课程,记得在第二节主要讲述的就是梯度降低法,与梯度上升所不一样的是它求得的是函数的最小值,不过思想是一致的。dom
二 python实现 机器学习
基于以前的分析,在本节咱们对logistic回归一步一步采用python编程实现,今天我用的是2.7版本的,代码以下:函数
#coding:utf-8 from numpy import * import math import matplotlib.pyplot as plt #导入数据 def loadDataSet(): dataMat = [] labelMat = [] fr = open('testSet.txt') for line in fr.readlines(): lineArr = line.strip().split()#将文本中的每行中的字符一个个分开,变成list 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 gradAscent(data,label): dataMat = mat(data) labelMat = mat(label).transpose() m,n = shape(dataMat) alpha = 0.001 maxCycles = 500 weights = ones((n,1)) for item in range(maxCycles): h = sigmoid(dataMat * weights) error = (labelMat - h)#注意labelMat中的元素的数据类型应为int weights = weights + alpha * dataMat.transpose() * error return weights ''' #测试 data,label = loadDataSet() print gradAscent(data,label) ''' ##求出回归系数以后,就肯定了不一样数据类别之间的分隔线,为了便于理解,能够画出那条线 def plotBestFit(weights): dataMat,labelMat = loadDataSet() dataArr = array(dataMat) n = shape(dataArr)[0] xcode1 = [] ycode1 = [] xcode2 = [] ycode2 = [] for i in range(n): if int(labelMat[i]) == 1: xcode1.append(dataArr[i,1]) ycode1.append(dataArr[i,2]) else: xcode2.append(dataArr[i,1]) ycode2.append(dataArr[i,2]) fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(xcode1,ycode1,s = 30,c = 'red',marker = 's') ax.scatter(xcode2,ycode2,s = 30,c = 'green') x = arange(-3.0,3.0,0.1) y = (-weights[0] - weights[1] * x) / weights[2] ax.plot(x,y) plt.xlabel('x1') plt.ylabel('y1') plt.show() ''' #测试 data,label = loadDataSet() weights = gradAscent(data,label) plotBestFit(weights.getA()) ''' ##改进的梯度上升法 def stocGradAscent1(dataMatrix, classLabels, numIter=150): m,n = shape(dataMatrix) weights = ones(n) #initialize to all ones for j in range(numIter): dataIndex = range(m) for i in range(m): alpha = 4/(1.0+j+i)+0.0001 randIndex = int(random.uniform(0,len(dataIndex))) h = sigmoid(sum(dataMatrix[randIndex]*weights)) error = classLabels[randIndex] - h weights = weights + alpha * error * dataMatrix[randIndex] del(dataIndex[randIndex]) return weights ''' #测试 data,label = loadDataSet() weights = stocGradAscent1(array(data),label) plotBestFit(weights) '''
三 实例分析 学习
基于以前的分析,本节采用Logistic回归来预测患有疝病的马的存活问题,代码以下:测试
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(float(currLine[21])) trainWeights = stocGradAscent1(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(array(lineArr), trainWeights))!= int(currLine[21]): errorCount += 1 errorRate = (float(errorCount)/numTestVec) print "错误率是:",errorRate return errorRate def multiTest(): numTests = 10; errorSum=0.0 for k in range(numTests): errorSum += colicTest() print "平均错误率是",(numTests, errorSum/float(numTests)) multiTest()
最后能够看出错误率在35%左右,经过调节步长仍是能够进一步减少错误率。
Logistic回归的目的是寻找到一个非线性sigmoid函数的最佳拟合参数,能够采用梯度上升法优化,而在这个过程当中,为了减小时间复杂度,又可使用随机梯度上升法来简化梯度上升法。