《Machine Learning in Action》—— Taoye給你講講Logistic迴歸是咋回事

在手撕機器學習系列文章的上一篇,我們詳細講解了線性迴歸的問題,並且最後通過梯度下降算法擬合了一條直線,從而使得這條直線儘可能的切合數據樣本集,已到達模型損失值最小的目的。

在本篇文章中,我們主要是手撕Logistic迴歸,這個在李航老師的《統計學習方法》一書中也叫做爲邏輯斯諦迴歸。聽到迴歸一詞,有的讀者可能會想,上一篇線性迴歸求解的是擬合問題,這篇文章手撕的是Logistic迴歸,會不會也是一個擬合問題?只不過使用到的算法原理不同而已,而求解的問題是一致的???

其實不然,Logistic迴歸模型是一種廣義的線性迴歸模型,主要是針對的是分類問題。只不過這個分類模型與上一章中的擬合模型有一些相似之處,或者我們可以這樣說,如果你明白了上篇文章中所講解的線性迴歸,那麼這篇文章中所涉及到的Logistic迴歸的內容,你將會學的很輕鬆。這也是爲什麼Taoye首先肝線性迴歸的原因。

手撕機器學習系列目前已經更新了八篇,讀者可自行根據需要“充電”(持續更新中):

本文主要包括以下兩個部分的內容:

  • 和Logistic迴歸交個朋友,互相認識一下吧(原理剖析,公式推導)
  • 基於Logistic迴歸手撕解決二分類問題

一、和Logistic迴歸交個朋友,互相認識一下吧(原理剖析)

關於機器學習中的分類算法,我們前面已經肝了不少。而Logistic迴歸是同樣也是分類算法中的一員,一般用於二分類問題,比如患者是否患有胃癌、明天是否會下雨等等。當然了,對於多分類問題,Logistic迴歸也是有應對之法的,畢竟你有張良計,我也有過牆體嘛。本文主要是以二分類問題爲例,來剖析Logistic迴歸中的那些小祕密。

假設現在有一些樣本數據點,每個樣本包括兩個屬性,我們可以利用一條直線來對其進行擬合,這個擬合的過程就叫做迴歸,擬合效果如下所示:

這個也是我們在上一篇文章中所詳細講到的內容,具體可見:《Machine Learning in Action》—— 淺談線性迴歸的那些事https://www.zybuluo.com/tianxingjian/note/1761762

而Logistic迴歸是一種分類算法,它分類的核心思想是建立在線性迴歸基礎之上的,並且對其進行了拓展,主要利用到了Sigmoid函數閾值在[0,1]這麼一個特性,而這個特性則正好符合概率所在區間。所以說,Logistic迴歸的本質就是一個基於條件概率的判別模型(在已知樣本屬性特徵的前提下,判斷其屬於哪一類別)。

現在就讓我們來和Logistic迴歸互相認識一下吧,看看能不能挖出它的一些小祕密,一睹廬山真面目。

不知道各位看官還記不記得之前在講解SVM的時候,我們是通過一種間隔最大化的形式來找出最佳的決策面,以此來對數據集進行分類。

而在Logistic迴歸看來,每一個樣本的類別標籤都對應着一個概率,哪個類別標籤的概率大,那麼我就將樣本歸於哪一類。我們不妨假設單個樣本有\(N+1\)個屬性特徵,我們可以把它看做一個向量形式,且每個樣本對應的標籤情況只可能有兩類,即:

\[\begin{aligned} & x_i = (x_i^{(0)},x_i^{(1)},x_i^{(2)},...,x_i^{(N)}) \\ &y_i\in (0,1) \end{aligned} \]

也就是說,我們現在的目的就是找到一個超平面,在超平面的一側爲一個類別樣本,在另一側爲另一類樣本。且每個樣本只可能存在兩種情況,非0即1。對此,我們不妨假設在已知樣本屬性特徵和模型參數\(w=(w_0,w_1,...,w_N)\)的前提下,令該樣本標籤類別爲1的概率爲\(h_w(x)\),因爲只可能存在兩個類別,所以樣本標籤爲0的概率爲\(1-h_w(x)\),即:

