邏輯迴歸

日萌社

人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度學習實戰(不定時更新)


 

3.1 邏輯迴歸介紹

邏輯迴歸(Logistic Regression)是機器學習中的一種分類模型,邏輯迴歸是一種分類算法,雖然名字中帶有迴歸。由於算法的簡單和高效,在實際中應用非常廣泛。

1 邏輯迴歸的應用場景

  • 廣告點擊率
  • 是否爲垃圾郵件
  • 是否患病
  • 金融詐騙
  • 虛假賬號

看到上面的例子,我們可以發現其中的特點,那就是都屬於兩個類別之間的判斷。邏輯迴歸就是解決二分類問題的利器

2 邏輯迴歸的原理

要想掌握邏輯迴歸,必須掌握兩點:

  • 邏輯迴歸中,其輸入值是什麼

  • 如何判斷邏輯迴歸的輸出

2.1 輸入

邏輯迴歸的輸入就是一個線性迴歸的結果。

2.2 激活函數

  • sigmoid函數

判斷標準

  • 迴歸的結果輸入到sigmoid函數當中
  • 輸出結果:[0, 1]區間中的一個概率值,默認爲0.5爲閾值

邏輯迴歸最終的分類是通過屬於某個類別的概率值來判斷是否屬於某個類別,並且這個類別默認標記爲1(正例),另外的一個類別會標記爲0(反例)。(方便損失計算)

輸出結果解釋(重要):假設有兩個類別A,B,並且假設我們的概率值爲屬於A(1)這個類別的概率值。現在有一個樣本的輸入到邏輯迴歸輸出結果0.55,那麼這個概率值超過0.5,意味着我們訓練或者預測的結果就是A(1)類別。那麼反之,如果得出結果爲0.3那麼,訓練或者預測結果就爲B(0)類別。

關於邏輯迴歸的閾值是可以進行改變的,比如上面舉例中,如果你把閾值設置爲0.6,那麼輸出的結果0.55,就屬於B類。

在之前,我們用最小二乘法衡量線性迴歸的損失

在邏輯迴歸中,當預測結果不對的時候,我們該怎麼衡量其損失呢?

我們來看下圖(下圖中,設置閾值爲0.6),

那麼如何去衡量邏輯迴歸的預測結果與真實結果的差異呢?

3 損失以及優化

3.1 損失

邏輯迴歸的損失,稱之爲對數似然損失,公式如下:

  • 分開類別:

無論何時,我們都希望損失函數值,越小越好

分情況討論,對應的損失函數值:

接下來我們呢就帶入上面那個例子來計算一遍,就能理解意義了。

3.2 優化

同樣使用梯度下降優化算法,去減少損失函數的值。這樣去更新邏輯迴歸前面對應算法的權重參數,提升原本屬於1類別的概率,降低原本是0類別的概率。


4 小結

  • 邏輯迴歸概念【知道】
    • 解決的是一個二分類問題
    • 邏輯迴歸的輸入是線性迴歸的輸出
  • 邏輯迴歸的原理【掌握】
    • 輸入:
      • 線性迴歸的輸出
    • 激活函數
      • sigmoid函數
      • 把整體的值映射到[0,1]
      • 再設置一個閾值,進行分類判斷
  • 邏輯迴歸的損失和優化【掌握】
    • 損失
      • 對數似然損失
      • 藉助了log思想,進行完成
      • 真實值等於0,等於1兩種情況進行劃分
    • 優化
      • 提升原本屬於1類別的概率,降低原本是0類別的概率。

3.2 邏輯迴歸api介紹

  • sklearn.linear_model.LogisticRegression(solver='liblinear', penalty=‘l2’, C = 1.0)

    • solver可選參數:{'liblinear', 'sag', 'saga','newton-cg', 'lbfgs'},

      • 默認: 'liblinear';用於優化問題的算法。
      • 對於小數據集來說,“liblinear”是個不錯的選擇,而“sag”和'saga'對於大型數據集會更快。

      • 對於多類問題,只有'newton-cg', 'sag', 'saga'和'lbfgs'可以處理多項損失;“liblinear”僅限於“one-versus-rest”分類。

    • penalty:正則化的種類

    • C:正則化力度

