【機器學習算法系列】邏輯回歸

一、原理簡述

1.1 LR定義

邏輯回歸(Logistic Regression)削葱,簡稱LR,是目前較流行使用廣泛的一種學習算法淳梦,用于解決預測的變量y是離散值的二分類問題析砸。例如:判斷一封電子郵件是否是垃圾( 0 or 1)。Y=0表示為非垃圾郵件爆袍,Y=1為是垃圾郵件首繁,這里的響應變量是一個兩點(0-1)分布變量,但不能用h函數(shù)連續(xù)的值來預測因變量Y螃宙,只能取0或1解決二分類問題。

邏輯回歸的模型本質(zhì)上是一個線性回歸模型所坯,假設因變量 ?? 服從伯努利分布谆扎,通過Sigmoid函數(shù)引入了非線性因素處理0/1分類問題。

1.2 Sigmoid函數(shù)

邏輯回歸模型的假設是: h??(??) = ??(??????) 其中: ?? 代表特征向量 ?? 代表邏輯函數(shù)(logistic function)是一個常用的邏輯函數(shù)為 S 形函數(shù)(Sigmoid function) 芹助,該模型的輸出變量范圍始終在 0 和 1 之間 堂湖。公式為:

image.png

該函數(shù)的圖像為:

image.png

邏輯回歸模型的假設:

h?? (??) = ?? (?? = 1|??; ??)

h??(??)的作用是闲先,對于給定的輸入變量,根據(jù)選擇的參數(shù)計算輸出變量=1 的可能性无蜂,例如伺糠,假設給定的??,通過已經(jīng)確定的參數(shù)計算得出h?? (??) = 0.7斥季,則表示有 70%的幾率??為正向類训桶,相應地??為負向類的幾率為 1-0.7=0.3 。

1.3 決策邊界

決策邊界(decision boundary) 可以理解為將樣本劃分為不同類別的一條邊界酣倾。

image.png

在邏輯回歸中舵揭,我們預測:

當h??(??) >= 0.5時,預測 ?? = 1躁锡。

當h??(??) < 0.5時午绳,預測 ?? = 0。

根據(jù)上面繪制出的 S 形函數(shù)圖像映之,我們知道當

??=0 時 ??(??)=0.5

??>0 時 ??(??)>0.5

??<0 時 ??(??)<0.5

又 ?? = ?????? 拦焚,即:

?????? >= 0 時,預測 ?? = 1

?????? < 0 時杠输,預測 ?? = 0

sigmoid函數(shù)將回歸函數(shù)得到的值求得一個介于0和1之間的概率赎败,當h??(??)>0.5時,預測值為1抬伺,ph??(??)<0.5時螟够,預測值為0。那么h??(??)=0.5就是一個臨界值峡钓,此時e的系數(shù)就是0妓笙,決策邊界的公式為:

圖片

這里引用Andrew Ng 課程上的兩張圖來解釋這個問題:

1.3.1 線性決策邊界

image.png

參數(shù)?? 是向量[-3 1 1]。 則當?3 + ??1 + ??2 ≥ 0能岩,即??1 + ??2 ≥ 3時寞宫,模型將預測 ?? = 1。 我們可以繪制直線??1 + ??2 = 3拉鹃,這條線便是我們模型的分界線辈赋,將預測為 1 的區(qū)域和預 測為 0 的區(qū)域分隔開。

1.3.1 非線性決策邊界

image.png

因為需要用曲線才能分隔 ?? = 0 的區(qū)域和 ?? = 1 的區(qū)域膏燕,我們需要二次方特征: h (??)=??(?? +?? ?? +?? ?? +?? ??2 +?? ??2)是[-1 0 0 1 1]钥屈,則我們得到的判定邊界恰好是圓點在原點且半徑為 1 的圓形。

1.4 代價函數(shù)

對于線性回歸模型坝辫,我們定義的代價函數(shù)是所有模型誤差的平方和篷就。 公式為:

image.png

但對于邏輯回歸來說,邏輯回歸是一個非凸函數(shù)(non-convexfunction)近忙,意味著會出現(xiàn)很多局部最小值竭业,這也將會影響梯度下降算法尋找全局最優(yōu)解智润。

邏輯回歸的代價函數(shù)為:

image.png

!

image.png

h??(??)與 ????????(h??(??),??)之間的關系如下圖所示:


image.png
image.png

當實際的 ?? = 1 且h??(??)也為 1 時誤差為 0, 當 ?? = 1 但h??(??)不為 1 時誤差隨著h??(??)變小而變大;當實際的 ?? = 0 且h??(??)也為 0 時 代價為 0未辆,當?? = 0 但h??(??)不為 0 時誤差隨著 h??(??)的變大而變大窟绷。

image.png

1.5 梯度下降法

