在bert-bilstm-softmax中加入MultiheadAttention

其实看到这个题目会感觉很奇怪,因为bert中本来就有MultiheadAttention机制,那为何还要加入呢?其实是介绍一种水论文(大胆!!!)的方法,之前看到一篇更离谱的论文,论文的模型为(rnn-lstm架构)。所以,一个普通的模型,加入MultiheadAttention,然后在搞点其他的小动作,也许某些中文核心就够了。

         

本文的框架是bert-bilstm-softmax做ner任务(别问为什么不用crf,就是任性)。下面展示本模型的model

class BertBilstm(nn.Module):
    def __init__(self,
                 output_size,
                 embed_size,
                 num_layers,
                 hidden_size,
                 drop_prob,
                 pretrained_path):
        super(BertBilstm, self).__init__()
        self.output_size = output_size
        # 加载Bert预训练模型
        self.bert = AutoModel.from_pretrained(pretrained_path)

先加载了一个预训练模型,这里的预训练模型输出的肯定是个tuple(之前犯了错,想看看究竟是什么东西,于是就size了一下发现出错,原来是tuple的原因),这里只需要知道预训练bert模型的输出的第一个列表也就是embed_x = self.bert(x)[0]是词向量,这里的词向量的维度是不能超过768的,因为这个模型最大就是768维的词向量,如果用更好的预训练模型比如roberta之类的会到1024对应模型的参数就会越多,计算时间也就越长。预训练模型介绍完毕。

第二个就该到bilstm了,这个太普通了,但是如果找细节还是会发现很多问题。

        # 定义BiLSTM层
        self.bilstm = nn.LSTM(bidirectional=True,
                              num_layers=num_layers,
                              input_size=embed_size,
                              hidden_size=hidden_size,
                              batch_first=True,
                              dropout=drop_prob)

这里的参数网上介绍有很多,bidirectional=true的意思是双向lstm也就是bilstm,num_layers就是层数(这里设定为1),input_size就是输入到bilstm的词向量维度,之前bert输出的是768,那这个地方出入就是768(车间流水线的感觉),hidden_size就是输出的维度(可以这么理解),因为是bilstm就相当于来回,那么输出的就是2*hidden_size,我这里hidden_size设定为256,那么从bilstm输出的维度就是512了。

 这里放一张偷过来的解释图(其实这个是便于理解的图),x(t)为当前时许的输入(这里网络上经常有人加入这里是一个词或者一个字用10维度的词向量表示),和前一时刻的输出concat为一个向量,经过4个参数矩阵变化形成输出,这里的c(t)是长时记忆(看图也看的出来),h(t)为短时记忆,会输出结果。里面的计算过程都很详细。

bilstm的输出结果是output,(c_n,h_n) ,原文档对于输出的解释是output是最后一层每个时序的h(t)的拼接,而(c_n,h_n)是最后一个时序的输出。

 一般不经常用(h_n,c_n),只会用到out_put也就是代码中的lstmout。这里的代码中,_的意思是(c_n,h_n)我都不要了,

lstmout, _ = self.bilstm(embed_x)

因为是batch_first=TRUE,所以输出的lstmout(也就是output)的输出size是(batch_size,seq_len,hidden_size*num_directions)上面文档中写了,这里的batch_size网上解释很多,就是把整个数据切成batch_size大小的batch,第二个是时序的意思,通俗来说就是一个数据有几个词,这个设定一般在dataloader中,就是训练集,测试集,验证集制作的函数当中,我的代码是设定为256就是要是一句话少于256用padding加上,多于256砍掉。好现在bilstm输出的结果是256个词,每个词512维度。

接下来到了MultiheadAttention,MultiheadAttention的selfheadAttention网上有太多介绍,有的自己封装,有的直接用torch,这里我用的torch的

#定于多头注意力层
        self.attention = nn.MultiheadAttention(embed_dim = 512,num_heads = 8,dropout = 0.1)

很简单,bilstm出来的是512为,那么MultiheadAttention方法的第一个参数就是输入的词向量维度为512,第二个参数是num_heads就是有几个头,这个数值一定能被第一个参数整除也就是512/8.好了现在就是全部model

import torch
import torch.nn as nn
from transformers import AutoModel


class BertBilstm(nn.Module):
    def __init__(self,
                 output_size,
                 embed_size,
                 num_layers,
                 hidden_size,
                 drop_prob,
                 pretrained_path):
        super(BertBilstm, self).__init__()
        self.output_size = output_size
        # 加载Bert预训练模型
        self.bert = AutoModel.from_pretrained(pretrained_path)
        # 定义BiLSTM层
        self.bilstm = nn.LSTM(bidirectional=True,
                              num_layers=num_layers,
                              input_size=embed_size,
                              hidden_size=hidden_size,
                              batch_first=True,
                              dropout=drop_prob) #(64,256,512)
        #定于多头注意力层
        self.attention = nn.MultiheadAttention(embed_dim = 512,num_heads = 8,dropout = 0.1)
        # 定义全连接层
        self.fc = nn.Linear(2 * hidden_size, output_size)

    def forward(self, x):
        # Bert模型太大,参数固定住
        with torch.no_grad():
            embed_x = self.bert(x)[0]
        lstmout, _ = self.bilstm(embed_x)
        print(lstmout.shape)
        output,_ = self.attention(lstmout,lstmout,lstmout)
        
        return self.fc(output)


if __name__ == "__main__":
    pass

output,_=self.attention(lstmout,lstmout,lstmout)是MultiheadAttention的输出,这三个参数是query,key,value的维度是(batch_size,seq_len,hidden_size*num_directions)=(64,256,512)

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值