赞
踩
论文原文:
Self-Attention with Relative Position Representations
NEZHA: NEURAL CONTEXTUALIZED REPRESENTATION FOR CHINESE LANGUAGE UNDERSTANDING
最近在研究苏神的《SPACES:“抽取-生成”式长文本摘要(法研杯总结)》
面向法律领域裁判文书的长文本摘要生成,涉及到长文的输入与输出,其输入加输出长度远超过bert限定的512,(Bert的postion_embedding是在预训练过程中训练好的,最长为512)。因此需要寻找解决突破输入长度限制的方法,目前了解到的解决方案:
本文选择了华为的NEZHA模型的相对位置编码作为复现目标,先比T5来说,NEZHA沿用了 Self-attention with relative position representations 文中的相对位置编码方法,实现起来较为简单,并不需要给模型增加额外的可训练参数,问题在于增加了模型的计算量。
这里只阐述NEZHA的相对位置编码方法,模型的其他细节还是看论文来的实在啦~
Tensorflow-GPU 2.0.0
Transformers 3.1.0
class Sinusoidal(tf.keras.initializers.Initializer): def __call__(self, shape, dtype=None): """ Sin-Cos形式的位置向量 用于创建relative position embedding 后续通过计算位置差来对embedding进行查询 得到相对位置向量 embedding的shape 为[max_k(最大距离),deep(相对位置向量长度)] """ vocab_size, depth = shape embeddings = np.zeros(shape) for pos in range(vocab_size): for i in range(depth // 2): theta = pos / np.power(10000, 2. * i / depth) embeddings[pos, 2 * i] = np.sin(theta) embeddings[pos, 2 * i + 1] = np.cos(theta) return embeddings class RelativePositionEmbedding(tf.keras.layers.Layer): ''' input_dim: max_k 对最大相对距离进行截断 output_dim:与最后的eij相加,由于各个head之间共享相对位置变量, 因此该参数为 hidden_size / head_num = head_size embeddings_initializer:初始化的权重,此处使用Sinusoidal() ''' def __init__( self, input_dim, output_dim, embeddings_initializer=None, **kwargs ): super(RelativePositionEmbedding, self).__init__(**kwargs) self.input_dim = input_dim self.output_dim = output_dim self.embeddings_initializer = embeddings_initializer def build(self, input_shape): super(RelativePositionEmbedding, self).build(input_shape) self.embeddings = self.add_weight( name='embeddings', shape=(self.input_dim, self.output_dim), initializer = self.embeddings_initializer, trainable=False # 此处注意设置trainable = False 固定相对位置编码 ) def call(self, inputs): ''' (l,l) 根据embedding查表得到相对位置编码矩阵 (l,l,d) ''' pos_ids = self.compute_position_ids(inputs) return K.gather(self.embeddings, pos_ids) def compute_position_ids(self, inputs): ''' 通过传入的hidden_size (b,l,h) 根据长度计算相对位置矩阵(l,l)(k个相对位置值) ''' q, v = inputs # 计算位置差 q_idxs = K.arange(0, K.shape(q)[1], dtype='int32') q_idxs = K.expand_dims(q_idxs, 1) v_idxs = K.arange(0, K.shape(v)[1], dtype='int32') v_idxs = K.expand_dims(v_idxs, 0) pos_ids = v_idxs - q_idxs # 后处理操作 max_position = (self.input_dim - 1) // 2
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。