1. 程式人生 > >機器學習——從線性迴歸到邏輯迴歸【附詳細推導和程式碼】

機器學習——從線性迴歸到邏輯迴歸【附詳細推導和程式碼】

本文始發於個人公眾號:TechFlow,原創不易,求個關注


在之前的文章當中,我們推導了線性迴歸的公式,線性迴歸本質是線性函式,模型的原理不難,核心是求解模型引數的過程。通過對線性迴歸的推導和學習,我們基本上了解了機器學習模型學習的過程,這是機器學習的精髓,要比單個模型的原理重要得多。

新關注和有所遺忘的同學可以點選下方的連結回顧一下之前的線性迴歸和梯度下降的內容。

一文講透梯度下降法

詳細推導線性迴歸模型


迴歸與分類


在機器學習當中,模型根據預測結果的不同分為兩類,如果我們希望模型預測一個或者多個連續值,這類問題被稱為是迴歸問題。像是常見的未來股票價格的估計、未來溫度估計等等都算是迴歸問題。還有一類呢是分類問題,模型的預測結果是一個離散值,也就是說只有固定的種類的結果。常見的有垃圾郵件識別、網頁圖片鑑黃等等。

我們之前介紹的邏輯迴歸顧名思義是一個迴歸問題,今天的文章講的呢是如何將這個迴歸模型轉化成分類模型,這個由線性迴歸推導得到的分類模型稱為邏輯迴歸。


邏輯迴歸


邏輯迴歸這個模型很神奇,雖然它的本質也是迴歸,但是它是一個分類模型,並且它的名字當中又包含”迴歸“兩個字,未免讓人覺得莫名其妙。

如果是初學者,覺得頭暈是正常的,沒關係,讓我們一點點捋清楚。

讓我們先回到線性迴歸,我們都知道,線性迴歸當中\(y=WX+b\)。我們通過W和b可以求出X對應的y,這裡的y是一個連續值,是迴歸模型對吧。但如果我們希望這個模型來做分類呢,應該怎麼辦?很容易想到,我們可以人為地設定閾值對吧,比如我們規定y > 0最後的分類是1,y < 0最後的分類是0。從表面上來看,這當然是可以的,但實際上這樣操作會有很多問題。

最大的問題在於如果我們簡單地設計一個閾值來做判斷,那麼會導致最後的y是一個分段函式,而分段函式不連續,使得我們沒有辦法對它求梯度,為了解決這個問題,我們得找到一個平滑的函式使得既可以用來做分類,又可以解決梯度的問題。

很快,資訊學家們找到了這樣一個函式,它就是Sigmoid函式,它的表示式是:

\[\sigma(x)= \frac{1}{1+e^{-x}}\]

它的函式影象如下:

可以看到,sigmoid函式在x=0處取值0.5,在正無窮處極限是1,在負無窮處極限是0,並且函式連續,處處可導。sigmoid的函式值的取值範圍是0-1,非常適合用來反映一個事物發生的概率。我們認為\(\sigma(x)\)表示x發生的概率,那麼x不發生的概率就是\(1-\sigma(x)\)。我們把發生和不發生看成是兩個類別,那麼sigmoid函式就轉化成了分類函式,如果\(\sigma(x)>0.5\)表示類別1,否則表示類別0.

到這裡就很簡單了,通過線性迴歸我們可以得到\(y = WX + b, P(1)=\sigma(y), P(0)=1-\sigma(y)\)。也就是說我們線上性迴歸模型的外面套了一層sigmoid函式,我們通過計算出不同的y,從而獲得不同的概率,最後得到不同的分類結果。


損失函式


下面的推導全程高能,我相信你們看完會三連的(點贊、轉發、關注)。

讓我們開始吧,我們先來確定一下符號,為了區分,我們把訓練樣本當中的真實分類命名為\(y\),\(y\)的矩陣寫成\(Y\)。同樣,單條樣本寫成\(x\),\(x\)的矩陣寫成\(X\)。單條預測的結果寫成\(\hat{y}\),所有的預測結果寫成\(\hat{Y}\)。

