算法与深度学习·

从 SGD 到梯度累积:Epoch、Batch、Step 的关系全解析

介绍深度学习里的几个基本概念:Epoch、Batch、Step 三者的关系,SGD、BGD、MBGD 的区别,以及梯度累积怎么用。

首发于 CSDN原文链接

本篇目录18 节
本文将简单介绍一些深度学习中的基本概念:
Epoch、Batch、Step 三者之间的关系
SGD、BGD、MBGD 方法的区别
梯度累积的使用和…

Epoch、Batch、Step 三者之间的关系

概念
定义
公式
Epoch
整个训练集完整遍历一次
-
Batch
一小组样本,用于一次参数更新前的前/后向传播
Number of Batches per Epoch=⌈NB⌉\text{Number of Batches per Epoch} = \left\lceil \frac{N}{B} \right\rceil
Step
一次完整的参数更新过程(前向+反向传播+更新参数)
Total Steps=⌈NB⌉×E\text{Total Steps} = \left\lceil \frac{N}{B} \right\rceil \times E

举例说明

假设:
  • 数据集大小 N=10,000N = 10{,}000
  • batch size B=32B = 32
  • epoch 数 E=5E = 5
  1. 计算 1 个 epoch 中的 batch 数量:
Number of Batches per Epoch=⌈10,00032⌉=⌈312.5⌉=313\text{Number of Batches per Epoch} = \left\lceil \frac{10{,}000}{32} \right\rceil = \lceil 312.5 \rceil = 313
  1. 计算总步数:
Total Steps=⌈10,00032⌉×5=313×5=1565\text{Total Steps} = \left\lceil \frac{10{,}000}{32} \right\rceil \times 5 = 313 \times 5 = 1565
图示(以前 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 is 0.6238939762115479
我们来不断的尝试降低loss

首先了解调度器

  1. 学习率调度器(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 is 0.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

评论加载中…