機器學習筆記(七)——初識邏輯迴歸、兩種方法推導梯度公式

1、算法概述

邏輯迴歸(Logistic)雖帶有迴歸二字,但它倒是一個經典的二分類算法,它適合處理一些二分類任務,例如疾病檢測、垃圾郵件檢測、用戶點擊率以及上文所涉及的正負情感分析等等。python

首先了解一下何爲迴歸?假設如今有一些數據點,咱們利用一條直線對這些點進行擬合(該線稱爲最佳擬合直線),這個擬合的過程就稱做迴歸。利用邏輯迴歸進行分類的主要思想是:根據現有數據對分類邊界線創建迴歸公式,以此進行分類。算法

線性迴歸算法後面的筆記會介紹,這裏簡單對比一下二者,邏輯迴歸和線性迴歸的本質相同,都意在擬合一條直線,但線性迴歸的目的是擬合輸入變量的分佈,儘量讓全部樣本到該條直線的距離最短;而邏輯迴歸的目的是擬合決策邊界,使數據集中不一樣的樣本儘量分開,因此兩個算法的目的是不一樣的,處理的問題也不一樣。數組

2、Sigmoid函數與相關推導

咱們想要的函數應該是,能接受全部的輸入而且預測出類別,好比二分類中的0或者一、正或者負,這種性質的函數被稱爲海維賽德階躍函數,圖像以下:app

在這裏插入圖片描述

但這種函數的問題在於從0跳躍到1的過程很是難處理,好比咱們常接觸的屢次函數,可能在某種條件下須要求導解決問題;而Sigmoid函數也具備相似的性質,而且在數學上更容易處理,其公式以下:函數

在這裏插入圖片描述

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

在這裏插入圖片描述

若咱們將Sigmoid函數的輸入記做z,可推出下面公式:spa

在這裏插入圖片描述

它表示將這兩個數值向量對應元素相乘而後所有相加起來獲得z值,其中向量x是分類器的輸入數據,向量w就是咱們要找到的能使分類器儘量準確的最佳參數。3d

由上述公式就可得:code

在這裏插入圖片描述

其中$h_w(x)$的做用就是給定輸入時,輸出分類爲正向類(1)的可能性。例如,對於一個給定的x,$h_w(x)$的值爲0.8,則說明有80%的可能輸出爲正向類(1),有20%的可能輸出爲負向類(0),兩者成補集關係。視頻

對於一個二分類問題而言,咱們給定輸入,函數最終的輸出只能有兩類,0或者1,因此咱們能夠對其分類。

在這裏插入圖片描述

爲了運算便捷,咱們將其整合爲一個公式,以下:

在這裏插入圖片描述

因爲乘法計算量過大,因此能夠將乘法變加法,對上式求對數,以下:

在這裏插入圖片描述

能夠看出當y=1時,加號後面式子的值爲0;當y=0時,加號前面式子的值爲0,這與上文分類式子達到的效果是同樣的。L(w)稱爲似然函數,l(w)稱爲對數似然函數,是依據最大似然函數推導而成。此時的應用是梯度上升求最大值,若是梯度降低求最小值,可在公式以前乘以$-\frac{1}{n}$。

爲了學習嘛,這裏再介紹一下另外一種方式,利用損失函數推導應用於梯度降低的公式;損失函數是衡量真實值與預測值之間差距的函數,因此損失函數值越小,對應模型的效果也越好,損失函數公式以下:

在這裏插入圖片描述

可能只看公式理解相對抽象,經過對應的函數圖像足以理解上式,以下:

在這裏插入圖片描述

注意!!!公式後面的y*不表明縱座標 !!!
當類標籤y=1時,對應的-log(x)圖像越接近於1,其距離x軸越近,表明其損失越小;反之當類標籤y=0時,對應的-log(1-x)圖像越接近於0,其距離x軸越近,表明其損失越小,也就是預測值越接近於真實值。

將兩個損失函數綜合起來得:

在這裏插入圖片描述

對於m個樣本,總損失函數爲:

在這裏插入圖片描述

其中m爲樣本個數、yi爲標籤,可取0或一、i爲第i個樣本、$p(x_i)$爲預測輸出。

3、梯度

3.1梯度上升

上面已經列出了一大堆的公式,難道這又要開始一連串的大公式?

在這裏插入圖片描述

心態放平,上文雖然說公式有點多,但目的都是爲了推出最後的對數似然函數或者總損失函數,掌握這兩個是關鍵,梯度上升和梯度降低也會利用上面的公式作推導,因此兩者之間存在關聯。首先梯度降低你須要瞭解一下何爲梯度?