最小化代價函數(shù)的方法,是使用梯度下降法(gradient descent)咐柜。 梯度下降中的梯度指的是代價函數(shù)對各個參數(shù)的偏導數(shù)兼蜈,偏導數(shù)的方向決定了在學習過程中參數(shù)下降的方向,學習率(通常用α表示)決定了每步變化的步長炕桨,有了導數(shù)和學習率就可以使用梯度下降算更新參數(shù), 即 :

image.png

1.6 多類別分類:一對多

邏輯回歸本身只能解決二分類問題饭尝,但可以通過一些方法使得二分類轉(zhuǎn)換成多分類問題。常見的方式有OvR和OvO兩種献宫。

舉個例子钥平,如果一個病人因為鼻塞來去醫(yī)院看病,他可能并沒有生病姊途,用 ?? = 1 這個類別來代表涉瘾;或者患了感冒,用 ?? = 2 來代表捷兰;或者得了流感用?? = 3來代表立叛。例子為一個多分類問題。前面我們已經(jīng)知道使用邏輯回歸進行二元分類贡茅,對于直線或許你也知道秘蛇,可以將數(shù)據(jù)集一分為二為正類和負類。用一對多的分類思想顶考,我們可以將其用在多類分類問題上赁还,這種方法為"一對余"方法 ,也稱OvR(One vs Rest)驹沿。

image.png