默認將類別數量少的當做正例

LogisticRegression方法相當於 SGDClassifier(loss="log", penalty=" "),SGDClassifier實現了一個普通的隨機梯度下降學習。而使用LogisticRegression(實現了SAG)


3.3 案例:癌症分類預測-良/惡性乳腺癌腫瘤預測

1 背景介紹

  • 數據介紹

數據描述

(1)699條樣本,共11列數據,第一列用語檢索的id,後9列分別是與腫瘤

相關的醫學特徵,最後一列表示腫瘤類型的數值。

(2)包含16個缺失值,用”?”標出。

2 案例分析

1.獲取數據
2.基本數據處理
2.1 缺失值處理
2.2 確定特徵值,目標值
2.3 分割數據
3.特徵工程(標準化)
4.機器學習(邏輯迴歸)
5.模型評估

3 代碼實現

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

import ssl
ssl._create_default_https_context = ssl._create_unverified_context
# 1.獲取數據
names = ['Sample code number', 'Clump Thickness', 'Uniformity of Cell Size', 'Uniformity of Cell Shape',
                   'Marginal Adhesion', 'Single Epithelial Cell Size', 'Bare Nuclei', 'Bland Chromatin',
                   'Normal Nucleoli', 'Mitoses', 'Class']

data = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data",
                  names=names)
data.head()
# 2.基本數據處理
# 2.1 缺失值處理
data = data.replace(to_replace="?", value=np.NaN)
data = data.dropna()
# 2.2 確定特徵值,目標值
x = data.iloc[:, 1:10]
x.head()
y = data["Class"]
y.head()
# 2.3 分割數據
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=22)
# 3.特徵工程(標準化)
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4.機器學習(邏輯迴歸)
estimator = LogisticRegression()
estimator.fit(x_train, y_train)
# 5.模型評估
y_predict = estimator.predict(x_test)
y_predict
estimator.score(x_test, y_test)

在很多分類場景當中我們不一定只關注預測的準確率!!!!!

比如以這個癌症舉例子!!!我們並不關注預測的準確率,而是關注在所有的樣本當中,癌症患者有沒有被全部預測(檢測)出來。


4 小結

  • 腫瘤預測案例實現【知道】
    • 如果數據中有缺失值,一定要對其進行處理
    • 準確率並不是衡量分類正確的唯一標準

In [5]:

# 1.獲取數據
# 2.基本數據處理
# 2.1 缺失值處理
# 2.2 確定特徵值,目標值
# 2.3 分割數據
# 3.特徵工程(標準化)
# 4.機器學習(邏輯迴歸)
# 5.模型評估

In [21]:

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, roc_auc_score

In [3]:

# 1.獲取數據
names = ['Sample code number', 'Clump Thickness', 'Uniformity of Cell Size', 'Uniformity of Cell Shape',
                   'Marginal Adhesion', 'Single Epithelial Cell Size', 'Bare Nuclei', 'Bland Chromatin',
                   'Normal Nucleoli', 'Mitoses', 'Class']

data = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data",
                  names=names)

In [4]:

data.head()

Out[4]:

  Sample code number Clump Thickness Uniformity of Cell Size Uniformity of Cell Shape Marginal Adhesion Single Epithelial Cell Size Bare Nuclei Bland Chromatin Normal Nucleoli Mitoses Class
0 1000025 5 1 1 1 2 1 3 1 1 2
1 1002945 5 4 4 5 7 10 3 2 1 2
2 1015425 3 1 1 1 2 2 3 1 1 2
3 1016277 6 8 8 1 3 4 3 7 1 2
4 1017023 4 1 1 3 2 1 3 1 1 2

In [7]:

# 2.基本數據處理
# 2.1 缺失值處理
data = data.replace(to_replace="?", value=np.nan)
data = data.dropna()

In [8]:

# 2.2 確定特徵值,目標值
data.head()

Out[8]:

  Sample code number Clump Thickness Uniformity of Cell Size Uniformity of Cell Shape Marginal Adhesion Single Epithelial Cell Size Bare Nuclei Bland Chromatin Normal Nucleoli Mitoses Class
0 1000025 5 1 1 1 2 1 3 1 1 2
1 1002945 5 4 4 5 7 10 3 2 1 2
2 1015425 3 1 1 1 2 2 3 1 1 2
3 1016277 6 8 8 1 3 4 3 7 1 2
4 1017023 4 1 1 3 2 1 3 1 1 2

In [10]:

x = data.iloc[:, 1:-1]
x.head()

Out[10]:

  Clump Thickness Uniformity of Cell Size Uniformity of Cell Shape Marginal Adhesion Single Epithelial Cell Size Bare Nuclei Bland Chromatin Normal Nucleoli Mitoses
0 5 1 1 1 2 1 3 1 1
1 5 4 4 5 7 10 3 2 1
2 3 1 1 1 2 2 3 1 1
3 6 8 8 1 3 4 3 7 1
4 4 1 1 3 2 1 3 1 1

In [11]:

y = data["Class"]
y.head()

Out[11]:

0    2
1    2
2    2
3    2
4    2
Name: Class, dtype: int64

In [12]:

# 2.3 分割數據
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=22, test_size=0.2)

In [13]:

# 3.特徵工程(標準化)
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)

In [14]:

# 4.機器學習(邏輯迴歸)
estimator = LogisticRegression()
estimator.fit(x_train, y_train)

Out[14]:

LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
          penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
          verbose=0, warm_start=False)

In [15]:

# 5.模型評估
# 5.1 準確率
ret = estimator.score(x_test, y_test)
print("準確率爲:\n", ret)

# 5.2 預測值
y_pre = estimator.predict(x_test)
print("預測值爲:\n", y_pre)

準確率爲:
 0.9854014598540146
預測值爲:
 [2 4 4 2 2 2 2 2 2 2 2 2 2 4 2 2 4 4 4 2 4 2 4 4 4 2 4 2 2 2 2 2 4 2 2 2 4
 2 2 2 2 4 2 4 4 4 4 2 4 4 2 2 2 2 2 4 2 2 2 2 4 4 4 4 2 4 2 2 4 2 2 2 2 4
 2 2 2 2 2 2 4 4 4 2 4 4 4 4 2 2 2 4 2 4 2 2 2 2 2 2 4 2 2 4 2 2 4 2 4 4 2
 2 2 2 4 2 2 2 2 2 2 4 2 4 2 2 2 4 2 4 2 2 2 4 2 2 2]

In [19]:

# 5.3 精確率\召回率指標評價
ret = classification_report(y_test, y_pre, labels=(2, 4), target_names=("良性", "惡性"))
print(ret)

             precision    recall  f1-score   support

         良性       0.99      0.99      0.99        89
         惡性       0.98      0.98      0.98        48

avg / total       0.99      0.99      0.99       137

In [22]:

# 5.4 auc指標計算
y_test = np.where(y_test>3, 1, 0)

roc_auc_score(y_test, y_pre)

Out[22]:

0.9839653558052434

  

3.4 分類評估方法

1.分類評估方法

1.1 精確率與召回率

1.1.1 混淆矩陣

在分類任務下,預測結果(Predicted Condition)與正確標記(True Condition)之間存在四種不同的組合,構成混淆矩陣(適用於多分類)

1.1.2 精確率(Precision)與召回率(Recall)

  • 精確率:預測結果爲正例樣本中真實爲正例的比例(瞭解)

  • 召回率:真實爲正例的樣本中預測結果爲正例的比例(查得全,對正樣本的區分能力)

1.2 F1-score