\[\begin{aligned} & P(y_i=1|x_i;w)=h_w(x_i) \\ & P(y_i=0|x_i;w)=1-h_w(x_i) \end{aligned} \]

對於上式,它表示的意思是在已知樣本屬性特徵x和模型參數\(w\)的前提下,該樣本標籤爲1和0的概率分別爲\(h_w(x)\)\(1-h_w(x)\)。根據我們自己意願,我們當然是希望這兩者相差越大越好咯,這樣得到的分類結果才更具有說服力。

比如說對於一個樣本來講,該樣本標籤爲0的概率爲0.9,爲1的概率則等於0.1,我們當然是更加情願將這個樣本歸於0那一類別,而且這樣的分類結果比較容易服衆。那假設該樣本標籤爲0的概率爲0.51,爲1的概率爲0.49,那麼這個時候你願意將這個樣本歸於哪一類呢???是不是很難做出抉擇???是不是相當的糾結???因爲這樣得出的分類概率結果和我們盲猜的概率也相差不多,完全達不到一個服衆的目的。

對此,我們更加希望是這樣的:標籤的分類概率相差越大越好,這樣我們對樣本的分類結果更加具有說服力。

上述兩個概率其實就是兩種情況,且其樣本標籤爲非0即1,根據這個特性,爲了方便我們表示分類的概率情況,可以將上述兩個概率值合二爲一,得到如下:

\[P(y_i|x_i;w)=h_w(x_i)^{y_i}(1-h_w(x_i))^{1-y_i} \]

上述這種將二者合二爲一的處理方式,曾經在SVM那篇文章中也是有謀面過的,如有遺忘,讀者可暫且跳轉進行復習:《Machine Learning in Action》—— 剖析支持向量機,單手狂撕線性SVMhttps://www.zybuluo.com/tianxingjian/note/1755051

合併出來的上式,當y等於1時,(1-y)項(第二項)爲0;當y等於0時,y項(第一項)爲0。也就是說,我們現在的目的就是根據訓練樣本集,使得上式的值最大化,這樣我們對樣本集分類的準確性就越高。

此外,上述\(P(y|x_i;w)\)單個樣本所表示的概率值,而我們知道,樣本集是由大量的單個樣本所組成的一個集合,所以此時我們的極大似然法就該出場了,假設樣本與樣本之間是相互獨立的,那麼其似然函數爲(假定有n個樣本):

\[\prod_{i=1}^nh_w(x_i)^{y_i}(1-h_w(x_i))^{1-y_i} \]

此時,我們的目的就是要根據數據樣本集,來求解上述似然函數的最大值。求最值問題,我們自然會使用到求解導函數,而對於上述的乘積形式,我們直接求導並不簡單,而且還會大大提高求解的效率和複雜度。對此我們需要對其進行對數化,從而將乘積的形式轉化成求和的形似,這樣一來對於求導來講就比較的友好了。

假設我們對上述式子對數化之後,命名爲\(L(w)\),則其爲我們最終的損失函數,或者說是待優化的目標函數,具體形式如下:

\[L(w)=\sum_{i=1}^ny_ilog(h_w(x))+(1-y_i)log(1-h_w(x)) \]

寫到這裏,我們算是得到了最終所需要求解的目標函數了,現在就是需要將上述的損失函數值最大化,這樣才能使得最終分類的結果集的準確性更高。

注意一點:對於上述的損失函數,讀者可能在這裏有個疑問,按道理將應該是使得損失值最小化纔對,爲什麼會需要使得上式最大化呢???其實是這樣的,上述的式子說是說損失函數,其實它真正代表的意思是使得整個樣本集的分類正確率儘可能的提高。這一點若讀者還有疑問,可返回仔細想想該式子的推導過程,及其背後隱藏的真正含義。

這樣一來,對於上述的損失函數還有一個\(h_w(x)\)我們是不知道的。通過前面分析,我們也可以知道\(h_w(x)\)表示的是一個概率,其值爲0-1。然而,我們通過計算\(w_0x_i^{(0)}+w_1x_i^{(1)}+w_2x_i^{(2)}+...+w_Nx_i^{(N)}\),可以發現該值的具體範圍是不確定的。爲此,我們需要對該計算得到的值進行一定的處理,將其轉化到0-1範圍之間,如此一來,才能符合概率的範圍特性。

