transformers模型加载与seed随机状态

14 篇文章 0 订阅

Transformers的模型加载会改变seed的随机状态

这里使用了一个自己写的库进行测试:py-seeds(直接pip就可以安装,目前是0.0.2版本)

import py_seeds
from transformers import AutoModel


def state_str(state_dict):
    random_state = str(state_dict["random"])
    numpy_state = str(state_dict["numpy"][0]) + str(state_dict["numpy"][1].tolist())
    torch_state = str(state_dict["torch"].numpy().tolist())
    torch_cuda_state = "".join([str(i.numpy().tolist()) for i in state_dict["torch_cuda"]])
    return random_state + numpy_state + torch_state + torch_cuda_state


# not load model
state = py_seeds.get_seed_state()
now_state = py_seeds.get_seed_state()
print(state_str(state) == state_str(now_state))
# True: no change to the random state

# load model
model = AutoModel.from_pretrained('roberta-base')
now_state = py_seeds.get_seed_state()
print(state_str(state) == state_str(now_state))
# False: the loading of transformers model would change the random state

# set state after loading
py_seeds.set_seed_state(state)
now_state = py_seeds.get_seed_state()
print(state_str(state) == state_str(now_state))
# True: must set state after loading to keep the random state same
True
False
True

使用了一种很简易的方式进行状态间对比:把所有表示状态的变量都转换为list再转换为str,并拼接,判断两个状态代表的字符串是否相同(不可以用hash)

总结

transformers的模型的from_pretrained将会改变随机状态,如果需要确保随机状态一致,最好在加载完后重新设定一遍随机状态(适用于训练过程中的断点恢复,避免训练出错后恢复随机状态不一致)
(tokenizer的from_pretrained并不会影响随机状态)

笔者语

真的是一个很小的点,本来以为只有在训练的过程才涉及到随机状态的改变,没有想到一个加载的过程也会影响,试了好久才发现,希望能给大家避避坑吧~
可能考虑在下一个版本的py-seeds里更新成更方便判断是否相同的功能~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,针对您的问题,我将为您提供一份基于 Transformers 实现 CIFAR-10 图像分类任务的 Python 代码。请注意,由于训练时间较长,我将仅提供代码框架,您可以按照注释中的提示进行修改和完善。 ```python import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets, transforms from transformers import ViTModel, ViTForImageClassification, ViTConfig, AdamW, get_linear_schedule_with_warmup # 设置随机种子 torch.manual_seed(42) # 定义超参数 BATCH_SIZE = 32 LEARNING_RATE = 2e-5 EPOCHS = 10 WARMUP_STEPS = 1000 # 加载 CIFAR-10 数据集 transform = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) test_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=False) # 加载 ViT 模型 config = ViTConfig(image_size=224, num_classes=10, hidden_size=768, num_hidden_layers=12, num_attention_heads=12) model = ViTForImageClassification(config) # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() optimizer = AdamW(model.parameters(), lr=LEARNING_RATE) # 设置学习率调度器 total_steps = len(train_loader) * EPOCHS scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=WARMUP_STEPS, num_training_steps=total_steps) # 训练模型 for epoch in range(EPOCHS): model.train() for i, (images, labels) in enumerate(train_loader): optimizer.zero_grad() outputs = model(images) loss = criterion(outputs.logits, labels) loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0) optimizer.step() scheduler.step() if i % 100 == 0: print(f'Epoch [{epoch+1}/{EPOCHS}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item():.4f}') # 测试模型 model.eval() with torch.no_grad(): correct = 0 total = 0 for images, labels in test_loader: outputs = model(images) _, predicted = torch.max(outputs.logits.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() accuracy = 100 * correct / total print(f'Test Accuracy: {accuracy:.2f}%') # 保存模型 torch.save(model.state_dict(), 'vit_cifar10.pth') ``` 在上述代码中,我们首先使用 PyTorch 内置的 `datasets` 和 `transforms` 模块加载并预处理 CIFAR-10 数据集;然后使用 Transformers 提供的 `ViTForImageClassification` 类定义 ViT 模型,并使用 AdamW 优化器和学习率调度器进行训练;最后在测试集上评估模型,并使用 `torch.save()` 方法保存模型参数。 您可以根据自己的需要对代码进行修改和完善,例如调整超参数、使用其他预训练模型等。在训练完成后,您可以使用 Matplotlib 绘制训练和测试曲线图,例如: ```python import matplotlib.pyplot as plt # 绘制训练和测试曲线图 plt.plot(train_losses, label='Training loss') plt.plot(test_losses, label='Testing loss') plt.legend() plt.show() ``` 其中 `train_losses` 和 `test_losses` 分别为每个 epoch 的训练损失和测试损失。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值