1. 程式人生 > >《Machine Learning in Action》—— Taoye給你講講Logistic迴歸是咋回事

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

在手撕機器學習系列文章的上一篇,我們詳細講解了線性迴歸的問題,並且最後通過梯度下降演算法擬合了一條直線,從而使得這條直線儘可能的切合資料樣本集,已到達模型損失值最小的目的。 在本篇文章中,我們主要是手撕Logistic迴歸,這個在李航老師的《統計學習方法》一書中也叫做為**邏輯斯諦迴歸**。聽到**迴歸**一詞,有的讀者可能會想,上一篇線性迴歸求解的是擬合問題,這篇文章手撕的是Logistic迴歸,會不會也是一個擬合問題?只不過使用到的演算法原理不同而已,而求解的問題是一致的??? 其實不然,Logistic迴歸模型是一種廣義的線性迴歸模型,主要是針對的是**分類問題**。只不過這個分類模型與上一章中的擬合模型有一些相似之處,或者我們可以這樣說,如果你明白了上篇文章中所講解的線性迴歸,那麼這篇文章中所涉及到的Logistic迴歸的內容,你將會學的很輕鬆。這也是為什麼Taoye首先肝線性迴歸的原因。 手撕機器學習系列目前已經更新了八篇,讀者可自行根據需要“充電”(持續更新中): * [《Machine Learning in Action》—— 剖析支援向量機,單手狂撕線性SVM](https://www.zybuluo.com/tianxingjian/note/1755051): [https://www.zybuluo.com/tianxingjian/note/1755051](https://www.zybuluo.com/tianxingjian/note/1755051) * [《Machine Learning in Action》—— 剖析支援向量機,優化SMO](https://www.zybuluo.com/tianxingjian/note/1756832): [https://www.zybuluo.com/tianxingjian/note/1756832](https://www.zybuluo.com/tianxingjian/note/1756832) * [《Machine Learning in Action》—— 懂的都懂,不懂的也能懂。非線性支援向量機](https://www.zybuluo.com/tianxingjian/note/1758624): [https://www.zybuluo.com/tianxingjian/note/1758624](https://www.zybuluo.com/tianxingjian/note/1758624) * [《Machine Learning in Action》—— Taoye給你講講決策樹到底是支什麼“鬼”](https://www.zybuluo.com/tianxingjian/note/1757662): [https://www.zybuluo.com/tianxingjian/note/1757662](https://www.zybuluo.com/tianxingjian/note/1757662) * [《Machine Learning in Action》—— 小朋友,快來玩啊,決策樹呦](https://www.zybuluo.com/tianxingjian/note/1758236): [https://www.zybuluo.com/tianxingjian/note/1758236](https://www.zybuluo.com/tianxingjian/note/1758236) * [《Machine Learning in Action》—— 女同學問Taoye,KNN應該怎麼玩才能通關](https://www.zybuluo.com/tianxingjian/note/1759263): [https://www.zybuluo.com/tianxingjian/note/1759263](https://www.zybuluo.com/tianxingjian/note/1759263) * [《Machine Learning in Action》—— 白話貝葉斯,“恰瓜群眾”應該恰好瓜還是恰壞瓜](https://www.zybuluo.com/tianxingjian/note/1758540): [https://www.zybuluo.com/tianxingjian/note/1758540](https://www.zybuluo.com/tianxingjian/note/1758540) * [《Machine Learning in Action》—— 淺談線性迴歸的那些事](https://www.zybuluo.com/tianxingjian/note/1761762): [https://www.zybuluo.com/tianxingjian/note/1761762](https://www.zybuluo.com/tianxingjian/note/1761762) * [《Machine Learning in Action》—— Taoye給你講講Logistic迴歸是咋回事](https://www.zybuluo.com/tianxingjian/note/1761888): [https://www.zybuluo.com/tianxingjian/note/1761888](https://www.zybuluo.com/tianxingjian/note/1761888) 本文主要包括以下兩個部分的內容: * 和Logistic迴歸交個朋友,互相認識一下吧(原理剖析,公式推導) * 基於Logistic迴歸手撕解決二分類問題 ## 一、和Logistic迴歸交個朋友,互相認識一下吧(原理剖析) 關於機器學習中的分類演算法,我們前面已經肝了不少。而Logistic迴歸是同樣也是分類演算法中的一員,一般用於二分類問題,比如患者是否患有胃癌、明天是否會下雨等等。當然了,對於多分類問題,Logistic迴歸也是有應對之法的,畢竟你有張良計,我也有過牆體嘛。本文主要是以二分類問題為例,來剖析Logistic迴歸中的那些小祕密。 假設現在有一些樣本資料點,每個樣本包括兩個屬性,我們可以利用一條直線來對其進行擬合,這個擬合的過程就叫做迴歸,擬合效果如下所示: ![](https://gitee.com/tianxingjian123/my-images-repository/raw/master/img/linear_regression_8_.png) 這個也是我們在上一篇文章中所詳細講到的內容,具體可見:[《Machine Learning in Action》—— 淺談線性迴歸的那些事](https://www.zybuluo.com/tianxingjian/note/1761762): [https://www.zybuluo.com/tianxingjian/note/1761762](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》—— 剖析支援向量機,單手狂撕線性SVM](https://www.zybuluo.com/tianxingjian/note/1755051): [https://www.zybuluo.com/tianxingjian/note/1755051](https://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}} $$ ![](https://gitee.com/tianxingjian123/my-images-repository/raw/master/img/logistic_1.png) 通過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 ``` 視覺化資料之後的分佈如下: ![](https://gitee.com/tianxingjian123/my-images-repository/raw/master/img/logistic_2.jpg) 從上圖我們可以看出資料的大致分佈情況,並且能夠通過一條直線將兩類資料分割開來。在這裡,我們假設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) # 繪製分類的決策直線 ``` 視覺化分類結果如下所示: ![](https://gitee.com/tianxingjian123/my-images-repository/raw/master/img/logistic_5.jpg) 上圖主要包括倆個部分,一個是通過Logistic迴歸分類的結果,另一個是每次迭代之後損失值的變換情況。 從視覺化的結果來看,這個分類效果相當不錯,基本上所有的資料點都能夠被正確分類,讀者可根據需要來決定是否使用隨機種子,從而觀察不同資料集的分類效果。 從第二張圖中,我們可以看出通過Logistic迴歸進行訓練的過程中,損失函式的值是不斷增大。而且我們還可以發現,其增大的斜率逐漸減小,尤其是在前面幾次迭代過程中,這種現象尤為明顯。當損失函式值提高到一定程度之後,這個時候基本屬於飽和了,也就是說分類的過程基本結束了。 上圖是損失函式的值的視覺化結果,我們也可以從其每次迭代之後的具體值來觀察這一變化趨勢: ![](https://gitee.com/tianxingjian123/my-images-repository/raw/master/img/logistic_6.jpg) 總共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》—— 淺談線性迴歸的那些事](https://mp.weixin.qq.com/s?__biz=MzI4NjMyMDM4Mg==&mid=2247484386&idx=1&sn=22be1be777b70b17af603d21b22fec96&chksm=ebdff073dca8796583566d969658af26f1e6d20326e02b212fed487e99db46cb0c93fff27e08&token=189681706&lang=zh_CN#rd) [《Machine Learning in Action》—— 白話貝葉斯,“恰瓜群眾”應該恰好瓜還是恰壞瓜](https://mp.weixin.qq.com/s?__biz=MzI4NjMyMDM4Mg==&mid=2247484355&idx=1&sn=1860bd8c1cab29d0a29adbfe92127908&chksm=ebdff052dca879446a950ca0b0e533dea12dda3858ceb3ddadb607add207c57b907f515c922f&token=189681706&lang=zh_CN#rd) [《Machine Learning in Action》—— 女同學問Taoye,KNN應該怎麼玩才能通關](https://mp.weixin.qq.com/s?__biz=MzI4NjMyMDM4Mg==&mid=2247484281&idx=1&sn=54d05ab278b6ab1469a20851760256cf&chksm=ebdff0e8dca879fea15dd185a88707d1d5748db7cacb51039110340de3859c2979dfa981efde&token=189681706&lang=zh_CN#rd) [《Machine Learning in Action》—— 懂的都懂,不懂的也能懂。非線性支援向量機](https://mp.weixin.qq.com/s?__biz=MzI4NjMyMDM4Mg==&mid=2247484260&idx=1&sn=c3283c986c8c95438e93eaac630879df&chksm=ebdff0f5dca879e358a687aeaf1d35f2509918799f5a56a8781d59f21374b1fd77ec7259920f&token=1403642957&lang=zh_CN#rd) [《Machine Learning in Action》—— hao朋友,快來玩啊,決策樹呦](https://mp.weixin.qq.com/s?__biz=MzI4NjMyMDM4Mg==&mid=2247484226&idx=1&sn=33bf19042d274a773085a43f04224fee&chksm=ebdff0d3dca879c567a5a1612da317cf1d1c7393c11a1b7485d92c07e2e2605923f8f613daba&token=1694351021&lang=zh_CN#rd) [《Machine Learning in Action》—— Taoye給你講講決策樹到底是支什麼“鬼”](https://mp.weixin.qq.com/s?__biz=MzI4NjMyMDM4Mg==&mid=2247484197&idx=1&sn=2d5293ffbb6f32cabcbd817cccd1c2c8&chksm=ebdff0b4dca879a236e8ae6cdaed612d2c7e041b1f07ca6a2611d74b37d3e26a260deac1a814&token=1534971367&lang=zh_CN#rd) [《Machine Learning in Action》—— 剖析支援向量機,優化SMO](https://mp.weixin.qq.com/s?__biz=MzI4NjMyMDM4Mg==&mid=2247484159&idx=1&sn=4d31214dbab885456f24b4291a0d58ee&chksm=ebdff16edca87878341c7ab922d62935aecafccfc948ea899fbc12116cb4bac98ec042c7cf9e&token=503846651&lang=zh_CN#rd) [《Machine Learning in Action》—— 剖析支援向量機,單手狂撕線性SVM](https://mp.weixin.qq.com/s?__biz=MzI4NjMyMDM4Mg==&mid=2247484147&idx=1&sn=a823c20a4a02b819487a491a34771eec&chksm=ebdff162dca87874e33ae6d8fdc0026e1d15bfeb683b6d4451b05b844b37139c2019feb0d2b9&token=1814981738&lang=zh_CN#rd) [print( "Hello,NumPy!" )](https://mp.weixin.qq.com/s?__biz=MzI4NjMyMDM4Mg==&mid=2247483962&idx=1&sn=f1fd5b0b3a158356bb56494764135561&chksm=ebdff1abdca878bd729aa663452f907b5e1a17ea62cf9931ec66fcb7a0709e5c897624af6080&token=1239854634&lang=zh_CN#rd) [幹啥啥不行,吃飯第一名](https://mp.weixin.qq.com/s?__biz=MzI4NjMyMDM4Mg==&mid=2247483942&idx=1&sn=70cacac0414637254e10ea35ba328cc5&chksm=ebdff1b7dca878a1895ef45dac886f0d084c409d84014284e3a8700ad3bcadd3d07d6ea19409&token=1281450696&lang=zh_CN#rd) [Taoye滲透到一家黑平臺總部,背後的真相細思極恐](https://mp.weixin.qq.com/s?__biz=MzI4NjMyMDM4Mg==&mid=2247483902&idx=1&sn=8fb1b76b9b4095469b3b0ee9e5d84d97&chksm=ebdff26fdca87b79dffc7dbf79466ea5ec0effcf032134d67be98f84b161c07b224789ffab6c&token=1984820117&lang=zh_CN#rd) [《大話資料庫》-SQL語句執行時,底層究竟做了什麼小動作?](https://mp.weixin.qq.com/s?__biz=MzI4NjMyMDM4Mg==&mid=2247483871&idx=1&sn=ae9976268a0efb03a9ba30ffeb3cb419&chksm=ebdff24edca87b585c5cb8d6ff2212846dd270db71de573f8240b314e7c3143a78d56644ed00&token=1984820117&lang=z