機器學習實踐系列3——二項邏輯回歸

本文主要介紹邏輯回歸的基本概念,并結合實際案例說明邏輯回歸的應用。

從線性回歸到邏輯回歸

在【機器學習系列2——線性回歸】和【機器學習系列3——多項式回歸】中我們結合實際案例解釋了線性回歸的基本概念和應用。線性回歸解決的是連續型數值的預測問題,例如預測房價,產品銷量等。
但是生活中存在大量的分類問題,例如:判斷垃圾短息,垃圾郵件;銀行判斷是否給用戶放貸;電商判斷用戶是否會喜歡某類商品,從而確定是否要推薦給用戶等等;
解決以上這類問題,線性回歸不再適用,我們需要采用邏輯回歸(Logistic Regression)。

邏輯回歸解決的是分類問題,從分類數量上看,有二項分類多項分類
二項分類一般是0和1,或者True和False的問題,例如預測病人是否患某種疾病;
多項分類中,分類標簽比較多,例如根據歌詞將歌曲分類,可以有多種類別:民謠,搖滾,輕音樂,說唱等等。我們通常把構建的用于分類的邏輯回歸模型叫做分類器

雖然機器學習算法中還有很多其他的分類算法,但邏輯回歸是最常用的,也是首選的分類算法,它的原理非常簡單,但是分類能力非常強大。一般我們拿到一個分類問題,都會先用邏輯回歸看一下效果,然后再去嘗試復雜的算法,看能否在邏輯回歸的效果基礎上有進一步的效果改進。

邏輯回歸基本概念

假設t為連續隨機變量,則t服從邏輯分布是指,它具有下列分布函數(Sigmoid函數):

該公式包含兩個關鍵的部分:

  • 指數變換:將所有的數值轉換為正數,即e^t
  • 歸一化:將所有數值轉換為0到1之間的數值,即1/(1+t)

所以邏輯函數輸出的,是0到1之間的數值,表示的是一個概率。

我們可以用Python看一下邏輯分布函數的圖形化表示。
由于 t = 6的時候,邏輯分布函數 f(t) 的值趨近于1,t = -6時,f(t) 的值趨近于0,因此我們觀察 t = {-6,6} 范圍內的邏輯分布函數圖形:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

x = np.arange(-6,6,0.01)
y = np.exp(x)/(1 + np.exp(x))

plt.figure()
plt.axis([-6,6,0,1])
plt.grid(True)
plt.plot(x, y)
plt.show()

一般化邏輯回歸模型

我們一般定義邏輯回歸模型的預測函數如下:

其中:

其實這就是我們的一元線性回歸模型;一元線性回歸的輸出結果取值范圍是負無窮到正無窮,把它的輸出結果,當做邏輯回歸模型的輸入,我們就把數值問題,映射為了(0,1)之間的數值,從而轉換成為了分類問題(0還是1),即求y=1的概率問題(一般概率大于0.5,分類為1,概率小于0.5,分類為0)。

二項邏輯回歸模型

所謂二項邏輯回歸,就是y的取值只有兩種可能:我們一般分別用0和1表示。
它的模型表示如下:

也即整合后的模型:

只要計算出θ參數的值,我們就能根據輸入x來分別計算y = 0和y=1的概率,根據概率大小,就可以判斷x應該歸類到0還是1。
一般我們可以簡化二項邏輯回歸模型,用基本的邏輯回歸模型表示:

案例

假設我們有一個樣本大小為50的GPA成績和錄取與否的樣本數據,我們希望通過邏輯回歸,根據GPA成績預測學生是否能被錄取。數據樣例如下所示,其中【gpa】是介于0到5之間的數值,表示學生的GPA成績,【Admission】0代表沒有錄取,1代表被錄取:

ID gpa Admission
1 3.177 0
2 3.412 0
3 2.728 0
4 4.523 1
5 3.781 1

數據基本信息探索:


我們使用Scikit-learn的linear_model中的LogisticRegression來做邏輯回歸。

from sklearn.linear_model import LogisticRegression
from sklearn.cross_validation import train_test_split, cross_val_score

#讀取數據
data = pd.read_csv('admissions.csv')

#拆分訓練集和測試集
xtrain, xtest, ytrain, ytest = train_test_split(data['gpa'], data['Admission'])
x_train = xtrain.reshape(len(xtrain),1)
y_train = ytrain.reshape(len(ytrain),1)
x_test = xtest.reshape(len(xtest),1)
y_test = ytest.reshape(len(ytest),1)