那麼,該如何處理呢???

聰明的研究人員就發現,有這麼一個函數,無論該值的有多大,或者有多小,都能將其映射到0-1之間。這個函數就是大名鼎鼎的Sigmoid函數,其具體形式和圖像如下所示:

\[g(z)=\frac{1}{1+e^{-z}} \]

通過Sigmoid函數的表達式和具體圖像,我們也可以發現,其正好滿足我們的實際需求。另外,Sigmoid函數在今後的學習過程中還會經常見到的,比如在卷積神經網絡中,就經常會使用Sigmoid函數來作爲我們的激活函數,以解決非線性問題。

如此一來,我們通過Sigmoid函數來處理樣本,得到如下結果:

\[h_w(x)=g(w^Tx)=\frac{1}{1+e^{-w^Tx}} \]

瞭解了\(h_w(x)\)具體表達之後,我們就能對損失函數進行進一步的處理變換,處理過程如下:

\[\begin{aligned} L(w) & =\sum_{i=1}^ny_ilog(h_w(x_i))+(1-y_i)log(1-h_w(x_i)) \\ & = \sum_{i=1}^n[y_i\log\frac{h_w(x_i)}{1-h_w(x_i)}+log(1-h_w(x_i))] \\ & = \sum_{i=1}^n[y_i(w^Tx_i)-w^Tx_i-log(1+e^{-w^Tx_i})] \end{aligned} \]

將損失函數處理成如上式子之後,我們可以發現在整個訓練數據樣本集中,\(x_i和y_i\)都是已知的,唯一不確定的就是\(w\),其是一個與單個樣本屬性特徵相對應的向量形式。我們對\(w\)進行求導之後可以得到如下結果:

\[\frac{\partial L(w)}{\partial w}=\sum_{i=1}^n(y_i-h_w(x_i))x_i \]

由此,我們計算得到損失函數關於\(w\)的梯度之後,就可以通過梯度上升算法來不斷更新迭代\(w\)參數,從而使得損失函數的值最大化,即使得訓練樣本集分類的正確性儘可能高。

另外,我們知道\(w\)參數其實是一個向量的形式,其與\(x\)的屬性特徵是相對應的,對此我們對\(w\)進行更新的時候,是對其內部的每一個元素同時更新。根據上述的求導結果,我們得到每個元素的具體更新如下:

\[\begin{aligned} & w_0^{new}=w_0^{old}+\alpha\sum_{i=1}^n(y_i-h_w(x_i))x_i^0 \\ & w_1^{new}=w_1^{old}+\alpha\sum_{i=1}^n(y_i-h_w(x_i))x_i^1 \\ & w_2^{new}=w_2^{old}+\alpha\sum_{i=1}^n(y_i-h_w(x_i))x_i^2 \\ & \vdots \\ & w_N^{new}=w_N^{old}+\alpha\sum_{i=1}^n(y_i-h_w(x_i))x_N^2 \\ \end{aligned} \]

注意,在這裏我們是假設每個元素有\(N+1\)個屬性特徵的,即\(x_i = (x_i^{(0)},x_i^{(1)},x_i^{(2)},...,x_i^{(N)})\),這一點在前面也是有提到。其中\(old\)表示的是更新迭代之前的\(w\)值,而\(new\)表示的是更新迭代之後的\(w\)值,而\(\alpha\)表示的是一個學習率,也代表着學習的快慢,這個在之前講解線性迴歸的時候也是有詳細講到的。

二、基於Logistic迴歸手撕解決二分類問題

得到Logistic迴歸模型之後,我們就能根據\(w^{old}\)來不斷更新迭代得到\(w^{new}\),最終使得損失函數值最大化。

接下來,我們嘗試着通過Python代碼來實現Logistic迴歸分類,本次主要針對於二分類。數據集依然通過NumPy隨機生成,定義一個establish_data方法隨機生成數據集的代碼如下:

