Pytorch 如何在Pytork中处理TransformerEncoderLayer输出

Pytorch 如何在Pytork中处理TransformerEncoderLayer输出,pytorch,bert-language-model,transformer,Pytorch,Bert Language Model,Transformer,我正在尝试使用bio-bert语句嵌入对较长文本片段进行文本分类 按照目前的情况,我对每段文本中的句子数量进行了标准化(有些句子仅由(“[PAD]”)组成),并通过biobert运行每个句子,以获得句子向量,就像这里所做的那样: 然后,我通过一个具有8层和16个注意头的TrasnformerEncoder运行这些嵌入 TrasnformerEncoder输出一些形状(批量大小、句子数量、嵌入大小) 然后我尝试用一个线性层来解码它,并将它映射到我的类(其中有7个)和softmax输出以获得概率

我正在尝试使用bio-bert语句嵌入对较长文本片段进行文本分类

按照目前的情况,我对每段文本中的句子数量进行了标准化(有些句子仅由(“[PAD]”)组成),并通过biobert运行每个句子,以获得句子向量,就像这里所做的那样:

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

TrasnformerEncoder输出一些形状(批量大小、句子数量、嵌入大小)

然后我尝试用一个线性层来解码它,并将它映射到我的类(其中有7个)和softmax输出以获得概率

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

首先,我对TransformerEncoder输出的维度1进行求和,以获得一定的大小(批量大小、嵌入大小)。这一不变值导致我的网络收敛于始终以绝对确定性预测其中一个标签。通常是数据集中最常见的标签

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

这导致了类似的结果

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

这会更快地收敛到仅预测其中一个标签的值为1,而预测其他标签的值则小到消失

我觉得我误解了使用pytorch变压器的输出。 我的学习率很低,为0.00001,这有助于延迟收敛,但最终还是收敛了

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


我所设计的架构中是否存在明显的缺陷?

因此,transformer编码器的输入和输出形状是
批量大小、序列长度、嵌入大小)
。 有三种可能处理变压器编码器的输出(不使用解码器时)

  • 取序列长度维度的平均值:
  • x=self.transformer\u编码器(x)
    x=x.重塑(批量大小、顺序大小、嵌入大小)
    x=x.平均值(1)
    
  • 如你所说,总结一下:
  • x=self.transformer\u编码器(x)
    x=x.重塑(批量大小、顺序大小、嵌入大小)
    x=x.sum(1)
    
  • 使用递归神经网络沿
    序列长度
    维度组合信息:
  • x=self.transformer\u编码器(x)
    x=x.重塑(批量大小、序列长度、嵌入大小)
    #初始隐藏状态
    隐藏=火炬。零(层、批量大小、嵌入大小)。到(设备=设备)
    x、 隐藏=self.rnn(x,隐藏)
    x=x.重塑(批量大小、顺序大小、嵌入大小)
    #取最后输出
    x=x[:,-1]
    
    我认为,获取变压器输出的最后一个元素不是一个好主意。因为这样只获取1/seq len的信息。但是使用rnn,最后一个输出仍然包含其他输出的信息

    我说中庸之道是最好的主意


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

    哦,谢谢你的回答。平均w工作得很好。一个问题是我一开始没有正确屏蔽序列中的[PAD]部分。这样做真的很有帮助。