#初始化模型
lor = LogisticRegression()

#擬合
lor.fit(x_train, y_train)

#預測,其中predict預測函數返回標簽數值,即0或者1,predict_proba函數返回概率數值,即標簽為0的概率和標簽為1的概率,它是基于默認的0.5為閾值,概率大于0.5,標簽為1,概率小于0.5,標簽為0
pred_label = pd.DataFrame(lor.predict(x_test), columns=['label'])
pred_proba = pd.DataFrame(lor.predict_proba(x_test), columns=['proba_0', 'proba_1'])

#數據合并
gpa = pd.DataFrame(x_test, columns=['gpa'])
admission = pd.DataFrame(y_test, columns=['admission'])
pd.concat([gpa, admission, pred_label, pred_proba], axis = 1)

最終預測所得結果如下:

預測結果 VS 實際結果

模型效果評估

二項分類模型效果的評估方法有很多,常用的有準確率(accuracy),精確率(precision),召回率(recall),ROC(Receiver Operating Characteristic),AUC(Area Under the Curve)。

準確率

準確率 = 正確預測數 / 測試集樣本數
在上面的栗子中,我們的測試集樣本數 = 13,其中正確預測的(admission = label)有8個,所以這里準確率 = 8 / 13 = 0.61538461538461542

我們也可以用Scikit-learn中自帶的方法來計算準確率:

from sklearn.metrics import accuracy_score
accuracy = accuracy_score(admission, pred_label)

但是準確度只能用來評估模型在測試集上的準確度,無法評估非測試集的預測準確度。

精確率

首先來看一下,在二項分類問題中,我們可以將觀察值和預測值的關系用以下混淆矩陣表示出來:

二項分類—混淆矩陣

精確率 = TP / (TP + FP)

在上面的栗子中,精確率指的是,在預測出來的被錄取學生人數中,有多少是真正被錄取的。所以測試集反映出的 精確率 = 7/12 = 0.5833333333333334

召回率

召回率在醫學領域也叫做靈敏度(Sensitivity),它反映的是在模型識別陽性結果(Positive Result)的效果。

召回率 = TP / (TP + FN)

在上面的栗子中指的是,在正真被錄取的學生人數中,被正確正確預測出來的人數。所以測試集反映的 召回率 = 7/7 = 1。

可以看出,精確率和召回率各自含有的信息都很少,它們對分類器效果的觀察角度不同。精確率和召回率都不能從表現差的一種分類器中區分出好的分類器。

Scikit-learn中提供了計算精確率和召回率的計算函數,我們介紹使用方法之前,順便介紹一下K折交叉驗證(K-Fold Cross Validation)

我們在【機器學習系列1——機器學習概況】中介紹到,在數據集本身非常少,可能存在訓練集不夠而無法很好的構建模型的情 況下,可以使用交叉驗證方法。主體思想就是將數據集分成K等份,用其中K-1份做訓練,剩余1份做測試,然后依次迭代。如下圖所示,這里K=5。

K折交叉驗證——K=5

在數據集非常大的情況下,數據集拆分不宜過多,否則迭代將耗費太多時間。

Scikit-learn提供了K折交叉驗證所需要的函數KFold,可以直接調用。

下面我們結合K折交叉驗證,來說明二項分類邏輯回歸中的精確率和召回率的計算。

from sklearn.cross_validation import KFold
from sklearn.cross_validation import cross_val_score

#shuffle = True表示打亂數據集順序,random_state = 1表示在shuffle設置為True的時候,隨機種子的值,相當于如果設置該值,每次執行代碼時,數據集的拆分結果都是固定的,如果不設置,每次數據集的拆分都是隨機的,計算所得結果也會有差異
kf = KFold(len(data), 5, shuffle = True,random_state = 1)

accuracy = cross_val_score(lor, data[['gpa']], data['Admission'], cv = kf, scoring = 'accuracy')
recall = cross_val_score(lor, data[['gpa']], data['Admission'], cv = kf, scoring = 'recall')
precision = cross_val_score(lor, data[['gpa']], data['Admission'], cv = kf, scoring = 'precision')

print('準確率:', accuracy.mean(), accuracy)
print('精確率:', precision.mean(), precision)
print("召回率:", recall.mean(), recall)

所得結果為:
準確率: 0.68 [ 1. 0.3 0.5 0.9 0.7]
精確率: 0.677777777778 [ 1. 0.22222222 0.5 0.83333333 0.83333333]
召回率: 0.942857142857 [ 1. 1. 1. 1. 0.71428571]

