一步步教你輕鬆學邏輯迴歸模型算法

一步步教你輕鬆學邏輯迴歸模型算法
( 白寧超2018年9月6日15: 01:20)

導讀:邏輯迴歸(Logistic regression)即邏輯模型,屬於常見的一種分類算法。本文將從理論介紹開始,搞清楚什麼是邏輯迴歸、迴歸係數、算法思想、工做原理及其優缺點等。進一步經過兩個實際案例深化理解邏輯迴歸,以及在工程應用進行實現。(本文原創,轉載必須註明出處: 一步步教你輕鬆學邏輯迴歸模型算法php

目錄

機器學習:一步步教你輕鬆學KNN模型算法

機器學習:一步步教你輕鬆學決策樹算法

機器學習:一步步教你輕鬆學樸素貝葉斯模型算法理論篇1 

機器學習:一步步教你輕鬆學樸素貝葉斯模型實現篇2 

機器學習:一步步教你輕鬆學樸素貝葉斯模型算法Sklearn深度篇3

機器學習:一步步教你輕鬆學邏輯迴歸模型算法

機器學習:一步步教你輕鬆學K-means聚類算法

機器學習:一步步教你輕鬆學關聯規則Apriori算法

機器學習: 一步步教你輕鬆學支持向量機SVM算法之理論篇1

10 機器學習: 一步步教你輕鬆學支持向量機SVM算法之案例篇2

11 機器學習: 一步步教你輕鬆學主成分分析PCA降維算法

12 機器學習: 一步步教你輕鬆學支持向量機SVM降維算法

更多文章請點擊這裏>>

理論介紹

邏輯迴歸和Sigmoid 函數

邏輯迴歸html

迴歸:假設如今有一些數據點,咱們用一條直線對這些點進行擬合(這條直線稱爲最佳擬合直線),這個擬合的過程就叫作迴歸。git

邏輯迴歸(Logistic Regression)是一種用於解決二分類(0 or 1)問題的機器學習方法,用於估計某種事物的可能性。好比某用戶購買某商品的可能性,某病人患有某種疾病的可能性,以及某廣告被用戶點擊的可能性等。 注意,這裏用的是「可能性」,而非數學上的「機率」,logisitc迴歸的結果並不是數學定義中的機率值,不能夠直接當作機率值來用。該結果每每用於和其餘特徵值加權求和,而非直接相乘。github

Sigmoid 函數算法

Sigmoid函數是一個常見的S型數學函數,在信息科學中,因爲其單增以及反函數單增等性質,Sigmoid函數常被用做神經網絡的閾值函數,將變量映射到0,1之間。在邏輯迴歸、人工神經網絡中有着普遍的應用。Sigmoid函數的數學形式是:apache

對x求導能夠推出以下結論:數組

下圖給出了 Sigmoid 函數在不一樣座標尺度下的兩條曲線圖。當 x 爲 0 時,Sigmoid 函數值爲 0.5 。隨着 x 的增大,對應的 Sigmoid 值將逼近於 1 ; 而隨着 x 的減少, Sigmoid 值將逼近於 0 。若是橫座標刻度足夠大, Sigmoid 函數看起來很像一個階躍函數。網絡


所以,爲了實現 Logistic 迴歸分類器,咱們能夠在每一個特徵上都乘以一個迴歸係數,而後把全部結果值相加,將這個總和代入 Sigmoid 函數中,進而獲得一個範圍在 0~1 之間的數值。任何大於 0.5 的數據被分入 1 類,小於 0.5 即被納入 0 類。因此,Logistic 迴歸也是一種機率估計,好比這裏Sigmoid 函數得出的值爲0.5,能夠理解爲給定數據和參數,數據被分入 1 類的機率爲0.5。(注意:針對二分類問題,0.5不是惟一肯定分類的值,你能夠根據需求調整這個機率值。)app

邏輯迴歸與線性迴歸的關係dom

邏輯迴歸(Logistic Regression)與線性迴歸(Linear Regression)都是一種廣義線性模型(generalized linear model)。邏輯迴歸假設因變量 y 服從伯努利分佈,而線性迴歸假設因變量 y 服從高斯分佈。 所以與線性迴歸有不少相同之處,去除Sigmoid映射函數的話,邏輯迴歸算法就是一個線性迴歸。能夠說,邏輯迴歸是以線性迴歸爲理論支持的,可是邏輯迴歸經過Sigmoid函數引入了非線性因素,所以能夠輕鬆處理0/1分類問題。

最優化方法的迴歸係數

Sigmoid 函數的輸入記爲 z ,由下面公式獲得:

若是採用向量的寫法,上述公式能夠寫成 Sigmoid 函數計算公式向量形式 ,它表示將這兩個數值向量對應元素相乘而後所有加起來即獲得 z 值。其中的向量 x 是分類器的輸入數據,向量 w 也就是咱們要找到的最佳參數(係數),從而使得分類器儘量地精確。爲了尋找該最佳參數,須要用到最優化理論的一些知識。咱們這裏使用的是——梯度上升法(Gradient Ascent)。

梯度上升與梯度降低

梯度

對於梯度這個詞一些人比較陌生,咱們先看看維基百科的解釋:在向量微積分中,標量場(向量場)中某一點的梯度指向在這點標量場增加最快的方向(固然要比較的話必須固定方向的長度),梯度的絕對值是長度爲1的方向中函數最大的增長率,也就是說,其中 表明方向導數。

  • 在單變量的實值函數的狀況,梯度只是導數,或者,對於一個線性函數,也就是線的斜率。
  • 梯度一詞有時用於斜度,也就是一個曲面沿着給定方向的傾斜程度。能夠經過取向量梯度和所研究的方向的內積來獲得斜度。梯度的數值有時也被稱爲梯度。(更多梯度相關知識參照維基百科詞條

梯度形式化描述

考慮一座高度在 (x, y)點是 H(x, y)的山。H這一點的梯度是在該點坡度(或者說斜度)最陡的方向。梯度的大小告訴咱們坡度到底有多陡。這個現象能夠以下數學的表示。山的高度函數 H的梯度點積一個單位向量給出了表面在該向量的方向上的斜率。這稱爲方向導數。

理解梯度

爲了你們更容易理解什麼是梯度,咱們介意向量的概念,向量是一個矢量具備大小和方向的。一樣,梯度也能夠類比爲具有大小和方向的這麼一個概念。其二者比較以下:(這裏嚴格意義上講是不成立的,便於你們理解。)

向量 = 值 + 方向  
梯度 = 向量
梯度 = 梯度值 + 梯度方向

梯度上升

要找到某函數的最大值,最好的方法是沿着該函數的梯度方向探尋。若是梯度記爲 ▽ ,則函數 f(x, y) 的梯度由下式表示:

這個梯度意味着要沿 x 的方向移動 ,沿 y 的方向移動。其中,函數f(x, y) 必需要在待計算的點上有定義而且可微。下圖是一個具體的例子。


上圖展現的,梯度上升算法到達每一個點後都會從新估計移動的方向。從 P0 開始,計算完該點的梯度,函數就根據梯度移動到下一點 P1。在 P1 點,梯度再次被從新計算,並沿着新的梯度方向移動到 P2 。如此循環迭代,直到知足中止條件。迭代過程當中,梯度算子老是保證咱們能選取到最佳的移動方向。

上圖中的梯度上升算法沿梯度方向移動了一步。能夠看到,梯度算子老是指向函數值增加最快的方向。這裏所說的是移動方向,而未提到移動量的大小。該量值稱爲步長,記做 α 。用向量來表示的話,梯度上升算法的迭代公式以下:

例如:y = w0 + w1x1 + w2x2 + ... + wnxn
梯度:參考上圖的例子,二維圖像,x方向表明第一個係數,也就是 w1,y方向表明第二個係數也就是 w2,這樣的向量就是梯度。
α:上面的梯度算法的迭代公式中的阿爾法,這個表明的是移動步長(step length)。移動步長會影響最終結果的擬合程度,最好的方法就是隨着迭代次數更改移動步長。步長通俗的理解,100米,若是我一步走10米,我須要走10步;若是一步走20米,我只須要走5步。這裏的一步走多少米就是步長的意思。
▽f(w):表明沿着梯度變化的方向,也能夠理解該方向求導。

該公式將一直被迭代執行,直至達到某個中止條件爲止,好比迭代次數達到某個指定值或者算法達到某個能夠容許的偏差範圍。

梯度上升與梯度降低的區別

梯度降低是你們聽的最多的,本質上梯度降低與梯度上升算法是同樣的,只是公司中加法變減法,梯度降低的公式以下:

在求極值的問題中,有梯度上升和梯度降低兩個最優化方法。梯度上升用於求最大值,梯度降低用於求最小值。如logistic迴歸的目標函數:表明的是機率,咱們想求機率最大值,即對數似然函數的最大值,因此使用梯度上升算法。而線性迴歸的代價函數:表明的則是偏差,咱們想求偏差最小值,因此用梯度降低算法。

邏輯迴歸分類核心思想

根據現有數據對分類邊界創建迴歸公司,以此進行分類。迴歸即最佳擬合。

邏輯迴歸工做原理

每一個迴歸係數初始化爲 1
重複 R 次:
    計算整個數據集的梯度
    使用 步長 x 梯度 更新迴歸係數的向量
返回迴歸係數

邏輯迴歸算法流程

收集數據: 採用任意方法收集數據
準備數據: 因爲須要進行距離計算,所以要求數據類型爲數值型。另外,結構化數據格式則最佳。
分析數據: 採用任意方法對數據進行分析。
訓練算法: 大部分時間將用於訓練,訓練的目的是爲了找到最佳的分類迴歸係數。
測試算法: 一旦訓練步驟完成,分類將會很快。
使用算法: 首先,咱們須要輸入一些數據,並將其轉換成對應的結構化數值;接着,基於訓練好的迴歸係數就能夠對這些數值進行簡單的迴歸計算,斷定它們屬於哪一個類別;

邏輯迴歸優缺點

優勢: 計算代價不高,易於理解和實現。
缺點: 容易欠擬合,分類精度可能不高。
適用數據類型: 數值型和標稱型數據。

案例分析1:Logistic迴歸在簡單數據集上的分類

案例描述

在一個簡單的數據集上,採用梯度上升法找到 Logistic 迴歸分類器在此數據集上的最佳迴歸係數

開發流程

收集數據: 可使用任何方法
準備數據: 因爲須要進行距離計算,所以要求數據類型爲數值型。另外,結構化數據格式則最佳
分析數據: 畫出決策邊界
訓練算法: 使用梯度上升找到最佳參數
測試算法: 使用 Logistic 迴歸進行分類
使用算法: 對簡單數據集中數據進行分類

數據採集

本文采用100行的測試集文本。其中前兩列是特徵1,和特徵2,第三類是對應的標籤。(這裏特徵1,特徵2做爲測試使用沒有實際意義,你能夠理解爲特徵1 是水裏遊的,特徵2是有魚鱗。類別判斷是否爲魚類。)


讀取文本文件,加載數據集和類標籤,這裏將特徵集第一列加1,便於後續迴歸係數的計算:

'''加載數據集和類標籤'''
def loadDataSet(file_name):
    # dataMat爲原始數據, labelMat爲原始數據的標籤
    dataMat,labelMat = [],[]
    fr = open(file_name)
    for line in fr.readlines():
        lineArr = line.strip().split(',')
        if len(lineArr) == 1:
            continue    # 這裏若是就一個空的元素,則跳過本次循環
        # 爲了方便計算,咱們將每一行的開頭添加一個 1.0 做爲 X0
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
        labelMat.append(int(lineArr[2]))
    return dataMat, labelMat

梯度上升訓練算法模型

梯度上升算法

使用梯度上升訓練算法模型,其代碼實現以下:

''' 正常的梯度上升法,獲得的最佳迴歸係數 '''
def gradAscent(dataMatIn, classLabels):
    dataMatrix = mat(dataMatIn)  # 轉換爲 NumPy 矩陣
    # 轉化爲矩陣[[0,1,0,1,0,1.....]],並轉制[[0],[1],[0].....]
    # transpose() 行列轉置函數
    # 將行向量轉化爲列向量   =>  矩陣的轉置
    labelMat = mat(classLabels).transpose()  # 首先將數組轉換爲 NumPy 矩陣,而後再將行向量轉置爲列向量
    # m->數據量,樣本數 n->特徵數
    m, n = shape(dataMatrix) # 矩陣的行數和列數
    # print(m,n)
    alpha = 0.001  # alpha表明向目標移動的步長
    maxCycles = 500 # 迭代次數
    weights = ones((n, 1)) # 表明迴歸係數,ones((n,1)) 長度和特徵數相同矩陣全是1
    for k in range(maxCycles):
        h = sigmoid(dataMatrix * weights)  # 矩陣乘法
        # labelMat是實際值
        error = (labelMat - h)  # 向量相減
        # 0.001* (3*m)*(m*1) 表示在每個列上的一個偏差狀況,最後得出 x1,x2,xn的係數的偏移量
        weights = weights + alpha * dataMatrix.transpose() * error  # 矩陣乘法,最後獲得迴歸係數
    return array(weights)

其中sigmoid函數實現以下:

''' sigmoid跳躍函數 '''
def sigmoid(ZVar):
    return 1.0 / (1 + exp(-ZVar))

代碼分析:函數的兩個參數是數據加載返回的特徵集和標籤類集合。對數據集進行mat矩陣話轉化,而類標籤集進行矩陣以後轉置,便於行列式的計算。而後設定步長,和迭代次數。整個特徵矩陣與迴歸係數乘積求sigmoid值,最後返回迴歸係數的值。運行結果以下:

[[ 4.12414349]
 [ 0.48007329]
 [-0.6168482 ]]

思考?步長和迭代次數的初始值如何設定?

隨機梯度上升算法

梯度上升算法在每次更新迴歸係數時都須要遍歷整個數據集,該方法在處理 100 個左右的數據集時尚可,但若是有數十億樣本和成千上萬的特徵,那麼該方法的計算複雜度就過高了。一種改進方法是一次僅用一個樣本點來更新迴歸係數,該方法稱爲 隨機梯度上升算法。因爲能夠在新樣本到來時對分類器進行增量式更新,於是隨機梯度上升算法是一個在線學習(online learning)算法。與 「在線學習」 相對應,一次處理全部數據被稱做是 「批處理」 (batch) 。其僞代碼是:

全部迴歸係數初始化爲 1
對數據集中每一個樣本
    計算該樣本的梯度
    使用 alpha x gradient 更新迴歸係數值
返回迴歸係數值

隨機梯度上升算法的代碼實現以下:

''' 隨機梯度上升'''
# 梯度上升與隨機梯度上升的區別?梯度降低在每次更新數據集時都須要遍歷整個數據集,計算複雜都較高;隨機梯度降低一次只用一個樣本點來更新迴歸係數
def stocGradAscent0(dataMatrix, classLabels):
    m, n = shape(dataMatrix)
    alpha = 0.01
    weights = ones(n)  # 初始化長度爲n的數組,元素所有爲 1
    for i in range(m):
        # sum(dataMatrix[i]*weights)爲了求 f(x)的值,f(x)=a1*x1+b2*x2+..+nn*xn
        h = sigmoid(sum(dataMatrix[i] * weights))
        # 計算真實類別與預測類別之間的差值,而後按照該差值調整迴歸係數
        error = classLabels[i] - h
        # 0.01*(1*1)*(1*n)
        weights = array(weights) + alpha * error * array(mat(dataMatrix[i]))
    return array(weights.transpose())

能夠看到,隨機梯度上升算法與梯度上升算法在代碼上很類似,但也有一些區別: 第一,後者的變量 h 和偏差 error 都是向量,而前者則全是數值;第二,前者沒有矩陣的轉換過程,全部變量的數據類型都是 NumPy 數組。

判斷優化算法優劣的可靠方法是看它是否收斂,也就是說參數是否達到了穩定值,是否還會不斷地變化?下圖展現了隨機梯度上升算法在 200 次迭代過程當中迴歸係數的變化狀況。其中的係數2,也就是 X2 只通過了 50 次迭代就達到了穩定值,但係數 1 和 0 則須要更屢次的迭代。以下圖所示:


針對波動問題,咱們改進了以前的隨機梯度上升算法,具體代碼實現以下:

''' 改進版的隨機梯度上升,使用隨機的一個樣原本更新迴歸係數'''
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
    m, n = shape(dataMatrix)
    weights = ones(n)  # 建立與列數相同的矩陣的係數矩陣
    # 隨機梯度, 循環150,觀察是否收斂
    for j in range(numIter):
        dataIndex = list(range(m)) # [0, 1, 2 .. m-1]
        for i in range(m):
            # i和j的不斷增大,致使alpha的值不斷減小,可是不爲0
            alpha = 4 / (1.0 + j + i) + 0.0001 # alpha隨着迭代不斷減少非0
            # random.uniform(x, y) 隨機生成下一個實數,它在[x,y]範圍內
            Index = int(random.uniform(0, len(dataIndex)))
            # sum(dataMatrix[i]*weights)爲了求 f(x)的值, f(x)=a1*x1+b2*x2+..+nn*xn
            h = sigmoid(sum(dataMatrix[dataIndex[Index]] * weights))
            error = classLabels[dataIndex[Index]] - h
            weights = weights + alpha * error *array(mat(dataMatrix[dataIndex[Index]]))
            del (dataIndex[Index])
    # print(weights.transpose())
    return weights.transpose()

上面的改進版隨機梯度上升算法改了兩處代碼。

  • 改進爲 alpha 的值。alpha 在每次迭代的時候都會調整,這回緩解上面波動圖的數據波動或者高頻波動。另外,雖然 alpha 會隨着迭代次數不斷減小,但永遠不會減少到 0,由於咱們在計算公式中添加了一個常數項。
  • 修改成 randIndex 更新,這裏經過隨機選取樣本拉來更新迴歸係數。這種方法將減小週期性的波動。這種方法每次隨機從列表中選出一個值,而後從列表中刪掉該值(再進行下一次迭代)。

分析數據:畫出決策邊界

邊界可視化的代碼實現以下:

''' 數據可視化展現 '''
def plotBestFit(dataArr, labelMat, weights):
    n = shape(dataArr)[0]
    xcord1,xcord2,ycord1,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)
    """
    dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
    w0*x0+w1*x1+w2*x2=f(x)
    x0最開始就設置爲1, x2就是咱們畫圖的y值,而f(x)被咱們磨合偏差給算到w0,w1,w2身上去了
    因此: w0+w1*x+w2*y=0 => y = (-w0-w1*x)/w2
    """
    y = (-weights[0] - weights[1] * x) / weights[2]
    ax.plot(x, y)
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.show()

運行結果分別是:

梯度上升算法可視化結果圖1-1:





圖1-1 梯度上升算法分類

隨機梯度上升算法可視化結果:


圖1-2 隨機梯度上升算法分類

優化隨機梯度上升算法可視化結果:


圖1-3 優化隨機梯度上升算法分類

結果分析:

圖1-1的梯度上升算法在每次更新迴歸係數時都須要遍歷整個數據集,雖然分類結果還不錯該方法的計算複雜度就過高了。圖1-2的隨機梯度上升算法雖然分類效果不是很好(分類1/3左右),可是其迭代次數遠遠小於圖1-1迭代次數(500次)。總體性能有所改進,可是其存在局部波動現象。基於此改進後的圖1-3效果顯示好不少。

測試算法: 使用Logistic迴歸進行分類

代碼實現以下:

'''數據集決策可視化'''
def simpleTest(file_name):
    # 1.收集並準備數據
    dataMat, labelMat = loadDataSet(file_name)
    # 2.訓練模型,  f(x)=a1*x1+b2*x2+..+nn*xn中 (a1,b2, .., nn).T的矩陣值
    dataArr = array(dataMat)
    weights = stocGradAscent1(dataArr, labelMat)
    # 數據可視化
    plotBestFit(dataArr, labelMat, weights)

案例分析2:從病毒性流感預測病人的死亡狀況

案例描述

使用 Logistic 迴歸來預測病毒性流感預測病人的死亡問題。這個數據集中包含了醫院檢測病毒性流感的一些指標,有的指標比較主觀,有的指標難以測量,例如人的疼痛級別。

開發流程
收集數據: 給定數據文件
準備數據: 用 Python 解析文本文件並填充缺失值
分析數據: 可視化並觀察數據
訓練算法: 使用優化算法,找到最佳的係數
測試算法: 爲了量化迴歸的效果,須要觀察錯誤率。根據錯誤率決定是否回退到訓練階段,
經過改變迭代的次數和步長的參數來獲得更好的迴歸係數
使用算法: 實現一個簡單的命令行程序來收集馬的症狀並輸出預測結果並不是難事,
這能夠做爲留給你們的一道習題

收集數據: 給定數據文件

訓練數據已經給出,這裏對文件處理便可,代碼以下:

'''加載數據集和類標籤2'''
def loadDataSet2(file_name):
    frTrain = open(file_name)
    trainingSet,trainingLabels = [],[]
    for line in frTrain.readlines():
        currLine = line.strip().split(',')
        # print(len(currLine))
        lineArr = []
        for i in range(len(currLine)-1):
            lineArr.append(float(currLine[i]))
        trainingSet.append(lineArr)
        trainingLabels.append(float(currLine[len(currLine)-1]))
    return trainingSet,trainingLabels

準備數據: 用 Python 解析文本文件並填充缺失值

處理數據中的缺失值

假設有100個樣本和20個特徵,這些數據都是機器收集回來的。若機器上的某個傳感器損壞致使一個特徵無效時該怎麼辦?此時是否要扔掉整個數據?這種狀況下,另外19個特徵怎麼辦? 它們是否還能夠用?答案是確定的。由於有時候數據至關昂貴,扔掉和從新獲取都是不可取的,因此必須採用一些方法來解決這個問題。下面給出了一些可選的作法:

  • 使用可用特徵的均值來填補缺失值;
  • 使用特殊值來填補缺失值,如 -1;
  • 忽略有缺失值的樣本;
  • 使用有類似樣本的均值添補缺失值;
  • 使用另外的機器學習算法預測缺失值。

如今,咱們對下一節要用的數據集進行預處理,使其能夠順利地使用分類算法。在預處理須要作兩件事:全部的缺失值必須用一個實數值來替換,由於咱們使用的 NumPy 數據類型不容許包含缺失值。咱們這裏選擇實數 0 來替換全部缺失值,剛好能適用於 Logistic 迴歸。這樣作的直覺在於,咱們須要的是一個在更新時不會影響係數的值。迴歸係數的更新公式以下:
weights = weights + alpha * error * dataMatrix[dataIndex[randIndex]]
若是 dataMatrix 的某個特徵對應值爲 0,那麼該特徵的係數將不作更新,即:weights = weights
另外,因爲 Sigmoid(0) = 0.5 ,即它對結果的預測不具備任何傾向性,所以咱們上述作法也不會對偏差形成任何影響。基於上述緣由,將缺失值用 0 代替既能夠保留現有數據,也不須要對優化算法進行修改。此外,該數據集中的特徵取值通常不爲 0,所以在某種意義上說它也知足 「特殊值」 這個要求。
若是在測試數據集中發現了一條數據的類別標籤已經缺失,那麼咱們的簡單作法是將該條數據丟棄。這是由於類別標籤與特徵不一樣,很難肯定採用某個合適的值來替換。採用 Logistic 迴歸進行分類時這種作法是合理的,而若是採用相似 kNN 的方法,則保留該條數據顯得更加合理。

訓練算法: 使用優化算法,找到最佳的係數

訓練算法模型代碼以下:

'''測試Logistic算法分類'''
def testClassier():
    # 使用改進後的隨機梯度上升算法 求得在此數據集上的最佳迴歸係數 trainWeights
    file_name = './HorseColicTraining.txt'
    trainingSet,trainingLabels = loadDataSet2(file_name)
    trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 500)
    # 根據特徵向量預測結果
    teststr = '2.000000,1.000000,38.300000,40.000000,24.000000,1.000000,1.000000,3.000000,1.000000,3.000000,3.000000,1.000000,0.000000,0.000000,0.000000,1.000000,1.000000,33.000000,6.700000,0.000000,0.000000'
    currLine = teststr.strip().split(',')
    lineArr = []
    for i in range(len(currLine)):
        lineArr.append(float(currLine[i]))
    res = classifyVector(array(lineArr), trainWeights)
    # 打印預測結果
    reslut = ['死亡','存活']
    print('預測結果是:',int(res))

