# 羅吉斯回歸模型與評估
## Source
- 成為python數據分析達人的第一堂課 6
(成為python數據分析達人的第一堂課 7: SVM, Kmeans)
- 大數據分析與資料探勘 W6
- 應⽤機器學習於Python C2-1~2-2
## 課堂投影片與練習
- [ ] **羅吉斯迴歸 (Logistic Regression) 原理介紹**
* **羅吉斯迴歸** 與線性迴歸的命名相似,但它**不是一個迴歸模型**!
* 它是一個**分類模型 (Classification Model)**。
* **目的比較:**
* **線性迴歸:** 用來處理**數量的問題**
* 預測連續數值,例如房價、薪資
* **羅吉斯迴歸:** 用來處理**分類的問題**
* 預測類別,例如銀行客戶是否會申辦貸款、郵件是否為垃圾郵件
* **羅吉斯迴歸的目標:** 找到一條可以將資料點**區隔開來的「線」或「決策邊界」**。
* 它主要用於**二元分類 (Binary Classification)** 問題,也就是將資料分成兩個類別 (例如:是/否、1/0)。
* 羅吉斯迴歸的自變數 (特徵) 可以是**類別變數**,也可以是**連續變數**。
---
- [ ] **羅吉斯迴歸的公式與核心函數**
* **線性迴歸的係數解釋:** 當自變數增加一個單位,應變數會依據係數增加多少個單位。
* 假設我們在看「廣告費」對「銷售額」的影響,如果係數是 5,意思是:每多花 1 單位的廣告費,銷售額會增加 5 單位。
* **羅吉斯迴歸的係數解釋:**
* 如果某個變數(例如:收到優惠券)對結果有影響,係數代表的是:這個變數讓人購買的「勝率」變幾倍。
* 勝率(Odds)和機率不一樣,它是「成功次數 : 失敗次數」的比值,但我們常透過轉換來解釋成「幾倍的影響」。
---
- [ ] **羅吉斯函數 (Logistic Function) / Sigmoid 函數**:
* 在羅吉斯迴歸裡,我們不直接預測結果是 0 或 1,而是先預測「機率」,再決定分類。
* Sigmoid函數的輸出值 **介於 0 和 1 之間**,這恰好符合**機率 (Probability)** 的範圍。
* 公式記為:
$$ P(Y=1|X) = \frac{1}{1 + e^{-(\beta_0 + \beta_1X_1 + \dots + \beta_mX_m)}} $$
* **如何判斷分類?** 通常會設定一個閾值 (Threshold),例如 **0.5**。如果函數值**大於等於 0.5**,則判斷為一類 (例如 A 類或 1),如果**小於 0.5**,則判斷為另一類 (例如 B 類或 0)。
---
- [ ] **如何找出最好的係數?**
* 最大概似函數估計法 (Maximal Likelihood Estimation, MLE)
* 線性迴歸使用最小平方誤差來求解係數,但羅吉斯迴歸用於分類問題,因此不能這樣做。
* 羅吉斯迴歸採用 **最大概似函數估計法** 來求解參數 ($\beta$ 值)。
* 這個方法基於 **白努利分佈 (Bernoulli Distribution)**,因為分類問題的結果只有兩種 (成功或失敗,1 或 0)。
* 目標: 找出一組係數,讓模型預測正確的機率最大。
---
- [ ] **羅吉斯迴歸的優點與缺點**
* **優點 (Advantages)**:
* **理解分類機率的好模型 (Good model for understanding classification probabilities)**:它輸出的是屬於某一類別的機率,而不是直接的類別結果,這使得結果更具解釋性。
* **適用於線上學習和批次學習 (Online and Batch Learning)**:可以有效地處理即時或分批到達的資料。
* **學習效率非常快 (Very fast learning efficiency)**:訓練過程相對迅速。
* **缺點 (Disadvantages)**:
* **預測性可能較為普通 (Prediction performance might be ordinary)**:對於複雜的非線性分類問題,羅吉斯迴歸的分類邊界可能是線性的,可能無法捕捉資料中更複雜的模式。
* **決策邊界不一定是最完美的 (Separating line may not always be optimal)**:有時模型計算出的最佳線性分割線,在視覺上可能不是最理想的分類方式。
---
- [ ] **課中練習三:羅吉斯迴歸概念釐清**
1. **任務:** 羅吉斯迴歸和線性迴歸最核心的差異是什麼?它們分別解決哪一類型的問題?
2. **任務:** 為什麼羅吉斯迴歸要使用 `Sigmoid 函數` 來作為輸出?這個函數的輸出範圍和意義是什麼?
3. **任務:** 線性迴歸使用「最小平方估計法」來求解係數,而羅吉斯迴歸使用哪種方法?為什麼它們選擇不同的方法?
---
* [ ] **羅吉斯迴歸 VS. 線性回歸**
雖然名稱相似,**羅吉斯迴歸和線性迴歸的目標、用途與模型形式完全不同**。以下是它們的關鍵差異整理:
| 比較項目 | 線性迴歸(Linear Regression) | 羅吉斯迴歸(Logistic Regression) |
| ---------- | ----------------------- | -------------------------- |
| **任務類型** | 回歸(預測連續數值) | 分類(預測類別) |
| **輸出值範圍** | 任意實數 | 0 到 1 之間的機率值 |
| **常見應用** | 預測房價、銷售額、氣溫等 | 預測是否購買、是否為垃圾郵件等 |
| **模型形式** | 線性函數 | 邏輯函數(Sigmoid 函數) |
| **損失函數** | 均方誤差(MSE) | 交叉熵(Cross-Entropy) |
| **模型輸出解釋** | 預測值本身為數值 | 預測為「屬於某類別的機率」 |
| **結果判斷** | 可直接使用預測值 | 通常設定閾值(如 0.5)進行分類 |
---
- [ ] **羅吉斯迴歸實例:銀行分類範例 (1/4) - 資料準備**
* 我們將使用一個**銀行分類範例**,來預測銀行客戶是否會申辦某項業務。
* 這份資料集通常包含客戶的人口統計資料、電話推銷結果以及其他社會經濟指標。
* **步驟一:載入常用套件與資料集**
```python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split # 切割資料集
from sklearn.preprocessing import LabelEncoder, StandardScaler # 資料前處理
from sklearn.linear_model import LogisticRegression # 羅吉斯迴歸模型
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix # 評估指標
# 載入資料集 (假設 bank-additional-full.csv 檔案存在)
# 注意:此資料集以分號 (;) 分隔
bank_df = pd.read_csv('bank-additional-full.csv', sep=';')
print(bank_df.info()) # 查看資料集資訊
print(bank_df.head()) # 查看前5筆資料
```
---
- [ ] **羅吉斯迴歸實例:銀行分類範例 (2/4) - 資料前處理**
* **資料前處理** 在機器學習中非常重要,特別是對於羅吉斯迴歸,因為模型**只認識數字**。
* **步驟二:處理類別變數 (Categorical Variables)**
* 將目標變數 `y` (是否申辦) 從 `yes`/`no` 轉換為 `1`/`0`。
```python
# 範例:將目標變數 'y' 轉換為 0 和 1
# 可以用 map 函式或 LabelEncoder
bank_df['y'] = bank_df['y'].map({'yes': 1, 'no': 0})
print("\n目標變數 'y' 轉換後的分佈:")
print(bank_df['y'].value_counts())
# 處理其他類別特徵 (例如 'job', 'marital', 'education' 等)
# 這裡我們使用 LabelEncoder 進行轉換
categorical_cols = ['job', 'marital', 'education', 'default', 'housing', 'loan', 'contact', 'month', 'day_of_week', 'poutcome']
le = LabelEncoder()
for col in categorical_cols:
bank_df[col] = le.fit_transform(bank_df[col])
print("\n部分類別特徵轉換後的前5筆資料:")
print(bank_df[categorical_cols].head())
```
---
* **處理數值變數 (Numerical Variables) - 分箱 (Binning) 與標準化 (Standardization)**
* 有時數值變數(如 `age` 或 `duration`)雖然是數字,但我們可能需要將它們**分組或標準化**。
* **分箱:** 將連續數值轉換為類別區間 (例如:年齡分成 18-30 歲、31-45 歲等)。
* **標準化:** 將所有數值特徵縮放到相似的範圍,這有助於模型學習,尤其對於基於梯度下降的模型很重要。
```python
# 範例:對 'age' 進行分箱 (僅為示範,實際操作可能更複雜)
# 使用四分位數來設定區間
bank_df['age_group'] = pd.qcut(bank_df['age'], 4, labels=False) + 1 # 分為4組,標籤為1,2,3,4
print("\n'age' 分箱後的分佈:")
print(bank_df['age_group'].value_counts().sort_index())
# 選擇所有特徵 (X) 和目標 (Y)
X = bank_df.drop('y', axis=1) # 所有欄位,除了 'y'
# 這裡可以根據實際需求決定是否移除原始的 'age' 或 'duration',僅保留分箱後的欄位
Y = bank_df['y']
# 標準化數值特徵
# 選取需要標準化的數值欄位,例如 'campaign', 'pdays', 'previous', 'emp.var.rate', 'cons.price.idx', 'cons.conf.idx', 'euribor3m', 'nr.employed'
numeric_cols_to_scale = ['age', 'campaign', 'pdays', 'previous', 'emp.var.rate', 'cons.price.idx', 'cons.conf.idx', 'euribor3m', 'nr.employed']
scaler = StandardScaler()
X[numeric_cols_to_scale] = scaler.fit_transform(X[numeric_cols_to_scale])
print("\n部分數值特徵標準化後的前5筆資料:")
print(X[numeric_cols_to_scale].head())
```
---
- [ ] **羅吉斯迴歸實例:銀行分類範例 (3/4) - 模型訓練與預測**
* **步驟三:切割資料集** (與線性迴歸類似)
```python
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=2021)
print(f"\n訓練集特徵數量: {X_train.shape}")
print(f"測試集特徵數量: {X_test.shape}")
```
* **步驟四:建立羅吉斯迴歸模型**
```python
# 建立一個羅吉斯迴歸模型物件
# 為簡化,我們這裡不設定複雜參數
logistic_model = LogisticRegression(solver='liblinear', random_state=2021) # 指定 solver 避免警告
# 使用訓練資料來訓練模型
logistic_model.fit(X_train, Y_train)
print("\n羅吉斯迴歸模型訓練完成!")
```
* **步驟五:進行預測**
```python
# 對測試資料進行預測,得到預測的類別 (0 或 1)
Y_pred_logistic = logistic_model.predict(X_test)
# 也可以預測機率,如果需要判斷哪一類的機率
Y_prob_logistic = logistic_model.predict_proba(X_test)[:, 1] # 取得預測為 1 的機率
# 查看部分預測結果與真實值比較
logistic_results_df = pd.DataFrame({'真實 (Y_test)': Y_test, '預測 (Y_pred_logistic)': Y_pred_logistic})
print(logistic_results_df.head())
```
---
- [ ] **羅吉斯迴歸實例:銀行分類範例 (4/4) - 模型評估**
* **步驟六:評估模型績效**
* 對於分類問題,我們使用不同的指標來評估模型,其中**混淆矩陣 (Confusion Matrix)** 是核心。
* **混淆矩陣** 顯示了模型預測結果與真實結果的對應關係,包含:
* **True Positive (TP)**:真實為 1,預測也為 1。
* **True Negative (TN)**:真實為 0,預測也為 0。
* **False Positive (FP)**:真實為 0,預測為 1 (誤報)。
* **False Negative (FN)**:真實為 1,預測為 0 (漏報)。
* 從混淆矩陣,我們可以計算出:
* **準確性 (Accuracy)**:(TP+TN) / (TP+TN+FP+FN) - 整體預測正確的比例。
* **精確度 (Precision)**:TP / (TP+FP) - 預測為 1 的結果中,有多少是真的 1。
* **召回率 (Recall)**:TP / (TP+FN) - 所有真實為 1 的結果中,有多少被模型正確預測為 1 (又稱靈敏度)。
* **F1-Score**:精確度與召回率的調和平均數,綜合考量兩者。
```python
# 計算混淆矩陣
conf_matrix = confusion_matrix(Y_test, Y_pred_logistic)
print("\n混淆矩陣 (Confusion Matrix):")
print(conf_matrix)
# 計算各種分類指標
accuracy = accuracy_score(Y_test, Y_pred_logistic)
precision = precision_score(Y_test, Y_pred_logistic)
recall = recall_score(Y_test, Y_pred_logistic)
f1 = f1_score(Y_test, Y_pred_logistic)
print(f"\n模型的準確性 (Accuracy): {accuracy:.4f}") # 範例中顯示 0.910
print(f"模型的精確度 (Precision): {precision:.4f}") # 範例中顯示 0.66
print(f"模型的召回率 (Recall): {recall:.4f}")
print(f"模型的 F1-Score: {f1:.4f}")
```
---
- [ ] **課中練習四:羅吉斯迴歸實作與評估**
1. **任務:** 在銀行分類範例中,請修改資料前處理步驟,**移除 `duration` 欄位** (假設這個欄位代表了電話通話時間,在實際應用中可能無法在預測前得知)。
* **提示:** 在定義 `X` 時,使用 `X = bank_df.drop(['y', 'duration'], axis=1)`。
* 重新訓練模型並評估其績效。比較移除 `duration` 後的 `Accuracy`、`Precision`、`Recall` 和 `F1-Score`,並討論你的觀察。
2. **任務:** 觀察混淆矩陣,請解釋 `conf_matrix` 和 `conf_matrix` 這兩個數值分別代表什麼意義?
3. **任務:** 假設對於銀行來說,「漏掉一個潛在客戶 (False Negative)」比「誤打給一個非潛在客戶 (False Positive)」造成的損失更大。在這種情況下,你會更關注模型的哪個指標 (Precision 還是 Recall)?為什麼?
---