還有其他的評估標準,F1-score,反映了模型的穩健型

1.3 分類評估報告api

  • sklearn.metrics.classification_report(y_true, y_pred, labels=[], target_names=None )
    • y_true:真實目標值
    • y_pred:估計器預測目標值
    • labels:指定類別對應的數字
    • target_names:目標類別名稱
    • return:每個類別精確率與召回率
ret = classification_report(y_test, y_predict, labels=(2,4), target_names=("良性", "惡性"))
print(ret)

假設這樣一個情況,如果99個樣本癌症,1個樣本非癌症,不管怎樣我全都預測正例(默認癌症爲正例),準確率就爲99%但是這樣效果並不好,這就是樣本不均衡下的評估問題

問題:如何衡量樣本不均衡下的評估

2 ROC曲線與AUC指標

2.1 TPR與FPR

  • TPR = TP / (TP + FN)
    • 所有真實類別爲1的樣本中,預測類別爲1的比例
  • FPR = FP / (FP + TN)
    • 所有真實類別爲0的樣本中,預測類別爲1的比例

2.2 ROC曲線

  • ROC曲線的橫軸就是FPRate,縱軸就是TPRate,當二者相等時,表示的意義則是:對於不論真實類別是1還是0的樣本,分類器預測爲1的概率是相等的,此時AUC爲0.5

2.3 AUC指標

  • AUC的概率意義是隨機取一對正負樣本,正樣本得分大於負樣本得分的概率
  • AUC的範圍在[0, 1]之間,並且越接近1越好,越接近0.5屬於亂猜
  • AUC=1,完美分類器,採用這個預測模型時,不管設定什麼閾值都能得出完美預測。絕大多數預測的場合,不存在完美分類器。
  • 0.5<AUC<1,優於隨機猜測。這個分類器(模型)妥善設定閾值的話,能有預測價值。

2.4 AUC計算API

  • from sklearn.metrics import roc_auc_score
    • sklearn.metrics.roc_auc_score(y_true, y_score)
      • 計算ROC曲線面積,即AUC值
      • y_true:每個樣本的真實類別,必須爲0(反例),1(正例)標記
      • y_score:預測得分,可以是正類的估計概率、置信值或者分類器方法的返回值
# 0.5~1之間,越接近於1約好
y_test = np.where(y_test > 2.5, 1, 0)

print("AUC指標:", roc_auc_score(y_test, y_predict)
  • AUC只能用來評價二分類
  • AUC非常適合評價樣本不平衡中的分類器性能

3 小結

  • 混淆矩陣【瞭解】
    • 真正例(TP)
    • 僞反例(FN)
    • 僞正例(FP)
    • 真反例(TN)
  • 精確率(Precision)與召回率(Recall)【知道】
    • 準確率:(對不對)
      • (TP+TN)/(TP+TN+FN+FP)
    • 精確率 -- 查的準不準
      • TP/(TP+FP)
    • 召回率 -- 查的全不全
      • TP/(TP+FN)
    • F1-score
      • 反映模型的穩健性
  • roc曲線和auc指標【知道】
    • roc曲線
      • 通過tpr和fpr來進行圖形繪製,然後繪製之後,行成一個指標auc
    • auc
      • 越接近1,效果越好
      • 越接近0,效果越差
      • 越接近0.5,效果就是胡說
    • 注意:
      • 這個指標主要用於評價不平衡的二分類問題

3.5 ROC曲線的繪製

學習目標

  • 知道ROC曲線的繪製

關於ROC曲線的繪製過程,通過以下舉例進行說明

假設有6次展示記錄,有兩次被點擊了,得到一個展示序列(1:1,2:0,3:1,4:0,5:0,6:0),前面的表示序號,後面的表示點擊(1)或沒有點擊(0)。

然後在這6次展示的時候都通過model算出了點擊的概率序列。

下面看三種情況。

1 曲線繪製

1.1 如果概率的序列是(1:0.9,2:0.7,3:0.8,4:0.6,5:0.5,6:0.4)。

與原來的序列一起,得到序列(從概率從高到低排)

1 1 0 0 0 0
0.9 0.8 0.7 0.6 0.5 0.4

繪製的步驟是:

1)把概率序列從高到低排序,得到順序(1:0.9,3:0.8,2:0.7,4:0.6,5:0.5,6:0.4);

