【问题标题】:How to convert output to 1/0如何将输出转换为 1/0
【发布时间】:2021-05-03 23:10:19
【问题描述】:

我对构建深度学习模型比较陌生,我似乎完全被与形状和大小相关的错误所困扰。

这是 LSTM 模型和相关代码:

    class LSTMTagger(nn.Module):

        def __init__(self):
            super(LSTMTagger, self).__init__()
            self.embedding = 
    nn.Embedding(wv.vectors.shape[0],512)#embedding_matrix.shape[1])
            self.lstm1 = nn.LSTM(input_size = 512, hidden_size = 64, dropout = 
    0.1,batch_first=True,bidirectional = True)
            self.dropout = nn.Dropout(p = 0.25)
            self.linear1 = nn.Linear(in_features = 128, out_features = 64)
            self.dropout = nn.Dropout(p = 0.25)
            self.linear2 = nn.Linear(in_features = 64, out_features = 1)
            self.sigmoid = nn.Sigmoid()


        def forward(self, X):
            X_embed = self.embedding(X)
            outr1, _ = self.lstm1(X_embed)
            xr = self.dropout(outr1) 
            xr= self.linear1(xr)
            xr = self.dropout(xr)
            xr= self.linear2(xr)
            outr4 = self.sigmoid(xr)
            outr4 = outr4.view(1,-1)

            return outr4

model = LSTMTagger()
torch.multiprocessing.set_sharing_strategy('file_system')
if torch.cuda.device_count() > 1:
  print("Using ", torch.cuda.device_count(), " GPUs")
  # dim = 0 [30, xxx] -> [10, ...], [10, ...], [10, ...] on 3 GPUs

# model =model.load_state_dict(torch.load('best_model_state.bin'))
model = nn.DataParallel(model, device_ids=[0]) #py r
torch.cuda.empty_cache()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

model = model.to(device)

def train_epoch(
      model,
      data_loader,
      loss_fn,
      optimizer,
      device,
      scheduler,
      n_examples
    ):
      model = model.train()
      losses = []
      correct_predictions = 0
      for d in data_loader:
        print(f"Input ids: {np.shape(d['input_ids'])}\n len: {len(d['input_ids'][0])}")
        input_ids = d["input_ids"].to(device)
        targets = d["targets"].to(device)
        outputs = model(input_ids)
        _, preds = torch.max(outputs, dim=1)
        print(f"outputs is {np.shape(outputs)}")
        print(f"targets is {targets}")
        # continue
        loss = criterion(outputs.squeeze(), targets)
        # loss.backward()
        # nn.utils.clip_grad_norm_(model.parameters(), clip)
        # optimizer.step()
        # loss = loss_fn(outputs, targets)
        correct_predictions += torch.sum(preds == targets)
        losses.append(loss.item())
        loss.backward()
        nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
        optimizer.step()
        scheduler.step()
        optimizer.zero_grad()
      return correct_predictions.double() / n_examples, np.mean(losses)
EPOCHS = 6
optimizer = optim.Adam(model.parameters(), lr=2e-5)
total_steps = len(data_train) * EPOCHS
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=1)
loss_fn = nn.CrossEntropyLoss().to(device)
history = defaultdict(list)
best_accuracy = 0
criterion = nn.BCELoss()


print('starting training')
# exit()

for epoch in range(EPOCHS):
      print(f'Epoch {epoch + 1}/{EPOCHS}')
      print('-' * 10)
      train_acc, train_loss = train_epoch(
        model,
        data_train,
        loss_fn,
        optimizer,
        device,
        scheduler,
        len(df_train)
      )

在这种情况下,样本输入是一个大小为:torch.Size([1, 512]) ,看起来像这样:

tensor([[44561, 972, 7891, 94, 2191, 131, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0]], device=‘cuda:0’)

并输出标签(来自 train_epoch 函数的目标),以防只是张量形式的简单 1 或 0 标签,例如 tensor([1], device='cuda:0')。

我一直面临这种方法的问题。最初的输出是 1x512x1。所以,我加了

outr4 = outr4.view(1,-1)

在 sigmoid 层之后。然后,输出形状减少到 1x512,我使用了挤压功能,但我仍然面临如下错误:

ValueError: Using a target size (torch.Size([1])) that is different to the input size (torch.Size([512])) is deprecated. Please ensure they have the same size.

我花了很多时间试图弄清楚发生了什么,但无济于事。输出不应该是 1 还是 0,而不是 1x512 形状的张量?

我对构建模型比较陌生,所以请原谅我缺乏知识。

【问题讨论】:

  • 你想在这里完成什么?您正在输出 512 个值,然后尝试将 BCELoss 与单个目标一起使用?你期望这是什么计算? BCE 损失期望每个输出都有一个目标,这就是它的定义方式。
  • 感谢回复,根据需要更改问题。
  • 你能给我们你整个模型的输入形状吗?另外,为什么您的__init__ 中有前向定义?
  • 更正了转发功能。我正在传递一堆句子向量,每个句子向量被分类为 1 或 0。每个句子向量的形状是 1x512。我最初传递了 200 个这样的向量来测试模型并确保在我真正开始训练之前一切正常。但是,批量大小为 1,因此对于每个前向/后向传递,输入为 1x512。我在上面的问题中发布了示例输入张量。

标签: python deep-learning neural-network nlp pytorch


【解决方案1】:

我建议您在张量通过前向函数时跟踪它们的形状,例如每次操作后打印X.shape。 这样你就不会那么困惑了,因为你可以理解这些转换。

在你的情况下,我认为它是这样的:

  1. 输入:[1, 512, 1]
  2. 嵌入:[1, 512, 512]
  3. LSTM:[1, 512, 64x2]
  4. 林一:[1, 512, 64]
  5. 林2:[1, 512, 1]

然后您的激活函数不会重塑张量,它只是将最后一维中的值压缩到 0 和 1 之间。

从逻辑上讲,您遇到了一个问题,因为您有 512 个输出(每个单词/标记一个)而不是 1 个(用于句子)。您从未将单词维度降低到 1。

要解决此问题,您必须在模型中的某个位置展平/合并 512 维度。 例如,您可以在通过 LSTM 运行之后对单词维度进行平均:

  1. LSTM:[1, 512, 64x2]
  2. 平均:[1, 64x2]
  3. 林一:[1, 64]
  4. 林2:[1, 1]

或者你可以只取 LSTM 的最后一个隐藏状态,它的形状也是 [1, 1, 128]。

编辑:另外,要小心使用这么多的填充。 这可能会对您的结果产生不良影响。您应该尝试使用能够记住哪些输入是实际单词以及哪些是填充点的掩码。例如,对如此多的填充进行平均会大大降低结果;您应该只对实际令牌进行平均。 PyTorch 也为 LSTM 提供了一些功能,形式为pack_padded_sequence (https://pytorch.org/docs/stable/generated/torch.nn.utils.rnn.pack_padded_sequence.html) 和pad_packed_sequence。它们的使用示例:https://suzyahyah.github.io/pytorch/2019/07/01/DataLoader-Pad-Pack-Sequence.html

【讨论】:

    猜你喜欢
    • 2014-01-17
    • 2019-11-22
    • 2020-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-09
    • 2018-10-09
    • 2013-04-25
    相关资源
    最近更新 更多