PyTorch NN 未训练

青葱年少 pytorch 874

原文标题PyTorch NN not training

我有一个定制的 NN 模型,它可以工作并希望将其移至 PyTorch 框架。然而,由于一些错误配置,网络可能没有训练。如果您看到奇怪/错误或可能是促成原因的东西,请告知。

import torch
from torch import nn, optim
import torch.nn.functional as F
X_train_t = torch.tensor(X_train).float()
X_test_t = torch.tensor(X_test).float()
y_train_t = torch.tensor(y_train).long().reshape(y_train_t.shape[0], 1)
y_test_t = torch.tensor(y_test).long().reshape(y_test_t.shape[0], 1)

class Classifier(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(22, 10)
        self.fc2 = nn.Linear(10, 1)
        
    def forward(self, x):
        # make sure input tensor is flattened
        x = x.view(x.shape[0], -1)
        
        x = F.relu(self.fc1(x))
        x = F.log_softmax(self.fc2(x), dim=1)
        
        return x

model = Classifier()
criterion = nn.BCELoss()
optimizer = optim.SGD(model.parameters(), lr=0.003)

epochs = 2000
steps = 0

train_losses, test_losses = [], []
for e in range(epochs):
    # training loss
    optimizer.zero_grad()

    log_ps = model(X_train_t)
    loss = criterion(log_ps, y_train_t.type(torch.float32))
    loss.backward()
    optimizer.step()
    train_loss = loss.item()

    # test loss
    # Turn off gradients for validation, saves memory and computations
    with torch.no_grad():
        log_ps = model(X_test_t)
        test_loss = criterion(log_ps, y_test_t.to(torch.float32))
        ps = torch.exp(log_ps)

    train_losses.append(train_loss/len(X_train_t))
    test_losses.append(test_loss/len(X_test_t))
    
    if (e % 100 == 0):
        print("Epoch: {}/{}.. ".format(e, epochs),
          "Training Loss: {:.3f}.. ".format(train_loss/len(X_train_t)),
          "Test Loss: {:.3f}.. ".format(test_loss/len(X_test_t)))

培训未进行:

Epoch: 0/2000..  Training Loss: 0.014..  Test Loss: 0.082.. 
Epoch: 100/2000..  Training Loss: 0.014..  Test Loss: 0.082.. 
...

原文链接:https://stackoverflow.com//questions/71457035/pytorch-nn-not-training

回复

我来回复
  • CountTracula的头像
    CountTracula 评论

    我相信我找到了解决方案。我错误地使用了 log_softmax 而不是简单的 sigmoid。这解决了问题。

    2年前 0条评论
  • Tomer Geva的头像
    Tomer Geva 评论

    问题的根源在于您对 self.fc2 的输出应用了 softmax 操作。self.fc2 的输出大小为 1,因此无论输入如何,softmax 的输出都将为 1。阅读更多关于这里的pytorch包中的softmax激活函数。我怀疑你想使用Sigmoid函数将最后一个线性层的输出转换为区间[0,1],然后应用某种对数函数。

    因为无论输入如何,softmax 的输出都是 1,因此模型训练得不好。我无权访问您的数据,所以我无法准确模拟它,但根据我拥有的信息,用 sigmoid 替换 softmaxactivation 应该可以解决这个问题。

    更好和更稳定的方法是使用 BCEWITHLOGITSLOSS 代替criteria = nn.BCELoss() 中的标准,并在最后删除激活函数,因为该标准将 sigmoid 与 BCE 损失一起应用以实现更稳定的数值计算。

    总而言之,我的建议是将标准 = nn.BCELoss() 更改为标准 = nn.BCEWithLogitsLoss() 并将 forawrd 函数更改如下:

    def forward(self, x):
            # make sure input tensor is flattened
            x = x.view(x.shape[0], -1)
            
            x = F.relu(self.fc1(x))
            x = self.fc2(x)
    
    2年前 0条评论