3、数据准备:下载或构造二分类数据集,展示真实标签与预测标签的格式要求

数据准备这事儿,看起来不起眼,但坑最多。我刚开始做模型评估时,就因为在标签格式上翻了车,整整浪费了一下午。说白了,堆叠图的横轴是样本,纵轴是指标值,但底色和轮廓完全依赖真实标签和预测标签的对应关系。格式不对,图就画不出来,或者画出来也是错的。

所以这一节,我们就干两件事:搞到数据,理清格式。我会给你三种常用的路子,你随便挑。

3.1 方法一:用 scikit-learn 自带数据集

最快的方式。比如乳腺癌数据集(二分类,0 表示恶性,1 表示良性),直接 load 就行。我个人习惯先用它做快速验证,因为标签干净,样本量也适中。

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

data = load_breast_cancer()
X, y_true = data.data, data.target

# 随便切个训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y_true, test_size=0.3, random_state=42
)

# 训练一个模型,得到预测标签
model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

print("真实标签前10个:", y_test[:10])
print("预测标签前10个:", y_pred[:10])
print("形状:", y_test.shape, y_pred.shape)

输出类似这样:

真实标签前10个: [1 0 0 1 1 0 0 0 1 1]
预测标签前10个: [1 0 0 1 1 0 0 0 1 1]
形状: (171,) (171,)

你看,两个数组长度一样,每个位置对应一个样本。这就是我们画堆叠图需要的原始输入。

3.2 方法二:自己构造二分类数据

有时候我们需要模拟特定场景——比如不平衡数据、异常预测、极端概率。这时候自己造数据反而更灵活。我用 make_classification 比较多,可以控制样本数、特征数、类别比例。

from sklearn.datasets import make_classification
import numpy as np

X, y_true = make_classification(
    n_samples=500,       # 500个样本
    n_features=5,        # 5个特征
    n_informative=3,     # 3个有用特征
    n_redundant=0,
    n_clusters_per_class=1,
    flip_y=0.05,         # 5%的噪声标签
    class_sep=1.0,
    random_state=42
)

# 模拟预测:故意加入一些错误
y_pred = y_true.copy()
# 随机翻转10%的标签当作预测错误
flip_idx = np.random.RandomState(42).choice(
    len(y_pred), size=int(len(y_pred)*0.1), replace=False
)
y_pred[flip_idx] = 1 - y_pred[flip_idx]

print("前10个真实标签:", y_true[:10])
print("前10个预测标签:", y_pred[:10])
print("类别分布 - 真实:", np.bincount(y_true))
print("类别分布 - 预测:", np.bincount(y_pred))

输出:

前10个真实标签: [0 1 1 1 0 1 0 0 1 0]
前10个预测标签: [0 1 1 1 0 1 1 0 1 0]
类别分布 - 真实: [254 246]
类别分布 - 预测: [247 253]

嗯,这里要注意,模拟错误时要保证预测标签数组的形状和数据类型与真实标签完全一致,不然画图时会报形状不匹配的错。

3.3 方法三:纯手工构建(最简演示)

有时候为了跑通一个 demo,几行代码就够了。我建议初学者先从这种开始,把注意力集中在堆叠图本身,而不是数据清洗。

import numpy as np

# 10个样本,二分类
y_true = np.array([0, 1, 0, 0, 1, 1, 0, 1, 1, 0])
y_pred = np.array([0, 0, 0, 0, 1, 1, 1, 1, 1, 0])

print("真实标签:", y_true)
print("预测标签:", y_pred)
print("数组长度一致?", len(y_true) == len(y_pred))

3.4 格式要求的核心要点

我刚才翻过车,所以总结了几条硬性规则:

  • 长度必须相等:每条样本在真实标签和预测标签中各占一个位置,一一对应。
  • 数据类型一致:要么都是 int,要么都是 float(但建议 int)。避免混用 np.int32 和 Python int。
  • 取值规范:二分类推荐用 0 和 1。如果模型输出是 -1 和 1,记得映射。堆叠图的色块通常把 0 当负类,1 当正类。
  • 维度:必须是一维数组(形状为 (n_samples,) 或 (n_samples, 1),但后者可能需要 squeeze)。

我曾经接手过一个项目,同事把真实标签存成了 (n_samples, 1) 的二维数组,预测标签却是一维的。结果画图时索引全对不上,找 bug 找了半小时。所以建议统一用 reshape(-1) 拍扁。

⚠️ 小心样本不平衡:如果你的真实标签里0和1的比例差距很大(比如1:9),直接拿原始数据画堆叠图,背景色块会严重不对称,视觉上容易误判。我建议先查看一下 np.bincount(y_true),如果比例过于悬殊,考虑用分层采样或重新平衡后再绘图。
💡 小技巧:在训练模型之前,先把真实标签和预测标签都存成 .npy 或 .csv,后面画图时直接加载,避免每次重新跑模型。我的做法是:
np.save('y_true.npy', y_test)
np.save('y_pred.npy', y_pred)
后面用 np.load 加载,干净利落。

3.5 不同数据源对比一览

数据来源 样本量 类别比例 有无真实标签 适用场景
breast_cancer 569 212:357(较平衡) 有 快速验证模型和堆叠图
make_classification 自定义 可调(默认平衡) 有(可加噪声) 模拟不同难度的分类场景
手工构建 自定义 完全控制 自己定义 仅用作代码演示/单元测试

你想想看,如果只是想验证堆叠图代码有没有写对,手工构建10个样本就够了。但如果是正式的项目分析,我建议用真实数据集或者至少模拟 500+ 样本,这样画出来的图才有统计意义。

3.6 数据准备的完整流程

我把整个数据准备到格式检查的步骤画成了流程图,方便你对照着走。

数据准备到格式检查流程 原始数据源 提取真实标签 y_true 得到预测标签 y_pred 格式校验 三指标堆叠图 校验内容: ✓ 长度一致 ✓ 类型为int ✓ 取值{0,1}

这张图里,数据源可以是 sklearn 数据集、make_classification 或手工数组。箭头方向很明确:先提取真实标签,再通过模型得到预测标签,然后进行格式校验,最后才能进入堆叠图绘制。红色节点就是我们的目标。

总结一句话:数据准备的核心就是拿到两个形状相同、取值 0/1 的一维数组。你可以在任意步骤插入检查代码:

assert y_true.shape == y_pred.shape
assert y_true.dtype == y_pred.dtype
assert set(np.unique(y_true)).issubset({0,1})

跑通过这三条断言,后面画图就不会因为数据格式翻车了。