對於單條樣本來說,y有兩個取值,可能是1,也可能是0,1和0代表兩個不同的分類。我們希望\(y = 1\)的時候,\(\hat{y}\)儘量大,\(y = 0\)時,\(1 - \hat{y}\)儘量大,也就是\(\hat{y}\)儘量小,因為它取值在0-1之間。我們用一個式子來統一這兩種情況:

\[P(y|x)=\hat{y}^y(1-\hat{y})^{1-y}\]

我們代入一下,\(y=0\)時前項為1,表示式就只剩下後項,同理,\(y=1\)時,後項為1,只剩下前項。所以這個式子就可以表示預測準確的概率,我們希望這個概率儘量大。顯然,\(P(y|x)>0\),所以我們可以對它求對數,因為log函式是單調的。所以\(P(y|x)\)取最值時的取值,就是\(logP(y|x)\)取最值的取值。

\[\log P(y|x)=y\log \hat{y} + (1-y)\log (1-\hat{y})\]

我們期望這個值最大,也就是期望它的相反數最小,我們令\(J=-\log P(y|x)\),這樣就得到了它的損失函式:

\[J(\theta)=-\frac{1}{m}Y\log \hat{Y} + (1-Y)\log (1-\hat{Y})\]

如果知道交叉熵這個概念的同學,會發現這個損失函式的表示式其實就是交叉熵。交叉熵是用來衡量兩個概率分佈之間的”距離“,交叉熵越小說明兩個概率分佈越接近,所以經常被用來當做分類模型的損失函式。關於交叉熵的概念我們這裡不多贅述,會在之後文章當中詳細介紹。我們隨手推導的損失函式剛好就是交叉熵,這並不是巧合,其實底層是有一套資訊理論的數學邏輯支撐的,我們不多做延伸,感興趣的同學可以瞭解一下。


硬核推導


損失函式有了,接下來就是求梯度來實現梯度下降了。

這個函式看起來非常複雜,要對它直接求偏導過於硬核(危),如果是許久不碰高數的同學直接肝不亞於硬抗葦名一心。

為了簡化難度,我們先來做一些準備工作。首先,我們先來看下\(\sigma\)函式,它本身的形式很複雜,我們先把它的導數搞定。

