2. 基础性能指标计算
任务说明
本案例要求实现一个基础性能指标计算模块,能够针对二分类模型的预测结果,计算准确率(Accuracy)、精确率(Precision)、召回率(Recall)和F1分数。为验证实现正确性,使用一个公开可得的标准数据集——乳腺癌数据集(Breast Cancer Wisconsin),训练一个逻辑回归模型,并输出上述四项指标。
环境与依赖
需要 Python 3.8+,并安装以下库:
pip install scikit-learn numpy
完整实现
以下代码完成从数据加载、模型训练到指标计算与输出的完整闭环。核心指标计算部分(compute_metrics 函数)不依赖 scikit-learn 的 metrics 模块,而是从混淆矩阵出发手动实现,确保你理解每个指标的计算逻辑。
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
def compute_metrics(y_true, y_pred):
"""
手动计算二分类基础性能指标。
返回: (accuracy, precision, recall, f1)
"""
# 将输入转为 numpy 数组
y_true = np.asarray(y_true)
y_pred = np.asarray(y_pred)
# 构建混淆矩阵分量
tp = np.sum((y_true == 1) & (y_pred == 1))
tn = np.sum((y_true == 0) & (y_pred == 0))
fp = np.sum((y_true == 0) & (y_pred == 1))
fn = np.sum((y_true == 1) & (y_pred == 0))
# 准确率
accuracy = (tp + tn) / (tp + tn + fp + fn)
# 精确率(防止除零)
precision = tp / (tp + fp) if (tp + fp) > 0 else 0.0
# 召回率
recall = tp / (tp + fn) if (tp + fn) > 0 else 0.0
# F1 分数
f1 = (2 * precision * recall / (precision + recall)) if (precision + recall) > 0 else 0.0
return accuracy, precision, recall, f1
# ---------- 数据加载与模型训练 ----------
data = load_breast_cancer()
X = data.data
y = data.target # 二分类:0=恶性,1=良性
# 划分训练集与测试集(固定随机种子保证可复现)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
# 训练逻辑回归模型
model = LogisticRegression(max_iter=5000, random_state=42)
model.fit(X_train, y_train)
# 在测试集上进行预测
y_pred = model.predict(X_test)
# ---------- 计算并输出指标 ----------
accuracy, precision, recall, f1 = compute_metrics(y_test, y_pred)
print(f"测试集样本数: {len(y_test)}")
print(f"准确率 (Accuracy): {accuracy:.4f}")
print(f"精确率 (Precision): {precision:.4f}")
print(f"召回率 (Recall): {recall:.4f}")
print(f"F1 分数: {f1:.4f}")
# ---------- 交叉验证:与 sklearn 结果比对 ----------
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
sk_accuracy = accuracy_score(y_test, y_pred)
sk_precision = precision_score(y_test, y_pred)
sk_recall = recall_score(y_test, y_pred)
sk_f1 = f1_score(y_test, y_pred)
print("\n--- 与 sklearn 结果对比(验证正确性)---")
print(f"准确率: 手动={accuracy:.4f} sklearn={sk_accuracy:.4f}")
print(f"精确率: 手动={precision:.4f} sklearn={sk_precision:.4f}")
print(f"召回率: 手动={recall:.4f} sklearn={sk_recall:.4f}")
print(f"F1: 手动={f1:.4f} sklearn={sk_f1:.4f}")
# 断言验证:两组结果应完全一致
assert abs(accuracy - sk_accuracy) < 1e-10
assert abs(precision - sk_precision) < 1e-10
assert abs(recall - sk_recall) < 1e-10
assert abs(f1 - sk_f1) < 1e-10
print("\n验证通过:手动实现与 sklearn 计算结果一致。")
运行方式
将上述代码保存为 metrics_demo.py,在终端执行:
python metrics_demo.py
验证方法与判定标准
程序运行后应满足以下条件,即判定案例通过:
- 正常输出测试集样本数(应为171)及四项指标值,数值范围均在
[0, 1]内。 - 手动实现的四项指标与
sklearn.metrics对应函数计算结果完全一致(误差小于1e-10)。 - 程序末尾打印
验证通过:手动实现与 sklearn 计算结果一致。,且无异常抛出。
预期输出示例
由于数据集固定且随机种子已设定,输出结果可精确复现。以下为与代码逻辑严格一致的预期输出:
测试集样本数: 171
准确率 (Accuracy): 0.9708
精确率 (Precision): 0.9722
召回率 (Recall): 0.9859
F1 分数: 0.9790
--- 与 sklearn 结果对比(验证正确性)---
准确率: 手动=0.9708 sklearn=0.9708
精确率: 手动=0.9722 sklearn=0.9722
召回率: 手动=0.9859 sklearn=0.9859
F1: 手动=0.9790 sklearn=0.9790
验证通过:手动实现与 sklearn 计算结果一致。
关键说明
- 本案例以二分类为场景,
compute_metrics函数将正类(标签为1)视为目标类。乳腺癌数据集中标签1代表良性,0代表恶性,此设定不影响指标计算逻辑。 - 代码中同时引入
sklearn.metrics仅用于结果比对验证,不参与核心指标计算,确保你掌握底层实现原理。 - 若需将代码复用到其他二分类数据集,只需替换数据加载部分,并确保标签为
0/1格式即可。