1. 程式人生 > >《機器學習實戰》Logistic迴歸python3原始碼

《機器學習實戰》Logistic迴歸python3原始碼

邏輯迴歸:

1 梯度上升優化演算法     2 隨機梯度上升演算法      3 改進的隨機梯度上升法

開啟pycharm建立一個logRegression.py檔案,輸入如下程式碼:

#coding:utf-8
from numpy import *

"""下載資料集,返回dataMat和labelMat,都是list型別"""
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])]) #將x0設為1.0
        labelMat.append(float(lineArr[2]))
    # print("shape(labelMat):",shape(labelMat))
    # print("type(dataMat", type(dataMat))
    # print("shape(dataMat",shape(dataMat))
    return dataMat,labelMat

"""sigmod 函式的定義"""
def sigmod(inX):
    return 1.0/(1+exp(-inX))



"""----------------Logistic迴歸梯度上升優化演算法-----------------"""
"""
梯度上升法的虛擬碼:
每個迴歸係數初始化為1
重複R次:
    計算整個資料集的梯度
    使用alpha*gradient更新迴歸係數的向量
    返回迴歸係數
"""
def gradAscent(dataMatIn,classLabels): #dataMatIn,classLabels都是list型別
    dataMatrix=mat(dataMatIn)  #dataMatrix是矩陣型別
    #labelMat=mat(classLabels).T
    labelMat = mat(classLabels).transpose()  #和上面一條語句含義相同,對行進行轉置,labelMat是m*1的列向量
    m,n=shape(dataMatrix) #求出dataMatrix的行(樣本數)和列(特徵數)
    alpha=0.001  #向目標移動的步長
    maxCycles=500  #迭代的次數
    weights=ones((n,1))  #建立一個n行1列全為1的陣列,即初始化迴歸係數全為1
    for k in range(maxCycles):
        h=sigmod(dataMatrix*weights)  #這個步驟包含了m*n次乘積。h是sigmod返回的結果,即預測值,h為m*1的列向量
        error=(labelMat-h)  #真實值與預測值之差
        weights=weights+alpha*dataMatrix.transpose()*error
    return weights




"""----------畫出資料集和Logistic迴歸最佳擬合直線的函式(輸入wei為矩陣)------"""
def plotBestFit(wei):  # wei是一個矩陣
    import matplotlib.pyplot as plt
    weights=wei.getA()  #矩陣.getA()是把矩陣變成陣列array型別
    dataMat,labelMat=loadDataSet()  #下載資料集,dataMat,labelMat都是list型別
    dataArr=array(dataMat)  #轉換成array型別,方便後面陣列訪問 dataArr[i,j]
    n=shape(dataArr)[0]  #dataArr資料集的行數,即樣本的個數
    xcord1=[];ycord1=[] #定義兩個空陣列,用來存放不同label的x1和x2值
    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='r',marker='s')
    ax.scatter(xcord2,ycord2,s=30,c='g')
    #畫出最佳擬合直線
    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("X2")
    plt.show()



"""----------畫出資料集和Logistic迴歸最佳擬合直線的函式(輸入weights為陣列)------"""
def plotBestFit2(weights):  # weights是numpy的array陣列
    import matplotlib.pyplot as plt
    dataMat, labelMat = loadDataSet()  # 下載資料集,dataMat,labelMat都是list型別
    dataArr = array(dataMat)  # 轉換成array型別,方便後面陣列訪問 dataArr[i,j]
    n = shape(dataArr)[0]  # dataArr資料集的行數,即樣本的個數
    xcord1 = [];ycord1 = []  # 定義兩個空陣列,用來存放不同label的x1和x2值
    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='r', marker='s')
    ax.scatter(xcord2, ycord2, s=30, c='g')
    # 畫出最佳擬合直線
    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("X2")
    plt.show()


"""-----------------------------隨機梯度上升演算法------------------------"""
"""
虛擬碼:
所有迴歸係數初始化為1
對資料集中每個樣本
        計算該樣本的梯度
        使用alpha*gradient更新迴歸係數值
返回迴歸係數值
"""
def stocGradAscent0(dataMatIn,classlabels):
    dataMatrix=array(dataMatIn)
    m,n=shape(dataMatrix)
    alpha=0.01
    weights=ones(n)  #建立n行1列全為1的陣列
    for i in range(m):
        h=sigmod(sum(dataMatrix[i]*weights))#兩個一維陣列對應元素相乘返回一個一維陣列再求和作為sigmod的輸入
        error=classlabels[i]-h
        #h,error都是數值
        weights=weights+alpha*error*dataMatrix[i]
    return weights



"""--------------------------改進的隨機梯度上升法-----------------------"""
def stocGradAscent1(dataMatIn,classlabels,numIter=150):
    dataMatrix = array(dataMatIn)
    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.01 #alpha每次迭代時需要調整
            randIndex=int(random.uniform(0,len(dataIndex)))# 隨機選取更新
            # uniform() 方法將隨機生成下一個實數,它在[0,len(dataIndex)]範圍內。
            h=sigmod(sum(dataMatrix[randIndex]*weights))
            error=classlabels[randIndex]-h #計算誤差
            weights=weights+alpha*error*dataMatrix[randIndex] #更新迴歸係數
            #del(dataMatrix[randIndex])   #刪除已使用的樣本
    return weights

重新建立一個python檔案,用於呼叫logRegression.py檔案,對各個演算法進行驗證並畫出擬合曲線。

#couding:utf-8

from numpy import *
import matplotlib.pyplot as plt
import logRegress
dataAtrr,labelMat=logRegress.loadDataSet()

"""----------------Logistic迴歸梯度上升優化演算法-----驗證----------------"""
wei=logRegress.gradAscent(dataAtrr,labelMat)  #wei是一個矩陣
logRegress.plotBestFit(wei)

"""-----------------隨機梯度上升演算法---驗證---------------------"""
w=logRegress.stocGradAscent0(dataAtrr,labelMat) #w是1*3陣列
logRegress.plotBestFit2(w)

"""---------------改進的隨機梯度上升法---驗證--------------------"""
w1=logRegress.stocGradAscent1(dataAtrr,labelMat,500) #w是1*3陣列
logRegress.plotBestFit2(w1)