邏輯回歸
- 前言
- 最大似然估計
- 概率
- 似然函數(likelihood function)
- 最大似然估計
- 邏輯回歸
- 邏輯回歸的似然函數與梯度
- 分類問題常用評價指標
- 項目案例
- 拓展內容
- 作業
前言
邏輯回歸與線性回歸均屬于廣義線性模型,區別在于線性回歸用于解決回歸問題,例如身高、銷量等連續變量預測,邏輯回歸用于二分類問題,例如判斷是否為垃圾郵件,客戶是否會點擊廣告。本章我們將首先了解最大似然估計,一步步推導出邏輯回歸模型,最大似然估計廣泛用于各類機?學習、深度學習,需要認真理解。接著會以實際案例,講解非結構化數據處理的基礎方法,分類問題建模流程。
學習目標:
- List item
- 最大似然估計
- 邏輯回歸模型
- 常用的分類問題評價指標
- 基礎數據處理&分類問題建模
- 獨自完成?aggle Titanic競賽首次提交,得分需要高于0.75鏈接: Titanic Machine Learning from Disaster
最大似然估計
概率
硬幣有正反兩面,如果硬幣正反兩面是均勻的,即每次拋擲后硬幣為正的概率是0.5。使用這個硬幣,很可能拋10次,有5次是正面。但是假如有人對硬幣做了手腳,比如提前對硬幣做了修改,硬幣正面朝上概率大幅度提升了,你拿到硬幣在嘗試拋了10次,結果8次都是正面,如何估算下次硬幣為正的概率呢?
P ( 8 正 2 反 ∣ θ ) = C 10 2 ( 1 ? θ ) 2 ? θ 8 P(8正2反|\theta) = C_{10}^2(1 - \theta)^2 \cdot \theta^8 P(8正2反∣θ)=C102?(1?θ)2?θ8
import numpy as np
print(f"theta = 0.6, 概率為{10*9/2 * np.power(10.6, 2) * np.power(0.6, 8):.3}")
print(f"theta = 0.7, 概率為{10*9/2 * np.power(10.7, 2) * np.power(0.7, 8):.3}")
print(f"theta = 0.8, 概率為{10*9/2 * np.power(10.8, 2) * np.power(0.8, 8):.3}")
theta = 0.6, 概率為0.121
theta = 0.7, 概率為0.233
theta = 0.8, 概率為0.302
可以看出,我們假設硬幣朝正面參數為0.8的時候,出現8正2反情況的概率最大。我們有理由相信,0.8是候選的3個參數中的最接近真實概率的選項。
似然函數(likelihood function)
在上面的嘗試中,0.8似乎是一個不錯的猜測沒,,但是否可能是0.81或者0.79呢,我們當然可以按照上面的方法再次計算概率,但是問題是我們無法遍歷整個空間。因此我們需要定義一個函數來表示不同的參數 下,表示多個獨立事件θ (x1, x2,…,xn)發生的整體概率,這個函數我們叫它似然函數( likelihood function, 通常用L表),其中組合數部分是常數,我們可以直接忽略。 L ( x 1 , x 2 , … , x n ∣ θ ) = ∏ i = 1 n p ( x i ∣ θ ) L(x_1, x_2, \dots, x_n|\theta) = \prod_{i=1}^{n} p(x_i|\theta) L(x1?,x2?,…,xn?∣θ)=i=1∏n?p(xi?∣θ)
似然函數通常用L表示,觀察到拋硬幣“8正2反”的事實,硬幣參數 取不同值時,似然函數表示為: L ( 8 正 2 反 ∣ θ ) = ( 1 ? θ ) 2 ? θ 8 L(8正2反|\theta) = (1 - \theta)^2 \cdot \theta^8 L(8正2反∣θ)=(1?θ)2?θ8
通過似然函數,我們只要能找到使得似然函數最大(多個獨立事件發生的整體概率最大化),就可以完成對硬幣參數的估計了,這就是最大似然估計:
θ ^ = arg ? max ? θ ∏ i = 1 n p ( x i ∣ θ ) \hat{\theta} = \arg\max_{\theta} \prod_{i=1}^{n} p(x_i|\theta) θ^=argθmax?i=1∏n?p(xi?∣θ)
最大似然估計
通常,由于似然函數為連乘,會造成小數位過高,無法有效表示,我們采用對數似然函數進行表示,把連乘轉化為累加形式: l ( x 1 , x 2 , … , x n ∣ θ ) = ∑ i = 1 n log ? p ( x i ∣ θ ) l(x_1, x_2, \dots, x_n|\theta) = \sum_{i=1}^{n} \log p(x_i|\theta) l(x1?,x2?,…,xn?∣θ)=i=1∑n?logp(xi?∣θ)
θ ^ = arg ? max ? θ ∑ i = 1 n log ? p ( x i ∣ θ ) \hat{\theta} = \arg\max_{\theta} \sum_{i=1}^{n} \log p(x_i|\theta) θ^=argθmax?i=1∑n?logp(xi?∣θ)
邏輯回歸
邏輯回歸是線性分類模型,說線性是因為其決策邊界是線性的(平面或超平面),模型輸出值域為(0,1),通常我們將輸出結果視為屬于正樣(y = 1)的概率。我們先來看一下邏輯回歸模型的數學表示: P ( x ) = σ ( w T x ) = 1 1 + exp ? ? w T x P(x) = \sigma(w^T x) = \frac{1}{1 + \exp^{-w^T x}} P(x)=σ(wTx)=1+exp?wTx1?
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
def sigmoid(x): return 1 / (1 + np.exp(-x))
data = np.arange(-10, 10, 0.1)
plt.plot(data, sigmoid(data))
邏輯回歸的似然函數與梯度
tips: 本段包含了不少公式計算,但公式本身的推導細節并不是最重要的,最重要的是通過引入似然函數,我們構造了邏輯回歸的損失函數,且該損失函數可以利用梯度下降進行優化。
p ( y = y i ∣ x i ) = p ( x i ) y i ( 1 ? p ( x i ) ) 1 ? y i p(y = y^i | x^i) = p(x^i)^{y^i}(1 - p(x^i))^{1-y^i} p(y=yi∣xi)=p(xi)yi(1?p(xi))1?yi
Likelihood = ∏ i p ( y = y i ∣ x i ) = ∏ i p ( x i ) y i ( 1 ? p ( x i ) ) 1 ? y i \text{Likelihood} = \prod_i p(y = y^i | x^i) = \prod_i p(x^i)^{y^i} (1 - p(x^i))^{1-y^i} Likelihood=i∏?p(y=yi∣xi)=i∏?p(xi)yi(1?p(xi))1?yi
兩邊同時取對數,對數似然函數為:
loglikelihood = ∑ i [ y i log ? p ( x i ) + ( 1 ? y i ) log ? ( 1 ? p ( x i ) ) ] \text{loglikelihood} = \sum_i \left[y^i \log p(x^i) + (1 - y^i) \log (1 - p(x^i))\right] loglikelihood=i∑?[yilogp(xi)+(1?yi)log(1?p(xi))]
loglikelihood = ∑ i [ y i log ? p ( x i ) 1 ? p ( x i ) + log ? ( 1 ? p ( x i ) ) ] \text{loglikelihood} = \sum_i \left[y^i \log \frac{p(x^i)}{1 - p(x^i)} + \log (1 - p(x^i))\right] loglikelihood=i∑?[yilog1?p(xi)p(xi)?+log(1?p(xi))]
那么這個對數似然函數就是我們需要優化的目標的,其值越大越好,越大說明模型預測概率和真實發生概率一致性越高。由于梯度下降法是驗證最小化損失函數目標進行的,因此我們對對數似然函數乘以?1。
J ( w ) = ? ∑ i [ y i log ? p ( x i ) 1 ? p ( x i ) + log ? ( 1 ? p ( x i ) ) ] J(w) = -\sum_i \left[y^i \log \frac{p(x^i)}{1 - p(x^i)} + \log (1 - p(x^i))\right] J(w)=?i∑?[yilog1?p(xi)p(xi)?+log(1?p(xi))]
求關于參數的梯度,根據求導法則可得:
g = ? J ? w = ∑ i ( p ( x i ) ? y i ) ? x i g = \frac{\partial J}{\partial w} = \sum_i \left(p(x^i) - y^i\right) \cdot x^i g=?w?J?=i∑?(p(xi)?yi)?xi
有了梯度,根據上節課我們學習的梯度下降,就可以根據學習率α逐步迭代更新模型參數 w = w ? α ? g w = w - \alpha \cdot g w=w?α?g
分類問題常用評價指標
在二分類場景,模型所有的預測結果可以分為四類:
- TP(True positive),意思是模型預測為正樣本(Positive),預測是正確的(True)
- FP(False positive),意思是模型預測為正樣本(Positive),預測是錯誤的(False)
- TN(True negtive),意思是模型預測為負樣本(negtive),預測是正確的(True)
- FN(False negtive),意思是模型預測為負樣本(negtive),預測是錯誤的(False)
基于以上四類預測結果,我們可以定義指標:
指標 | 公式 | 含義 |
---|---|---|
準確率 | Accuracy = # T P + # T N # A L L \text{Accuracy} = \frac{\#TP + \#TN}{\#ALL} Accuracy=#ALL#TP+#TN? | 所有預測結果中,預測正確的比例,值越大說明模型表現越好。 |
精準率 | Precision = # T P # T P + # F P \text{Precision} = \frac{\#TP}{\#TP + \#FP} Precision=#TP+#FP#TP? | 所有預測的正樣本中,正確的比例,值越大說明模型表現越好。 |
召回率 | Recall = # T P # T P + # F N \text{Recall} = \frac{\#TP}{\#TP + \#FN} Recall=#TP+#FN#TP? | 所有正樣本被正確預測的比例,值越大說明模型表現越好。 |
from sklearn.metrics import accuracy_score, precision_score, recall_score
y_true = [1, 1, 0, 1, 0]
y_pred = [0, 1, 0, 1, 0]
accuracy_score(y_true, y_pred)#0.8
precision_score(y_true, y_pred)#1.0
recall_score(y_true, y_pred)#0.6666666666666666
在一些極端場景下,準確率會失效,比如正負樣本及其不均勻的情況:
y_true = [1, 1, 1, 1, 1, 0]
y_pred = [1, 1, 1, 1, 1, 1]
accuracy_score(y_true, y_pred) #0.8333333333333334
不過什么輸入,模型都預測為正樣本,導致模型本質上沒有預測能力,但是依然能夠取得很高的Accuracy。為了避免評估指標失效,我們可以同時查看precision 和 recall指標
precision_score(y_true, y_pred) #0.8333333333333334
recall_score(y_true, y_pred) # 1.0
也可以應用一個由recall,precision 一起組成的復合指標 f1?score,該值越大,說明模型表現越好:
f 1 = 2 ? recall ? precision recall + precision f1 = \frac{2 \cdot \text{recall} \cdot \text{precision}}{\text{recall} + \text{precision}} f1=recall+precision2?recall?precision?
from sklearn.metrics import f1_scoref1_score(y_true, y_pred) # 0.9090909090909091
p = precision_score(y_true, y_pred)
r = recall_score(y_true, y_pred) 2 * p * r / (p + r) #0.9090909090909091
項目案例
鏈接: Titanic Machine Learning from Disaster
# 導入所需的庫
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import re
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler, PolynomialFeatures, OneHotEncoder
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
%matplotlib inline # 讀取 Titanic 數據集
train = pd.read_csv("./titanic/train.csv") # 訓練數據
test = pd.read_csv("./titanic/test.csv") # 測試數據
submission = pd.read_csv("./titanic/gender_submission.csv") # 示例提交文件# 數據概覽
print(train.head()) # 查看訓練數據的前幾行
print(test.head()) # 查看測試數據的前幾行
print(train.isnull().sum()) # 檢查訓練數據的缺失值# 填充缺失值
# 用中位數填充缺失的年齡數據
train['Age'] = train['Age'].fillna(train['Age'].median())
test['Age'] = test['Age'].fillna(test['Age'].median())# 用眾數填充缺失的登船港口數據
train['Embarked'] = train['Embarked'].fillna('S')
test['Embarked'] = test['Embarked'].fillna('S')# 用票價的中位數填充缺失的票價數據
test['Fare'] = test['Fare'].fillna(test['Fare'].median())# 數據預處理
# 將性別和登船港口轉換為數值類型
train = pd.get_dummies(train, columns=['Sex', 'Embarked'], drop_first=True)
test = pd.get_dummies(test, columns=['Sex', 'Embarked'], drop_first=True)# 刪除不需要的列
train.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)
test.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)# 提取目標變量和特征
train_target = train['Survived'] # 目標變量
train_features = train.drop(['Survived', 'PassengerId'], axis=1) # 特征
test_features = test.drop(['PassengerId'], axis=1) # 測試集特征# 標準化特征
scaler = StandardScaler()
train_features = scaler.fit_transform(train_features)
test_features = scaler.transform(test_features)# 邏輯回歸模型
model = LogisticRegression() # 創建邏輯回歸模型
model.fit(train_features, train_target) # 訓練模型# 模型評估
predictions = model.predict(train_features) # 在訓練集上預測
print("Accuracy:", accuracy_score(train_target, predictions)) # 準確率
print("Precision:", precision_score(train_target, predictions)) # 精準率
print("Recall:", recall_score(train_target, predictions)) # 召回率
print("F1 Score:", f1_score(train_target, predictions)) # F1 分數# 在測試集上進行預測
test_predictions = model.predict(test_features)# 生成提交文件
submission['Survived'] = test_predictions
submission.to_csv("./submission.csv", index=False) # 保存結果到 CSV 文件print("結果已保存至 submission.csv")
拓展內容
需要注意的是,邏輯回歸雖然存在sigmoid函數將輸出結果映射到0~1區間,但本質依然是一個線性模型,因為模型的分類決策邊界是一個平面,而不是曲面或其他,以下圖為例,中間的藍色直線就是我們的分類(超)平面,位于平面上方的點為正樣本,下方的點為負樣本,這個分類(超)平面可以用一個線性方程表示出來。
作業
- 分類問題中,在正負樣本不均衡的情況下,我們如何評價模型?
- 在Titanic Machine Learning from Disaster比賽提交邏輯回歸建模預測結果,需要得分高于0.75