PyTorch Clothing-1M基线模型运行时已导入dataloader仍触发NameError错误的技术问询
解决Clothing-1M基线复现中的NameError: 'dataloader' is not defined问题
我一眼就看出问题出在你代码里的导入语句位置上,咱们来一步步拆解:
问题根源
你的import dataloader和import models是放在if __name__ == '__main__':代码块里面的,但创建loader的代码却在这个块的外面。Python脚本执行时,会先从上到下运行所有全局作用域的代码,再执行if __name__ == '__main__':块里的内容。也就是说,当脚本运行到loader = dataloader.clothing_dataloader(...)这行时,dataloader模块还根本没被导入,自然就触发了NameError。
你调试时看到变量存在,应该是调试器已经执行到if __name__ == '__main__':块内部、完成导入后的状态,但实际脚本的执行顺序是先跑全局代码,这时候导入还没发生。
两种修复方案
方案一:把导入移到全局作用域
直接把import dataloader和import models移到脚本最顶部的全局导入区,这样整个脚本都能访问到这两个模块:
from __future__ import print_function import sys import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F import torch.backends.cudnn as cudnn import torchvision import torchvision.transforms as transforms import os import sys import time import argparse import datetime from torch.autograd import Variable # 移到全局作用域的导入 import dataloader as dataloader import models as models if __name__ == '__main__': parser = argparse.ArgumentParser(description='PyTorch Clothing-1M Training') parser.add_argument('--lr', default=0.0008, type=float, help='learning_rate') parser.add_argument('--start_epoch', default=2, type=int) parser.add_argument('--num_epochs', default=3, type=int) parser.add_argument('--batch_size', default=32, type=int) parser.add_argument('--optim_type', default='SGD') parser.add_argument('--seed', default=7) parser.add_argument('--gpuid', default=1, type=int) parser.add_argument('--id', default='cross_entropy') args = parser.parse_args() best_acc = 0 # Model net = models.resnet50(pretrained=True) net.fc = nn.Linear(2048,14) criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=args.lr, momentum=0.9, weight_decay=1e-3) loader = dataloader.clothing_dataloader(batch_size=args.batch_size,num_workers=5,shuffle=True) train_loader,val_loader = loader.run() # Training def train(epoch): net.train() train_loss = 0 correct = 0 total = 0 learning_rate = args.lr if epoch > args.start_epoch: learning_rate=learning_rate/10 for param_group in optimizer.param_groups: param_group['lr'] = learning_rate print('\n=> %s Training Epoch #%d, LR=%.4f' %(args.id,epoch, learning_rate)) for batch_idx, (inputs, targets) in enumerate(train_loader): optimizer.zero_grad() inputs, targets = Variable(inputs), Variable(targets) outputs = net(inputs) # Forward Propagation loss = criterion(outputs, targets) # Loss loss.backward() # Backward Propagation optimizer.step() # Optimizer update train_loss += loss.data[0] _, predicted = torch.max(outputs.data, 1) total += targets.size(0) correct += predicted.eq(targets.data).cpu().sum() for epoch in range(1, 1+args.num_epochs): train(epoch)
方案二:把所有执行代码放进if __name__ == '__main__':块
如果想保持导入在块内,那就要把所有依赖这些模块的代码也移到块里,确保导入先发生:
from __future__ import print_function import sys import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F import torch.backends.cudnn as cudnn import torchvision import torchvision.transforms as transforms import os import sys import time import argparse import datetime from torch.autograd import Variable # 训练函数可以放在外面,因为它不直接依赖导入模块(依赖的变量会在块内定义) def train(epoch, net, optimizer, criterion, train_loader, args): net.train() train_loss = 0 correct = 0 total = 0 learning_rate = args.lr if epoch > args.start_epoch: learning_rate=learning_rate/10 for param_group in optimizer.param_groups: param_group['lr'] = learning_rate print('\n=> %s Training Epoch #%d, LR=%.4f' %(args.id,epoch, learning_rate)) for batch_idx, (inputs, targets) in enumerate(train_loader): optimizer.zero_grad() inputs, targets = Variable(inputs), Variable(targets) outputs = net(inputs) # Forward Propagation loss = criterion(outputs, targets) # Loss loss.backward() # Backward Propagation optimizer.step() # Optimizer update train_loss += loss.data[0] _, predicted = torch.max(outputs.data, 1) total += targets.size(0) correct += predicted.eq(targets.data).cpu().sum() if __name__ == '__main__': # 先导入模块 import dataloader as dataloader import models as models parser = argparse.ArgumentParser(description='PyTorch Clothing-1M Training') parser.add_argument('--lr', default=0.0008, type=float, help='learning_rate') parser.add_argument('--start_epoch', default=2, type=int) parser.add_argument('--num_epochs', default=3, type=int) parser.add_argument('--batch_size', default=32, type=int) parser.add_argument('--optim_type', default='SGD') parser.add_argument('--seed', default=7) parser.add_argument('--gpuid', default=1, type=int) parser.add_argument('--id', default='cross_entropy') args = parser.parse_args() best_acc = 0 # Model net = models.resnet50(pretrained=True) net.fc = nn.Linear(2048,14) criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=args.lr, momentum=0.9, weight_decay=1e-3) # 现在导入已经完成,可以创建loader了 loader = dataloader.clothing_dataloader(batch_size=args.batch_size,num_workers=5,shuffle=True) train_loader,val_loader = loader.run() for epoch in range(1, 1+args.num_epochs): train(epoch, net, optimizer, criterion, train_loader, args)
我更推荐方案二,因为它能避免全局变量污染,是Python脚本的最佳实践之一。
内容的提问来源于stack exchange,提问作者ZENG LINLIN _
相关产品推荐
相关产品推荐

