【问题标题】:How to process TransformerEncoderLayer output in pytorch如何在pytorch中处理TransformerEncoderLayer输出
【发布时间】:2021-03-19 06:15:15
【问题描述】:

我正在尝试使用 bio-bert 句子嵌入来对较长的文本进行文本分类。

就目前而言,我标准化了每段文本中的句子数量(一些句子仅由 ("[PAD]") 组成,并通过 biobert 运行每个句子以获得句子向量,就像它们在这里所做的那样: https://pypi.org/project/biobert-embedding/

然后我通过具有 8 层和 16 个注意力头的 TrasnformerEncoder 运行这些嵌入。

TrasnformerEncoder 输出一些形状(batch_size、num_sentences、embedding_size)。

然后我尝试使用线性层对其进行解码并将其映射到我的类(其中有 7 个)和 softmax 输出以获得概率。

我的损失函数就是 nn.CrossEntropyLoss()。

首先,我对 TransformerEncoder 输出的维度 1 求和以获得大小(batch_size、embedding_size)。这种不变性导致我的网络始终以绝对确定的方式预测其中一个标签。通常是数据集中最常见的标签。

然后我尝试只获取 TransformerEncoder 输出的最后一句的输出。即 TransformerEncoderOutput[:, -1, :]。

这导致了类似的结果。

然后我尝试在 TransformerEncoder 输出的每个输出上运行我的线性层,以生成大小为 (batch_size, num_sentences, 7) 的张量。然后我对 dim 1 求和(生成一个大小为 (batch_size, 7) 和 softmax 的张量)。这里的想法是,每个句子在被告知其在序列中的位置后都可以投票给标签。

这收敛得更快,只为其中一个标签预测 1,而为其他标签预测极小的值。

我觉得我误解了以某种方式使用 pytorch Transformer 的输出。 我的学习率非常低,为 0.00001,这有助于延迟收敛,但最终还是收敛了。

这对我来说意味着我的网络无法弄清楚文本的任何内容,而只是在学习寻找最常见的标签。我猜这要么是我的损失函数的问题,要么是我使用 Transformer 的问题。

我布置的架构中是否存在明显缺陷?

【问题讨论】:

    标签: pytorch bert-language-model transformer


    【解决方案1】:

    所以transformer-encoder的输入输出形状是batch-size, sequence-length, embedding-size)。 处理 Transformer 编码器输出的三种可能性(不使用解码器时)。

    1. 您取sequence-length 维度的平均值:
    x = self.transformer_encoder(x)
    x = x.reshape(batch_size, seq_size, embedding_size)      
    x = x.mean(1)
    
    1. 按你说的总结一下:
    x = self.transformer_encoder(x)
    x = x.reshape(batch_size, seq_size, embedding_size)      
    x = x.sum(1)
    
    1. 使用循环神经网络沿sequence-length 维度组合信息:
    x = self.transformer_encoder(x)
    x = x.reshape(batch_size, seq_len, embedding_size)      
    
    # init hidden state
    hidden = torch.zeros(layers, batch_size, embedding_size).to(device=device)  
    x, hidden = self.rnn(x, hidden)
    x = x.reshape(batch_size, seq_size, embedding_size)
    
    # take last output
    x = x[:, -1]
    

    我认为采用 Transformer 输出的最后一个元素并不是一个好主意。因为那时你只需要 1 / seq-len 的信息。但是使用 rnn,最后一个输出仍然具有其他所有输出的信息。

    我说取平均值是最好的主意。

    对于学习率:对我来说,当我使用热身训练时,它总是效果更好。如果您不知道那是什么:您从低学习率开始,例如 0.00001,然后增加它直到达到某个目标 lr,例如 0.002。从那时起,您只需像往常一样衰减 lr。

    【讨论】:

    • 哦,谢谢你的好回答。平均效果很好。一个问题是我一开始没有正确屏蔽序列的 [PAD] 部分。这样做真的很有帮助。
    猜你喜欢
    • 1970-01-01
    • 2019-08-16
    • 2019-05-28
    • 1970-01-01
    • 2014-10-10
    • 1970-01-01
    • 2018-07-27
    • 2019-07-12
    • 1970-01-01
    相关资源
    最近更新 更多