问题与目标

模型训练位于基线之后、独立评估之前;没有推理与监控,就不是完整闭环。
一次 fit() 成功不等于项目完成。机器学习闭环还包含指标、基线、数据划分、误差分析和独立推理。
完成标准:用自建分类数据完成三份数据划分,比较简单基线和模型,并只在最终阶段查看测试集。
核心概念
训练集用于学习参数,验证集用于选择方案,测试集只用于最终无偏估计。基线可以是多数类、简单规则或旧方案;模型若不能稳定超过基线,复杂度没有带来价值。
欠拟合表示模型连训练规律都没学好;过拟合表示训练表现很好但新数据变差。实验应固定随机种子、记录数据与依赖版本,并保存从原始输入到预测的完整步骤。
问题定义模板
使用者:谁根据预测采取行动?
预测对象:一行样本代表什么?
预测时点:什么时候产生预测?
输入:该时点已经知道哪些字段?
目标:预测什么结果、观察窗口多长?
指标:哪类错误代价更高?
基线:当前规则或最简单策略是什么?
预测时点决定特征合法性。预测任务开始前是否超时时,实际耗时、结束状态和重试次数都属于未来信息。
数据划分不只有随机划分
- 随机划分适合近似独立同分布样本。
- 时间划分用过去训练、未来验证,适合随时间变化的数据。
- 分组划分保证同一用户、设备或文档不会跨集合,避免近似副本泄漏。
分类任务还要关注各集合标签比例。stratify 保持类别分布,但不能替代时间或分组约束。
基线与实验记录
分类基线可以是多数类或已有规则,回归基线可以预测训练集均值或中位数。实验表至少记录数据版本、特征版本、切分方式、随机种子、模型参数和验证指标。
from dataclasses import asdict, dataclass
@dataclass
class Experiment:
data_version: str
random_state: int
model: str
validation_f1: float
record = Experiment("batch-v1", 42, "logistic-regression", 0.71)
print(asdict(record))
这类记录不能替代专业实验平台,但能防止“这次分数来自哪份数据”无人回答。
可运行实现
python -m pip install scikit-learn
from sklearn.datasets import make_classification
from sklearn.dummy import DummyClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import f1_score
from sklearn.model_selection import train_test_split
X, y = make_classification(
n_samples=800, n_features=8, n_informative=5,
weights=[0.75, 0.25], random_state=42,
)
X_train, X_temp, y_train, y_temp = train_test_split(
X, y, test_size=0.4, stratify=y, random_state=42,
)
X_valid, X_test, y_valid, y_test = train_test_split(
X_temp, y_temp, test_size=0.5, stratify=y_temp, random_state=42,
)
baseline = DummyClassifier(strategy="most_frequent").fit(X_train, y_train)
model = LogisticRegression(max_iter=1000, random_state=42).fit(X_train, y_train)
print("baseline valid F1:", f1_score(y_valid, baseline.predict(X_valid)))
print("model valid F1:", round(f1_score(y_valid, model.predict(X_valid)), 3))
print("final test F1:", round(f1_score(y_test, model.predict(X_test)), 3))
输入是固定随机种子生成的 800 条样本,输出是基线、验证集和最终测试集 F1。真实项目不能因为测试分数不满意而反复调整后继续称其为“最终测试”。
识别欠拟合和过拟合
训练与验证分数都低,可能是特征不足、模型过简单或标签噪声大;训练高而验证低,可能是模型过复杂、数据太少或分布不一致。解决方式不是统一换更强模型,而是查看学习曲线、错误样本和数据分布。
最终推理还应在新进程中加载产物,用原始字段运行一条样本。只有训练脚本能预测,通常说明预处理或特征契约没有被交付。
用学习曲线区分数据与容量问题
只看一次训练/验证分数很难判断“继续收集数据”是否有用。学习曲线逐步增加训练样本,观察两类分数:
from sklearn.model_selection import learning_curve
import numpy as np
sizes, train_scores, valid_scores = learning_curve(
LogisticRegression(max_iter=1000),
X_train,
y_train,
cv=5,
scoring="f1",
train_sizes=np.linspace(0.2, 1.0, 5),
)
for size, train_mean, valid_mean in zip(
sizes, train_scores.mean(axis=1), valid_scores.mean(axis=1)
):
print(size, round(train_mean, 3), round(valid_mean, 3))
训练分数高、验证分数低,且随样本增加间隔缩小,补数据可能有帮助。两者都低且早早收敛,更应检查特征、标签和模型假设。这些只是诊断线索,仍要结合错误样本。
数据分布会成为闭环的一部分
离线测试只评估历史分布。上线后至少记录特征缺失率、取值范围、预测正类比例、服务延迟和真实标签回流时间。输入改变不一定立即导致效果变差,但它是触发调查的信号。
进一步验证
- 将项目信息写成问题定义卡,确保预测时点早于所有特征产生时间。
- 使用至少两个基线:多数类和一条可解释规则。
- 在独立进程加载产物,对一条原始样本完成预测,不复制训练脚本的预处理。
- 保存数据版本、代码版本、切分方式、参数、指标和模型文件哈希。
常见问题与排查
- 先看测试集再选模型:测试集已经参与决策,应重新保留独立数据。
- 没有基线:无法判断模型是否真正增加价值。
- 随机划分后类别消失:分类任务使用
stratify,时间数据按时间划分。 - 只保存模型对象:推理还需要相同列、类型和预处理。
小结
可靠闭环是问题与指标 → 基线 → 数据划分 → 训练验证 → 错误分析 → 一次最终测试 → 独立推理。模型只是其中一个环节。
License: CC BY-NC 4.0
Updated 2 hours ago
Was this article helpful? Give it a like.
0 comments


