transformer工程实现笔记

上线形式:
tensorflow直接加载上线
基于openblas重新实现
基于cublas库重新实现
优点:
tensorflow:有谷歌开源代码,不需要另外实现
cublas/openblas:可以定制化优化,耗时更短,可微调
缺点:
tensorflow:耗时长,内部黑盒无法微调
cublas/openblas:部分核心功能要重写,只支持基础包


以下为工程实现细节:

input/output为序列:

基础架构:

每个Encoders中分别由6个Encoder组成(论文中是这样配置的)。而每个Decoders中同样也是由6个Decoder组成:

假设现在存在一个输出vocabulary为32768,输入vocabulary53000
流程:

  • 切词/embedding
    • 0位置不可用,1位置为EOS,作为空格等其他非文本符号的替换
    • 输入词embedding 将词转化为下标 通过映射来查找
    • 输入词embedding维度:1024float
    • 输入词embedding初始化结果来源:w2v
    • 输入词位置信息embedding:左半部分的值是一由一个正弦函数生成的,而右半部分是由另一个函数(余弦)生成。其中,get_timing_signal_1d()源码地址
    • input Embedding = word Embedding + position Embedding
  • Encode(假设每个batch有15个input词)
    • multi-headed attention
      • self-attention
        • 创建一个Query/Key/Value的矩阵,单个矩阵size:1024(16(头数量)x64(q,k,v向量的长度))x1024(词向量的长度)
        • Query/Key/Value的矩阵合并后为15x3x1024x1024
        • 将query向量和key向量点击来对相应的单词打分
        • 再将得到的输出通过softmax函数标准化,使得最后的列表和为1
        • 将每个Value向量乘以softmax后的得分。这里实际上的意义在于保存对当前词的关注度不变的情况下,降低对不相关词的关注。
        • QK的点击为15x64x64x15,结果15x15,这样的矩阵有16个,再对此进行sotfmax压缩
        • 如果batch小于15,则填充负无穷
        • KQ的15x15x16再点积V=XxWv15x64x16,16个15x64的矩阵
        • KQxV得16x(15x15x15x64)=16x15x64
        • 后接一个dense,1024x1024,得到15x1024
        • add一个bias,再normalization
      • resudual feed forward neural network
        • multi-headed attention前的矩阵设为in
        • multi-headed attention后的矩阵设为out
        • 残差处理:Z = sqrt(∑(out-in)xx2)
        • 第一层的激活函数是ReLU,第二层是一个线性变换,W1和W2分别为1024x4096,4096x1024
        • encode out = resudual feed forward neural network in + resudual feed forward neural network out
    • Encoder结束
  • Decode过程与Encode过程保持一致,不同点如下:
    • Decode出来靠近的词更重要,则把对应的input的矩阵的上三角矩阵进行mask,保证尽量减少对已经decode出来的词的影响
    • self-attention – > resudual —> in/out attention —> resudual —> FFN —> resudual,一次解码完成
    • 每次计算Decode完成后把decode出来的词进行储存,下一次的input直接拼接之前m次的带入下一次decode即可
    • 参数矩阵:KV来自encode部分计算好的(1024x2048),Q来自decode部分新建的(1024x1024)
    • Decode:Q:nx16x64,K/V:15x16x64,
      QK:16x(nx64)x(15x64)= 16xnx15
      QKxV=16x(nx15x15x64)=nx1024,n即为decode得词数
    • Q的行数是Decode的词的数量,第一轮是1,第二轮是2…,解多少个词就有多少轮
    • Decode出来的结果矩阵点乘vocabulary_sizex1024,得出vocabulary_size的向量后softmax(所有vocabulary_size和为1),得到top8
    • beam search,beam=4,一直算到eosid;如果下一个就是eosid的话,用top8其他的其他4个
  • trick:
    • Embedding采取半float,绝大多数都是0,所以不会对最后的结果有很大影响
    • 出现eosid及finished的时候,记一次综合score,当后续继续往下解beam search的时候score不如之前的话就以综合score出现的地方为截止点
    • train的过程中,input_size+50为最长decode长度,降低学习耗时

欢迎大家关注我的个人bolg知乎,更多代码内容欢迎follow我的个人Github,如果有任何算法、代码、转行疑问都欢迎通过邮箱发消息给我。

打赏的大佬可以联系我,赠送超赞的算法资料