"""
    Author: Taoye
    微信公衆號: 玩世不恭的Coder
    Explain: 通過NumPy準備數據集
    Return:
        x_data:樣本的屬性特徵
        y_label:樣本屬性特徵所對應的標籤
"""
def establish_data():
    # np.random.seed(1) # 可根據需要是否選擇隨機種子
    x_data = np.concatenate((np.add(np.random.randn(50, 2), [1.5, 1.5]),       
                                 np.subtract(np.random.randn(50, 2), [1.5, 1.5])),
                                 axis = 0)      # random隨機生成數據,+ -1.5達到不同類別數據分隔的目的 
    y_label = np.concatenate((np.zeros([50]), np.ones([50])), axis = 0)    # concatenate合併數據集
    return x_data. y_label

可視化數據之後的分佈如下:

從上圖我們可以看出數據的大致分佈情況,並且能夠通過一條直線將兩類數據分割開來。在這裏,我們假設Sigmoid函數的輸入記爲\(z\),那麼\(z=w_0x_0+w_1x_1+w_2x_2\),即可將數據分割開。其中,爲了體現出直線的截距,我們將\(x_0\)當作是數值爲1的固定值,\(x_1\)爲數據集的第一個屬性特徵,\(x_2\)爲數據集的第二個屬性特徵。另z=0,則得到該直線的一般表達式\(w_0+w_1x_1+w_2x_2=0\)

對於這個方程,我們已知的是樣本數據,也就是橫座標爲\(x_1\),縱座標爲\(x_2\),表示樣本的兩個屬性。而未知的參數爲\(w_0,w_1,w_2\),也就是我們需要求的迴歸係數(最優參數),也正是需要通過梯度上升算法訓練的模型參數。

在開始訓練模型參數之前,我們把迭代更新的\(w\)式子再次搬出來看看:

\[\frac{\partial L(w)}{\partial w}=\sum_{i=1}^n(y_i-h_w(x_i))x_i \]

即:

\[\begin{aligned} & w_0^{new}=w_0^{old}+\alpha\sum_{i=1}^n(y_i-h_w(x_i))x_i^0 \\ & w_1^{new}=w_1^{old}+\alpha\sum_{i=1}^n(y_i-h_w(x_i))x_i^1 \\ & w_2^{new}=w_2^{old}+\alpha\sum_{i=1}^n(y_i-h_w(x_i))x_i^2 \\ & \vdots \\ & w_N^{new}=w_N^{old}+\alpha\sum_{i=1}^n(y_i-h_w(x_i))x_i^N \\ \end{aligned} \]

我們知道,對於求和的式子我們可以將其轉換成矩陣或向量 的形式來表示,這也是矢量化的一種操作,比如\(\sum_{i=1}^nw_ix_1\)可以轉化成\(w^Tx\)。因此,對於上式,我們同樣可以對其進行矢量化,得到如下結果:

\[w^{new}=w^{old}+\alpha x^T(y-h_w(x)) \]

這裏對上式再解釋一下,比如說我們有100個數據樣本,每個樣本含有2個屬性,那麼此時的x代表整個樣本集,其\(x.shape=(100,2)\),所以\(x^T.shape=(2,100)\),而\((y-h_w(x)).shape=(100, 1)\),所以兩者相乘之後得到的shape是\((2,1)\),正好與所需要的\(w\)向量的維數一致。

根據上述矢量化之後的結果,我們定義一個gradient_ascent方法來通過代碼實現這個功能。

"""
    Author: Taoye
    微信公衆號: 玩世不恭的Coder
    Explain: Sigmoid函數
    Parameters:
        in_data: sigmoid處理的輸入數據
    Return:
        sigmoid_result:sigmoid函數處理之後的結果
"""
def sigmoid(in_data):
    return 1 / (1 + np.exp(-in_data))