上圖為多分類轉(zhuǎn)換成二分類過程艘策,圖中原有紅、藍渊季、紫朋蔫、綠四個類別。以左下角為例却汉,假設紅色類標記為正向類(?? = 1)驯妄,而灰色類(除紅色外的其他類標記為負向類(?? = 0)。接著合砂,類似地選擇另一個類標記為正向類(?? = 2)青扔,再將其它類都標記為負向類,最后我們得到一系列的模型簡記為: h?? (??)(??) = ??(?? = ??|??; ??)其中:?? = (1,2,3. . . . ??) 。

簡單來說赎懦,OvR的思路是將所有類別分為兩個類,當前類別是一類幻工,其他類別合并視為一個類励两。有K個類別的數(shù)據(jù)樣本就會被分為K個由兩個類組成的新樣本集合,這樣就將多分類問題轉(zhuǎn)化為二分類問題囊颅,然后對每個數(shù)據(jù)樣本進行模型訓練当悔,得到模型使用樣本進行驗證,選擇分類得分最高的作為最終的樣本類別踢代。

二盲憎、代碼實現(xiàn)

2.1 手寫批量梯度下降

import numpy as np
from sklearn.metrics import mean_squared_error
import sklearn.datasets as dataset
from sklearn.model_selection import train_test_split

class Logistic_Regression:

    def __init__(self):
        '''
        初始化Logistic Regression模型
        '''
        self.coef_ = None
        self.interept_ = None
        self._theta = None

    def _sigmoid(self, t):
        '''
        sigmoid函數(shù)
        :param t:
        :return:
        '''
        return 1 / (1 + np.exp(-t))
    def fit(self, X_train, y_train, eta=0.01, n_iters=1e4, epsilon=0.0001):
        '''
        梯度下降
        :param X_train:
        :param y_train:
        :param eta:
        :param n_iters:
        :return:
        '''
        assert X_train.shape[0] == y_train.shape[0], 'the size of X_train must equals the size of y_train'

        def J(theta, X_b, y):
            '''
            計算代價
            :param theta:
            :param X_b:
            :param y:
            :return:
            '''
            y_hat = self._sigmoid(X_b.dot(theta))
            try:
                return - np.sum(y * np.log(y_hat) + (1 - y) * np.log(1 - y_hat)) / len(y)
            except:
                return float('inf')
        def dJ(theta, X_b, y):
            '''
            計算梯度
            :param theta:
            :param X_b:
            :param y:
            :return:
            '''
            return X_b.T.dot(self._sigmoid(X_b.dot(theta)) - y) / len(X_b)

        def gradient_descent(X_b, y, theta_init, eta=eta, n_iters=n_iters, epsilon=epsilon):
            '''
            梯度下降
            :param X_b:
            :param y:
            :param theta_init:
            :param eta:
            :param n_iters:
            :param epsilon:
            :return:
            '''
            theta = theta_init
            cur_iters = 0

            while cur_iters < n_iters:
                gradient = dJ(theta, X_b, y)
                last_theta = theta
                theta = theta - gradient * eta
                if abs(J(theta, X_b, y) - J(last_theta, X_b, y)) < epsilon:
                    break
                cur_iters = cur_iters + 1

            return theta

        X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
        theta_init = np.zeros(X_b.shape[1])
        self._theta = gradient_descent(X_b, y_train, theta_init, eta, n_iters, epsilon)
        self.interept_ = self._theta[0]
        self.coef_ = self._theta[1:]
        return self

    def predict_probability(self, X_test):
        '''
        預測概率函數(shù)
        :param X_test:
        :return:
        '''
        assert self.coef_ is not None, 'coef can not be None'
        assert X_test.shape[1] == len(self.coef_), 'the size of X_test must equals the size of coef'

        X_b = np.hstack([np.ones((len(X_test), 1)), X_test])
        return self._sigmoid(X_b.dot(self._theta))
    def predict(self, X_test):
        '''
        預測函數(shù)
        :param X_test:
        :return:
        '''
        assert self.coef_ is not None, 'coef can not be None'
        assert X_test.shape[1] == len(self.coef_), 'the size of X_test must equals the size of coef'

        prob = self.predict_probability(X_test)
        return np.array(prob >= 0.5, dtype='int')

    def mse(self, X_test, y_test):
        '''
        測試預測準確度
        :param X_test:
        :param y_test:
        :return:
        '''
        y_predict = self.predict(X_test)
        return mean_squared_error(y_predict, y_test)

data = dataset.load_iris()
X = data.data
y = data.target
X = X[y < 2, :2]
y = y[y<2]
X_train, X_test, y_train, y_test = train_test_split(X, y)
logistics = Logistic_Regression()
logistics.fit(X_train, y_train)
mse = logistics.mse(X_test, y_test)
print(mse)
print("the coef of 2 features:"f )

定義一個Logistic_Regression類,通過coef_和interept_記錄特征的系數(shù)和回歸曲線的截距胳挎。fit()函數(shù)封裝了梯度下降相關的所有函數(shù)饼疙,包括代價函數(shù)J、求梯度的函數(shù)dJ以及梯度下降函數(shù)gradient_descent()慕爬,gradient_descent()函數(shù)的執(zhí)行過程和總結線性回歸時的批量梯度下降基本一樣窑眯,不過是代價函數(shù)和求梯度的方式有所變化而已。之后可以調(diào)用predict()方法進行測試預測并使用mse函數(shù)求預測值與實際值之間的均方誤差檢驗模型預測效果医窿。

聲明:此文章為本人學習筆記磅甩,課程來源于:
1、吳恩達機器學習課程
2姥卢、慕課網(wǎng):python3入門機器學習經(jīng)典算法與應用卷要。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市独榴,隨后出現(xiàn)的幾起案子僧叉,更是在濱河造成了極大的恐慌,老刑警劉巖括眠,帶你破解...
    沈念sama閱讀 221,406評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彪标,死亡現(xiàn)場離奇詭異,居然都是意外死亡掷豺,警方通過查閱死者的電腦和手機捞烟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來当船,“玉大人题画,你說我怎么就攤上這事〉缕担” “怎么了苍息?”我有些...
    開封第一講書人閱讀 167,815評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我竞思,道長表谊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,537評論 1 296
  • 正文 為了忘掉前任盖喷,我火速辦了婚禮爆办,結果婚禮上,老公的妹妹穿的比我還像新娘课梳。我一直安慰自己距辆,他們只是感情好,可當我...
    茶點故事閱讀 68,536評論 6 397
  • 文/花漫 我一把揭開白布暮刃。 她就那樣靜靜地躺著跨算,像睡著了一般。 火紅的嫁衣襯著肌膚如雪椭懊。 梳的紋絲不亂的頭發(fā)上诸蚕,一...
    開封第一講書人閱讀 52,184評論 1 308
  • 那天,我揣著相機與錄音氧猬,去河邊找鬼挫望。 笑死,一個胖子當著我的面吹牛狂窑,可吹牛的內(nèi)容都是我干的媳板。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼泉哈,長吁一口氣:“原來是場噩夢啊……” “哼蛉幸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起丛晦,我...
    開封第一講書人閱讀 39,668評論 0 276
  • 序言:老撾萬榮一對情侶失蹤奕纫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后烫沙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體匹层,經(jīng)...
    沈念sama閱讀 46,212評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,299評論 3 340
  • 正文 我和宋清朗相戀三年锌蓄,在試婚紗的時候發(fā)現(xiàn)自己被綠了升筏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,438評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡瘸爽,死狀恐怖您访,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情剪决,我是刑警寧澤灵汪,帶...
    沈念sama閱讀 36,128評論 5 349
  • 正文 年R本政府宣布檀训,位于F島的核電站,受9級特大地震影響享言,放射性物質(zhì)發(fā)生泄漏峻凫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,807評論 3 333
  • 文/蒙蒙 一览露、第九天 我趴在偏房一處隱蔽的房頂上張望蔚晨。 院中可真熱鬧,春花似錦肛循、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至浩考,卻和暖如春夹孔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背析孽。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評論 1 272
  • 我被黑心中介騙來泰國打工搭伤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人袜瞬。 一個月前我還...
    沈念sama閱讀 48,827評論 3 376
  • 正文 我出身青樓怜俐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親邓尤。 傳聞我的和親對象是個殘疾皇子拍鲤,可洞房花燭夜當晚...
    茶點故事閱讀 45,446評論 2 359

推薦閱讀更多精彩內(nèi)容