PyTorch磁盘模型加载与使用:是否需模型定义?如何拆分推理代码?
PyTorch模型加载与拆分训练推理的解决方案
核心问题解答
用state_dict保存的模型(也就是你代码里torch.save(model.state_dict(), "model.pth")的方式)必须依赖模型定义,因为state_dict本质只是模型各层参数权重的字典,不包含任何模型结构信息。你觉得预训练模型不用自己写定义,是因为像TorchVision这类库已经把模型类(比如resnet50)封装好了,调用相关API的时候,其实是内部帮你实例化了模型类并加载了预训练权重,本质还是依赖了模型定义。
拆分训练与推理文件的具体步骤
最规范的做法是把模型定义单独抽成一个文件,让训练和推理文件都导入这个定义,既保证结构一致,也符合模块化开发习惯。
1. 单独创建模型定义文件 model_def.py
from torch import nn class NeuralNetwork(nn.Module): def __init__(self): super().__init__() self.flatten = nn.Flatten() self.linear_relu_stack = nn.Sequential( nn.Linear(28*28, 512), nn.ReLU(), nn.Linear(512, 512), nn.ReLU(), nn.Linear(512, 10) ) def forward(self, x): x = self.flatten(x) logits = self.linear_relu_stack(x) return logits
2. 训练文件 train.py
只保留训练和保存模型的逻辑,导入上面的模型类:
import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets from torchvision.transforms import ToTensor from model_def import NeuralNetwork # 导入模型定义 # 下载数据、创建DataLoader training_data = datasets.FashionMNIST( root="data", train=True, download=True, transform=ToTensor(), ) test_data = datasets.FashionMNIST( root="data", train=False, download=True, transform=ToTensor(), ) batch_size = 64 train_dataloader = DataLoader(training_data, batch_size=batch_size) test_dataloader = DataLoader(test_data, batch_size=batch_size) # 选择设备 device = ( "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu" ) print(f"Using {device} device") # 初始化模型、损失函数、优化器 model = NeuralNetwork().to(device) loss_fn = nn.CrossEntropyLoss() optimizer = torch.optim.SGD(model.parameters(), lr=1e-3) # 训练函数 def train(dataloader, model, loss_fn, optimizer): size = len(dataloader.dataset) model.train() for batch, (X, y) in enumerate(dataloader): X, y = X.to(device), y.to(device) pred = model(X) loss = loss_fn(pred, y) loss.backward() optimizer.step() optimizer.zero_grad() if batch % 100 == 0: loss, current = loss.item(), (batch + 1) * len(X) print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]") # 测试函数 def test(dataloader, model, loss_fn): size = len(dataloader.dataset) num_batches = len(dataloader) model.eval() test_loss, correct = 0, 0 with torch.no_grad(): for X, y in dataloader: X, y = X.to(device), y.to(device) pred = model(X) test_loss += loss_fn(pred, y).item() correct += (pred.argmax(1) == y).type(torch.float).sum().item() test_loss /= num_batches correct /= size print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n") # 开始训练 epochs = 5 for t in range(epochs): print(f"Epoch {t+1}\n-------------------------------") train(train_dataloader, model, loss_fn, optimizer) test(test_dataloader, model, loss_fn) print("Done!") # 保存模型权重 torch.save(model.state_dict(), "model.pth") print("Saved PyTorch Model State to model.pth")
3. 推理文件 infer.py
只保留加载模型和推理的逻辑,同样导入模型定义:
import torch from torchvision import datasets from torchvision.transforms import ToTensor from model_def import NeuralNetwork # 导入模型定义 # 选择设备 device = ( "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu" ) # 加载模型 model = NeuralNetwork().to(device) model.load_state_dict(torch.load("model.pth")) # 类别定义 classes = [ "T-shirt/top", "Trouser", "Pullover", "Dress", "Coat", "Sandal", "Shirt", "Sneaker", "Bag", "Ankle boot", ] # 加载测试数据(也可以换成自己的输入图片) test_data = datasets.FashionMNIST( root="data", train=False, download=True, transform=ToTensor(), ) # 推理 model.eval() x, y = test_data[0][0], test_data[0][1] with torch.no_grad(): x = x.to(device) pred = model(x) predicted, actual = classes[pred[0].argmax(0)], classes[y] print(f'Predicted: "{predicted}", Actual: "{actual}"')
可选方案:保存整个模型(不推荐)
如果你确实不想依赖模型定义文件,可以直接保存整个模型对象:
# 训练时保存 torch.save(model, "full_model.pth") # 推理时直接加载,不需要模型定义 model = torch.load("full_model.pth").to(device)
但这种方式不推荐,因为序列化的模型和PyTorch版本、依赖库版本绑定紧密,换环境很容易加载失败,而且无法灵活修改模型结构。
内容的提问来源于stack exchange,提问作者Tmp
相关产品推荐
相关产品推荐

