Pytorch错误记录,关于多GPU训练的问题

刚刚遇到一个极其奇葩的问题。我搭建好了模型,先是在一个GPU下,以如下形式进行了测试

model = xxxNet()
model.train()
model.cuda()

x = torch.randn(1,3,320,640)
model(x)

代码正确运行,说明在单GPU下,模型搭建的没问题。满心欢喜,要开始训练了。然后用了DataParallel,结果报了如下错误。

RuntimeError: Expected tensor for argument #1 ‘input’ to have the same device as tensor for argument

错误描述没有截取全。大致说某一个卷积层的输入tensor和weight不是在一个GPU上。
然后我就纳了闷了,数据都是有DataParallel自动去分配到各个GPU上的啊,为啥提示这种错误。

开始在网上找答案,说法不一,都不适合我。
然后终于意识到,DataParallel仅仅支持forward的并行,但我在model的构造函数中是这么写的。

class xxxNet(Module):
	def __init__()
		super.........
		...
		if self.training:
			self.forward = self.training_forward
		else:
			self.forward = self.test_forward

我的本意是想根据是否训练,采用两种不同的前向传播。然后我做了如下修改,成功运行了训练代码

def self.forward(self, x):
	return self.training_forward(x)

这样就跑通了,说明在使用多GPU,一定要让代码通过forward计算前向过程。因为DataParallel仅支持forward的并行,有其他函数想并行,一定要显式的写进forward中。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供示例代码。 首先,您需要安装PyTorchtorchvision。如果您的计算机上有GPU,最好安装GPU版本的PyTorch,以提高训练速度。 然后,您可以使用以下代码来加载MNIST数据集并进行训练和测试: ``` python import torch import torch.nn as nn import torch.optim as optim import torchvision.transforms as transforms import torchvision.datasets as datasets # 定义变换 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) # 加载数据集 train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform) test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform) # 定义数据加载器 train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True) test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=64, shuffle=False) # 定义模型 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 10, kernel_size=5) self.conv2 = nn.Conv2d(10, 20, kernel_size=5) self.fc1 = nn.Linear(320, 50) self.fc2 = nn.Linear(50, 10) def forward(self, x): x = nn.functional.relu(nn.functional.max_pool2d(self.conv1(x), 2)) x = nn.functional.relu(nn.functional.max_pool2d(self.conv2(x), 2)) x = x.view(-1, 320) x = nn.functional.relu(self.fc1(x)) x = self.fc2(x) return nn.functional.log_softmax(x, dim=1) net = Net().cuda() # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.5) # 训练函数 def train(epoch): net.train() for batch_idx, (data, target) in enumerate(train_loader): data, target = data.cuda(), target.cuda() optimizer.zero_grad() output = net(data) loss = criterion(output, target) loss.backward() optimizer.step() if batch_idx % 10 == 0: print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( epoch, batch_idx * len(data), len(train_loader.dataset), 100. * batch_idx / len(train_loader), loss.item())) # 测试函数 def test(): net.eval() test_loss = 0 correct = 0 with torch.no_grad(): for data, target in test_loader: data, target = data.cuda(), target.cuda() output = net(data) test_loss += criterion(output, target).item() pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() test_loss /= len(test_loader.dataset) print('Test set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)'.format( test_loss, correct, len(test_loader.dataset), 100. * correct / len(test_loader.dataset))) return 100. * correct / len(test_loader.dataset) # 训练模型 best_acc = 0 for epoch in range(1, 11): train(epoch) acc = test() if acc > best_acc: best_acc = acc torch.save(net.state_dict(), 'mnist_cnn.pt') # 加载模型 net.load_state_dict(torch.load('mnist_cnn.pt')) # 遍历测试集并记录错误的图片信息 error_images = [] for data, target in test_loader: data, target = data.cuda(), target.cuda() output = net(data) pred = output.argmax(dim=1, keepdim=True) for i in range(len(target)): if pred[i] != target[i]: error_images.append(data[i]) # 保存错误的图片 for i, image in enumerate(error_images): torchvision.utils.save_image(image, f'error_images/{i}.png') ``` 上述代码中,我们定义了一个卷积神经网络来进行手写数字识别,并使用SGD优化器进行训练训练过程中,我们记录了每个epoch的测试准确率,并在测试准确率最高的候保存模型。 在训练完成后,我们遍历测试集并记录所有错误的图片信息,并将这些错误的图片单独保存到一个文件夹中。 注意,为了使用GPU加速,我们将模型和数据都移动到了GPU上,这可以通过调用`.cuda()`方法来实现。如果您的计算机上没有GPU,可以将`.cuda()`替换为`.cpu()`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值