【问题标题】:pytorch multilabel classification network not trainingpytorch 多标签分类网络未训练
【发布时间】:2021-01-26 20:58:09
【问题描述】:

我正在尝试一个简单的多标签分类示例,但由于损失停滞不前,网络似乎没有正确训练。

我已经按照 pytorch 文档的建议使用了 multilabel_soft_margin_loss,但没有什么可做的了。在文档中找不到任何合适的示例。

任何人都可以仔细观察并指出它有什么问题吗?下面的完整工作示例(下面还有关于预测的问题)

完整的示例代码

from __future__ import print_function
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.optim.lr_scheduler import StepLR
from sklearn.datasets import make_multilabel_classification
from torch.utils.data import TensorDataset, DataLoader
from sklearn.model_selection import train_test_split
import xgboost as xgb
from sklearn.metrics import accuracy_score
num_classes = 3
X, y = make_multilabel_classification(n_samples=1000,n_classes=num_classes)
X_tensor, y_tensor = torch.tensor(X), torch.tensor(y)
print("X Shape :{}".format(X_tensor.shape))
print("y Shape :{}".format(y_tensor.shape))


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(X.shape[1], 300)
        self.fc2 = nn.Linear(300, 10)
        self.fc3 = nn.Linear(10, num_classes)

    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
    

device = torch.device("cpu") 
lr = 1
batch_size = 128
gamma = 0.9
epochs = 100
args = {'log_interval': 10, 'dry_run':False}
kwargs = {'batch_size': batch_size}
kwargs.update({'num_workers': 1,
               'pin_memory': True,
               'shuffle': True},
                 )

model = Net().to(device)
optimizer = optim.Adam(model.parameters(), lr=lr, weight_decay=0.1)    
scheduler = StepLR(optimizer, step_size=1, gamma=gamma)

# data loader
my_dataset = TensorDataset(X_tensor,y_tensor) # create tensor dataset 

train_dataset, test_dataset, = train_test_split(
    my_dataset, test_size=0.2, random_state=42)

train_loader = DataLoader(train_dataset,**kwargs) 
test_loader = DataLoader(test_dataset,**kwargs) 

## Train step ##
for epoch in range(1, epochs + 1):
    model.train() # set model to train
    
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        output = model(data.float())
        loss = F.multilabel_soft_margin_loss(output,target)
        loss.backward()
        optimizer.step()
        if batch_idx % args['log_interval'] == 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()))
            if args['dry_run']:
                break
    
    scheduler.step()

训练损失进度

Train Epoch: 1 [0/800 (0%)] Loss: 0.694400
Train Epoch: 2 [0/800 (0%)] Loss: 0.697095
Train Epoch: 3 [0/800 (0%)] Loss: 0.705593
Train Epoch: 4 [0/800 (0%)] Loss: 0.651981
Train Epoch: 5 [0/800 (0%)] Loss: 0.704895
Train Epoch: 6 [0/800 (0%)] Loss: 0.650302
Train Epoch: 7 [0/800 (0%)] Loss: 0.658809
Train Epoch: 8 [0/800 (0%)] Loss: 0.904834
Train Epoch: 9 [0/800 (0%)] Loss: 0.655516
Train Epoch: 10 [0/800 (0%)]    Loss: 0.662808
Train Epoch: 11 [0/800 (0%)]    Loss: 0.664752
Train Epoch: 12 [0/800 (0%)]    Loss: 0.656390
Train Epoch: 13 [0/800 (0%)]    Loss: 0.664982
Train Epoch: 14 [0/800 (0%)]    Loss: 0.664430
Train Epoch: 15 [0/800 (0%)]    Loss: 0.664603 # stagnates

除此之外,我将如何获得对此的预测?这与将 argmax 视为多标签问题不同吧? (下面网络的示例输出) 输出

tensor([[ 0.2711,  0.1754, -0.3354],
    [ 0.2711,  0.1754, -0.3354],
    [ 0.2711,  0.1754, -0.3354],
    [ 0.2711,  0.1754, -0.3354],
    [ 0.2711,  0.1754, -0.3354],
    [ 0.2711,  0.1754, -0.3354],
    [ 0.2711,  0.1754, -0.3354]]

谢谢!

【问题讨论】:

    标签: python pytorch


    【解决方案1】:

    除此之外,我将如何获得对此的预测?

    如果它是一个多标签任务并且您正在输出 logits(就像您一样),那么只需执行以下操作:

    output = model(data.float())
    labels = output > 0
    

    指出它有什么问题?

    这是艰难而固执的,我会按顺序做:

    • 验证您的数据。您的神经网络响应对于每个输入都是相同的(假设您的示例输出是真实的)。也许您传递的是同一个样本(尽管似乎不太可能,因为它是 sklearn 创建的数据)
    • 从简单开始;没有 LR 调度器,没有权重衰减,只有简单的神经网络和优化器(Adam 可以留下)。如果您的模型过度拟合,请使用权重衰减,这显然不是现在。
    • 修正你的学习率;它是最重要的超参数之一。 1 可能太高了,以3e-41e-3 之类的开头。
    • 尝试在少量样本(比如32 样本)上过拟合(损失~0.0)。如果你做不到,你的神经网络可能没有足够的容量,或者你的代码有错误(除了我上面提到的之外,没有快速发现它)。您应该手动验证输入和输出形状是否正确并返回值(似乎每个示例网络都返回相同的 logits?)。
    • 如果您确定没有错误,请增加网络容量。添加一个或两个新的隐藏层(只有一个)并在单个批次上过拟合。如果它有能力使用更多数据

    我已经按照 pytorch 文档的建议使用了 multilabel_soft_margin_loss,

    这与使用torch.nn.BCEWithLogitsLoss 相同,我认为这是更常见的,但这是一个附录。

    【讨论】:

    • 感谢您的详细回复!我怀疑这与我设置损失的方式有关?我不确定它是否正确向后传播..
    • @Wboy 它正在正确传播,您丢失的可能原因在上面
    • 你是对的,尝试 0.001 的静态 LR 是有效的。这真的很奇怪,为什么这么低的静态 LR 会起作用..?
    • 这是相当标准的学习率,1 通常太高了,参数可能不断跳出最小值。
    • 嗯,虽然我的 LR 衰减很明显,但它应该可以工作的。嗯,谢谢!
    猜你喜欢
    • 2020-06-17
    • 2018-10-19
    • 2019-05-20
    • 2019-05-14
    • 2022-08-03
    • 2020-04-16
    • 2020-04-08
    • 1970-01-01
    • 2018-03-07
    相关资源
    最近更新 更多