若是將梯度記爲▽,則函數f(x,y)的梯度可由下式表示:

在這裏插入圖片描述

通俗的說,即對多元函數的參數求偏導,並把求得的各個參數的偏導以向量的形式寫出來。或者你只要理解這個梯度要沿着x的方向移動$\frac{\delta f(x,y)}{\delta x}$,沿着y方向移動$\frac{\delta f(x,y)}{\delta y}$足以,但f(x,y)必需要在待計算的點上有定義且可微。

下圖爲一個梯度降低的例子,梯度降低法在到達每個點以後都會從新評估下一步將要移動的方向。從x0開始,在計算完該點的梯度,函數就會移動到下一個點x1。在x1點,梯度會從新計算,繼而移動到x2點。如此循環迭代此過程,直到知足中止條件,每次迭代過程都是爲了找出當前能選取到的最佳移動方向。

在這裏插入圖片描述

以前一直在討論移動方向,而未提到過移動量的大小。該量值稱爲步長,記做$\alpha$。那麼就能夠得出梯度上升法的迭代公式

在這裏插入圖片描述

因此對於上文所說起的對數似然函數$J(w)$,咱們也能夠利用上述迭代的方式,一步一步移動到目標值或者無限接近於目標值,$J(w)$求偏導的公式以下:

在這裏插入圖片描述

可能有的人看到這個偏導公式有點蒙,其實這裏面用到的三個函數公式都是上文所說起的,來回顧一下。

在這裏插入圖片描述

求偏導過程涉及到高數知識,即最外層函數對外層函數求偏導、外層函數對內層函數求偏導、內層函數對其元素求偏導,三者相乘可得出所需偏導。推導過程有些麻煩,這裏只給出推導結果,在後面運用時咱們也只會運用到最終結果,以下:

在這裏插入圖片描述

3.2梯度降低

若是利用將對數似然函數換成損失函數$J(\Theta)$,則獲得的是有關計算梯度降低的公式,以下:

在這裏插入圖片描述

兩個公式中的w和$\Theta$的含義是同樣的,都表明咱們所求的最佳迴歸係數,兩個公式對比能夠看出梯度上升和梯度降低只有加減號區別之分。下面這個動圖就能夠很好的展現梯度降低法的過程:
在這裏插入圖片描述
公式推導部分至此結束了,基礎偏好的夥伴可能一遍就懂了,但基礎偏弱理解起來比較困難,偶當時也是對着書、跟着視頻啃了很久,多啃幾遍終歸會理解的。
在這裏插入圖片描述

4、算法應用

4.1數據概覽

有這樣一份數據集,共100個樣本、兩個特徵(X1與X2)以及一個分類標籤,部分數據和所繪製圖像以下:

X1 X2 類別
0.197445 9.744638 0
0.078557 0.059736 1
-1.099458 1.688274 1
1.319944 2.171228 1
-0.783277 11.009725 0

在這裏插入圖片描述

在此數據集上,咱們將經過梯度降低法找到最佳迴歸係數,也就是擬合出Logistic迴歸模型的最佳參數。
該算法的僞代碼以下:

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

4.2加載數據集

def loadDataSet():
    dataMat = []    # 建立數據列表
    labelMat = []    # 建立標籤列表
    fr = open('LRData.txt','r',encoding='utf-8')
    #逐行讀取所有數據
    for line in fr.readlines():
        #將數據分割、存入列表
        lineArr = line.strip().split()
        #數據存入數據列表
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
        #標籤存入標籤列表
        labelMat.append(int(lineArr[2]))
    fr.close()
    return dataMat, labelMat

loadDataSet函數的做用是打開存儲數據的文本文件並逐行讀取。每行的前兩個值分別對應X1和X2,第三個值是數據對應的類別標籤。爲了方便計算,函數還在X1和X2以前添加了一個值爲1.0的X1,X1能夠理解爲偏置,即下圖中的x0。

在這裏插入圖片描述

4.3訓練算法

#sigmoid函數
def sigmoid(inX):
    return 1.0 / (1 + np.exp(-inX))

sigmoid函數就是傳入一個參數(這裏是一個100*1的向量),經過公式計算並返回值。

