前面几篇文章讲了人工智能概念、机器学习流程、模型训练评估和神经网络基础。这一篇用一个小实战把流程跑通:使用 Python 和 scikit-learn 完成一个二分类任务。
这个例子使用 scikit-learn 内置的 breast cancer 数据集,不需要额外下载文件。重点不是追求最高分,而是完整经历数据加载、拆分、标准化、训练、预测和评估。
注意:这个数据集只用于机器学习教学练习,不能用于医疗判断或现实诊断。本文关注的是分类流程,而不是医学结论。
一、准备环境
建议先创建虚拟环境,再安装依赖:
python3 -m venv .venv
source .venv/bin/activate
pip install scikit-learn
本文只使用 scikit-learn,不依赖深度学习框架。这样可以把注意力放在机器学习的基本流程上。
二、完整代码
下面是一份可以直接运行的代码:
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
def main():
dataset = load_breast_cancer()
X = dataset.data
y = dataset.target
X_train, X_test, y_train, y_test = train_test_split(
X,
y,
test_size=0.2,
random_state=42,
stratify=y,
)
model = Pipeline(
steps=[
("scaler", StandardScaler()),
("classifier", LogisticRegression(max_iter=500)),
]
)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print("Accuracy:", accuracy_score(y_test, y_pred))
print("Confusion matrix:")
print(confusion_matrix(y_test, y_pred))
print("Classification report:")
print(classification_report(y_test, y_pred, target_names=dataset.target_names))
if __name__ == "__main__":
main()
保存为 ai_classification_demo.py 后运行:
python ai_classification_demo.py
如果你第一次运行时下载或导入依赖较慢,可以先确认虚拟环境已经启用,并用 python -c "import sklearn; print(sklearn.__version__)" 检查 scikit-learn 是否安装成功。
三、数据集是什么
load_breast_cancer() 会返回一个二分类数据集。每条样本包含多个数值特征,标签表示样本属于哪一类。
在代码里:
X是特征矩阵,每一行是一条样本y是标签数组,每个元素对应一条样本的类别dataset.target_names保存类别名称
这个数据集已经被整理成数值特征,适合用来练习基础分类流程。
四、为什么要拆分训练集和测试集
代码中使用了 train_test_split():
X_train, X_test, y_train, y_test = train_test_split(
X,
y,
test_size=0.2,
random_state=42,
stratify=y,
)
这里 test_size=0.2 表示 20% 数据用于测试。stratify=y 表示划分后尽量保持类别比例一致,这对分类任务很有用。
如果不拆分测试集,只在训练集上看结果,模型可能只是记住了训练样本,而不是真的具备泛化能力。
五、为什么使用 Pipeline
代码里没有单独先标准化再训练,而是使用了 Pipeline:
model = Pipeline(
steps=[
("scaler", StandardScaler()),
("classifier", LogisticRegression(max_iter=500)),
]
)
这样做有两个好处:
- 标准化和模型训练被放在同一个流程里,不容易漏步骤
- 测试集会使用训练集上学到的标准化参数,避免数据泄漏
数据泄漏是初学者常见错误。如果你先对完整数据做标准化,再拆分训练集和测试集,测试集的信息就已经提前影响了训练过程。
六、模型为什么选逻辑回归
逻辑回归是分类任务里非常经典的基线模型。它训练速度快、结果稳定、容易解释,适合作为入门模型。
这里没有直接使用神经网络,是因为入门时先跑通完整流程更重要。等你能解释这段代码的每一步,再换成随机森林、支持向量机或神经网络会更自然。
七、怎么看评估结果
代码会输出三类结果:
Accuracy:整体预测正确比例confusion_matrix:模型把哪些类别预测错了classification_report:precision、recall、F1-score 等指标
如果准确率很高,也不要马上结束。你还应该看混淆矩阵,确认模型主要错在哪一类;再看 recall 和 precision,判断错误类型是否符合业务要求。
八、实际运行:从 114 条预测复核 98.25%
2026-09-07 用 Python 3.13.9、scikit-learn 1.7.2、NumPy 2.3.5 和 SciPy 1.17.1 重跑上面的完整代码,得到以下输出。本节替换了旧版不准确的示意数字;这是一份固定示例的复现记录,不是新的独立测试。
Accuracy: 0.9824561403508771
Confusion matrix:
[[41 1]
[ 1 71]]
Classification report:
precision recall f1-score support
malignant 0.98 0.98 0.98 42
benign 0.99 0.99 0.99 72
accuracy 0.98 114
macro avg 0.98 0.98 0.98 114
weighted avg 0.98 0.98 0.98 114
原数据有 569 条样本、30 个特征,训练集 455 条,测试集 114 条。矩阵按 [0=malignant, 1=benign] 排列,行是真实标签,列是预测标签。因此正确数是 41+71=112,准确率是 112/114,不是把四舍五入后的分类报告再求平均。原数据和类别定义见 scikit-learn 数据集说明。
两个错误究竟发生在哪
| 原始索引 | 真实类别 | 预测类别 | 模型输出 P(类别 0) |
|---|---|---|---|
| 541 | 1,benign | 0,malignant | 0.634138 |
| 73 | 0,malignant | 1,benign | 0.091272 |
第二条尤其值得注意:模型并不是只在 0.5 附近犹豫时才出错。这两个概率没有经过本实验的校准评估,不能解释成个人患病风险。这里也没有证据说明某一个特征“造成”了错误;要做原因分析,需要另外设计对照,不能从一个概率倒推医学结论。
只预测训练集多数类的 DummyClassifier(strategy="most_frequent") 在相同测试集上也能得到 72/114=63.16%,但类别 0 的召回率为 0。逻辑回归本次类别 0 召回率为 41/42=97.62%。这个对照说明模型不只是复述多数类,仍不证明它适用于现实诊断。
下载代码与完整预测,不只看截图
下载复现包,解压进入 ml-basics-lab 后运行下面命令。run_lab.py 保留上文固定的模型和划分,另外导出行号、概率、数据校验值和基线;114 条参考预测 CSV 与 指标及划分 JSON 可直接检查。
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python run_lab.py --output results
python -m unittest -v test_lab
参考环境和脚本 SHA-256 保存在 reference/environment.json。依赖安装后脚本不再请求外部数据。不同平台的浮点概率可能略有差异;如果测试集不是 114 条、类别数量不是 42/72,应先核对数据和拆分参数,而不是把结构差异归因于小数误差。
九、可以继续尝试什么
跑通代码后,可以做几个小实验:
以下实验属于开发探索,不是继续使用同一测试集挑最高分。若要比较模型或标准化方案,应在原训练集内部交叉验证。本文已经公开了测试错误,利用它们改模型后,这份测试集就不能再被称为未见数据;随机换一个种子也不会自动让旧数据变成新的独立证据。
- 把
test_size改成 0.3,观察结果是否稳定 - 去掉
StandardScaler,比较指标变化 - 把
LogisticRegression换成RandomForestClassifier - 打印
dataset.feature_names,理解每个特征的含义 - 尝试找出预测错误的样本索引,看看它们有什么特点
人工智能基础学习的关键,是把每个例子都拆成可解释的步骤。你不只是运行了一个分类模型,而是完整走过了一次机器学习工作流。
十、对照实验怎么设计
小实战最有价值的部分是对照实验。不要一次改很多东西,否则不知道结果变化来自哪里。建议一次只改一个变量,并记录指标变化。
| 实验 | 只改变什么 | 观察重点 |
|---|---|---|
| 去掉标准化 | 删除 StandardScaler |
逻辑回归是否更难收敛,指标是否下降 |
| 改变测试集比例 | test_size 从 0.2 改成 0.3 |
指标波动是否仍在可接受范围 |
| 更换模型 | 换成随机森林 | 是否真正超过基线,错误类型是否改变 |
| 去掉分层抽样 | 删除 stratify=y |
类别比例是否变化,少数类 recall 是否不稳定 |
这样做能帮助你从“跑通代码”过渡到“理解实验”。一个结果是否可靠,通常不是看一次分数,而是看在合理扰动下是否仍然稳定。
十一、把这个练习写进学习笔记
建议你运行完代码后,记录下面几项:
- 数据集有多少样本、多少特征、几个类别
- 训练集和测试集分别有多少样本
- 准确率、precision、recall 和 F1-score 分别是多少
- 混淆矩阵里哪一类错误更多
- 去掉标准化或换模型后,结果有什么变化
这些记录比单纯截图一个准确率更有价值,因为它们能帮助你解释实验,而不是只保存结果。
十二、系列回顾
这篇文章把前面的内容落到了代码上。需要回看概念时,可以从 人工智能基础学习路线 重新开始,也可以回到 博客页 查看完整系列。