"""
    Author: Taoye
    微信公衆號: 玩世不恭的Coder
    Explain: Logistic迴歸的核心方法,主要使用到了梯度上升算法
    Parameters:
        x_data:樣本集的屬性特徵
        y_label:樣本集的標籤
    Return:
        weights: 模型訓練完成之後的w參數
"""
def gradient_ascent(x_data, y_label):
    x_data, y_label = np.mat(x_data), np.mat(y_label).T    # 轉換成矩陣形式,方便操作
    data_number, attr_number = x_data.shape                # 獲取樣本數量以及屬性特徵的數量
    learning_rate, max_iters, weights = 0.001, 500, np.ones([attr_number, 1])    # 一些超參數和參數的初始化
    loss_list = list()
    for each_iter in range(max_iters):         # 更新迭代max_iters次
        sigmoid_result = sigmoid(np.matmul(x_data, weights))        # sigmoid處理 x*w
        difference = y_label - sigmoid_result                             # 計算損失值
        weights = weights + learning_rate * np.matmul(x_data.T, difference)    # 更新權重w向量
        loss = np.matmul(y_label.T, np.log(sigmoid_result)) + np.matmul((1 - y_label).T, np.log(1 - sigmoid_result))
        loss_list.append(loss.tolist()[0][0])
    return weights.getA(), loss_list

獲取到了模型的最終訓練的參數之後,就可以對結果進行可視化了,以便直觀感受下Logistic迴歸的分類結果。爲此,定義一個show_result方法來實現結果的可視化:

"""
    Author: Taoye
    微信公衆號: 玩世不恭的Coder
    Explain: 可視化分類結果,也就是Logistic迴歸的可視化
    Parameters:
        x_data:樣本集的屬性特徵
        y_label:樣本集的標籤
        weights:模型所需要的參數,也就是權重
"""
def show_result(x_data, y_label, weights):
    from matplotlib import pyplot as plt
    w_1, w_2, w_3 = weights[0][0], weights[1][0], weights[2][0]    # 獲取權重參數
    min_x_1, min_x_2 = np.min(x_data, axis = 0)[:-1]               # 獲取屬性特徵的最小值
    max_x_1, max_x_2 = np.max(x_data, axis = 0)[:-1]               # 獲取屬性特徵的最大值
    line_x_1 = np.linspace(min_x_1 - 0.2, max_x_1 + 0.2, 1000)     # 決策直線的橫座標
    line_x_2 = (-w_3 - w_1 * line_x_1) / w_2                       # 決策直線的縱座標
    plt.scatter(x_data[:, 0], x_data[:, 1], c = y_label)           # 繪製數據的散點圖
    plt.plot(line_x_1, line_x_2)                                   # 繪製分類的決策直線

可視化分類結果如下所示:

上圖主要包括倆個部分,一個是通過Logistic迴歸分類的結果,另一個是每次迭代之後損失值的變換情況。

從可視化的結果來看,這個分類效果相當不錯,基本上所有的數據點都能夠被正確分類,讀者可根據需要來決定是否使用隨機種子,從而觀察不同數據集的分類效果。

從第二張圖中,我們可以看出通過Logistic迴歸進行訓練的過程中,損失函數的值是不斷增大。而且我們還可以發現,其增大的斜率逐漸減小,尤其是在前面幾次迭代過程中,這種現象尤爲明顯。當損失函數值提高到一定程度之後,這個時候基本屬於飽和了,也就是說分類的過程基本結束了。

上圖是損失函數的值的可視化結果,我們也可以從其每次迭代之後的具體值來觀察這一變化趨勢:

總共500次迭代,共輸出500次損失值,起初的損失值爲300多,每次迭代之後的損失值逐漸增大,且增大的速度在不斷減小,最終的損失值停留在3左右達到飽和。這就是梯度上升算法所體現出來的效果,也就是說我們的損失函數值越小,我們梯度上升法優化的效果也就越明顯。

完整代碼:

import numpy as np

"""
    Author: Taoye
    微信公衆號: 玩世不恭的Coder
    Explain: 通過NumPy準備數據集
    Return:
        x_data:樣本的屬性特徵
        y_label:樣本屬性特徵所對應的標籤
"""
def establish_data():
#     np.random.seed(1)
    x_data = np.concatenate((np.add(np.random.randn(50, 2), [1.5, 1.5]),       
                                 np.subtract(np.random.randn(50, 2), [1.5, 1.5])),
                                 axis = 0)      # random隨機生成數據,+ -1.5達到不同類別數據分隔的目的
    x_data = np.concatenate((x_data, np.ones([100, 1])), axis = 1)
    y_label = np.concatenate((np.zeros([50]), np.ones([50])), axis = 0)    # concatenate合併數據集
    return x_data, y_label

