如何将 BERT 提供给神经机器翻译?

数据挖掘 喀拉斯 张量流 序列到序列 伯特 机器翻译
2022-03-01 02:17:54

我正在尝试将inputandtarget句子提供给 NMT 模型,我正在尝试在这里使用 BERT,但我不知道如何将它提供给我的模型。在此之前,我使用的是 one-hot 编码,但我遇到了问题,我想使用 BERT。

另外,我必须指出,我是 TensorFlow 和深度学习的新手。因此,请与我分享您对在 NMT 中使用 BERT 的看法。

我的目标只是在我的模型中使用 BERT 进行翻译

我的模型定义:

def build_model(in_vocab, out_vocab, in_timesteps, out_timesteps, units):
    model = Sequential()
    model.add(Embedding(in_vocab, units, input_length=in_timesteps, mask_zero=True))
    model.add(LSTM(units))
    model.add(RepeatVector(out_timesteps))
    model.add(LSTM(units, return_sequences=True))
    model.add(Dense(out_vocab, activation='softmax'))
    return model
1个回答

我发现这种在我的翻译系统中使用 BERT 的方式,它允许我加载和使用更多数据来训练我的模型。当我想为我的任务使用更多数据(例如 100k)时出现内存错误。我发现我的标记器在这里是一个问题,因为为如此大量的数据制作标记器需要大量内存,所以像 BERT 这样的预训练模型是解决这个问题的解决方案,可以提供更多数据,比如 200k或更多您的模型,而不必担心内存错误太多。

另外,在我的任务中,我担心在我的训练阶段不存在但在测试阶段存在的单词,所以 bert 也为我解决了这个问题,因为它是在一个大型语料库上训练的。让我们深入了解一下我是如何使用 BERT 来解决我的问题的。

在这里,我将制作英语到英语的翻译系统。

  1. 加载预先训练BERT的英语(如果您的源语言和目标语言彼此不同,您必须分别加载它们,您可以查看tfhub.dev它们)
max_seq_length =  50 # i need to test the bert so I will keep this small for now
input_word_ids = tf.keras.layers.Input(shape=(max_seq_length,), dtype=tf.int32,name="input_word_ids")
input_mask = tf.keras.layers.Input(shape=(max_seq_length,), dtype=tf.int32,name="input_mask")
segment_ids = tf.keras.layers.Input(shape=(max_seq_length,), dtype=tf.int32,name="segment_ids")
#this is the path to pre-trained bert model
bert_layer = hub.KerasLayer("https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/1",trainable=True)
  1. 然后我打电话给我的标记器
FullTokenizer = bert.bert_tokenization.FullTokenizer
vocab_file = bert_layer.resolved_object.vocab_file.asset_path.numpy()
do_lower_case = bert_layer.resolved_object.do_lower_case.numpy()
tokenizer = FullTokenizer(vocab_file, do_lower_case)

这是使用标记器的示例:

tokenizer.convert_tokens_to_ids(['is'])
tokenizer.convert_ids_to_tokens([2003])
tokenizer.convert_ids_to_tokens([30521])

输出是:([2003], ['is'], ['##~'])

  1. 然后我使用我的火车数据来获取我的序列
s = "This is a nice sentence."
stokens = tokenizer.tokenize(s)
stokens = ["[CLS]"] + stokens + ["[SEP]"]
input_ids = get_ids(stokens, tokenizer, max_seq_length)

我的输出是:

input Ids: [101, 2023, 2003, 1037, 3835, 6251, 1012, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  1. 获取令牌 ID 也需要此方法,您应该将其添加到您的代码中
def get_ids(tokens, tokenizer, max_seq_length):
    """Token ids from Tokenizer vocab"""
    token_ids = tokenizer.convert_tokens_to_ids(tokens)
    input_ids = token_ids + [0] * (max_seq_length-len(token_ids))
    return input_ids

  1. 对于您的模型词汇大小,您可以使用这些值,
len(tokenizer.vocab)

在我的情况下是:30522

在这些步骤之后,您可以获得输入和输出的序列,然后将它们提供给您的模型。

我希望它有所帮助。如果我在这种情况下错了,请分享您的意见。

谢谢