【发布时间】:2018-09-23 08:14:31
【问题描述】:
我试图在 pytorch 中跟踪整个数据集的误差并计算整个数据集的误差。我在 cifar10 pytorch 0.3.1 中写了以下(可重现的示例并且完全包含):
import torch
from torch.autograd import Variable
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from math import inf
from pdb import set_trace as st
def error_criterion(outputs,labels):
max_vals, max_indices = torch.max(outputs,1)
train_error = (max_indices != labels).sum().data[0]/max_indices.size()[0]
return train_error
def evalaute_mdl_data_set(loss,error,net,dataloader,enable_cuda,iterations=inf):
'''
Evaluate the error of the model under some loss and error with a specific data set.
'''
running_loss,running_error = 0,0
for i,data in enumerate(dataloader):
if i >= iterations:
break
inputs, labels = extract_data(enable_cuda,data,wrap_in_variable=True)
outputs = net(inputs)
running_loss += loss(outputs,labels).data[0]
running_error += error(outputs,labels)
return running_loss/(i+1),running_error/(i+1)
def extract_data(enable_cuda,data,wrap_in_variable=False):
inputs, labels = data
if enable_cuda:
inputs, labels = inputs.cuda(), labels.cuda() #TODO potential speed up?
if wrap_in_variable:
inputs, labels = Variable(inputs), Variable(labels)
return inputs, labels
def train_and_track_stats(enable_cuda, nb_epochs, trainloader,testloader, net,optimizer,criterion,error_criterion, iterations=inf):
''' Add stats before training '''
train_loss_epoch, train_error_epoch = evalaute_mdl_data_set(criterion, error_criterion, net, trainloader, enable_cuda, iterations)
test_loss_epoch, test_error_epoch = evalaute_mdl_data_set(criterion, error_criterion, net, testloader, enable_cuda, iterations)
print(f'[-1, -1], (train_loss: {train_loss_epoch}, train error: {train_error_epoch}) , (test loss: {test_loss_epoch}, test error: {test_error_epoch})')
##
''' Start training '''
print('about to start training')
for epoch in range(nb_epochs): # loop over the dataset multiple times
running_train_loss,running_train_error = 0.0,0.0
for i,data_train in enumerate(trainloader):
''' zero the parameter gradients '''
optimizer.zero_grad()
''' train step = forward + backward + optimize '''
inputs, labels = extract_data(enable_cuda,data_train,wrap_in_variable=True)
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_train_loss += loss.data[0]
running_train_error += error_criterion(outputs,labels)
''' End of Epoch: collect stats'''
train_loss_epoch, train_error_epoch = running_train_loss/(i+1), running_train_error/(i+1)
#train_loss_epoch, train_error_epoch = evalaute_mdl_data_set(criterion,error_criterion,net,trainloader,enable_cuda,iterations)
test_loss_epoch, test_error_epoch = evalaute_mdl_data_set(criterion,error_criterion,net,testloader,enable_cuda,iterations)
print(f'[{epoch}, {i+1}], (train_loss: {train_loss_epoch}, train error: {train_error_epoch}) , (test loss: {test_loss_epoch}, test error: {test_error_epoch})')
return train_loss_epoch, train_error_epoch, test_loss_epoch, test_error_epoch
class Flatten(torch.nn.Module):
def forward(self, input):
return input.view(input.size(0), -1)
def main():
enable_cuda = True
print('running main')
num_workers = 0
''' Get Data set '''
batch_size_test = 10000
batch_size_train = 10000
data_path = './data'
transform = [transforms.ToTensor(),transforms.Normalize( (0.5, 0.5, 0.5), (0.5, 0.5, 0.5) )]
transform = transforms.Compose(transform)
trainset = torchvision.datasets.CIFAR10(root=data_path, train=True,download=False, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size_train,shuffle=True, num_workers=num_workers)
testset = torchvision.datasets.CIFAR10(root=data_path, train=False,download=False, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size_test,shuffle=False, num_workers=num_workers)
''' Get model '''
net = torch.nn.Sequential(
torch.nn.Conv2d(3,13,5), #(in_channels, out_channels, kernel_size),
Flatten(),
torch.nn.Linear(28*28*13, 13),
torch.nn.Linear(13, 10)
)
net.cuda()
''' Train '''
nb_epochs = 10
lr = 0.1
err_criterion = error_criterion
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=lr, momentum=0.0)
train_and_track_stats(enable_cuda, nb_epochs, trainloader,testloader, net,optimizer,criterion,err_criterion, iterations=inf)
''' Done '''
print('Done')
if __name__ == '__main__':
main()
当我运行它时,我收到以下错误:
python my_cifar10.py
running main
[-1, -1], (train_loss: 2.3172860145568848, train error: 0.0054) , (test loss: 2.317185878753662, test error: 0.0038)
about to start training
[0, 5], (train_loss: 2.22599835395813, train error: 0.015160000000000002) , (test loss: 2.0623881816864014, test error: 0.0066)
[1, 5], (train_loss: 2.014406657218933, train error: 0.00896) , (test loss: 1.9619578123092651, test error: 0.0195)
[2, 5], (train_loss: 1.9428715705871582, train error: 0.01402) , (test loss: 1.918603539466858, test error: 0.0047)
[3, 5], (train_loss: 1.9434458494186402, train error: 0.01192) , (test loss: 1.9194672107696533, test error: 0.0125)
[4, 5], (train_loss: 1.8804980754852294, train error: 0.00794) , (test loss: 1.8549214601516724, test error: 0.004)
[5, 5], (train_loss: 1.8573726177215577, train error: 0.010159999999999999) , (test loss: 1.8625996112823486, test error: 0.0158)
[6, 5], (train_loss: 1.8454653739929199, train error: 0.01524) , (test loss: 1.8155865669250488, test error: 0.0122)
[7, 5], (train_loss: 1.8140610456466675, train error: 0.01066) , (test loss: 1.808283805847168, test error: 0.0101)
[8, 5], (train_loss: 1.8036894083023072, train error: 0.00832) , (test loss: 1.799634575843811, test error: 0.007)
[9, 5], (train_loss: 1.8023016452789307, train error: 0.0077399999999999995) , (test loss: 1.8030155897140503, test error: 0.0114)
Done
显然它一定是错误的,因为对于一个非常小而简单的模型(1 conv 2 fcs),测试误差几乎为零。
代码看起来很简单,我不知道出了什么问题。这几天我一直在做事情和改变事情。有什么新建议可以尝试吗?
【问题讨论】:
-
我无法重现该错误。我只是在 cpu 上测试并得到
[-1, -1], (train_loss: 2.3224891445520894, train error: 0.8735254156010229) , (test loss: 2.3210103873965107, test error: 0.8691653481012658) about to start training [0, 391], (train_loss: 1.8232954066732656, train error: 0.6340393222506394) , (test loss: 1.7517535837390754, test error: 0.6045292721518988) ...。损失是有道理的:如果你有 10 个随机猜测的类,你会在大约 1/10 的时间里是对的,从而导致交叉熵损失为ln(-1/10) = 2.3。所以错误应该在error_criterion函数中。 -
我之前无法重现,因为我将批量大小更改为 128
-
@McLawrence 这似乎是字节张量或其他东西的溢出错误。相关帖子:discuss.pytorch.org/t/… 感谢您的帮助!
标签: python machine-learning neural-network conv-neural-network pytorch