跳过bidirectional_dynamic_rnn中的值

时间:2019-03-31 21:32:10

标签: python tensorflow lstm recurrent-neural-network

我想在整个文档上使用BERT嵌入实现NER。 一个文档由几个句子组成,每个句子由标记组成,并且长度可变。现在,我为每个句子创建带有BERT的单词嵌入,并填充每个句子。然后,我想对文档的 all 标记使用双向LSTM进行NER,而不仅限于句子。

如果我没有对BERT进行微调(提取诸如ElMo-embedding之类的功能),那么我可以删除填充的标记并合并所有句子,然后再将它们输入双向LSTM。

但是如何在微调设置中做到这一点?

我的输入格式如下:[文档,句子,标记]

对于BERT,我将输入重塑为:[文档*句子,标记]

然后,我想将BERT的输出放入形状为[documents,s句子* tokens]的bidirectional_dynamic_rnn中。不幸的是,这些句子包含填充标记(零),而bidirectional_rnn应该跳过它们。

我不能使用bidirectional_dynamic_rnn的sequence_length参数,因为填充的令牌可能在序列内部。例如,一个 该文档包含两个句子:

   s1=[1, 2, 3, 0, 0]
   s1=[10, 20, 30, 40, 50]

如果我将句子串联起来

   s1+s2=[1, 2, 3, 0, 0, 10, 20, 30, 40, 50]

bidirectional_dynamic_rnn现在应该跳过零。

我该怎么做?

1 个答案:

答案 0 :(得分:0)

我编写了一个小例子,将填充值排序到列表的末尾。我不确定该解决方案的效率如何,但我希望它会有所帮助。

import tensorflow as tf

vec = tf.convert_to_tensor([[1, 2, 3, 0, 0, 10, 20, 30, 40, 50], [1, 2, 3, 4, 5, 0, 0, 0, 7, 0]])

number_mask = tf.cast(tf.not_equal(vec, 0), dtype=tf.int32)
pad_mask = 1 - number_mask
index_list = tf.cumsum(tf.ones_like(number_mask), axis=-1) - 1
fill_values = tf.reduce_max(index_list, axis=-1, keep_dims=True) + 1
content = index_list * number_mask + pad_mask * fill_values
pad = index_list * pad_mask - number_mask

content_sort = tf.sort(content, axis=1)
pad_sort = tf.sort(pad, axis=1)

content_sort_mask = tf.cast(tf.less(content_sort, fill_values), tf.int32)
pad_sort_mask = tf.cast(tf.greater(pad_sort, -1), tf.int32)

result_index = content_sort * content_sort_mask + pad_sort * pad_sort_mask

result = tf.batch_gather(vec, result_index)

with tf.Session() as sess:
    print(sess.run([result]))
    # [array([[ 1,  2,  3, 10, 20, 30, 40, 50,  0,  0],
              [ 1,  2,  3,  4,  5,  7,  0,  0,  0,  0]], dtype=int32)]