"""
    Author: Taoye
    微信公衆號: 玩世不恭的Coder
    Explain: Sigmoid函數
    Parameters:
        in_data: sigmoid處理的輸入數據
    Return:
        sigmoid_result:sigmoid函數處理之後的結果
"""
def sigmoid(in_data):
    return 1 / (1 + np.exp(-in_data))

"""
    Author: Taoye
    微信公衆號: 玩世不恭的Coder
    Explain: Logistic迴歸的核心方法,主要使用到了梯度上升算法
    Parameters:
        x_data:樣本集的屬性特徵
        y_label:樣本集的標籤
    Return:
        weights: 模型訓練完成之後的w參數
"""
def gradient_ascent(x_data, y_label):
    x_data, y_label = np.mat(x_data), np.mat(y_label).T    # 轉換成矩陣形式,方便操作
    data_number, attr_number = x_data.shape                # 獲取樣本數量以及屬性特徵的數量
    learning_rate, max_iters, weights = 0.001, 500, np.ones([attr_number, 1])    # 一些超參數和參數的初始化
    loss_list = list()
    for each_iter in range(max_iters):         # 更新迭代max_iters次
        sigmoid_result = sigmoid(np.matmul(x_data, weights))        # sigmoid處理 x*w
        difference = y_label - sigmoid_result                             # 計算損失值
        weights = weights + learning_rate * np.matmul(x_data.T, difference)    # 更新權重w向量
        loss = np.matmul(y_label.T, np.log(sigmoid_result)) + np.matmul((1 - y_label).T, np.log(1 - sigmoid_result))
        loss_list.append(loss.tolist()[0][0])
    return weights.getA(), loss_list

"""
    Author: Taoye
    微信公衆號: 玩世不恭的Coder
    Explain: 可視化分類結果,也就是Logistic迴歸的可視化
    Parameters:
        x_data:樣本集的屬性特徵
        y_label:樣本集的標籤
        weights:模型所需要的參數,也就是權重
"""
def show_result(x_data, y_label, weights):
    from matplotlib import pyplot as plt
    w_1, w_2, w_3 = weights[0][0], weights[1][0], weights[2][0]    # 獲取權重參數
    min_x_1, min_x_2 = np.min(x_data, axis = 0)[:-1]               # 獲取屬性特徵的最小值
    max_x_1, max_x_2 = np.max(x_data, axis = 0)[:-1]               # 獲取屬性特徵的最大值
    line_x_1 = np.linspace(min_x_1 - 0.2, max_x_1 + 0.2, 1000)     # 決策直線的橫座標
    line_x_2 = (-w_3 - w_1 * line_x_1) / w_2                       # 決策直線的縱座標
    plt.scatter(x_data[:, 0], x_data[:, 1], c = y_label)           # 繪製數據的散點圖
    plt.plot(line_x_1, line_x_2)                                   # 繪製分類的決策直線

if __name__ == "__main__":
    x_data, y_label = establish_data()
    weights, loss_list = gradient_ascent(x_data, y_label)
    show_result(x_data, y_label, weights)
#     from matplotlib import pyplot as plt
#     plt.plot(np.arange(len(loss_result)), loss_list)

以上就是本篇文章中Logistic迴歸的全部內容了,我們在來總結一下Logistic迴歸實現的過程:

首先是通過分析推導,得到Logistic迴歸的損失函數\(L(w)\)(使用到了極大似然法):

\[L(w)=\sum_{i=1}^ny_ilog(h_w(x))+(1-y_i)log(1-h_w(x)) \]

其次,爲了將\(w\)\(x\)內積之後的結果映射到0-1範圍之內,以體現出概率的特性,我們引入了Sigmoid函數對內積結果進行處理:

\[h_w(x)=g(w^Tx)=\frac{1}{1+e^{-w^Tx}} \]

引入了Sigmoid函數之後,將損失函數化簡得到:

