機器學習(六)— logistic迴歸

  最近一直在看機器學習相關的算法,今天學習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函數的最佳擬合參數,能夠採用梯度上升法優化,而在這個過程當中,爲了減小時間複雜度,又可使用隨機梯度上升法來簡化梯度上升法。

相關文章
相關標籤/搜索