Python pytorch多标签分类网络未经培训
我正在尝试一个简单的多标签分类示例,但由于损失停滞不前,网络似乎没有正确训练 正如pytorch文档所建议的那样,我使用了多标签\u软\u保证金\u损失,但是没有太多其他的东西可供参考。在文档中找不到任何合适的例子 有人能仔细观察并指出它有什么问题吗?下面的完整工作示例(也是下面关于预测的问题) 完全工作的示例代码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
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调度器,没有重量衰减,只有简单的神经网络和优化器(
可以保留)。使用“权重衰减”(weight decay)如果您的模型过度拟合,那么现在显然不是Adam
- 固定你的学习速度;它是最重要的超参数之一<代码>1可能太高,请从
或3e-4
开始1e-3
- 尝试在少量样本(例如
样本)上过度拟合(损耗32
)。如果你不能,你的神经网络可能没有足够的容量,或者你的代码中有错误(除了我上面提到的以外,没有从快速浏览中发现)。您应该验证输入和输出形状是否正确,并手动返回值(似乎每个示例网络都返回相同的logit?)~0.0
- 如果确定没有错误,请增加网络容量。添加新的隐藏层或两层(只有一层)并在单个批次上过盈。如果它能够处理更多的数据
这与使用
torch.nn.BCEWithLogitsLoss是一样的,我认为这更常见,但这是一个附录。感谢您的详细回复!我怀疑这与我造成损失的方式有关?我不确定它是否正确地向后传播。@Wboy它正确地传播了,你失败的可能原因在上面。你是对的,尝试0.001的静态LR有效。这真的很奇怪,为什么这么低的静态LR会起作用……这是相当标准的学习率,1
通常太高,参数可能会不断跳出最小值。嗯,我有一个相当显著的LR衰减,但它应该起作用。好吧,谢谢!