\[ \begin{aligned} (\frac{1}{1+e^{-x}})'&=\frac{e^{-x}}{(1+e^{-x})^2} \\ &=\frac{1+e^{-x}-1}{(1+e^{-x})^2} \\ &=\frac{1}{1+e^{-x}}\cdot (1-\frac{1}{1+e^{-x}}) \\ &=\sigma(x) (1-\sigma(x)) \end{aligned} \]

因為\(\hat{y}=\sigma(\theta X)\),我們將它帶入損失函式,可以得到,其中\(\sigma(\theta)=\sigma(\theta X)\):

\[J(\theta)=-\frac{1}{m}Y\log \sigma(\theta) + (1 - Y)\log( 1- \sigma(\theta))\]

接著我們求\(J(\theta)\)對\(\theta\)的偏導,這裡要代入上面對\(\sigma(x)\)求導的結論:

\[ \begin{aligned} \frac{\partial}{\partial \theta}J(\theta)&=-\frac{1}{m}(Y\cdot \frac{1}{\sigma(\theta)}\cdot \sigma'(\theta)+(1-Y)\cdot \frac{1}{1-\sigma(\theta)}\cdot \sigma'(\theta)\cdot(-1)) \\ &=-\frac{1}{m}(Y\cdot \frac{1}{\sigma(\theta)}\cdot \sigma(\theta)(1-\sigma(\theta))\cdot X-(1-Y)\cdot \frac{1}{1-\sigma(\theta)}\cdot \sigma(\theta)(1-\sigma(\theta))\cdot X) \\ &=-\frac{1}{m}(Y(1-\sigma(\theta)) - \sigma(\theta)+Y\cdot \sigma(\theta))\cdot X\\ &=-\frac{1}{m}(\sigma(\theta) - Y)\cdot X\\ &=-\frac{1}{m}(\hat{Y} - Y)\cdot X \end{aligned} \]


程式碼實戰


梯度的公式都推出來了,離寫程式碼實現還遠嗎?

不過巧婦難為無米之炊,在我們擼模型之前,我們先試著造一批資料。

我們選擇生活中一個很簡單的場景——考試。假設每個學生需要參加兩門考試,兩門考試的成績相加得到最終成績,我們有一批學生是否合格的資料。希望設計一個邏輯迴歸模型,幫助我們直接計算學生是否合格。

為了防止sigmoid函式產生偏差,我們把每門課的成績縮放到(0, 1)的區間內。兩門課成績相加超過140分就認為總體及格。

import numpy as np
def load_data():
    X1 = np.random.rand(50, 1)/2 + 0.5
    X2 = np.random.rand(50, 1)/2 + 0.5
    y = X1 + X2
    Y = y > 1.4
    Y = Y + 0
    x = np.c_[np.ones(len(Y)), X1, X2]
    return x, Y

這樣得到的訓練資料有兩個特徵,分別是學生兩門課的成績,還有一個偏移量1,用來記錄常數的偏移量。

接著,根據上文當中的公式,我們不難(真的不難)實現sigmoid以及梯度下降的函式。

def sigmoid(x):
    return 1.0/(1+np.exp(-x))
    
def gradAscent(data, classLabels):
    X = np.mat(data)
    Y = np.mat(classLabels)
    m, n = np.shape(dataMat)
    # 學習率
    alpha = 0.01
    iterations = 10000
    wei = np.ones((n, 1))
    for i in range(iterations):
        y_hat = sigmoid(X * wei)
        error = Y - y_hat
        wei = wei + alpha * X.transpose()*error
    return wei

這段函式實現的是批量梯度下降,對Numpy熟悉的同學可以看得出來,這就是在直接套公式。

最後,我們把資料集以及邏輯迴歸的分割線繪製出來。

import matplotlib.pyplot as plt
def plotPic():
    dataMat, labelMat = load_data()
    #獲取梯度
    weis = gradAscent(dataMat, labelMat).getA()
    n = np.shape(dataMat)[0]
    xc1 = []
    yc1 = []
    xc2 = []
    yc2 = []
    #資料按照正負類別劃分
    for i in range(n):
        if int(labelMat[i]) == 1:
            xc1.append(dataMat[i][1])
            yc1.append(dataMat[i][2])
        else:
            xc2.append(dataMat[i][1])
            yc2.append(dataMat[i][2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xc1, yc1, s=30, c='red', marker='s')
    ax.scatter(xc2, yc2, s=30, c='green')
    #繪製分割線
    x = np.arange(0.5, 1, 0.1)
    y = (-weis[0]- weis[1]*x)/weis[2]
    ax.plot(x, y)
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.show()

最後得到的結果如下:


隨機梯度下降版本


可以發現,經過了1萬次的迭代,我們得到的模型已經可以正確識別所有的樣本了。

我們剛剛實現的是全量梯度下降演算法,我們還可以利用隨機梯度下降來進行優化。優化也非常簡單,我們計算梯度的時候不再是針對全量的資料,而是從資料集中選擇一條進行梯度計算。

基本上可以複用梯度下降的程式碼,只需要對樣本選取的部分加入優化。

def stocGradAscent(data, classLab, iter_cnt):
    X = np.mat(data)
    Y = np.mat(classLab)
    m, n = np.shape(dataMat)
    weis = np.ones((n, 1))
    for j in range(iter_cnt):
        for i in range(m):
            # 使用反比例函式優化學習率
            alpha = 4 / (1.0 + j + i) + 0.01
            randIdx = int(np.random.uniform(0, m))
            y_hat = sigmoid(np.sum(X[randIdx] * weis))
            error = Y[randIdx] - y_hat
            weis = weis + alpha * X[randIdx].transpose()*error
    return weis

我們設定迭代次數為2000,最後得到的分隔影象結果如下:

當然上面的程式碼並不完美,只是一個簡單的demo,還有很多改進和優化的空間。只是作為一個例子,讓大家直觀感受一下:其實自己親手寫模型並不難,公式的推導也很有意思。這也是為什麼我會設定高數專題的原因。CS的很多知識也是想通的,在學習的過程當中靈感迸發旁徵博引真的是非常有樂趣的事情,希望大家也都能找到自己的樂趣。

今天的文章就是這些,如果覺得有所收穫,請順手掃碼點個關注吧,你們的舉手之勞對我來說很重要。

相關推薦

機器學習——線性迴歸邏輯迴歸詳細推導程式碼

本文始發於個人公眾號:TechFlow,原創不易,求個關注 在之前的文章當中,我們推導了線性迴歸的公式,線性迴歸本質是線性函式,模型的原理不難,核心是求解模型引數的過程。通過對線性迴歸的推導和學習,我們基本上了解了機器學習模型學習的過程,這是機器學習的精髓,要比單個模型的原理重要得多。 新關注和有所遺忘的同

Andrew Ng斯坦福機器學習 Programming Exercise 2——邏輯迴歸

作業說明   Exercise 2,Week 3,使用Octave實現邏輯迴歸模型。資料集  ex2data1.txt ,ex2data2.txt   實現 Sigmoid 、代價函式計算Computing Cost 和 梯度下降Gradient Descent。   檔案清單

機器學習(四)邏輯迴歸模型訓練

本篇不講演算法 只講用Python (pandas, matplotlib, numpy, sklearn) 進行訓練的一些要點 1.合併index np.concatenate([index1,index2]) 2.from sklearn.cross_va

機器學習(一)邏輯迴歸與softmax迴歸程式碼示例

本文適合已經對機器學習、人工智慧有過一定了解,但是還沒有自己寫過程式碼,或者一直在使用現有框架的同學。不用框架自己寫一次程式碼的過程還是很有必要的,能讓你真正地理解原理與機器學習中各個步驟的實現過程,而不是停留在“好像懂了”、只會調庫的階段。 目錄

機器學習總結之----2.邏輯迴歸

我也只是在學習的過程中,相當於自己理解推導一遍做個筆記,參考了別人很多東西,文末有相關連結。 什麼是邏輯迴歸 邏輯迴歸也叫做對數機率迴歸,但它卻用來做二分類。 線性迴歸產生的預測值為 z=θTxz = \theta^{T}xz=θTx,線性迴歸通常用來做迴歸。

機器學習演算法之: 邏輯迴歸 logistic regression (LR)

by joey周琦 LR介紹 邏輯迴歸屬於probabilistic discriminative model這一類的分類演算法 probabilistic discriminative mode這類演算法的思路如下: - 直接建模 P(Ck|x)

吳恩達-機器學習(3)-分類、邏輯迴歸、多分類、過擬合

文章目錄 Classification and Representation Classification Hypothesis Representation Decision Boundary

機器學習筆記之七——邏輯迴歸簡單推導、softmax簡單理解以及sklearn中邏輯迴歸常用引數解釋

邏輯迴歸 對邏輯迴歸的理解:對線性迴歸的假設函式的 f(x) 又套上了一層sigmoid函式,即g(f(x)). 然後sigmoid函式是長這樣的: 它的影象長這樣: 對於線性迴歸得到的結果,再經過一層sigmoid函式,以x=0為界限,左邊為0,右邊為1,邏輯迴歸就是這樣一個二分類

機器學習筆記3:邏輯迴歸

機器學習筆記3:邏輯迴歸 Andrew Ng機器學習課程學習筆記3 邏輯迴歸就是分類問題,比如把郵件標示為垃圾郵件和正常郵件,判斷腫瘤是良性的還是惡性的. Sigmoid function 線性迴歸方程中,hθ(x) 的取值y是連續的,而邏輯迴歸中輸出則是離散的。以兩個類別

機器學習筆記04:邏輯迴歸(Logistic regression)、分類(Classification)

說明:本文章所有圖片均屬於Stanford機器學課程,轉載請註明出處 面對一些類似迴歸問題,我們可以通過線性迴歸方法來擬合一個函式,以此來預測資料,但它的輸出是連續的。有時候呢,我們需要一種方法給出一個判定結果,例如”同意(agree)”、”不同意

機器學習之核函式邏輯迴歸機器學習技法)

從軟間隔SVM到正則化從引數ξ談起在軟間隔支援向量機中引數ξ代表某一個資料點相對於邊界犯錯的程度,如下圖:在資料點沒有違反邊界時ξ的值為0,在違反邊界時的值就會大於0。所以總的來說ξ的值等於max(1 - y(WZ + b) , 0)。所以我們把問題合併如下:這樣這個問題就變

用Python開始機器學習(7:邏輯迴歸分類)

在本系列文章中提到過用Python開始機器學習(3:資料擬合與廣義線性迴歸)中提到過迴歸演算法來進行數值預測。邏輯迴歸演算法本質還是迴歸,只是其引入了邏輯函式來幫助其分類。實踐發現,邏輯迴歸在文字分類領域表現的也很優秀。現在讓我們來一探究竟。1、邏輯函式假設資料集有n個獨立的

機器學習之SVM與邏輯迴歸的聯絡區別

  通常說的SVM與邏輯迴歸的聯絡一般指的是軟間隔的SVM與邏輯迴歸之間的關係,硬間隔的SVM應該是與感知機模型的區別和聯絡。而且工程中也不能要求所有的點都正確分類,訓練資料中噪聲的存在使得完全正確分類很可能造成過擬合。   軟間隔SVM與邏輯迴歸的聯絡   要說軟間隔SVM與聯絡就要看軟間隔SVM的緣由。

Stanford機器學習---第三週.邏輯迴歸、正則化

第三週 邏輯迴歸與正則化 學完前三週簡要做個總結,梳理下知識框架: 第一講 邏輯迴歸Logistic Regression 1.分類問題Classification Problem for e

入門機器學習演算法交易:邏輯迴歸的理論交易

目前股市的量化交易已經成為了人工智慧研究的一個熱門領域,很多計算機人員都想利用自己的程式設計技術去量化交易,也有很多的金融人員想要學習程式設計技術。如果你想知道一些方法論上面的知識,可以檢視我上一個文章。本次 Chat,文章會一步一步向你介如何用最簡單的邏輯迴歸在股票資料上面

機器學習系列(3)_邏輯迴歸應用之Kaggle泰坦尼克之災

1.引言 先說一句,年末雙十一什麼的一來,真是非(mang)常(cheng)歡(gou)樂(le)!然後push自己抽出時間來寫這篇blog的原因也非常簡單: 寫完前兩篇邏輯迴歸的介紹和各個角度理解之後,我們討論群(戳我入群)的小夥伴們紛紛表示『好像很

Coursera機器學習-第三週-邏輯迴歸Logistic Regression

Classification and Representation 1. Classification Linear Regression (線性迴歸)考慮的是連續值([0,1]之間的數)的問題,而Logistic Regression(邏輯迴歸)考

機器學習(三):理解邏輯迴歸及二分類、多分類程式碼實踐

本文是[機器學習系列](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzUxMjU4NjI4MQ==&action=getalbum&album_id=1696710764742393857&scene=173&from_msgi

ML-64: 機器學習線性判別分析(Linear Discriminant Analysis)降維演算法+程式碼

線性判別分析(Linear Discriminant Analysis)降維演算法 機器學習分為監督學習、無監督學習和半監督學習(強化學習)。無監督學習最常應用的場景是聚類(clustering)和降維(dimension reduction)。聚類演算法包括

收藏機器學習的Pytorch實現資源集合下載連結

該專案用pytorch實現了從最基本的機器學習演算法:迴歸、聚類,到深度學習、強化學習等。該專案