You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

训练SciBERT验证阶段CUDA显存不足问题的解决方法咨询

解决SciBERT训练时验证阶段的CUDA显存不足问题

我用约10000行的数据集训练SciBERT,按0.6、0.2、0.2的比例划分训练集、验证集和测试集,训练代码如下:

from torch.optim import AdamW
from tqdm import tqdm
from statistics import mean

optim = AdamW(model.parameters(), lr=2e-5, eps=1e-8)

for epoch in range(4):
    epoch_losses = []
    validation_loss = []
    for x, y in tqdm(load_data(x_train, y_train, batch_size=10)):
        model.zero_grad()
        out = model(x, attention_mask=apply_attention_mask(x), labels=y)
        epoch_losses.append(out.loss.item())
        out.loss.backward()
        optim.step()
    print(f"epoch {epoch + 1} loss: {mean(epoch_losses)}")

    for x, y in load_data(x_validation, y_validation, batch_size=10):
    # validation data
        validation_output = model(x, attention_mask=apply_attention_mask(x), labels=y)
        validation_loss.append(validation_output.loss.item())
    print(f"Validation for epoch {epoch + 1} loss: {mean(validation_loss)}")

但完成一轮训练集训练后加载验证集时,Colab返回如下错误:

OutOfMemoryError: CUDA out of memory. Tried to allocate 120.00 MiB (GPU 0; 14.75 GiB total capacity; 13.84 GiB already allocated; 24.81 MiB free; 14.59 GiB reserved in total by PyTorch) If reserved memory is >> allocated memory try setting max_split_size_mb to avoid fragmentation.  See documentation for Memory Management and PYTORCH_CUDA_ALLOC_CONF

以下是具体修复方案:

核心修复步骤

  • 验证阶段关闭梯度计算:训练阶段产生的梯度会持续占用显存,验证时不需要反向传播,用torch.no_grad()上下文管理器包裹验证循环,彻底避免梯度相关的显存消耗。修改后的验证代码片段:

    with torch.no_grad():
        for x, y in load_data(x_validation, y_validation, batch_size=10):
            # validation data
            validation_output = model(x, attention_mask=apply_attention_mask(x), labels=y)
            validation_loss.append(validation_output.loss.item())
    
  • 手动清理显存缓存:在训练循环结束后、验证开始前,清理未使用的张量和显存碎片,释放被占用的冗余显存。添加代码:

    import torch
    torch.cuda.empty_cache()
    

    放在训练循环结束后,验证循环之前。

  • 调整验证批次大小:如果显存还是紧张,可适当降低验证集的batch_size(比如从10改为8或5),减少单步推理的显存占用。

  • 确保模型仅加载一次:确认训练前已将模型移至GPU,避免验证阶段重复加载。在代码开头添加:

    model = model.to('cuda')
    

整合优化后的完整代码

import torch
from torch.optim import AdamW
from tqdm import tqdm
from statistics import mean

# 确保模型加载到GPU
model = model.to('cuda')
optim = AdamW(model.parameters(), lr=2e-5, eps=1e-8)

for epoch in range(4):
    epoch_losses = []
    validation_loss = []
    
    # 训练阶段
    model.train()
    for x, y in tqdm(load_data(x_train, y_train, batch_size=10)):
        model.zero_grad()
        out = model(x, attention_mask=apply_attention_mask(x), labels=y)
        epoch_losses.append(out.loss.item())
        out.loss.backward()
        optim.step()
    print(f"epoch {epoch + 1} loss: {mean(epoch_losses)}")
    
    # 清理显存缓存
    torch.cuda.empty_cache()
    
    # 验证阶段
    model.eval()
    with torch.no_grad():
        for x, y in load_data(x_validation, y_validation, batch_size=10):
            validation_output = model(x, attention_mask=apply_attention_mask(x), labels=y)
            validation_loss.append(validation_output.loss.item())
    print(f"Validation for epoch {epoch + 1} loss: {mean(validation_loss)}")

内容的提问来源于stack exchange,提问作者Hoang Cuong Nguyen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 19:53:40