分類函數代碼以下:

'''分類函數,根據迴歸係數和特徵向量來計算 Sigmoid的值,大於0.5函數返回1,不然返回0'''
def classifyVector(featuresV, weights):
    prob = sigmoid(sum(featuresV * weights))
    print(prob)
    if prob > 0.9: return 1.0
    else: return 0.0

測試算法:使用決策樹執行分類

爲了量化迴歸的效果,須要觀察錯誤率。根據錯誤率決定是否回退到訓練階段,經過改變迭代的次數和步長的參數來獲得更好的迴歸係數

'''打開測試集和訓練集,並對數據進行格式化處理'''
def colicTest():
    file_name = './HorseColicTraining.txt'
    trainingSet,trainingLabels = loadDataSet2(file_name)
    # 使用改進後的隨機梯度上升算法 求得在此數據集上的最佳迴歸係數 trainWeights
    trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 500)
    frTest = open('./HorseColicTest.txt')
    errorCount = 0 ; numTestVec = 0.0
    # 讀取 測試數據集 進行測試,計算分類錯誤的樣本條數和最終的錯誤率
    for line in frTest.readlines():
        numTestVec += 1.0
        currLine = line.strip().split(',')
        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("邏輯迴歸算法測試集的錯誤率爲: %f" % errorRate)
    return errorRate


# 調用 colicTest() 10次並求結果的平均值
def multiTest():
    numTests = 10;errorSum = 0.0
    for k in range(numTests):
        errorSum += colicTest()
    print("迭代 %d 次後的平均錯誤率是: %f" % (numTests, errorSum / float(numTests)))

其運行結果以下:

邏輯迴歸算法測試集的錯誤率爲: 0.298507

參考文獻

  1. scikit中文社區:http://sklearn.apachecn.org/cn/0.19.0/
  2. 中文維基百科:https://zh.wikipedia.org/wiki/%E9%82%8F%E8%BC%AF%E8%BF%B4%E6%AD%B8
  3. GitHub:https://github.com/BaiNingchao/MachineLearning-1
  4. 圖書:《機器學習實戰》
  5. 圖書:《天然語言處理理論與實戰》

完整代碼下載

源碼請進【機器學習和天然語言QQ羣:436303759】文件下載:


做者聲明

本文版權歸做者全部,旨在技術交流使用。未經做者贊成禁止轉載,轉載後需在文章頁面明顯位置給出原文鏈接,不然相關責任自行承擔。

相關文章
相關標籤/搜索