PyTorch CNN 网络输出同质结果

数据挖掘 美国有线电视新闻网 火炬
2022-03-09 17:17:02

我是数据科学的初学者,我有一个项目想通过 PyTorch 中的卷积神经网络进行 nlp。问题是无论卷积层产生什么,感知器的输出总是重复的。就好像什么都没看到一样。

我已经尝试更改数据集、变量数量、损失函数、优化方法以及添加或删除层,但似乎没有任何反应。整整一周我都在处理这个问题,但我不知道出了什么问题。

在这种情况下,损失函数是torch.nn.MultiLabelSoftMarginLoss,这就是我在最后一层移除 Sigmoid 激活的原因。优化方法是SGD。它在 15 次左右的运行中收敛。

这是数据通过卷积层后的样子(我将张量层并排放置):

层

高度是通道数,宽度是特征数乘以批量大小。

测试数据

这是我用于训练的 y,X 对。我使用 torch.save 创建文件。

y: https://file.io/JiLnim

x: https://file.io/NKecI1

可重现的例子

import torch
from torch import nn

T = torch.load("X_ex")
y = torch.load("y_ex")

class model(nn.Module):
    def __init__(self,Test,n_cat=1):
        super(model, self).__init__()
        self.last_kernel = 3
        self.convolutions = nn.Sequential(
            nn.Conv1d(Test.shape[1], 500, kernel_size=7, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool1d(kernel_size=3),
            nn.Conv1d(500, 400, kernel_size=7, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool1d(kernel_size=3),
            nn.Conv1d(400, 300, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv1d(300, 200, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv1d(200, 100, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool1d(kernel_size=self.last_kernel),
            )
        self.test_conv = self.convolutions(Test) #I know it's dumb but I just wanted to get it working
        self.p_channels = self.test_conv.shape[1]*self.test_conv.shape[2]
        self.perceptron = nn.Sequential(
            nn.Linear(self.p_channels,100),
            nn.Sigmoid(),
            nn.Linear(100,16),
            nn.Sigmoid(),
            nn.Linear(16,n_cat),
            #nn.Sigmoid()
        )
    def forward(self, x):
        x = self.convolutions(x)
        x = x.view(x.size(0), -1)
        x = self.perceptron(x)
        return x

m=model(T,y.shape[1])
loss_fn = torch.nn.MultiLabelSoftMarginLoss(reduction="sum")

r = 0.001 #learning rate

optimizer = torch.optim.SGD(m.parameters(), lr=r, momentum=0.9)

for t in range(15):
    y_pred = m.forward(T)
    loss = loss_fn(y_pred, y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

#Final y:
y_final = torch.sigmoid(y_pred)

输出(前几个)

In [1]: y_actual
Out[1]: 
tensor([[0.0794, 0.0734, 0.0880,  ..., 0.0817, 0.0864, 0.0698],
        [0.0794, 0.0734, 0.0880,  ..., 0.0817, 0.0864, 0.0698],
        [0.0794, 0.0734, 0.0880,  ..., 0.0817, 0.0864, 0.0698],
        ...,
        [0.0794, 0.0734, 0.0880,  ..., 0.0817, 0.0864, 0.0698],
        [0.0794, 0.0734, 0.0880,  ..., 0.0817, 0.0864, 0.0698],
        [0.0794, 0.0734, 0.0880,  ..., 0.0817, 0.0864, 0.0698]],
       grad_fn=<SigmoidBackward>)
In [2]: y_actual.max(axis=1).indices
Out[2]: 
tensor([24, 24, 24, 24, <keeps going>, 24, 24])


1个回答

所以,我想我弄清楚了问题所在。它与算法本身无关,而与数据无关。输入网络的数据是一个稀疏张量;问题是网络无法从错误中吸取教训,因为每次出错时,它都会对权重进行零校正。

正因为如此,我只是简单地对张量进行了转换,将零点切换为 -1,然后网络开始给出异构结果。X2X1