由于這里采用了交叉驗證,和之前計算的精確率結果稍有差異。

綜合評價指標(F-measure)

一般情況下,我們希望精確率和召回率都越高越好,但在一些極端情況下,兩者是矛盾的。這時候我們需要用綜合評價指標:精確率和召回率的調和均值(harmonic mean),或加權平均值,也稱為F-measure或F-score。

F-measure = 2 * Precision * Recall / (Precision + Recall)

F-measure 平衡了精確率和召回率。當F-measure較高的時候,說明模型效果比較好。

Scikit-learn中提供了直接計算F-measure的方法:

f1 = cross_val_score(lor, data[['gpa']], data['Admission'], cv = kf, scoring = 'f1')

綜合評價指標: 0.741724941725 [ 1. 0.36363636 0.66666667 0.90909091 0.76923077]

ROC & AUC

介紹ROC之前,需要先介紹假陽性概率(False Positive Rate),即所有陰性樣本中,分類器預測出的假陽性樣本的比率,也叫做誤警率,FPR = FP / (TN + FP)

ROC曲線(Receiver Operating Characteristic curve,ROC curve),是以假陽性概率(誤警率)為橫坐標,以真陽性概率(召回率)為縱坐標所畫的曲線。可以理解為它是一系列混淆矩陣的結果組合所畫出的曲線。一般情況下,我們得到一個回歸模型的混淆矩陣,都是在提前設定好一個閾值的前提下獲得的。例如上面案例中,我們以默認的閾值0.5為界限,得到混淆矩陣如下:

預測值 \ 觀察值 Admitted (1) Rejected (1)
Admitted (1) 7 5
Rejected (1) 0 1

但如果我們調整這個閾值,得到的混淆矩陣就不同了。在模型預測的所有概率中,每一個概率值都可以作為一個閾值,相應的,我們就能得到一系列的混淆矩陣。對于每個混淆矩陣,我們都能計算出相應的假陽性概率FPR和真陽性概率TPR。然后我們以這些FPR為橫坐標軸,以TPR為縱坐標軸,所得到的曲線就是ROC。

Scikit-learn中提供了ROC曲線對應的函數roc_curve,我們根據上面案例,畫出對應的ROC曲線如下:

from sklearn import metrics

probabilities =lor.predict_proba(x_test)
fpr, tpr, thresholds = metrics.roc_curve(y_test, probabilities[:,1])
plt.plot(fpr, tpr)
plt.show()
ROC曲線

因為我們測試集樣本數量太少,畫出來的曲線不太好看。。。

理想的情況下,如果存在一個閾值,大于這個閾值的都是陽性的,低于這個閾值的都是陰性的,那么我們認為這個模型已經能夠非常完美的區分陽性和陰性了,對應到我們的案例中,就是我們找到一個回歸模型,能夠確定一個的閾值,高于這個閾值的都被錄取了,低于這個閾值的都沒有被錄取,那么這個模型就是完美的。此時對應的真陽性概率TPR為1,假陽性概率FPR為0,對應坐標軸上的(0,1)點,即左上角的點。所以如果ROC曲線經過該點,它就是完美的。但事實上,現實生活中不會有這么完美的模型。

AUC(Area Under the Curve)是指ROC曲線下面的面積。從AUC定義的角度來理解,AUC就是從所有標簽為1的樣本中隨機選取一個樣本, 從所有標簽為0的樣本中隨機選取一個樣本,然后根據分類器對兩個隨機樣本進行預測,假設標簽為1的樣本預測為1的概率為p1,標簽為0的樣本預測為1的概率為p0,那么p1>p0的概率就等于AUC。所以AUC反應的是分類器對樣本的排序能力。

一般情況下,AUC值介于0.5和1之間,AUC值越大,說明分類器效果越好,ROC曲線越接近于(0,1)點。AUC值越小,說明分類器效果越差,跟隨機分類沒什么差別,ROC曲線越趨近于下圖中的紅線。如果AUC值小于0.5,則可能是樣本數據標簽出了問題。

ROC & AUC

另外值得注意的是,AUC對樣本類別是否均衡并不敏感,這也是不均衡樣本通常用AUC評價分類器性能的一個原因。

Python中計算AUC值的方法如下:

auc_score = metrics.roc_auc_score(y_test, probabilities[:,1])

auc_score = 0.9285714285714286

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評論 6 540
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,275評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,368評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,736評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,919評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,481評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,235評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,427評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,656評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,160評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,380評論 2 379

推薦閱讀更多精彩內容