def gradAscent(dataMatIn, classLabels):
    # 將列表轉換成numpy的matrix(矩陣)
    dataMatrix = np.mat(dataMatIn)
    # 將列表轉換成numpy的mat,並進行轉置
    labelMat = np.mat(classLabels).T
    # 獲取dataMatrix的行數和列數。
    m, n = np.shape(dataMatrix)
    # 設置每次移動的步長
    alpha = 0.001
    # 設置最大迭代次數
    maxCycles = 500
    # 建立一個n行1列都爲1的矩陣
    weights = np.ones((n,1))
    for k in range(maxCycles):
        # 公式中hΘ(x)
        h = sigmoid(dataMatrix * weights)
        # 偏差,即公式中y-hΘ(x)
        error = labelMat - h
        # 套入總體公式
        weights = weights + alpha * dataMatrix.T * error
    return weights

最後weights返回的是一個3x1的矩陣,運行截圖以下:

在這裏插入圖片描述

gradAscent傳入參數爲loadDataSet的兩個返回值,而後經過numpymat方法將dataMatrixlabelMat 分爲轉化爲100x3和1x100的矩陣,但labelMat 通過T轉置後變成100x1的矩陣。而後初始化權重,利用的方法就是建立一個n行1列的矩陣。整個算法的關鍵處於for循環中,咱們先回顧一下上文的兩個公式。

在這裏插入圖片描述
在這裏插入圖片描述

其中h的計算結果即$h_w(x)$,權重weight爲W向量,輸入矩陣dataMatrix爲x向量。偏差error表明$y^{(i)}-h_w x^{(i)}$,有人可能會發現$\frac{1}{m}$沒有出如今代碼中,由於$\alpha$和$\frac{1}{m}$都爲常數,兩者相乘也爲常數,因此只須要用$\alpha$代替便可。

公式中的加和部分又怎麼體現呢?若是學過線性代數或者瞭解numpy運算的夥伴應該都理解矩陣的乘法,不理解也沒有關係,看下圖這個例子,當兩個矩陣相乘時,對應元素之間會求和做爲最終元素。

在這裏插入圖片描述

4.4繪製決策邊界

def plotDataSet(weight):
    #獲取權重數組
    weight = weight.getA()
    # 加載數據和標籤
    dataMat, labelMat = loadDataSet()
    # 將列表轉換成numpy的array數組
    dataArr = np.array(dataMat)
    #獲取樣本個數
    n = np.shape(dataMat)[0]
    #建立4個空列表,1表明正樣本、0表明負樣本
    xcord1 = []; ycord1 = []
    xcord0 = []; ycord0 = []
    # 遍歷標籤列表,根據數據的標籤進行分類
    for i in range(n):
        if int(labelMat[i]) == 1:
            # 若是標籤爲1,將數據填入xcord1和ycord1
            xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2])
        else:
            # 若是標籤爲0,將數據填入xcord0和ycord0
            xcord0.append(dataArr[i,1]); ycord0.append(dataArr[i,2])
    #繪製圖像
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s = 20, c = 'red', marker = '*',label = 'Class1')
    ax.scatter(xcord0, ycord0, s = 20, c = 'green',marker = 's',label = 'Class2')
    #繪製直線,sigmoid設置爲0
    x = np.arange(-3.0, 3.0, 0.1)
    y = (-weight[0] - weight[1] * x) / weight[2]
    ax.plot(x, y)
    #標題、x標籤、y標籤
    plt.title('LRData')
    plt.legend(loc='upper left')
    plt.xlabel('X1'); plt.ylabel('X2')
    plt.savefig("E:\machine_learning\LR03.jpg")
    plt.show()

這部分代碼惟一須要注意的是,將sigmoid的值設置爲0,能夠回憶一下文章剛開始時的Sigmoid函數圖像,0是兩個分類的分解處。所以,咱們設定$0=w_0x_0+w_1x_1+w_2x_2$,$x_0$的值爲1,因此已知迴歸係數,就可求得$x_1和x_2$的關係式,從而畫出決策邊界。

在這裏插入圖片描述

上圖能夠看出分類的效果仍是不錯的,根據函數繪製出的直線已經很大程度上將兩類樣本分隔開,100個樣本中,只有五個樣本分類錯誤,其中有三個仍是位於迴歸線上。

5、總結

本文所講的梯度上升公式,是屬於批量梯度上升,此外還有隨機梯度上升、小批量梯度上升,而批量梯度上升每次計算都要計算全部的樣本,因此程序計算過程是十分複雜的,而且容易收斂到局部最優,而隨機梯度上升將會對算法進行調優,下一篇文章將會介紹隨機梯度上升,並分析二者之間的區別。

歡迎關注公衆號【奶糖貓】,後臺回覆"邏輯迴歸"可獲取數據和源碼供參考,感謝閱讀。
相關文章
相關標籤/搜索