機器學習 | Logistic迴歸

由於近期學業繁重QAQ,所以我就不說廢話了,直接上代碼~

Logistic迴歸進行分類

分類效果

圖片描述


Logistic迴歸預測病馬的死亡率

預測結果

圖片描述


全部代碼

from numpy import *
import matplotlib.pyplot as plt

#使用梯度上升法找到最佳參數
#使用梯度上升法找到最佳迴歸係數,
#也就是擬合Logistic迴歸模型的最佳參數
#Logistic歸回梯度上升優化算法
#加載文件
def loadDataSet():
    dataMat=[];labelMat=[]
    #打開文本文件
    fr=open('testSet.txt')
    #逐行讀取
    for line in fr.readlines():
        lineArr=line.strip().split()
        #爲了方便計算,將x0設爲1,後面的x1,x2是文本中每行的前兩個值
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
        #文本中每行的第三個值爲數據對應的標籤
        labelMat.append(int(lineArr[2]))
    return dataMat,labelMat
    
#sigmiod函數
def sigmoid(inX):
    return 1.0/(1+exp(-inX))
    
#梯度上升算法
#第一個參數是一個2維的Numpy數組
#每列表示不同的特徵
#每行表示每個訓練樣本
#我們採用100個樣本,包含兩個x1,x2特徵
#再加上第0維特徵x0,所以dataMatIn是一個100X3的矩陣
#第二個參數是類別標籤,是一個1X100的行向量
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循環結束之後,將返回訓練好的迴歸係數
    for k in range(maxCycles):
        #注:此處是矩陣相乘
        #h是一個列向量,元素的個數等於樣本的個數
        h=sigmoid(dataMatrix*weights)
        #真實類別與預測類別的差別
        error=(labelMat-h)
        #按照該差別的方向調整迴歸係數
        weights=weights+alpha*dataMatrix.transpose()*error
    #返回迴歸係數——確定了不同類別數據之間的分割線
    return weights
    
    
#畫出決策邊界
#畫出數據集和Logistic迴歸最佳擬合直線的函數    
#X1表示一個特徵,X2表示另一個特徵
def plotBestFit(weights):
    #得到數據集與標籤
    dataMat,labelMat=loadDataSet()
    dataArr = array(dataMat)
    n = shape(dataArr)[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])
        else:
            xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
    ax.scatter(xcord2, ycord2, s=30, c='green')
    x = arange(-3.0, 3.0, 0.1)
    #根據gradAscent得到的迴歸係數繪製分割線
    y = (-weights[0]-weights[1]*x)/weights[2]
    #print(x)
    #print(y)
    ax.plot(x, y)
    plt.xlabel('X1'); plt.ylabel('X2');
    plt.show()
    
    
#梯度上升方法在每次更新迴歸係數時都需要遍歷整個數據集
#改進方法:一次僅使用一個樣本點來更新迴歸係數——隨機梯度上升算法
#由於可以在新樣本到來時對分類器進行增量式更新,因此隨機梯度上升
#算法是一個在線學習算法
#與“在線學習”相對應,一次數裏所有數據被稱作“批處理”
#隨機梯度上升算法
def stocGradAscent0(dataMatrix,classLabels):
    #得到矩陣的大小
    m,n=shape(dataMatrix)
    #向目標移動的步長
    alpha=0.01
    weights=ones(n)
    for i in range(m):
        #h爲向量
        h=sigmoid(sum(dataMatrix[i]*weights))
        #error爲向量
        error=classLabels[i]-h
        weights=weights+alpha*error*dataMatrix[i]
    return weights
        
    
#由於經過測試,多次迭代後,X0,X1收斂速度較小
#且存在一些小的週期性的波動,因此及逆行改進
#改進隨機梯度上升算法
#第三個參數爲迭代次數
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):
            #改進1:alpha[向目標移動的步長]會隨着迭代的次數不斷減小
            #可以緩解數據波動或高頻波動,
            alpha=4/(1.0+j+i)+0.01
            #通過隨機選取樣本來更新迴歸係數
            #可以減少週期性的波動
            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
    
    
#Logistic迴歸預測病馬的死亡率
#對於缺失數據,我們選擇用0來替換
#因爲這樣不會影響係數weights的值
#對於標籤已經丟失的,我們將這條數據丟棄
#使用Logistic迴歸進行分類的主要思路:
#把測試集上每個特徵向量乘最優方法得到的迴歸係數
#再將該乘積結果求和,最後輸入Sigmoid函數中即可,
#若對應的sigmoid值>0.5預測類別標籤爲1,否則爲0
#Logistic迴歸分類函數
def classifyVector(inX,weights):
    #以迴歸係數和特徵向量作爲輸入來計算對應的Sigmoid值
    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,500)
    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

#調用colicTest函數10次,並且結果的平均值    
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)))

    
def main():
    #dataArr,labelMat=loadDataSet()
    #weights=gradAscent(dataArr,labelMat)
    #print(weights)
    #plotBestFit(weights.getA())
    #weights=stocGradAscent0(array(dataArr),labelMat)
    #weights=stocGradAscent1(array(dataArr),labelMat)
    #plotBestFit(weights)
    multiTest()
    
if __name__=='__main__':
    main()
    
    
    
    
    
    
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章