1. 程式人生 > >使用Logistic迴歸預測病馬的死亡率

使用Logistic迴歸預測病馬的死亡率

1. 問題描述

疝病是描述馬胃腸痛的術語,然而,這種病不一定源自馬的腸胃問題,其他問題也可能引發馬疝病。由於馬的身體指標測量引數十分多,同時對於預測結果僅需做出病馬是否死亡這一二分的判斷,Logistic迴歸在這一點上就十分合適。

2. 資料準備

對於資料集中的缺失值使用0來替代。因為sigmoid(0) = 0.5,對預測結果不具有侵向性,同時迭代函式weights = weights + alpha * error * dataMatrix[randIndex]dataMatrix0時不會做出更新。

預處理後的資料分為測試資料horseColicTest.txt和訓練資料horseColicTraining.txt

3. 模型原理

3.1.Sigmoid函式

,在較大座標尺度下近似與單位階躍函式,同時:

Sigmoid函式具有很好的二分特性。

3.2.最佳迴歸係數確定

使用梯度上升法確定最佳迴歸係數。記梯度為▽,則函式f(x, y)的梯度由下式表示:

這個梯度意味著要沿x的方向移動,沿y的方向移動。其中,函式f(x, y)必須要在待計算的點有定義並且可微。

梯度運算元總是指向函式值增長最快的方向。移動量的值稱為步長,記作α。梯度演算法迭代公式為:

由此可快速得到最佳迴歸係數。

3.3.資料預測

Sigmoid函式的輸入值z,由下面公式得出:

z帶入sigmoid函式得到函式值,以0.5為分界得到該資料的預測分類。

4. 演算法實現

4.1.sigmoid函式

def sigmoid(inX):

    if inX>=0:

        return 1.0/(1+exp(-inX))

    else:

        return exp(inX)/(1+exp(inX))

4.2.梯度上升優化演算法

def gradAscent(dataMatIn, classLabels):

    dataMatrix = mat(dataMatIn)

    labelMat = mat(classLabels).transpose()

    m,n = shape(dataMatrix)

    alpha = 0.001

    maxCycles = 500

    weights = ones((n,1))

    for k in range(maxCycles):

        h = sigmoid(dataMatrix*weights)

        error = (labelMat - h)

        weights = weights + alpha * dataMatrix.transpose()* error

    return weights

4.3.隨機梯度上升

def stocGradAscent1(dataMatrix, classLabels, numIter=150):

    m,n = shape(dataMatrix)

    weights = ones(n)

    for j in range(numIter):

        dataIndex = list(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 * float64(dataMatrix[randIndex])

            del(dataIndex[randIndex])

    return weights

4.4.資料預測

def classifyVector(inX, weights):

    prob = sigmoid(sum(inX*weights))

    if prob > 0.5: return 1.0

    else: return 0.0

4.5.單次資料測試

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("the error rate of this test is: %f" % errorRate)

    return errorRate

4.6.統計求正確率

def multiTest():

    numTests = 10; errorSum=0.0

    for k in range(numTests):

        errorSum += colicTest()

    print("after %d iterations the average error rate is: %f" % (numTests, errorSum/float(numTests)))

5. 測試方法及結果

首先,針對一資料集進行演算法測試,得到分類效果:

 

圖一 梯度上升法得到的劃分

  

圖二 隨機梯度上升得到的劃分

可以看出,隨梯度上升得到的劃分與直接計算得到的劃分結果基本相同,但隨機梯度上升計算量更小。

對病馬資料集進行訓練測試,使用隨機梯度上升法做10次預測並統計平均正確率:

 

增加迭代次數得到結果:

 

6. 總結

Logistic迴歸是根據現有的資料對分類邊界線建立迴歸公式,並以此分類。其在最佳迴歸引數尋求中使用最優化的相關演算法並得出滿意結果。Logistic迴歸適用於數值型和標稱型資料,其計算代價不高,易於理解和實現,但容易出現欠擬合,分類精度可能不高。