从零构建乳腺癌分类模型:逻辑回归与KNN的实战对比

当医疗数据遇上机器学习,我们能从中挖掘出怎样的价值?乳腺癌数据集作为sklearn中最经典的二分类案例之一,为初学者提供了绝佳的实践平台。本文将带你完整走通从数据探索到模型优化的全流程,特别聚焦逻辑回归与KNN这两种基础但强大的分类算法。

1. 环境准备与数据初探

工欲善其事,必先利其器。在开始建模前,我们需要确保环境配置正确:

# 基础库导入
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

乳腺癌数据集包含569个样本,每个样本有30个特征维度,目标变量为恶性(0)与良性(1)两类。让我们先观察数据结构:

cancer = load_breast_cancer()
print(f"特征形状: {cancer.data.shape}")  # (569, 30)
print(f"类别分布:\n{np.bincount(cancer.target)}")  # [212 357]

数据标准化是许多机器学习算法的前提条件。特别是对于KNN这类距离敏感的算法:

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_scaled = scaler.fit_transform(cancer.data)

注意:标准化应该在数据划分后进行,避免测试集信息泄露到训练过程

2. 逻辑回归建模全流程

逻辑回归虽然名为"回归",实则是经典的分类算法。我们分步骤实现:

2.1 基础模型构建

from sklearn.linear_model import LogisticRegression

X_train, X_test, y_train, y_test = train_test_split(
    X_scaled, cancer.target, test_size=0.3, random_state=42)

lr = LogisticRegression(max_iter=5000)
lr.fit(X_train, y_train)
print(f"测试集准确率: {lr.score(X_test, y_test):.3f}")

2.2 模型评估指标

除了准确率,我们还需要关注:

  • 查全率(Recall):正确识别的阳性样本比例
  • 查准率(Precision):预测为阳性的样本中实际为阳性的比例
  • F1分数:查全率与查准率的调和平均
from sklearn.metrics import classification_report

y_pred = lr.predict(X_test)
print(classification_report(y_test, y_pred))

2.3 参数调优实战

逻辑回归有几个关键参数需要优化:

参数 可选值 说明
penalty ['l1', 'l2'] 正则化类型
C [0.001, 0.01, 0.1, 1, 10] 正则化强度
solver ['liblinear', 'saga'] 优化算法

使用网格搜索自动寻找最优组合:

from sklearn.model_selection import GridSearchCV

param_grid = {
    'penalty': ['l1', 'l2'],
    'C': [0.001, 0.01, 0.1, 1, 10],
    'solver': ['liblinear', 'saga']
}

grid_search = GridSearchCV(LogisticRegression(max_iter=5000), 
                          param_grid, cv=5)
grid_search.fit(X_train, y_train)
print(f"最优参数: {grid_search.best_params_}")

3. KNN算法实现与优化

K近邻算法是一种基于实例的学习方法,其性能高度依赖参数选择。

3.1 基础KNN模型

from sklearn.neighbors import KNeighborsClassifier

knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)
print(f"KNN测试准确率: {knn.score(X_test, y_test):.3f}")

3.2 关键参数解析

KNN的主要可调参数包括:

  • n_neighbors: 近邻数,通常取奇数避免平票
  • weights: 距离权重,可选'uniform'或'distance'
  • p: 距离度量(1为曼哈顿距离,2为欧氏距离)

通过交叉验证寻找最佳K值:

neighbors = range(1, 21, 2)
cv_scores = []

for k in neighbors:
    knn = KNeighborsClassifier(n_neighbors=k)
    scores = cross_val_score(knn, X_scaled, cancer.target, cv=5)
    cv_scores.append(scores.mean())

plt.plot(neighbors, cv_scores)
plt.xlabel('K值')
plt.ylabel('交叉验证准确率')

3.3 高级调优技巧

结合网格搜索全面优化KNN:

param_grid = {
    'n_neighbors': [3, 5, 7, 9],
    'weights': ['uniform', 'distance'],
    'p': [1, 2]
}

grid_knn = GridSearchCV(KNeighborsClassifier(), 
                       param_grid, cv=5)
grid_knn.fit(X_train, y_train)
print(f"最优KNN参数: {grid_knn.best_params_}")

4. 模型对比与可视化

将两种算法的性能进行系统对比:

4.1 准确率对比

models = {
    'Logistic Regression': lr,
    'KNN': knn
}

for name, model in models.items():
    score = model.score(X_test, y_test)
    print(f"{name}测试准确率: {score:.3f}")

4.2 学习曲线分析

观察模型在不同训练数据量下的表现:

from sklearn.model_selection import learning_curve

train_sizes, train_scores, test_scores = learning_curve(
    LogisticRegression(), X_scaled, cancer.target, cv=5)

plt.plot(train_sizes, np.mean(train_scores, axis=1), label='训练得分')
plt.plot(train_sizes, np.mean(test_scores, axis=1), label='交叉验证得分')

4.3 特征重要性分析

逻辑回归可以提供特征权重:

plt.figure(figsize=(10, 6))
plt.barh(range(30), lr.coef_[0])
plt.yticks(range(30), cancer.feature_names)
plt.xlabel("特征权重")

5. 工程实践中的注意事项

在实际项目中,有几个关键点需要特别注意:

  1. 数据泄露问题:确保标准化等预处理只在训练集上拟合
  2. 类别不平衡:乳腺癌数据集相对平衡,但实际场景可能需要考虑采样策略
  3. 计算效率:KNN在大型数据集上可能较慢,需权衡准确率与性能
  4. 可解释性:医疗领域模型需要解释性,逻辑回归通常比KNN更易解释
# 完整流程封装示例
def full_pipeline():
    data = load_breast_cancer()
    X_train, X_test, y_train, y_test = train_test_split(
        data.data, data.target, test_size=0.3)
    
    scaler = StandardScaler()
    X_train_scaled = scaler.fit_transform(X_train)
    X_test_scaled = scaler.transform(X_test)
    
    lr = LogisticRegression(max_iter=5000).fit(X_train_scaled, y_train)
    knn = KNeighborsClassifier(n_neighbors=5).fit(X_train_scaled, y_train)
    
    return {
        'Logistic Regression': lr.score(X_test_scaled, y_test),
        'KNN': knn.score(X_test_scaled, y_test)
    }

在医疗诊断这样的关键领域,即使1%的准确率提升也可能意义重大。通过本实验我们发现,虽然逻辑回归和KNN在这个数据集上表现相近(约95%准确率),但它们的误分类样本并不完全相同。实际应用中可以考虑模型集成策略。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