初次使用vim 实现手写数字识别错误汇总
# test.py 文件
import torch
import torch.nn as nn
import argparse
import torch.nn.functional as F
import torchvision.transforms as transform
import torchvision.datasets as datasets
from test_myself_net import MLP
from torch import optim
# create the argument parser to parse the argument
parser = argparse.ArgumentParser(description='Set parameters for training MNIST.')
# add arguments when used in the procedure
parser.add_argument("-bz", '--batch_size', type=int, default=32, help='training batch size, default to set 32')
parser.add_argument("-lr", '--learning_rate', type=float, default=0.001, help='training learning rate, default to 0.001')
parser.add_argument("-epo", '--epoches', type=int, default=20, help='train epoches, default to set 20')
parser.add_argument("-mm", '--momentum', type=float, default=0.9, help='SGD momentum, default to set 0.9')
# instance arguments
args = parser.parse_args()
# set device
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# print('now we use {} to process the data'.format(device))
# obtain MNIST dataset
train_set = datasets.MNIST(root='./data/',
train=True,
transform=transform.ToTensor(),
download=True)
test_set = datasets.MNIST(root='./data/',
train=False,
transform=transform.ToTensor(),
download=True)
# obtain the dataloader
train_loader = torch.utils.data.DataLoader(train_set,
batch_size=args.batch_size,
shuffle=True,
)
test_loader = torch.utils.data.DataLoader(test_set,
batch_size=args.batch_size,
)
model = MLP().to(device) # obtain the model
# set optimizer
optimizer = optim.SGD(model.parameters(), lr=args.learning_rate, momentum=args.momentum)
criteon = nn.CrossEntropyLoss() # create a loss instance
# now every thing is ok, start to train
def main():
for epoch in range(args.epoches):
sum_loss = 0.
for train_batch_idx, (train_data, train_target) in enumerate(train_loader):
train_data, train_target = train_data.to(device), train_target.to(device)
logits = model(train_data)
loss = criteon(logits, train_target)
optimizer.zero_grad()
loss.backward()
optimizer.step()
sum_loss += float(loss) # little trick can release a lot gpu memory
if (train_batch_idx+1) % 200 == 0:
print('Now, training at epoch {}, in {}th training batch, the loss is {:.3f}'.format(epoch, train_batch_idx+1, sum_loss/float(200)))
sum_loss = 0.
# each epoch test the acc
total_num_correct = 0
for test_batch_idx, (test_data, test_target) in enumerate(test_loader):
test_data, test_target = test_data.to(device), test_target.to(device)
logits = model(test_data)
loss = criteon(logits, test_target)
pred = logits.argmax(dim=1)
correct = pred.eq(test_target).sum().float().cpu()
total_num_correct += correct
print('Now, testing at epoch {}, the the test accuracy is {:.2f}%'.format(epoch, total_num_correct/len(test_loader.dataset)*100.))
if __name__ == "__main__":
main()
# 网络模型
import torch.nn as nn
from torch.nn import Sequential
class MLP(nn.Module):
"""
Multi-Layers perceptron net frame
"""
def __init__(self):
super(MLP, self).__init__()
self.model = Sequential(nn.Linear(784, 200),
nn.ReLU(),
nn.Linear(200, 100),
nn.ReLU(),
nn.Linear(100, 10))
def forward(self, inputs):
x = inputs.view(-1, 28*28)
x = self.model(x)
return x
使用vim手写代码,真的是太不容易了,不过确实能够帮助自己记住很多的bug,之前使用的都是PycharmIDE 确实也很好用,但是自己却总是太依赖代码提示。以上是自己运行成功之后的代码。
主要的问题还是书写代码时,变量出错较多,主要就是打字的时候,不经意间打错了。这里列举几个比较严重的错误。
问题1:Expected object of device type cuda but got device type cpu for argument #1 ‘self’ in call to _th_addmm
提示定位到错误所在行,大体意思就是原来在gpu上训练的数据,出现在cpu上了。主要原因有三点:
- 模型没有放到 gpu上, 检查==model=MLP().to(device)==是否正确;
- 数据没有放到gpu上,检查train_data, train_target = train_data.to(device), train_target.to(device) 和测试数据;
- 还有就是需要在gpu上的变量没有设置好,这个就需要仔细检查了。
- 还有最不可能的一点,也是最最需要检查的一点,就是变量名字是否写错!!!
我的问题就是将其中的target写成了traget,当时找了半天都不知道。。。
问题2:在网络模型中,少了第19行的内容
于是在训练模型的时候,数据输入的类型无法匹配,提示错误,加上之后就OK了。
问题3:提示if __name__ == "__main__":
最后的冒号提示语法syntax error
当时我就是死活不懂,哪里出错了,于是仔细核对之后,发现是这句话的上一句少了一个括号,当时吐血。。。要知道我可是找了将近半个小时。
问题4:argmax()在设置的时候一定要设置维度。
问题5:特别注意小trick的地方。
其中的loss在我们看来是不需要grad的,但是在执行的时候没有加上float就会自动求grad这极大的占用了内存资源。还有就是如果不需要在之后使用的变量,就可以使用 del 语句对改变量进行删除。