transformer做文本分类的keras实现完整版

更新时间:2023-07-30 14:26:20 阅读: 评论:0

transformer做⽂本分类的keras实现完整版
背景
但是,这个⽂章存在挺多问题。本⾝这个⽂章的实现其实是少了⼀部分的(缺少了LayerNorm+残差的部分),multi-head attention的实W o
现也少了⼀个再做⼀次全连接映射。加上其本⾝运⽤的参数跟原始论⽂也差很多,所以跟论⽂描述的encoder区块其实对应不太上,如果是想对着论⽂来看代码的话,这段代码可能会产⽣⼀定的误导。所以我从各个地⽅找了其他的缺少的部分实现,凑出⼀个基本能对应上论⽂的keras版本的transformer-encoder完整的实现;另⼀⽅⾯,也顺便结合原理和代码(会尽量把注释写清楚),将transformer的原理重新复习⼀遍。
keras的版本
为了兼容csdn上看到的代码,keras的版本采⽤的是2.2.4的keras版本(⾮tf.kreas)。如果需要其他更⾼阶版本或者tf.keras的版本,可能会需要有⼀定的改动,可以参考GitHub上的CyberZHG的代码进⾏改动即可。
主要参考链接法律知识内容
原理主要参考链接:
/p/44121378
/p/44731789
blog.csdn/u012526436/article/details/86295971
原始论⽂ arxiv/pdf/1706.03762.pdf
代码主要参考链接:
含有近义词的四字词语
blog.csdn/xiaosongshine/article/details/86595847
blog.csdn/qq_40742298/article/details/115011147
模型整体结构
因为是⽤来做⽂本分类,所以这个图⾥⾯我们只谈左边的encoder部分。
麻将胡牌型
encoder部分⾸先是input + embedding部分,其次是由N个block组成的编码部分,在原⽂中,这个N是6。每个block呢,⼜由multi-head attention、add & norm 、feedforward和残连接层组成,我们接下来还是⼀步⼀步的拆解。
Input 层
原始的Input层,为词向量+position embedding,这个跟⼀般的⽂本输⼊⼀样,假设输⼊为(batch_size, q_len, embedding_size),注意⼀点的是,这个embedding_size为了在后续可以接上残差连接层,其应该要在整个⽹络中保证⼀致,原⽂中,这个embedding_size 和各种⼦层的维度要⼀致,原⽂都是512维,以表⽰。
Position embedding 层
d =model 512
因为transformer与RNN不同,其没有了词位置顺序信息,因此为了保证位置信息,先将词过⼀个position embedding,然后再与词向量求和作为后续block的输⼊。注意⼀点的是,《Attention is all you need》原⽂提到了⽤sin和cos的⽅式以及训练词位置的embedding,经过实验发现⼆者没有区别,最后⽤的是sin和cos的⽅式。但是bert⾥⾯的position embedding是可训练的。
公式不赘述,⼤致表⽰如下:
具体的代码实现及注释见下:
#! -*- coding: utf-8 -*-
#%%
from __future__ import print_function
from keras import backend as K
pology import Layer
class Position_Embedding(Layer):
def__init__(lf, size=None, mode='sum',**kwargs):
lf.size = size #必须为偶数
拜师仪式徒弟说词
super(Position_Embedding, lf).__init__(**kwargs)
def call(lf, x):#上⼀层⼀般就是embedding层,batch_size,q_len,model_dim
if(lf.size ==None)de =='sum'):
lf.size =int(x.shape[-1])#d_model的长度,⽐如512
batch_size,q_len = K.shape(x)[0],K.shape(x)[1]#
qq收藏在哪里找
## K.arange(lf.size / 2, dtype='float32' ), ⽣成0~256,间隔1,即公式中的i
## 2*K.arange(lf.size / 2, dtype='float32' ), 0~512,间隔2,即公式中的2i, 0,2,4,6……,512,对应的i是0,1,2,3,4,5
## 再除以model_dim,按公式取pow
position_j =1./ K.pow(10000.,2* K.arange(lf.size /2, dtype='float32')/ lf.size)#
position_j = K.expand_dims(position_j,0)# (1,256)
#⽣成位置的序列
#x[:,:,0]取每个embedding的第⼀个分量---> bs,q_len
#ones_like -->bs,q_len [[1,1,1,1……],[1,1,1……],……]
归去来兮歌词#cumsum ---> bs,q_len,[[1,2,3,4……],[1,2,3……],……]
#cumsum-1 ----->bs,q_len,[[0,1,2,3……],[0,1,2……],……]
position_i = K.s_like(x[:,:,0]),1)-1#K.arange不⽀持变长,只好⽤这种⽅法⽣成
position_i = K.expand_dims(position_i,2)#bs,q_len,1
position_ij = K.dot(position_i, position_j)#bs,q_len,256
##经过dot之后,就是pe/10000^(2i/d_model)了
##原始的实现稍微有点问题,不应该直接concatenate偶数和奇数,应该交叉concatenate
虞河position_ij_2i = K.sin(position_ij)[...,tf.newaxis]#bs,q_len,model_dim/2,1
position_ij_2i_1 = K.cos(postition_ij)[...,tf.newaxis]#bs,q_len,model_dim/2,1
position_ij = K.concatenate([position_ij_2i,position_ij_2i_1])#bs,q_len,model_dim/2,2
position_ij = K.reshape(position_ij,(batch_size,q_len,lf.size))#bs,q_len,model_dim
#position_ij = K.concatenate([K.cos(position_ij), K.sin(position_ij)], 2)#这个实现没有交叉拼接,前半部分都⽤的cos,后半部分都⽤的sin de =='sum':
return position_ij + x
de =='concat':
atenate([position_ij, x],2)
def compute_output_shape(lf, input_shape):
de =='sum':
return input_shape
de =='concat':
return(input_shape[0], input_shape[1], input_shape[2]+lf.size)
单个block的各⾃实现
multi-head attention
scaled dot attention
看⼀下scaled dot attention的⽰意图及公式:
定义Wq,Wk,Wv三个矩阵分别⽤三个矩阵相乘得到Q,K ,V Q,K dot得到分数,算softmax权重权重 * V矩阵得到最后的加权后的V矩阵(H矩阵)
特别的是算softmax的时候要除以⼀个,具体原因见blog.csdn/qq_37430422/article/details/105042303代码实现:
class  ScaledDotProductAttention (Layer ):
r """The attention layer that takes three inputs reprenting queries, keys and values.    \text{Attention}(Q, K, V) = \text{softmax}(\frac{Q K^T}{\sqrt{d_k}}) V
See: arxiv/pdf/1706.03762.pdf
"""
建筑设备工程
def  __init__(lf ,
return_attention =Fal ,
history_only =Fal ,
**kwargs ):
"""Initialize the layer.
:param return_attention: Whether to return attention weights.
:param history_only: Whether to only u history data.
:param kwargs: Arguments for parent class.
"""
super (ScaledDotProductAttention , lf ).__init__(**kwargs )
lf .supports_masking = True
lf .return_attention = return_attention
lf .history_only = history_only
lf .intensity = lf .attention = None
def  get_config (lf ):
config = {
'return_attention': lf .return_attention ,
'history_only': lf .history_only ,
}
ba_config = super (ScaledDotProductAttention , lf ).get_config ()D k

本文发布于:2023-07-30 14:26:20,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1123805.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:实现   代码   没有   位置   矩阵   公式   连接   部分
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图