核心结论:训练一个模型的正确姿势不是「丢数据进模型等 loss 下降」,而是一条包含 10 个关键步骤的完整链路:① 划分数据(train/validation/test)→ ② 预处理归一化 → ③ 设计网络与损失函数 → ④ 选优化器与学习率 → ⑤ 写训练循环(前向/反向/更新)→ ⑥ 每轮用验证集监控过拟合 → ⑦ 早停与调参迭代 → ⑧ 用从未见过的测试集做最终评估 → ⑨ 保存并记录实验 → ⑩ 部署上线并持续监控。很多人只做第 ③~⑤ 步就宣告「训练完成」,结果上线就翻车——真正的坑全藏在数据划分、验证监控和测试评估里。本文配一段完整可跑的 PyTorch 代码,走一遍全流程。
目录
- 一句话结论
- 第 1 步:划分数据(train/validation/test)
- 第 2 步:预处理与归一化
- 第 3 步:设计网络与损失函数
- 第 4 步:选择优化器与学习率
- 第 5 步:写训练循环(前向/反向/更新)
- 第 6 步:验证集监控过拟合
- 第 7 步:早停与调参迭代
- 第 8 步:测试集做最终评估
- 第 9 步:保存模型与记录实验
- 第 10 步:部署上线与持续监控
- 完整可运行代码(PyTorch 端到端)
- 对照表:症状 → 原因 → 解法
- 判断收尾
1. 一句话结论
先建立一个直觉 🎭:训练模型像「请家教」——数据划分是「分好考场」,预处理是「把题目排版清晰」,网络结构是「家教本身的天赋」,损失函数是「考试大纲」,优化器是「怎么给家教反馈」,验证集是「模拟考」,测试集是「高考」。如果只关心「家教做了多少题」(训练 loss),却从不看「模拟考成绩」(验证 loss),等到高考(测试集)才发现全是「背题」,那就晚了。
一句话:训练 = 数据划分 + 预处理 + 网络 + 损失 + 优化器 + 训练循环 + 验证监控 + 测试评估,缺一步都可能让你上线崩盘。
2. 第 1 步:划分数据(train/validation/test)
训练的第一步不是建模,而是分数据。很多新手上来就把全部数据丢进模型,这是最大的坑之一。
- 训练集(training set):用来更新模型权重(weight),模型「做题」的地方。
- 验证集(validation set):用来指导超参数(hyperparameter)调整,并在训练过程中检查过拟合(overfitting),相当于「模拟考」。
- 测试集(test set):提供对最终模型性能的公正评估,整个训练调参过程都不能碰它,否则评估就失真了,相当于「高考」。
常见的划分比例是 70/20/10 或 80/10/10(数据量大时)。核心铁律只有一条:测试集只能碰一次,且必须在模型完全定稿后才用。
⚠️ 最隐蔽的坑:预处理(归一化)的统计量如果是在「全量数据」上算的,就会把测试集的信息泄露进训练,属于 data leakage(数据泄露),会让验证效果好、线上崩。
3. 第 2 步:预处理与归一化
原始数据通常不能直接喂给模型,要过一遍预处理 pipeline(流水线)。
- 数值特征:做归一化(normalization)或标准化(standardization)。标准化公式为 \(x' = \frac{x - \mu}{\sigma}\),让特征均值为 0、方差为 1,能显著加速梯度下降收敛。
- 分类特征:做 one-hot 编码或嵌入(embedding)。
- 缺失值:用均值、中位数填充或删除。
- 数据增强(data augmentation):图像做旋转裁剪、文本做同义词替换,人工把训练集扩大 2–10 倍,是最有效的防过拟合手段之一。
⚠️ 关键纪律:归一化用的 \(\mu\) 和 \(\sigma\) 必须在训练集上算好,再统一应用到验证/测试集,不能全量一起算。
4. 第 3 步:设计网络与损失函数
这一步决定「模型长什么样、怎么算考分」。
- 网络结构(network architecture):层数、每层神经元数决定了模型的「容量(capacity)」。参数越多容量越大,「记忆」能力越强,但也越容易过拟合。
- 损失函数(loss function):分类用交叉熵(cross-entropy),回归用均方误差(MSE)。损失函数就是「考试大纲」——它告诉优化器「错得多严重」。
一个直觉 🎭:网络容量像「记性」——容量太小学不会(欠拟合),容量太大就「死记硬背」(过拟合)。调参的本质就是找一个「刚好能学懂又不背题」的容量。
5. 第 4 步:选择优化器与学习率
模型训练的动力来源是优化器(optimizer),它决定「怎么根据 loss 更新权重」。
- SGD:朴素随机梯度下降,稳定但收敛慢。
- Adam:自适应学习率,收敛快、对学习率不敏感,实际工程最常用。
- 学习率(learning rate):是最重要的超参数之一。学习率 \(\eta\) 过大,loss 会在最小值附近震荡发散;过小则收敛极慢,甚至卡在局部最优。
经验值:SGD 常用 0.01,Adam 常用 1e-3。调参时通常用对数网格搜索,如 1e-2 / 1e-3 / 1e-4。
6. 第 5 步:写训练循环(前向/反向/更新)
这是「真正在训练」的核心循环,每个 batch(批次)都要走三步:
- 前向传播(forward):把输入 \(x\) 送入网络,算出预测 \(\hat{y}\) 和损失 \(\mathcal{L}\)。
- 反向传播(backward):调用 loss.backward(),用链式法则算出每个参数的梯度(gradient)。
- 参数更新(update):optimizer.step(),按梯度更新权重:\(\theta \leftarrow \theta - \eta \cdot g\)。
一个 epoch(轮次)就是把整个训练集完整过一遍。通常会跑多个 epoch,直到 loss 不再下降。
💡 每轮记得 optimizer.zero_grad() 清零梯度,否则梯度会累积,这是新手最容易漏的一行。
7. 第 6 步:验证集监控过拟合
训练循环之外,每个 epoch 结束时要在验证集上算一次 loss 和准确率。这是判断「该停还是该继续」的眼睛。
- 训练 loss 一直在降,验证 loss 先降后升 → 这就是经典的过拟合信号。
- 判断依据:当验证 loss 连续 N 个 epoch 不再下降(甚至上升)时,就该停。
一个直觉 🎭:训练 loss 像「平时作业」,模型背题可以拿满分;验证 loss 像「模拟考」,一旦模拟考分数开始变差,说明模型开始在背题而不是学规律。
8. 第 7 步:早停与调参迭代
监控到过拟合后,需要做两件事:
- 早停(early stopping):在验证 loss 开始回升时终止训练,并回滚到验证 loss 最低的那一个 checkpoint(检查点)。这是最省事的防过拟合手段。
- 调参迭代(hyperparameter tuning):如果欠拟合,加大容量或降正则;如果过拟合,加正则(正则化,L2)、加 dropout(随机丢弃,比例常取 0.2–0.5)、增大数据、降容量。每次调参都在验证集上评估,反复迭代直到验证指标不再提升。
9. 第 8 步:测试集做最终评估
模型调参完成后,才轮到测试集登场。
- 用之前完全没碰过的测试集,跑一遍最终评估(准确率、F1、回归的 MSE 等)。
- 铁律:测试集结果只能看一次。如果因为测试结果不好又回去调参,那么测试集信息就被泄露了,得到的是一个「被测试集污染」的虚高分数,线上必然崩。
10. 第 9 步:保存模型与记录实验
模型定稿后,要保存下来并记录整个实验过程。
- 保存权重:torch.save(model.state_dict(), "model.pth"),保存的是参数而非整个对象,更轻量、可移植。
- 记录实验(experiment tracking):记下这次用的数据版本、划分方式、超参数、最终指标。用 MLflow 或手动记日志都行。不记录就复现不了,等于白训。
11. 第 10 步:部署上线与持续监控
训练不是终点,上线后的表现才见真章。
- 部署(deployment):把模型导出为可服务的格式(如 ONNX、TensorRT),封装成 API 对外提供预测。
- 持续监控(monitoring):上线后要盯着真实数据的表现,因为线上数据分布会漂移(data drift),模型会悄悄变差。
- 再训练(retraining):当监控发现指标下滑时,用新数据重新训练,回到第 1 步开始新循环。
💡 一个完整的模型生命周期是闭环:训练 → 上线 → 监控 → 数据变化 → 再训练 → 再上线。单次训练只是这个循环里的一次迭代。
12. 完整可运行代码(PyTorch 端到端)
下面是一段复制粘贴就能跑的完整代码,把上面 10 个步骤串起来:数据划分 → 标准化 → 构建网络与损失 → 优化器 → 训练循环 → 每轮验证监控 → 早停 → 测试评估 → 保存。
运行前:pip install torch numpy scikit-learn。
import numpy as np
import torch
import torch.nn as nn
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
# ① 生成模拟数据:线性可分二分类,1000 个样本、8 维特征
np.random.seed(0)
X = np.random.randn(1000, 8) # 特征
y = (X[:, 0] + 0.5 * X[:, 1] > 0).astype(float) # 标签:线性组合为阈值
# ② 数据划分:先分出测试集(20%),再在剩余里分验证集(20% 的 80%)
X_tr_val, X_test, y_tr_val, y_test = train_test_split(X, y, test_size=0.2,
random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_tr_val, y_tr_val, test_size=0.25,
random_state=42) # 0.25*0.8=0.2 → 60/20/20
# ③ 标准化:只在训练集上 fit,再统一 transform 到验证/测试(防数据泄露)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_val = scaler.transform(X_val)
X_test = scaler.transform(X_test)
# ④ 转成张量
X_train, y_train = torch.tensor(X_train, dtype=torch.float32), torch.tensor(y_train).unsqueeze(1)
X_val, y_val = torch.tensor(X_val, dtype=torch.float32), torch.tensor(y_val).unsqueeze(1)
X_test, y_test = torch.tensor(X_test, dtype=torch.float32), torch.tensor(y_test).unsqueeze(1)
# ⑤ 定义网络(小容量 → 减少过拟合)
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc = nn.Sequential(nn.Linear(8, 16), nn.ReLU(), nn.Linear(16, 1))
def forward(self, x):
return self.fc(x)
model = Net()
criterion = nn.BCEWithLogitsLoss() # 二分类交叉熵
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) # Adam + 学习率 1e-3
# ⑥ 训练循环:前向 → 反向 → 更新,每轮在验证集上监控
best_val, patience, counter = float("inf"), 10, 0 # 早停:10 轮验证不升就停
for epoch in range(200):
model.train() # 切换到训练模式
optimizer.zero_grad() # 关键:清零梯度
logits = model(X_train) # 前向
loss = criterion(logits, y_train) # 算损失
loss.backward() # 反向,算梯度
optimizer.step() # 更新权重
model.eval() # 切到评估模式(关 dropout)
with torch.no_grad(): # 验证阶段不反传
val_logits = model(X_val)
val_loss = criterion(val_logits, y_val).item()
if val_loss < best_val:
best_val, counter = val_loss, 0 # 验证提升 → 保存最优并清零
torch.save(model.state_dict(), "best_model.pth")
else:
counter += 1 # 验证没提升 → 计数
if counter >= patience:
print(f"epoch {epoch}: early stop, best_val={best_val:.4f}")
break
# ⑦ 加载最优权重,在测试集做最终评估(碰一次)
model.load_state_dict(torch.load("best_model.pth"))
model.eval()
with torch.no_grad():
test_probs = torch.sigmoid(model(X_test))
test_acc = ((test_probs > 0.5).float() == y_test).float().mean().item()
print(f"test accuracy = {test_acc:.4f}")
怎么读这段代码:第 ③ 步 scaler.fit 只在训练集上做、再 transform 到验证/测试集,正是第 2 步强调的防 data leakage 关键;第 ⑥ 步每个 epoch 用验证 loss 监控,配合 patience=10 的早停——验证 loss 连续 10 轮不下降就中断并保存最优权重,对应第 7 步「早停」;第 ⑦ 步只在测试集上跑一次最终评估,对应第 9 步铁律。这套骨架几乎适配所有 PyTorch 训练任务。
13. 对照表:症状 → 原因 → 解法
14. 判断收尾
什么时候该用这套 10 步流程:任何「要上线、要复现、要评估可信」的模型训练任务,都该走完整链路——尤其要守住两条纪律:测试集只碰一次、预处理统计量只在训练集上算。什么时候可以简化:纯学习 demo、或只是验证一个 idea 时,可以省略实验记录和部署监控,但数据划分和测试评估一步都不能省,否则你根本不知道模型真实水平。
本专栏《机器学习》收录从数据预处理、模型评估、类别不平衡到训练流程等实战方法与面试考点,每篇都配一段可直接运行的代码,持续更新。想在实战里少踩坑,可在专栏页订阅。
本文由 AI图鉴自动抓取并翻译,版权归原作者所有;如需查看原文请点下方链接。
Core conclusion: Training a model in the correct position is not "los down, for example, by throwing data into models" but a complete chain consisting of 10 key steps: 1 dividing data (train/validation/test) → 2 pre-procession integration 3 Design network and loss function 4 Optimizer and learning 5 Writing training cycle (upward/reverse/update) 6 In the third and fifth steps, many people declared "training completed" and then turned over -- the real pit was hidden in data disaggregation, validation surveillance and testing assessments. This document is accompanied by a full runable PyTorch code, walk through the whole process.
Contents
- One conclusion.
- Step 1: Split data (train/validation/test)
- Step 2: Pre-treatment and harmonization
- Step 3: Design networks and loss functions
- Step 4: Select the optimizer and the learning rate
- Step 5: Write training cycles (upward/reverse/update)
- Step 6: Validation set controls
- Step 7: Early cessation and alignment Sub.
- Step 8: Test set for final evaluation
- Step 9: Models and record-keeping experiments
- Step 10: Deployment on line and continuous monitoring
- Full runable code (PyTorch-to-end)
- Checklist: Symptoms, causes, solutions
- Finish your judgment.
1. Conclusion Comment
Let's build a hunch. – Data is divided into “shows” and pre-processing is “sequencing the subject clearly”, the network structure is “the gift of the tutor”, the loss function is “the outline of the examination”, the optimist is “how to give feedback to the tutor”, the validation set is “simulation” and the test set is “simulation”. It would be too late if you only cared about "how many questions have been taught" and never looked at "simulation" until you found out it was all "backlines."
In one sentence: Training = data disaggregation + pre-processing + network + loss + optimizer + training cycle + validation monitoring + test evaluation, a lack of a step could cause you to crash.
Step 1: Disaggregating data (train/validation/test)
The first step in training is not modelling, but data disaggregation. Many beginners came up and threw all the data into the model, one of the largest pits.
- Training set: to update model weights, model "problems".
- Validation set: to guide the adjustment of hyperparameters and to check overfitting during training, which is equivalent to a "simulation test".
- Test set: provide an impartial assessment of the performance of the final model, which cannot be touched throughout the training transfer process, otherwise the assessment will be distorted, amounting to a “high examination”.
The common division is 70/20/10 or 80/10/10 (when data are large). There is only one core iron rule: the test set can only be touched once and must be used after the model has been fully finalized.
⚠️ The most hidden pit: if the pre-treatment (consolidated) statistics are calculated on "full data", the test collection is leaked into training, which belongs to the data leak, making the validation work well and online.
Step 2: Pre-treatment and harmonization
The raw data are usually not fed directly to the model and undergo a pre-processing pipeline.
- Numerical characteristics: integration or standardization. Standard formula is \\(x' = \\frac{x-mu}{\sigma}}, allowing an average feature value of 0 and a variance of 1 to significantly accelerate the gradient reduction.
- Classification characteristics: make one-hot encoding or embedding.
- Missing value: Fill or delete with average, median.
- Data enhancement: Images are rotated, text is replaced by synonyms and manual expansion of the training set 2-10 times is one of the most effective means of protection against cross-fertilization.
Key Disciplines: \\(mu\) and \\sigma\ must be calculated in the training set and applied uniformly to the validation/test set, not in full.
Step 3: Design networks and loss functions
This step determines what the model looks like and how it counts.
- Network structure: the number of layers and the number of neurons per layer determine the "capacity" of the model. The larger the parameters, the stronger the memory, the easier it is to match.
- Loss function (loss funcing): Categorize as cross-cross-entropy, revert to average error (MSE). The loss function is the "test outline" -- it tells the optimizer "too bad."
One intuitive: network capacity is like "recognizing" - too big for elementary school. The essence of the transfer is to find a capacity "that happens to understand and don't fall back."
5. Step 4: Optimizer selection and learning
Model training is driven by optimizers, which decide "how to update weights based on loss".
SSD: The plain and random gradient is down, stable but slow.
- Adam: Self-adapted learning rates, high growth rates, low sensitivity to learning rates, and practical engineering.
- Learning rate: one of the most important parametrics. The learning rate is too high, and loss will convulsate near the lowest value; at the lower end, it is very slow and even stuck to the best part.
Empirical value: SSD common 0.01, Adam common 1e-3. Reference is usually searched using a logarithmic grid such as 1e-2 / 1e-3 / 1e-4.
Step 5: Writing the training cycle (upward/reverse/update)
This is the core cycle of "real training" with three steps for each watch:
- Forward transmission (forward): send input \\(x\) into the network to calculate forecasts and losses (\matcal{L}).
- Backward transmission (backward transmission): call loss.backward() and calculate the gradient (gradient) for each parameter using a chain method.
- Parameter update (update): optimizer.step(), update weight by gradient: \\(theeta \\leftarrow \theta -\eta \cdot g\).
One epoch is to go through the whole set. Usually run multiple epochs until the loss doesn't fall.
Each round remembers the zero gradient, which otherwise accumulates, which is the line most easily missed by beginner.
7. Step 6: Validation cluster monitoring proposed
Outside the training cycle, each epoch ends with a loss and accuracy factor at the validation set. This is the eye that determines whether to stop or continue.
- Trained ross to be down, certified loss to be first down and then up.
- Basis of judgement: when verifying the loss of a continuous N epoch does not drop (or even rise) it should stop.
A hunch: Trains a ross like "business in normal times" and the model backlines can get a full score; validates a ross like "simulation exam" and once the simulation scores start to change, it means that the model begins to go back and not learn the pattern.
8. Step 7: Early cessation and participation Organisation Sub.
Two things need to be done when the surveillance is complete:
- Early stopping: terminates training at the time of validation of the loss and rolls back to the checkpoint (checkpoint) where the certificate is lowest. This is the least costly means of defence.
- Hyperparameter transition: increase capacity or lower normality if unsatisfied, plus regularity (regulated, L2), plus dropout (random discard, often 0.2 to 0.5), increase data and reduce capacity. Each reference is assessed on the validation set and is repeated until the validation indicator is not elevated.
Step 8: Test set for final evaluation
Once the model is completed, the test set will be ready.
- Run the final evaluation (accuracy rate, F1, returned MSE, etc.) using test sets that were never touched before.
- Iron: The results can only be seen once. If the test results are not good, then the test set information is leaked, and it's a "test-contaminated" high score, and the line is bound to collapse.
Step 9: Models and record keeping experiments
After the model has been finalized, the entire experiment is to be preserved and recorded.
- Save weight: torch.save (model.state dict(), "model.pth") saves parameters rather than the whole object, lighter, portable.
- Recording experiments: take note of the version of the data used, the way it was divided, the super-parameters, the final indicators. Use MLFlow or manual log. If you do not record, you will not be able to repeat it.
11. Step 10: Deployment of online and continuous monitoring
Training is not the end of the line, but only when it comes online.
- Deployment: export the model into a serviceable format (e.g. ONNX, TensorRT) and encapsulate it as an API external forecast.
- Continuous monitoring: keep an eye on the performance of real data on the line, because the distribution of data on the line moves (data drift) and the model changes quietly.
- Retraining: When surveillance indicators are down, retrain with new data and start a new cycle at step 1.
A complete model life cycle is a closed ring: training to go online, monitoring data changes, re-training and back online. Single training is just an iterative in this cycle.
12. Full runable code (PyTorch-to-end)
The following is a complete copy of the code that can be pasted, and a series of 10 steps above: data disaggregation standardization network construction and loss optimizationrs → training cycle → validation monitoring rounds → test evaluation → preservation.
Before running: pip install tool numpy scikit-learn.
import numpy as np
import torch
import torch.nn as nn
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
#1 Generate simulation data: linear split, 1,000 sample, 8-D features
np.random.seed(0)
X = np.random.rann(1,000,8)# feature
y = (X[: 0] + 0.5 *X[: 1] > 0). stype (fload) # label: linear combination is the threshold
#2 Disaggregation of data: first split test set (20%) and then split validation set in the remaining mile (80% of 20%)
X_tr_val, X_test, y_tr_val, y_test = train_test_split(X, y, test_size=0.2,
random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_tr_val, y_tr_val, test_size=0.25,
random_state=42) # 0.25*0.8=0.2 → 60/20/20
#3 Standardization: fit only on the training set, then harmonize transform to validation/test (preventing data leak)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_val = scaler.transform(X_val)
X_test = scaler.transform(X_test)
#4 Turn to the grid
X_train, y_train = torch.tensor(X_train, dtype=torch.float32), torch.tensor(y_train).unsqueeze(1)
X_val, y_val = torch.tensor(X_val, dtype=torch.float32), torch.tensor(y_val).unsqueeze(1)
X_test, y_test = torch.tensor(X_test, dtype=torch.float32), torch.tensor(y_test).unsqueeze(1)
#5 Define network (small capacity reduced)
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc = nn.Sequential(nn.Linear(8, 16), nn.ReLU(), nn.Linear(16, 1))
def forward(self, x):
return self.fc(x)
model = Net()
Criterion = nn. BCEW with LogitsLoss() #II Class Crossing
# Adam + Learning Rate 1e-3
#6 Training cycle: Forward # reverse # update, monitor each round on the validation set
# Early: 10 rounds of authentication without ascending
for epoch in range(200):
# Switch to training mode
# Key: zero gradient
logits = model (X train) # Forward
# Loss #
# Reverse, calculate gradient
# Right to update Heavy
model.eval() # Cut to evaluation mode (dropout)
# At the validation stage, do not reverse
val_logits = model(X_val)
val_loss = criterion(val_logits, y_val).item()
if val_loss < best_val:
Best val, cooler = val loss, 0 # Validation Upgrade Zoom Save Best and Clear
torch.save(model.state_dict(), "best_model.pth")
else:
Counter + = 1 # Authentication does not raise count
if counter >= patience:
print(f"epoch {epoch}: early stop, best_val={best_val:.4f}")
break
#7 Load the best weight and make a final assessment in the test set (touch)
model.load_state_dict(torch.load("best_model.pth"))
model.eval()
with torch.no_grad():
test_probs = torch.sigmoid(model(X_test))
test_acc = ((test_probs > 0.5).float() == y_test).float().mean().item()
print(f"test accuracy = {test_acc:.4f}")
How do you read this code: Step 3 scaler.fit is done only on the training set and transform to the validation/test set, which is the key to the protection against data leakage highlighted in step 2; Step 6 each epoch uses the LOS monitoring to match the early stop of the patience = 10 - to verify that the los 10 consecutive rounds interrupt and preserve the best weights, corresponding to the 7th step "early stop"; Step 7 runs the final evaluation only on the test set, corresponding to the 9th step bar. This skeleton is almost suitable for all PyTorch training missions.
13. Comparative table: Symptoms and causes
14. Closure of judgement
When should this 10-step process be used: any model training mission "to go online, to repeat, to assess credibility" should take a complete link - in particular, to maintain two disciplines: test set only once, pre-processing statistics only count on the training set. When it can be simplified: when it is pure learning demo, or when it's just testing an idea, you can omit experimental records and deploy monitoring, but you can't save data disaggregation and test evaluation one step, or you don't know the true level of the model.
This column, Machine Learning, includes operational methods and interview points, such as pre-processing of data, model assessment, category imbalance to training process, each with a direct running code and continuous updating. You can subscribe to it on the column page if you want to lower the pits in the field.
Auto-fetched and translated by AI Atlas. All rights belong to the original author.