本文将简单介绍一些深度学习中的基本概念:
Epoch、Batch、Step 三者之间的关系
SGD、BGD、MBGD 方法的区别
梯度累积的使用和…
Epoch、Batch、Step 三者之间的关系
概念 | 定义 | 公式 |
Epoch | 整个训练集完整遍历一次 | - |
Batch | 一小组样本,用于一次参数更新前的前/后向传播 | |
Step | 一次完整的参数更新过程(前向+反向传播+更新参数) |
举例说明
假设:
- 数据集大小
- batch size
- epoch 数
- 计算 1 个 epoch 中的 batch 数量:
- 计算总步数:
图示(以前 2 个 epoch 为例):
Epoch 1 └── Batch 1 → Step 1 (前向+反向传播+更新参数) └── Batch 2 → Step 2 └── Batch 3 → Step 3 └── ... └── Batch 313 → Step 313 Epoch 2 └── Batch 1 → Step 314 └── Batch 2 → Step 315 └── Batch 3 → Step 316 └── ... └── Batch 313 → Step 626
- 每个 epoch 包含多个 batch,每个 batch 对应 1 次参数更新(即 1 个 step)。
- 我们可以用
epochs控制训练回合数或用max_steps控制训练总 step 数(AI 画图的 UI 界面中常出现这个超参数选项)。
我们来实现了一个基础的PyTorch二分类神经网络训练流程来进一步学习
代码示例
import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset def same_seeds(seed=42): torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed) # 设置随机种子 same_seeds() # 数据集参数 N = 10000 # 数据集总样本数 B = 32 # batch_size E = 5 # epochs # 创建一个示例数据集 X = torch.randn(N, 10) # 生成服从标准正态分布(均值为0,方差为1)的随机数数列N*10 y = torch.randint(0, 2, (N,)) # 二分类标签 如果N=5,可能会得到类似这样的结果: tensor([0, 1, 1, 0, 1]) # 这里的 X 和 y 都是 torch.tensor 类型 # 定义数据集和 DataLoader dataset = TensorDataset(X, y) dataloader = DataLoader(dataset, batch_size=B, shuffle=True, drop_last=False) # 定义模型 model = nn.Sequential( nn.Linear(10, 50), nn.ReLU(), nn.Linear(50, 2) ) # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=0.01) # 训练模型 steps_per_epoch = len(dataloader) # 一个 epoch 内 batch 的数量 total_steps = steps_per_epoch * E device = "cuda" if torch.cuda.is_available() else "cpu" # 这里设置 device 为 cuda,如果没有 cuda 设备,则使用 cpu model.to(device) # 记录最佳损失 best_loss = float('inf') # 记录当前 step current_step = 0 # 这里设置成从 1 开始只是为了不在 print 中额外设置,实际写代码的时候不需要纠结这一点 for epoch in range(1, E + 1): for batch_idx, (inputs, targets) in enumerate(dataloader, start=1): inputs = inputs.to(device) targets = targets.to(device) # 清零梯度(这一步放在反向传播前和参数更新之后都可以) optimizer.zero_grad() # 前向传播 outputs = model(inputs) # 计算损失 loss = criterion(outputs, targets) # 反向传播(计算梯度) loss.backward() # 更新参数 optimizer.step() best_loss = min(best_loss, loss.item()) current_step += 1 # 每 50 步打印一次 if batch_idx % 50 == 0: # 如果不需要打印累积 step,可以去除 current_step 项直接使用 batch_idx print(f"Epoch [{epoch}/{E}], Batch [{batch_idx}/{steps_per_epoch}], " f"Step [{current_step}/{total_steps}], Loss: {loss.item():.4f}") # 参数更新 print(best_loss) # 可以看到: # - epoch 从 1 到 E # - batch 从 1 到 steps_per_epoch # - step 累计从 1 到 total_steps
输出:
Epoch [1/5], Batch [50/313], Step [50/1565], Loss: 0.6813 Epoch [1/5], Batch [100/313], Step [100/1565], Loss: 0.6892 Epoch [1/5], Batch [150/313], Step [150/1565], Loss: 0.7314 Epoch [1/5], Batch [200/313], Step [200/1565], Loss: 0.7105 Epoch [1/5], Batch [250/313], Step [250/1565], Loss: 0.6966 Epoch [1/5], Batch [300/313], Step [300/1565], Loss: 0.6974 Epoch [2/5], Batch [50/313], Step [363/1565], Loss: 0.6866 Epoch [2/5], Batch [100/313], Step [413/1565], Loss: 0.6960 Epoch [2/5], Batch [150/313], Step [463/1565], Loss: 0.7177 Epoch [2/5], Batch [200/313], Step [513/1565], Loss: 0.7086 Epoch [2/5], Batch [250/313], Step [563/1565], Loss: 0.7078 Epoch [2/5], Batch [300/313], Step [613/1565], Loss: 0.6947 Epoch [3/5], Batch [50/313], Step [676/1565], Loss: 0.6869 Epoch [3/5], Batch [100/313], Step [726/1565], Loss: 0.7031 Epoch [3/5], Batch [150/313], Step [776/1565], Loss: 0.6880 Epoch [3/5], Batch [200/313], Step [826/1565], Loss: 0.7015 Epoch [3/5], Batch [250/313], Step [876/1565], Loss: 0.6961 Epoch [3/5], Batch [300/313], Step [926/1565], Loss: 0.6881 Epoch [4/5], Batch [50/313], Step [989/1565], Loss: 0.7042 Epoch [4/5], Batch [100/313], Step [1039/1565], Loss: 0.6856 Epoch [4/5], Batch [150/313], Step [1089/1565], Loss: 0.6768 Epoch [4/5], Batch [200/313], Step [1139/1565], Loss: 0.6967 Epoch [4/5], Batch [250/313], Step [1189/1565], Loss: 0.6800 Epoch [4/5], Batch [300/313], Step [1239/1565], Loss: 0.6909 Epoch [5/5], Batch [50/313], Step [1302/1565], Loss: 0.6770 ... Epoch [5/5], Batch [200/313], Step [1452/1565], Loss: 0.6987 Epoch [5/5], Batch [250/313], Step [1502/1565], Loss: 0.6860 Epoch [5/5], Batch [300/313], Step [1552/1565], Loss: 0.7003 0.6238939762115479 ...
最best 的loss is0.6238939762115479
我们来不断的尝试降低loss
首先了解调度器
- 学习率调度器(Scheduler)
常见的学习率更新方式有两种:
- 以 step 为基础:在每个 step 结束后更新学习率。
scheduler = ... for epoch in range(E): for batch_idx, (inputs, targets) in enumerate(dataloader): # 前向、后向、更新参数 ... # 在每个 step 后更新学习率 scheduler.step()
- 以 epoch 为基础:在每个 epoch 结束后更新学习率。
scheduler = ... for epoch in range(E): for batch_idx, (inputs, targets) in enumerate(dataloader): # 前向、后向、更新参数 ... # 在每个 epoch 后更新学习率 scheduler.step()
让我们试一试以 epoch 为基础
修改如下
# 更新参数 # optimizer.step() best_loss = min(best_loss, loss.item()) current_step += 1 # 每 50 步打印一次 if batch_idx % 50 == 0: # 如果不需要打印累积 step,可以去除 current_step 项直接使用 batch_idx print(f"Epoch [{epoch}/{E}], Batch [{batch_idx}/{steps_per_epoch}], " f"Step [{current_step}/{total_steps}], Loss: {loss.item():.4f}") optimizer.step() print(best_loss)
此时best loss is0.5978379249572754
效果更好了,为什么?
在深度学习中,以 step 和以 epoch 为基础更新学习率的主要区别体现在更新频率、数据覆盖度和实际应用场景上。以下是具体对比:
更新频率不同
- Step-based:
- 每次迭代(batch)后更新:学习率在每个 step(即单个 batch 训练完成后)调整一次。
- 更频繁:若数据集有
N个样本,batch size 为B,则每 epoch 包含N/B次更新。
- 适用场景:适合动态调整(如损失波动大时需快速响应)或大数据集(epoch 耗时过长)。
- Epoch-based:
- 每轮完整遍历数据后更新:学习率在每个 epoch 结束后调整一次。
- 更稳定:适用于对噪声敏感的任务(如小数据集或需要稳定下降的场景)。
典型应用场景
- Step-based 的常见用途:
- 学习率预热(Warmup):如
BERT训练中,前几千个 step 线性增加学习率,避免初期梯度爆炸。
- 大模型/大数据集:当 1 个 epoch 包含百万级 step 时(如 GPT-3),按 step 调整更高效。
- 动态调度器:如
OneCycleLR按 step 精细控制学习率变化周期。
- Epoch-based 的常见用途:
- 简单衰减策略:如每 5 个 epoch 学习率乘以
0.1(经典 ResNet 训练)。
- 依赖验证指标时:如根据 epoch 结束时的验证准确率决定是否调整。
- 小数据集:epoch 耗时短,按 epoch 调整更易实现。
选择建议
- 优先 Step-based:当数据量大、需要高频调整或使用 warmup 时。
- 优先 Epoch-based:当训练稳定性和可解释性更重要(如学术实验复现)。
- 混合策略:某些调度器(如
CosineAnnealingLR)可同时支持两种模式,需根据任务需求选择。
总之,两者的核心差异在于 更新的时间粒度,选择时需权衡调整频率与训练稳定性。实际应用中,step-based 更常见于现代大规模训练,而 epoch-based 多用于传统小规模任务。
因为是小规模,所以我们的模型loss更低了
接下来我们添加早停机制,因为我们可以观察
训练过程
发现模型在某个epoch就达到了best loss,但还在训练导致了过拟合
早停(Early Stopping)
可以基于 epoch 或 step 来监控验证集性能,若在一定 patience(耐心值)内验证性能没有提高,则提前停止训练来避免过拟合。
首先把训练函数封装成一个train_one_epoch函数
具体完整代码
import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset def same_seeds(seed=42): torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed) # 设置随机种子 same_seeds() # 数据集参数 N = 10000 # 数据集总样本数 B = 32 # batch_size E = 5 # epochs # 创建一个示例数据集 X = torch.randn(N, 10) # 生成服从标准正态分布(均值为0,方差为1)的随机数数列N*10 y = torch.randint(0, 2, (N,)) # 二分类标签 如果N=5,可能会得到类似这样的结果: tensor([0, 1, 1, 0, 1]) # 这里的 X 和 y 都是 torch.tensor 类型 # 定义数据集和 DataLoader dataset = TensorDataset(X, y) dataloader = DataLoader(dataset, batch_size=B, shuffle=True, drop_last=False) # 定义模型 model = nn.Sequential( nn.Linear(10, 50), nn.ReLU(), nn.Linear(50, 2) ) # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=0.01) # 训练模型 steps_per_epoch = len(dataloader) # 一个 epoch 内 batch 的数量 total_steps = steps_per_epoch * E device = "cuda" if torch.cuda.is_available() else "cpu" # 这里设置 device 为 cuda,如果没有 cuda 设备,则使用 cpu model.to(device) # 记录最佳损失 best_loss = float('inf') # 记录当前 step current_step = 0 # 这里设置 patience=2,即如果连续 2 次没有提升,则提前结束训练 patience=5 origin_patience=patience def train_one_epoch(model, dataloader,optimizer,criterion,current_step=0): epoch_best_loss=float('inf') for batch_idx, (inputs, targets) in enumerate(dataloader, start=1): inputs = inputs.to(device) targets = targets.to(device) # 清零梯度(这一步放在反向传播前和参数更新之后都可以) optimizer.zero_grad() # 前向传播 outputs = model(inputs) # 计算损失 loss = criterion(outputs, targets) # 反向传播(计算梯度) loss.backward() # 更新参数 # optimizer.step() epoch_best_loss = min(epoch_best_loss, loss.item()) current_step += 1 # 每 50 步打印一次 if batch_idx % 50 == 0: # 如果不需要打印累积 step,可以去除 current_step 项直接使用 batch_idx print(f"Epoch [{epoch}/{E}], Batch [{batch_idx}/{steps_per_epoch}], " f"Step [{current_step}/{total_steps}], Loss: {loss.item():.4f}") optimizer.step() return epoch_best_loss # 这里设置成从 1 开始只是为了不在 print 中额外设置,实际写代码的时候不需要纠结这一点 for epoch in range(1, E + 1): current_loss=train_one_epoch(model, dataloader,optimizer,criterion,current_step=current_step) if current_loss<best_loss: best_loss=current_loss patience=origin_patience # 保存最佳模型参数 print(f"Best model saved with loss {best_loss:.4f}") torch.save(model.state_dict(), "best_model.pth") else: patience-=1 if patience==0: print(f"No improvement in validation for {epoch} epochs, stopping early.") break print(f'Training complete with best loss {best_loss:.6f}') # 可以看到: # - epoch 从 1 到 E # - batch 从 1 到 steps_per_epoch # - step 累计从 1 到 total_steps # - 最佳模型保存了
Epoch [1/5], Batch [50/313], Step [50/1565], Loss: 0.6825 Epoch [1/5], Batch [100/313], Step [100/1565], Loss: 0.6923 Epoch [1/5], Batch [150/313], Step [150/1565], Loss: 0.7371 Epoch [1/5], Batch [200/313], Step [200/1565], Loss: 0.7104 Epoch [1/5], Batch [250/313], Step [250/1565], Loss: 0.6962 Epoch [1/5], Batch [300/313], Step [300/1565], Loss: 0.6859 Best model saved with loss 0.6125 Epoch [2/5], Batch [50/313], Step [50/1565], Loss: 0.7190 Epoch [2/5], Batch [100/313], Step [100/1565], Loss: 0.7225 Epoch [2/5], Batch [150/313], Step [150/1565], Loss: 0.7078 Epoch [2/5], Batch [200/313], Step [200/1565], Loss: 0.7102 Epoch [2/5], Batch [250/313], Step [250/1565], Loss: 0.6941 Epoch [2/5], Batch [300/313], Step [300/1565], Loss: 0.7258 Epoch [3/5], Batch [50/313], Step [50/1565], Loss: 0.7133 Epoch [3/5], Batch [100/313], Step [100/1565], Loss: 0.7375 Epoch [3/5], Batch [150/313], Step [150/1565], Loss: 0.6734 Epoch [3/5], Batch [200/313], Step [200/1565], Loss: 0.7107 Epoch [3/5], Batch [250/313], Step [250/1565], Loss: 0.7341 Epoch [3/5], Batch [300/313], Step [300/1565], Loss: 0.7034 Epoch [4/5], Batch [50/313], Step [50/1565], Loss: 0.7158 Epoch [4/5], Batch [100/313], Step [100/1565], Loss: 0.6138 Epoch [4/5], Batch [150/313], Step [150/1565], Loss: 0.6502 Epoch [4/5], Batch [200/313], Step [200/1565], Loss: 0.7071 Epoch [4/5], Batch [250/313], Step [250/1565], Loss: 0.7239 Epoch [4/5], Batch [300/313], Step [300/1565], Loss: 0.7386 ... Epoch [5/5], Batch [250/313], Step [250/1565], Loss: 0.6980 Epoch [5/5], Batch [300/313], Step [300/1565], Loss: 0.7369 Best model saved with loss 0.5978 Training complete with best loss 0.597838
没啥变化loss,我们可以增大epoch from 5 to 50
还是没任何变化
Training complete with best loss 0.597838
我们试一试增加
batch size不过要注意Batch Size 与显存
更大的 batch size 意味着每个 step 会处理更多数据,占用更多显存。当遇到 GPU
内存
不足(Out of Memory,OOM)错误时,可以尝试减小 batch size,如果仍想达成大 batch size 的效果,使用梯度累积技巧(见下文)。
梯度累积(Gradient Accumulation)
当 GPU 显存不足以支持较大的 batch_size 时,可以使用梯度累积。梯度累积的核心思想是将多个小批量(mini-batch)的梯度累加起来,然后再更新参数,这样可以模拟更大的 batch_size。
代码示例
假设理想 batch_size = 32,但受显存限制只能一次处理 8 个样本(b=8),则需要累积 4 次(32/8=4)小批次的梯度后再更新参数:
梯度累积的基本步骤:
在每个小批次(batch_size=8)中,我们执行一次前向传播、一次反向传播,并将梯度累加到模型参数的 .grad 中。
当累计了 4 次(也就是相当于处理了 32 个样本后),我们执行 optimizer.step() 来更新参数,然后用 optimizer.zero_grad() 清空累积的梯度。
使用
accelerate 可以自动管理设备与梯度累积逻辑,先进行安装:pip install accelerate
完整实现代码
import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset from accelerate import Accelerator def same_seeds(seed=42): torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed) # 设置随机种子 same_seeds() # 数据集参数 N = 10000 # 数据集总样本数 B = 32 # 理想batch_size b = 8 # 实际 batch size E = 50 # epochs gradient_accumulation_steps = B // b # 等于 4,可以手动设置 # gradient_accumulation_steps:梯度累积步数,这是一个重要的训练技巧。它允许你在较小的实际batch size下模拟较大的有效batch size。 accelerator=Accelerator(gradient_accumulation_steps=gradient_accumulation_steps) # 创建一个示例数据集 X = torch.randn(N, 10) # 生成服从标准正态分布(均值为0,方差为1)的随机数数列N*10 y = torch.randint(0, 2, (N,)) # 二分类标签 如果N=5,可能会得到类似这样的结果: tensor([0, 1, 1, 0, 1]) # 这里的 X 和 y 都是 torch.tensor 类型 # 定义数据集和 DataLoader dataset = TensorDataset(X, y) dataloader = DataLoader(dataset, batch_size=B, shuffle=True, drop_last=False) # 定义模型 model = nn.Sequential( nn.Linear(10, 50), nn.ReLU(), nn.Linear(50, 2) ) # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=0.01) # 将模型和优化器交给 Accelerator 管理 model, optimizer, dataloader = accelerator.prepare(model, optimizer, dataloader) # 训练模型 steps_per_epoch = len(dataloader) # 一个 epoch 内 batch 的数量 total_steps = steps_per_epoch * E device = "cuda" if torch.cuda.is_available() else "cpu" # 这里设置 device 为 cuda,如果没有 cuda 设备,则使用 cpu model.to(device) # 记录最佳损失 best_loss = float('inf') # 记录当前 step current_step = 0 # 这里设置 patience=2,即如果连续 2 次没有提升,则提前结束训练 patience=50 origin_patience=patience def train_one_epoch(model, dataloader,optimizer,criterion,current_step=0): epoch_best_loss=float('inf') for batch_idx, (inputs, targets) in enumerate(dataloader, start=1): # with accelerator with accelerator.accumulate(model): inputs = inputs.to(device) targets = targets.to(device) # 清零梯度(这一步放在反向传播前和参数更新之后都可以) optimizer.zero_grad() # 前向传播 outputs = model(inputs) # 计算损失 loss = criterion(outputs, targets) # 反向传播(计算梯度) # loss.backward() # accelerator.backward(loss) 会自动把 loss 累积到当前的 batch 内,然后反向传播 accelerator.backward(loss) # 更新参数 # optimizer.step() epoch_best_loss = min(epoch_best_loss, loss.item()) current_step += 1 # 每 50 步打印一次 if batch_idx % 50 == 0: # 如果不需要打印累积 step,可以去除 current_step 项直接使用 batch_idx print(f"Epoch [{epoch}/{E}], Batch [{batch_idx}/{steps_per_epoch}], " f"Step [{current_step}/{total_steps}], Loss: {loss.item():.4f}") optimizer.step() return epoch_best_loss # 这里设置成从 1 开始只是为了不在 print 中额外设置,实际写代码的时候不需要纠结这一点 for epoch in range(1, E + 1): current_loss=train_one_epoch(model, dataloader,optimizer,criterion,current_step=current_step) if current_loss<best_loss: best_loss=current_loss patience=origin_patience # 保存最佳模型参数 print(f"Best model saved with loss {best_loss:.4f}") torch.save(model.state_dict(), "best_model.pth") else: patience-=1 if patience==0: print(f"No improvement in validation for {epoch} epochs, stopping early.") break print(f'Training complete with best loss {best_loss:.6f}') # 可以看到: # - epoch 从 1 到 E # - batch 从 1 到 steps_per_epoch # - step 累计从 1 到 total_steps # - 最佳模型保存了
最后结果
Training complete with best loss 0.58797
使用了梯度累计实现了实际的batchsize=32和未实现但是batchsize=32相比Loss更低了
Q:使用了梯度累积后,step 和 batch 的对应关系有什么变化?
- 无梯度累积时:1 个 batch 对应 1 次参数更新(1 step)。
- 有梯度累积时:多个小批次(k 个 batch)累积后才更新一次参数,这时 k 个 batch 才对应 1 次 step。
也就是说,step 的频率降低了,但每次 step 的意义相当于在更大有效 batch_size 上进行一次更新。:
SGD、BGD、MBGD 之间的区别
SGD(随机梯度下降)、BGD(批量梯度下降)和MBGD(小批量梯度下降)是梯度下降
算法
的三种主要变体,核心区别在于每次迭代时使用的数据量不同,进而影响计算效率、收敛速度和稳定性。以下是具体对比:
1. BGD(批量梯度下降)
- 数据使用:每次迭代使用全部训练数据计算梯度。
- 特点:
- 稳定性高:梯度方向是全局最优方向,收敛平稳。
- 计算开销大:尤其数据量大时,每次更新需遍历整个数据集。
- 内存占用高:需同时加载所有数据。
- 适用场景:小数据集或凸优化问题。
2. SGD(随机梯度下降)
- 数据使用:每次迭代随机选取一个样本计算梯度。
- 特点:
- 速度快:单样本计算,迭代频率高。
- 波动大:梯度噪声多,可能无法收敛到最优解(但可能跳出局部最优)。
- 泛化性好:适合在线学习(动态数据流)。
- 适用场景:大数据集、非凸问题(如深度学习)。
3. MBGD(小批量梯度下降)
- 数据使用:每次迭代使用小批量样本(如32、64个)计算梯度。
- 特点:
- 平衡BGD和SGD:兼顾计算效率和稳定性。
- 并行化友好:适合GPU加速(深度学习常用)。
- 需调批量大小:批量过小则波动大,过大则接近BGD。
- 适用场景:绝大多数深度学习任务。
对比总结
指标 | BGD | SGD | MBGD |
梯度准确性 | 高(全局最优) | 低(单样本噪声) | 中(小批量平均) |
收敛速度 | 慢(每步计算量大) | 快(但需更多迭代) | 中(平衡步长与迭代) |
内存需求 | 高 | 低 | 中 |
收敛稳定性 | 平滑 | 波动大 | 相对稳定 |
典型应用 | 传统机器学习 | 在线学习 | 深度学习 |
选择建议
- 数据量小 → 用BGD。
- 数据量大或动态数据 → 用SGD或MBGD。
- 深度学习 → 默认MBGD(结合动量、Adam等优化器效果更佳)。
扩展
如果你还想进一步降低Loss但是没有好的方法,或者效果不好
,我只能说这是没有意义的
因为数据是随机生成的
X = torch.randn(N, 10) y = torch.randint(0, 2, (N,))
X 是 高斯分布噪声
y 是 完全随机的 0/1 标签
这里 特征和标签之间没有任何关系!换句话说,模型是没法“学会规律”的,因为压根没有规律
当然你还是执着于的话可以这样设置
N = 10000 # 数据集总样本数 B = 1 # 理想batch_size b = 1 # 实际 batch size E = 50 # epochs gradient_accumulation_steps = B // b # 等于 4,可以手动设置
Epoch [1/50], Batch [50/10000], Step [50/500000], Loss: 0.8390 Epoch [1/50], Batch [100/10000], Step [100/500000], Loss: 0.6147 Epoch [1/50], Batch [150/10000], Step [150/500000], Loss: 0.5295 Epoch [1/50], Batch [200/10000], Step [200/500000], Loss: 0.6609 Epoch [1/50], Batch [250/10000], Step [250/500000], Loss: 0.4225 Epoch [1/50], Batch [300/10000], Step [300/500000], Loss: 1.0206 Epoch [1/50], Batch [350/10000], Step [350/500000], Loss: 0.8659 Epoch [1/50], Batch [400/10000], Step [400/500000], Loss: 0.5234 Epoch [1/50], Batch [450/10000], Step [450/500000], Loss: 0.8742 Epoch [1/50], Batch [500/10000], Step [500/500000], Loss: 0.8313 Epoch [1/50], Batch [550/10000], Step [550/500000], Loss: 0.5952 Epoch [1/50], Batch [600/10000], Step [600/500000], Loss: 0.7431 Epoch [1/50], Batch [650/10000], Step [650/500000], Loss: 0.5761 Epoch [1/50], Batch [700/10000], Step [700/500000], Loss: 0.6298 Epoch [1/50], Batch [750/10000], Step [750/500000], Loss: 0.6725 Epoch [1/50], Batch [800/10000], Step [800/500000], Loss: 0.5078 Epoch [1/50], Batch [850/10000], Step [850/500000], Loss: 0.8275 Epoch [1/50], Batch [900/10000], Step [900/500000], Loss: 0.5330 Epoch [1/50], Batch [950/10000], Step [950/500000], Loss: 0.8798 Epoch [1/50], Batch [1000/10000], Step [1000/500000], Loss: 0.8836 Epoch [1/50], Batch [1050/10000], Step [1050/500000], Loss: 0.5622 Epoch [1/50], Batch [1100/10000], Step [1100/500000], Loss: 0.5411 Epoch [1/50], Batch [1150/10000], Step [1150/500000], Loss: 0.7891 Epoch [1/50], Batch [1200/10000], Step [1200/500000], Loss: 0.7982 Epoch [1/50], Batch [1250/10000], Step [1250/500000], Loss: 0.4537 ... Epoch [19/50], Batch [9950/10000], Step [9950/500000], Loss: 0.5194 Epoch [19/50], Batch [10000/10000], Step [10000/500000], Loss: 1.6206 No improvement in validation for 19 epochs, stopping early. Training complete with best loss 0.143794
最后best_loss:
0.143794
评论加载中…