Python pytorch多标签分类网络未经培训

Python pytorch多标签分类网络未经培训,python,pytorch,Python,Pytorch,我正在尝试一个简单的多标签分类示例,但由于损失停滞不前,网络似乎没有正确训练 正如pytorch文档所建议的那样,我使用了多标签\u软\u保证金\u损失,但是没有太多其他的东西可供参考。在文档中找不到任何合适的例子 有人能仔细观察并指出它有什么问题吗?下面的完整工作示例(也是下面关于预测的问题) 完全工作的示例代码 from __future__ import print_function import torch import torch.nn as nn import torch.nn.fu

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

正如pytorch文档所建议的那样,我使用了多标签\u软\u保证金\u损失,但是没有太多其他的东西可供参考。在文档中找不到任何合适的例子

有人能仔细观察并指出它有什么问题吗?下面的完整工作示例(也是下面关于预测的问题)

完全工作的示例代码

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]]
谢谢

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

如果这是一个多标签任务,并且您正在输出Logit(您现在的状态),那么只需执行以下操作:

output = model(data.float())
labels = output > 0
指出它有什么问题

这很难,也很固执己见,为了:

  • 验证您的数据。您的神经网络响应对于每个输入都是相同的(假设您的示例输出是真实的)。可能您传递的是同一个样本(尽管看起来不太可能,因为它是
    sklearn
    创建的数据)
  • 从简单开始;没有LR调度器,没有重量衰减,只有简单的神经网络和优化器(
    Adam
    可以保留)。使用“权重衰减”(weight decay)如果您的模型过度拟合,那么现在显然不是
  • 固定你的学习速度;它是最重要的超参数之一<代码>1可能太高,请从
    3e-4
    1e-3
    开始
  • 尝试在少量样本(例如
    32
    样本)上过度拟合(损耗
    ~0.0
    )。如果你不能,你的神经网络可能没有足够的容量,或者你的代码中有错误(除了我上面提到的以外,没有从快速浏览中发现)。您应该验证输入和输出形状是否正确,并手动返回值(似乎每个示例网络都返回相同的logit?)
  • 如果确定没有错误,请增加网络容量。添加新的隐藏层或两层(只有一层)并在单个批次上过盈。如果它能够处理更多的数据
我使用了pytorch文档建议的多标签软利润损失


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

感谢您的详细回复!我怀疑这与我造成损失的方式有关?我不确定它是否正确地向后传播。@Wboy它正确地传播了,你失败的可能原因在上面。你是对的,尝试0.001的静态LR有效。这真的很奇怪,为什么这么低的静态LR会起作用……这是相当标准的学习率,
1
通常太高,参数可能会不断跳出最小值。嗯,我有一个相当显著的LR衰减,但它应该起作用。好吧,谢谢!