2)從概率最大開始取一個點作爲正類,取到點1,計算得到TPR=0.5,FPR=0.0;

3)從概率最大開始,再取一個點作爲正類,取到點3,計算得到TPR=1.0,FPR=0.0;

4)再從最大開始取一個點作爲正類,取到點2,計算得到TPR=1.0,FPR=0.25;

5)以此類推,得到6對TPR和FPR。

然後把這6對數據組成6個點(0,0.5),(0,1.0),(0.25,1),(0.5,1),(0.75,1),(1.0,1.0)。

這6個點在二維座標系中能繪出來。

看看圖中,那個就是ROC曲線。

1.2 如果概率的序列是(1:0.9,2:0.8,3:0.7,4:0.6,5:0.5,6:0.4)

與原來的序列一起,得到序列(從概率從高到低排)

1 0 1 0 0 0
0.9 0.8 0.7 0.6 0.5 0.4

繪製的步驟是:

6)把概率序列從高到低排序,得到順序(1:0.9,2:0.8,3:0.7,4:0.6,5:0.5,6:0.4);

7)從概率最大開始取一個點作爲正類,取到點1,計算得到TPR=0.5,FPR=0.0;

8)從概率最大開始,再取一個點作爲正類,取到點2,計算得到TPR=0.5,FPR=0.25;

9)再從最大開始取一個點作爲正類,取到點3,計算得到TPR=1.0,FPR=0.25;

10)以此類推,得到6對TPR和FPR。

然後把這6對數據組成6個點(0,0.5),(0.25,0.5),(0.25,1),(0.5,1),(0.75,1),(1.0,1.0)。

這6個點在二維座標系中能繪出來。

看看圖中,那個就是ROC曲線。

1.3 如果概率的序列是(1:0.4,2:0.6,3:0.5,4:0.7,5:0.8,6:0.9)

與原來的序列一起,得到序列(從概率從高到低排)

0 0 0 0 1 1
0.9 0.8 0.7 0.6 0.5 0.4

繪製的步驟是:

11)把概率序列從高到低排序,得到順序(6:0.9,5:0.8,4:0.7,2:0.6,3:0.5,1:0.4);

12)從概率最大開始取一個點作爲正類,取到點6,計算得到TPR=0.0,FPR=0.25;

13)從概率最大開始,再取一個點作爲正類,取到點5,計算得到TPR=0.0,FPR=0.5;

14)再從最大開始取一個點作爲正類,取到點4,計算得到TPR=0.0,FPR=0.75;

15)以此類推,得到6對TPR和FPR。

然後把這6對數據組成6個點(0.25,0.0),(0.5,0.0),(0.75,0.0),(1.0,0.0),(1.0,0.5),(1.0,1.0)。

這6個點在二維座標系中能繪出來。

看看圖中,那個就是ROC曲線。

2 意義解釋

如上圖的例子,總共6個點,2個正樣本,4個負樣本,取一個正樣本和一個負樣本的情況總共有8種。

上面的第一種情況,從上往下取,無論怎麼取,正樣本的概率總在負樣本之上,所以分對的概率爲1,AUC=1。再看那個ROC曲線,它的積分是什麼?也是1,ROC曲線的積分與AUC相等。

上面第二種情況,如果取到了樣本2和3,那就分錯了,其他情況都分對了;所以分對的概率是0.875,AUC=0.875。再看那個ROC曲線,它的積分也是0.875,ROC曲線的積分與AUC相等。

上面的第三種情況,無論怎麼取,都是分錯的,所以分對的概率是0,AUC=0.0。再看ROC曲線,它的積分也是0.0,ROC曲線的積分與AUC相等。