\[\begin{aligned} L(w) & =\sum_{i=1}^ny_ilog(h_w(x_i))+(1-y_i)log(1-h_w(x_i)) \\ & = \sum_{i=1}^n[y_i\log\frac{h_w(x_i)}{1-h_w(x_i)}+log(1-h_w(x_i))] \\ & = \sum_{i=1}^n[y_i(w^Tx_i)-w^Tx_i-log(1+e^{-w^Tx_i})] \end{aligned} \]

最後,因爲我們需要不斷地對\(w\)參數通過梯度上升算法進行更新迭代,所以我們需要對\(w\)進行求導,求導結果如下:

\[\frac{\partial L(w)}{\partial w}=\sum_{i=1}^n(y_i-h_w(x_i))x_i \]

如此一來,我們就能通過該梯度值對\(w\)參數一步步的優化,優化方法主要是通過梯度上升算法:

\[w^{new}=w^{old}+\alpha x^T(y-h_w(x)) \]

即對\(w\)向量內部的每個元素進行更新:

\[\begin{aligned} & w_0^{new}=w_0^{old}+\alpha\sum_{i=1}^n(y_i-h_w(x_i))x_i^0 \\ & w_1^{new}=w_1^{old}+\alpha\sum_{i=1}^n(y_i-h_w(x_i))x_i^1 \\ & w_2^{new}=w_2^{old}+\alpha\sum_{i=1}^n(y_i-h_w(x_i))x_i^2 \\ & \vdots \\ & w_N^{new}=w_N^{old}+\alpha\sum_{i=1}^n(y_i-h_w(x_i))x_i^N \\ \end{aligned} \]

當迭代次數達到一定程度時,最終更新迭代得到的\(w\)向量就是我們得到的參數結果,根據該參數就能構造一個模型將數據集分割開來,從而實現了數據的分類。

Logistic迴歸主要運用的是梯度上升算法,在上面案例實戰的過程中,我們的隨機生成的樣本數據集不是特別的多,所以訓練的速度還挺快。但是假定我們的訓練樣本數量比較多,這個時候的訓練效率就比較的低下了。這個時候可能就需要對梯度上升算法進行一定的優化了,而該部分優化常用的方式是使用隨機梯度上升算法,限於篇幅和時間原因,我們後面有機會再來肝。

這是手撕機器學習系列文章的第九篇了,也差不多接近尾聲了,初步計劃這周完成吧,因爲後面還有很多任務到現在還沒有開始,想到這,Taoye的眼角有不知覺地。。。

當然了,吾生也有涯,而知也無涯,以有涯隨無涯,殆已。學習本身就是一個無止境的過程,目前所講到的機器學習算法以及所涉及到的知識也只是該領域的冰山一角,我們最重要的是要保持一顆不斷積極進取的心。

我是Taoye,愛專研,愛分享,熱衷於各種技術,學習之餘喜歡下象棋、聽音樂、聊動漫,希望藉此一畝三分地記錄自己的成長過程以及生活點滴,也希望能結實更多志同道合的圈內朋友,更多內容歡迎來訪微信公主號:玩世不恭的Coder。

我們下期再見,拜拜~~~

參考資料:

[1] 《機器學習實戰》:Peter Harrington 人民郵電出版社
[2] 《統計學習方法》:李航 第二版 清華大學出版社

推薦閱讀

《Machine Learning in Action》—— 淺談線性迴歸的那些事
《Machine Learning in Action》—— 白話貝葉斯,“恰瓜羣衆”應該恰好瓜還是恰壞瓜
《Machine Learning in Action》—— 女同學問Taoye,KNN應該怎麼玩才能通關
《Machine Learning in Action》—— 懂的都懂,不懂的也能懂。非線性支持向量機
《Machine Learning in Action》—— hao朋友,快來玩啊,決策樹呦
《Machine Learning in Action》—— Taoye給你講講決策樹到底是支什麼“鬼”
《Machine Learning in Action》—— 剖析支持向量機,優化SMO
《Machine Learning in Action》—— 剖析支持向量機,單手狂撕線性SVM
print( "Hello,NumPy!" )
幹啥啥不行,喫飯第一名
Taoye滲透到一家黑平臺總部,背後的真相細思極恐
《大話數據庫》-SQL語句執行時,底層究竟做了什麼小動作?

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