神经网络序列分类中的高损失

Posted

技术标签:

【中文标题】神经网络序列分类中的高损失【英文标题】:High loss in neural network sequence classification 【发布时间】:2021-05-04 15:02:14 【问题描述】:

我正在使用神经网络将长度为 340 的序列分类为 8 类,我使用交叉熵作为损失。我的损失数字很高。我想知道我是否在计算每个时期的损失时犯了错误。或者我应该使用其他损失函数。

criterion = nn.CrossEntropyLoss()
if CUDA:
    criterion = criterion.cuda()
optimizer = optim.SGD(model.parameters(), lr=LEARNING_RATE, momentum=0.9)
loss_list = []                                                                                                                      
for epoch in range(N_EPOCHES):                                                                                                          
    tot_loss=0                                                                                                                          
    running_loss =0                                                                                                                     
    model.train()                                                                                                                       
    loss_values = []                                                                                                                    
    acc_list = []                                                                                                                       
    acc_list = torch.FloatTensor(acc_list)                                                                                              
    sum_acc = 0                                                                                                                         
    # Training                                                                                                                                                                                                                                                        
    for i, (seq_batch, stat_batch) in enumerate(training_generator):                                                                    
        # Transfer to GPU                                                                                                               
        seq_batch, stat_batch = seq_batch.to(device), stat_batch.to(device)                                                             
        optimizer.zero_grad()                                                                                                           
        # Model computation                                                                                                             
        seq_batch = seq_batch.unsqueeze(-1)                                                                                                                                                                                                                          
        outputs = model(seq_batch)                                                                                                                                                                                                                                                                                                                                                            
        loss = criterion(outputs.argmax(1), stat_batch.argmax(1))                                                                                                                                                                                                                                           
        loss.backward()                                                                                                                 
        optimizer.step()                                                                                                                
        # print statistics                                                                                                              
        running_loss += loss.item()*seq_batch.size(0)                                                                                   
        loss_values.append(running_loss/len(training_set))                                                                                                                                                                                                                                                   
        if i % 2000 == 1999:  # print every 2000 mini-batches                                                                           
            print('[%d, %5d] loss: %.3f' %                                                                                              
                  (epoch + 1, i + 1, running_loss / 50000),"acc",(outputs.argmax(1) == stat_batch.argmax(1)).float().mean())            
            running_loss = 0.0                                                                                                          
        sum_acc += (outputs.argmax(1) == stat_batch.argmax(1)).float().sum()                                                            
    print("epoch" , epoch, "acc", sum_acc/len(training_generator))                                                                                                                                                                                                                                                                                                                              
print('Finished Training')                                                                                                              
                                                                                                                                        
[1,  2000] loss: 14.205 acc tensor(0.5312, device='cuda:0')
[1,  4000] loss: 13.377 acc tensor(0.4922, device='cuda:0')
[1,  6000] loss: 13.159 acc tensor(0.5508, device='cuda:0')
[1,  8000] loss: 13.050 acc tensor(0.5547, device='cuda:0')
[1, 10000] loss: 12.974 acc tensor(0.4883, device='cuda:0')
epoch 1 acc tensor(133.6352, device='cuda:0')
[2,  2000] loss: 12.833 acc tensor(0.5781, device='cuda:0')
[2,  4000] loss: 12.834 acc tensor(0.5391, device='cuda:0')
[2,  6000] loss: 12.782 acc tensor(0.5195, device='cuda:0')
[2,  8000] loss: 12.774 acc tensor(0.5508, device='cuda:0')
[2, 10000] loss: 12.762 acc tensor(0.5156, device='cuda:0')
epoch 2 acc tensor(139.2496, device='cuda:0')
[3,  2000] loss: 12.636 acc tensor(0.5469, device='cuda:0')
[3,  4000] loss: 12.640 acc tensor(0.5469, device='cuda:0')
[3,  6000] loss: 12.648 acc tensor(0.5508, device='cuda:0')
[3,  8000] loss: 12.637 acc tensor(0.5586, device='cuda:0')
[3, 10000] loss: 12.620 acc tensor(0.6016, device='cuda:0')
epoch 3 acc tensor(140.6962, device='cuda:0')
[4,  2000] loss: 12.520 acc tensor(0.5547, device='cuda:0')
[4,  4000] loss: 12.541 acc tensor(0.5664, device='cuda:0')
[4,  6000] loss: 12.538 acc tensor(0.5430, device='cuda:0')
[4,  8000] loss: 12.535 acc tensor(0.5547, device='cuda:0')
[4, 10000] loss: 12.548 acc tensor(0.5820, device='cuda:0')
epoch 4 acc tensor(141.6522, device='cuda:0')

【问题讨论】:

【参考方案1】:

我的损失数字很高

是什么让你觉得这很高?你把这比作什么?

是的,您应该将nn.CrossEntropyLoss 用于多类分类任务。你的训练损失对我来说似乎很好。在初始化时,你应该有loss = -log(1/8) = ~2

【讨论】:

感谢@Ivan 的回复。作为一个初学者,我确实知道如何解释这些数字。我认为这将是 0 和 1 之间的数字。我能问你我怎么知道我的模型的准确性吗?如果它真的适用于我的数据集。你的意思是用 -log(1/8) 初始化 running_loss 吗? “你的意思是用 -log(1/8) 初始化 running_loss” 不,-log(1/8) 是它在 init 上的值(具有随机权重)因为您有 8 个课程并且正在使用nn.CrossEntropyLoss。用(outputs.argmax(1) == stat_batch.argmax(1)).float().mean()可以得到准确率,基本上是统计正确的类预测数。 @NoNa -log(1/8) 表示预测和目标之间的交叉熵最大(即与均匀分布的熵相同)。如果网络预测与目标标签无关,基本上这是您应该期望的数字。 @ivan ''' 我得到 [14, 340000] loss: 1.931 acc tensor(0.1250, device='cuda:0') ''',这个准确度意味着什么。现在我在第 14 个时代,它是相同的损失范围。这是否意味着过度拟合,另外,我怎么知道我的模型是否好,我应该做任何测试吗? @NoNa 这正是你应该在 init 上得到的:如果你采用统一策略来预测班级,那么1/8*100 = 12.5% 的时间你会是正确的,ie模型准确率为 12.5%。您的目标是训练模型,使准确度尽可能接近 100%。准确度实际上是预测总数中正确预测的数量。

以上是关于神经网络序列分类中的高损失的主要内容,如果未能解决你的问题,请参考以下文章

深度神经网络的本质(无一句代码)

武汉大学CVEO小组:一种基于卷积神经网络(CNN)的高分辨率遥感影像分类方法

使用神经网络执行文本分类时,准确性和损失之间是不是存在直接关系?

用于多类分类的深度神经网络的广义二次损失

二元分类网络中输出单元的数量和损失函数

结合回归和分类的多输出神经网络