用數據練習邏輯迴歸

邏輯迴歸也被稱爲廣義線性迴歸模型,它與線性迴歸模型的形式基本相同,最大的區別是它們的因變量不同,如果是連續的,就是多重線性迴歸,如果是二項分佈,就是 Logistic迴歸。

Logistic迴歸雖然名字裏帶“迴歸”,但它實際上是一種分類方法,主要用於二分類問題。邏輯迴歸就是這樣的一個過程:面對一個迴歸或者分類問題,建立相應的函數,然後通過優化方法迭代求解出最優的模型參數,然後測試驗證這個求解的模型的好壞。

它的優點有:

速度快,適合二分類問題;

簡單、易於理解,可以直接看到各個特徵的權重;

能容易地更新模型吸收新的數據。

它的缺點有:

對數據和場景的適應能力有侷限性,不如決策樹算法適應性強。

常規步驟:尋找預測函數,構造損失函數(J),使損失函數J最小並求得迴歸係數(\Theta

構造預測函數

二分類問題與自變量之間的關係圖形是往往是一個S型曲線。例:採用 sigmoid函數實現:

g(z) = 1/1+e^{-z}

對於線性邊界的形式如下:

\small z = \Theta ^{T}x =\Theta _{0 }x_{0} +\Theta _{1}x_{1}+...+\Theta _{k}x_{k} =\sum_{i=0}^{n}\Theta _{i}x_{i}

最佳參數:

\small \Theta =[\Theta _{0},\Theta _{1},\Theta _{2}...\Theta _{n}]^{T}

構造預測函數:         

\small h_{x} = g(\Theta ^{Tx}) = \frac{1}{1 + e^{-\Theta _{Tx}}}

sigmoid函數的輸出是介於(0,1)之間的,之間值是0.5。因爲hθ(x)輸出是介於(0,1)之間,也就表明了數據屬於某一類別的概率。例如,hθ(x)<0.5則說明當前數據屬於A類;hθ(x)>0.5則說明當前數據屬於B類。所以可以將sigmoid函數看成樣本數據的概率密度函數。

構造損失函數

最大似然法是邏輯迴歸所採用的參數估計方法,其原理是找到這樣一個參數,可以讓樣本數據所包含的觀察值被觀察到的可能性最大。最大似然估計的優點是大樣本數據中的參數的估計穩定,偏差小,估計方差小。

採用概率論中的極大似然估計的方法求解損失函數:

首先得到概率函數:                 \small p(y|x;\Theta ) = (h_{\Theta }(x))^{y}(1-h_{\Theta}(x))^{1-y}

因爲樣本獨立,所以對它們的聯合分佈可以表示爲各個邊際的分佈的乘積,取似然函數:

                                      \small L(\Theta ) = \prod_{i =1}^{n}P(y_{i}|x_{i};\Theta ) = \prod_{i=1}^{n}(h_{\Theta}(x_{i}))^{y_{i}}(1-h_{\Theta }(x_{i}))^{1-y_{i}}

取對數似然函數:

                                       l(\Theta ) = log L(\Theta ) = \sum_{i=1}^{n}(y_{i}log h_{\Theta}(x_{i})+(1-y_{i})log(1-h_{\Theta}(x_{i})))

最大似然估計就是要事 l(θ)取得最大值時的 θ,這裏可以用梯度上升法求解,得到最佳參數:

                                                         J(\Theta) = -\frac{1}{n}l(\theta)

 

梯度下降法求解最小值

 

θ更新

\theta_{j} = \theta_{j} - \alpha \frac{\delta }{\delta _{\theta_{j}}}J(\theta)

θ的更新過程可以寫成爲:

                                         \theta_{j} = \theta_{j} - \alpha \frac{1}{m}\sum_{i=1}^{m}(h_{\theta}(x_{i})-y_{i})x_{i}^j

向量化:把訓練數據約定爲矩陣的形式,x的每一行就表示一條數據,每一列爲不同的特徵

正則化:過擬合就是過分擬合了訓練數據,使得模型的複雜度提高,泛化能力降低

下列 左圖爲欠擬合,中圖爲合社的擬合,右圖爲過擬合

     使用正則化可以解決過擬合的問題,正則化是結構風險最小化策略的實現,是在經驗風險上加一個正則化項或懲罰項。正則化項一般是模型複雜度的單調遞增函數,模型越複雜,正則化項就越大。

正則化可以採取不同的形式,在迴歸問題上取平方損失,就是參數的L2範數,也可以取L1範數。取平方損失,模型的損失函數爲:

                                                                  J(\theta)=\frac{1}{2m}\sum_{i=1}^{n}(h_{\theta}(x_{i})-y_{i})^{2} + \lambda \sum_{j=1}^{n}\theta_{j}^{2}

正則化後的梯度下降算法θ的更新變爲

                                                                

數據操作

from numpy import *
import pandas as pd
from pandas import DataFrame
filename='./data.txt' #文件目錄
def loadDataSet():   #讀取數據(這裏只有兩個特徵)
    df=pd.read_csv(filename)
    dataMat = []
    labelMat = []
    fr = open(filename)
    for line in fr.readlines():
        lineArr = line.strip().split()
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])  #前面的1,表示方程的常量。比如兩個特徵X1,X2,共需要三個參數,W1+W2*X1+W3*X2
        labelMat.append(int(lineArr[2]))
    return dataMat,labelMat
def sigmoid(inX):  #sigmoid函數
    return 1.0/(1+exp(-inX))
def GradAscent(dataMat, labelMat): #改進版隨機梯度上升,在每次迭代中隨機選擇樣本來更新權重,並且隨迭代次數增加,權重變化越小。
    dataMatrix=mat(dataMat)
    classLabels=labelMat
    m,n=shape(dataMatrix)
    weights=ones((n,1))
    maxCycles=500
    for j in range(maxCycles): #迭代
        dataIndex=[i for i in range(m)]
        for i in range(m): #隨機遍歷每一行
            alpha=4/(1+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].transpose()
            del(dataIndex[randIndex]) #去除已經抽取的樣本
    return weights

def plotBestFit(weights):  #畫出最終分類的圖
    import matplotlib.pyplot as plt
    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)
    y = (-weights[0]-weights[1]*x)/weights[2]
    ax.plot(x, y)
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.show()
    plt.savefig('logExample.png', format='png')
def main():
    datamat,labelmat=loadDataSet()
    weights= GradAscent(datamat, labelmat).getA()
    plotBestFit(weights)

if __name__=='__main__':
    main()

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章