逻辑回归案例之癌症预测
1 课程概览
本课通过癌症分类预测案例讲解逻辑回归API的使用。介绍LogisticRegression的参数(solver、penalty、C),数据集描述(699条样本,11列数据),数据预处理(缺失值处理:问号转NaN),以及完整开发流程。
2 核心概念与定义
- LogisticRegression:逻辑回归API,位于sklearn.linear_model。
- solver:优化算法(liblinear小数据集,saga/sag大数据集)。
- penalty:正则化种类(L1或L2)。
- C:正则化力度,值越大权重系数越大。
- 正例:默认将类别数量少的当做正例。
- 缺失值处理:问号(?)需先转为NaN再处理。
3 算法与模型详解
3.1 LogisticRegression API
位置:sklearn.linear_model.LogisticRegression
参数:
| 参数 | 说明 | 可选值 |
|---|---|---|
| solver | 优化算法 | liblinear, sag, saga |
| penalty | 正则化种类 | l1, l2 |
| C | 正则化力度 | 数值(越小正则化越强) |
solver选择:
| solver | 适用场景 | 支持正则化 |
|---|---|---|
| liblinear | 小数据集 | L1, L2 |
| sag | 大数据集 | L2 |
| saga | 大数据集 | L1, L2 |
3.2 正则化参数
penalty:
- 'l1':L1正则化
- 'l2':L2正则化(默认)
C:
- 正则化力度
- C越小,正则化越强,权重系数越小
- C越大,正则化越弱,权重系数越大
3.3 正例设定
默认:将类别数量少的当做正例
示例:
- 班级男生多,女生少 → 女生为正例
- 癌症数据:恶性少,良性多 → 恶性为正例
手动设定:可以自己指定类别多的当正例
注意:如果记混了,混淆矩阵的推理会全部错误
3.4 数据集描述
癌症分类预测数据集:
- 样本数:699条
- 列数:11列
列说明:
| 列索引 | 说明 |
|---|---|
| 0 | 检索ID(不用) |
| 1-9 | 特征(9个) |
| 10 | Class标签 |
标签:
- 2:良性
- 4:恶性
缺失值:
- 数量:16个
- 表示:用问号(?)标记
- 处理:先转NaN,再处理
3.5 数据预处理
缺失值处理步骤:
- 将问号(?)替换为NaN
- 删除包含NaN的行(dropna)
代码:
data = data.replace('?', np.nan)
data = data.dropna()
3.6 开发流程
步骤:
- 获取数据
- 数据基本处理(缺失值处理)
- 数据分割(训练集和测试集)
- 特征工程(标准化)
- 机器学习(模型训练)
- 模型预测
- 模型评估
4 数学原理与推导
4.1 逻辑回归模型
$$h_\theta(X) = \sigma(W^TX + B) = \frac{1}{1 + e^{-(W^TX + B)}}$$
4.2 正则化损失
L1: $$L = L_{original} + \frac{1}{C} \sum |W_i|$$
L2: $$L = L_{original} + \frac{1}{C} \sum W_i^2$$
4.3 分类决策
$$\text{预测} = \begin{cases} 1, & h_\theta(X) \geq 0.5 \ 0, & h_\theta(X) < 0.5 \end{cases}$$
5 代码示例
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, classification_report
# 1. 获取数据
# 数据集:699条样本,11列
# 列:ID, 9个特征, Class标签
data = pd.read_csv('breast_cancer.csv', header=None)
# 2. 数据基本处理
# 2.1 查看数据信息
print("数据形状:", data.shape)
print(data.info())
# 2.2 处理缺失值(问号转NaN)
data = data.replace('?', np.nan)
print("缺失值数量:", data.isnull().sum().sum())
# 2.3 删除缺失值
data = data.dropna()
print("处理后数据形状:", data.shape)
# 2.4 提取特征和标签
# 第0列是ID,不用;最后一列是标签
X = data.iloc[:, 1:-1] # 特征(第1列到倒数第2列)
Y = data.iloc[:, -1] # 标签(最后一列)
# 2.5 标签转换(2→0良性,4→1恶性)
Y = Y.map({2: 0, 4: 1}) # 0:良性, 1:恶性
# 3. 数据分割
X_train, X_test, y_train, y_test = train_test_split(
X, Y, test_size=0.2, random_state=22
)
# 4. 特征工程(标准化)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 5. 模型训练
# 小数据集用liblinear,L2正则化
model = LogisticRegression(solver='liblinear', penalty='l2', C=1.0)
model.fit(X_train_scaled, y_train)
# 6. 模型预测
y_pred = model.predict(X_test_scaled)
# 7. 模型评估
print("\n=== 模型评估 ===")
print("准确率:", accuracy_score(y_test, y_pred))
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=['良性', '恶性']))
# 8. 查看模型参数
print("\n=== 模型参数 ===")
print("权重W:", model.coef_)
print("偏置B:", model.intercept_)
输出示例:
数据形状: (699, 11)
缺失值数量: 16
处理后数据形状: (683, 11)
=== 模型评估 ===
准确率: 0.9781
分类报告:
precision recall f1-score support
良性 0.97 0.99 0.98 95
恶性 0.98 0.95 0.96 42
accuracy 0.98 137
macro avg 0.98 0.97 0.97 137
weighted avg 0.98 0.98 0.98 137
=== 模型参数 ===
权重W: [[ 0.234 -0.156 0.345 ...]]
偏置B: [-0.123]
6 重难点与易错提醒
- ❗重点:默认将类别数量少的当做正例。
- ❗重点:问号缺失值需先转NaN再处理。
- ❗重点:小数据集用liblinear,大数据集用sag/saga。
- ❗重点:C是正则化力度,越小正则化越强。
- ⚠️易错:忘记将问号转NaN导致无法删除缺失值。
- ⚠️易错:混淆正例和负例。
- 💡深入理解:正例设定影响混淆矩阵的推理。
7 课堂问答精选
Q: 如何处理数据中的问号缺失值?
A: 数据中的缺失值用问号(?)表示,不能直接用dropna删除。需要先将问号替换为NaN:
data = data.replace('?', np.nan)
data = data.dropna()
然后再用dropna删除包含NaN的行。
Q: LogisticRegression的正例是如何确定的?
A: 默认将类别数量少的当做正例。例如癌症数据中,恶性样本少,良性样本多,所以恶性为正例。也可以手动指定类别多的当正例。如果记混了,混淆矩阵的推理会全部错误。
8 本课小结
- LogisticRegression:位于sklearn.linear_model。
- 参数:solver(优化算法)、penalty(正则化)、C(正则化力度)。
- 正例:默认类别少的为正例。
- 数据集:699样本,11列,16个缺失值(问号)。
- 缺失值处理:问号 → NaN → dropna。
- 流程:获取数据 → 处理 → 分割 → 标准化 → 训练 → 预测 → 评估。
9 延伸思考与实践
- 实践:用癌症数据集完成逻辑回归分类。
- 预习:分类评估方法(混淆矩阵)。
- 思考:如何选择solver和正则化方式?