很牛吧,其實AUC的意思是——Area Under roc Curve,就是ROC曲線的積分,也是ROC曲線下面的面積。

繪製ROC曲線的意義很明顯,不斷地把可能分錯的情況扣除掉,從概率最高往下取的點,每有一個是負樣本,就會導致分錯排在它下面的所有正樣本,所以要把它下面的正樣本數扣除掉(1-TPR,剩下的正樣本的比例)。總的ROC曲線繪製出來了,AUC就定了,分對的概率也能求出來了。


3 小結

  • ROC曲線的繪製【知道】
    • 1.構建模型,把模型的概率值從大到小進行排序
    • 2.從概率最大的點開始取值,一直進行tpr和fpr的計算,然後構建整體模型,得到結果
    • 3.其實就是在求解積分(面積)

In [37]:

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, roc_auc_score

In [38]:

from sklearn.datasets import make_classification
import matplotlib.pyplot as plt

#使用make_classification生成樣本數據
X, y = make_classification(n_samples=10000, 
                           n_features=2,  # 特徵個數= n_informative() + n_redundant + n_repeated 
                           n_informative=2,  # 多信息特徵的個數
                           n_redundant=0,   # 冗餘信息,informative特徵的隨機線性組合
                           n_repeated=0,  # 重複信息,隨機提取n_informative和n_redundant 特徵 
                           n_classes=2,  # 分類類別
                           n_clusters_per_class=1,  # 某一個類別是由幾個cluster構成的
                           weights=[0.01, 0.99],  # 列表類型,權重比
                           random_state=0)

In [39]:

X

Out[39]:

array([[ 1.58947421,  1.7850011 ],
       [ 0.6247364 ,  2.3497351 ],
       [ 2.05066541,  2.79510652],
       ...,
       [-0.65341837,  1.42889368],
       [ 0.51328558,  1.16702983],
       [ 1.75420418,  2.19322847]])

In [40]:

y

Out[40]:

array([1, 1, 1, ..., 1, 1, 1])

In [41]:

# 數據集可視化
plt.scatter(X[:, 0], X[:, 1], c=y)
plt.show()

In [29]:

# 分割數據
x_train, x_test, y_train, y_test = train_test_split(X, y, random_state=22, test_size=0.2)

In [30]:

# 特徵工程(標準化)
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)

In [31]:

# 機器學習(邏輯迴歸)
estimator = LogisticRegression()
estimator.fit(x_train, y_train)

Out[31]:

LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
                   intercept_scaling=1, l1_ratio=None, max_iter=100,
                   multi_class='auto', n_jobs=None, penalty='l2',
                   random_state=None, solver='lbfgs', tol=0.0001, verbose=0,
                   warm_start=False)

In [32]:

# 模型評估
# 準確率
ret = estimator.score(x_test, y_test)
print("準確率爲:\n", ret)

# 預測值
y_pre = estimator.predict(x_test)
print("預測值爲:\n", y_pre)

準確率爲:
 0.9885
預測值爲:
 [1 1 1 ... 1 1 1]

In [42]:

# 精確率\召回率指標評價
ret = classification_report(y_test, y_pre, labels=[1, 0], target_names=("非肺炎", "肺炎"))
print(ret)

              precision    recall  f1-score   support

         非肺炎       0.99      1.00      0.99      1976
          肺炎       1.00      0.04      0.08        24

    accuracy                           0.99      2000
   macro avg       0.99      0.52      0.54      2000
weighted avg       0.99      0.99      0.98      2000

In [43]:

# 5.4 auc指標計算
roc_auc_score(y_test, y_pre)

Out[43]:

0.5208333333333333


模型評估方法:交叉驗證。分類器性能評估:準確率accuracy、精確率precision(即查準率)、召回率recall(即查全率)、F1值、ROC曲線(受試者工作特徵曲線感受性曲線)

 

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