用BERT词嵌入和TensorFlow加速你的文本数据分析

380 阅读4分钟

有一件事是肯定的,人类自然互动的方式是计算机最难理解的任务之一。对于计算机来说,一切都要和数字打交道,所以我们说的语言,我们形成的句子,我们在其中使用的词和我们的意思的相关背景都需要转换为数字。然后我们在这些数字表示上训练ML/DL模型来完成我们的任务。

image.png

词语的矢量表示

*因此,为了训练ML模型而对单词进行的数字表示被称为单词嵌入。*这些嵌入随后被用于各种NLP任务,如机器翻译、情感分析、文本分类和文本生成,仅举几例。存在许多词嵌入技术,如Word2Vec、Fasttext、BERT等。BERT(Bidirectional Encoder Representations from Transformers)是一个强大的语言模型,可用于为特定任务创建自定义的词嵌入。在这篇文章中,我将带你学习如何使用BERT创建自定义词嵌入,以及如何使用它们来寻找最近的词。

完整的代码脚本可以在我的Github账户中找到 从这里开始。

BERT和自定义词嵌入

BERT是由谷歌AI语言的研究人员在2018年开发的,是11种以上最常见的语言任务的解决方案,如情感分析和命名实体识别。BERT是一个经过预训练的语言模型,在大量的文本语料库中进行了训练,在自然语言处理任务中的表现优于许多其他最先进的模型。

BERT的一个好处是,它可以在特定的任务上进行微调,为该任务创建定制的嵌入。这是因为BERT是使用掩蔽的语言建模任务进行训练的,它学会了预测句子中的缺失词。通过在一个特定的任务上对BERT进行微调,我们可以创建为该任务量身定做的嵌入。

通过下面的代码,你可以在你的数据集上为手头的具体任务微调BERT。

使用TensorFlow和Hugging Face transformers库,我们可以很容易地加载一个预先训练好的BERT模型和标记器:

import tensorflow as tffrom transformers import BertTokenizer, TFBertModelbert_model = TFBertModel.from_pretrained('bert-base-uncased')tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

你也可以使用 "bert-base-uncased "来代替 "bert-large-uncased"。这是一个更大的Bert模型,有更多的参数,因此需要更多的时间和资源来训练。但预计会有一个更好的结果。

接下来,我们可以加载我们的文本数据并使用标记器对其进行编码:

with open('data.txt', 'r') as f:    text_data = f.readlines()encoded_data = tokenizer.batch_encode_plus(text_data, add_special_tokens=True, return_attention_mask=True, return_token_type_ids=False, pad_to_max_length=True)

然后我们可以将我们的输入数据转换为TensorFlow数据集:

dataset = tf.data.Dataset.from_tensor_slices(({'input_ids': encoded_data['input_ids'], 'attention_mask': encoded_data['attention_mask']}, np.zeros(len(encoded_data['input_ids']))))

为了创建我们的自定义词嵌入模型,我们可以使用BERT模型作为基础,并添加一个GlobalAveragePooling1D层来平均所有的时间步骤的输出:

from tensorflow.keras.layers import Input, GlobalAveragePooling1Dfrom tensorflow.keras.models import Modelinput_ids = Input(shape=(None,), dtype=tf.int32, name='input_ids')attention_mask = Input(shape=(None,), dtype=tf.int32, name='attention_mask')bert_output = bert_model({'input_ids': input_ids, 'attention_mask': attention_mask})[0]embedding_layer = GlobalAveragePooling1D()(bert_output)embedding_model = Model(inputs=[input_ids, attention_mask], outputs=embedding_layer)

然后,我们可以编译我们的模型并训练它:

from tensorflow.keras.callbacks import EarlyStoppingembedding_model.compile(optimizer=tf.optimizers.Adam(), loss=tf.losses.CosineSimilarity(), metrics=[tf.metrics.CosineSimilarity()])early_stopping = EarlyStopping(monitor='loss', patience=3, restore_best_weights=True)embedding_model.fit(dataset.batch(32), epochs=10, callbacks=[early_stopping])

我们还可以保存我们的训练模型:

embedding_model.save('embedding_model')

一旦我们训练了我们的自定义词嵌入模型,我们就可以用它来生成新词的嵌入,并找到嵌入空间中最近的词。我们使用scikit-learn库中的 "NearestNeighbors "类来演示。

首先,我们加载训练好的嵌入模型,并使用它为我们的词汇表中的每个词生成嵌入。我们将这些嵌入存储在一个叫做 "向量 "的列表中。

embedding_model = tf.keras.models.load_model('embedding_model')vocabulary = ['word1', 'word2', 'word3', 'word4', 'word5']vectors = []for word in vocabulary:    input_ids = tokenizer.encode(word, add_special_tokens=True, return_tensors='tf')    vector = embedding_model.predict({'input_ids': input_ids, 'attention_mask': tf.ones_like(input_ids)})[0]    vectors.append(vector)

接下来,我们创建一个NearestNeighbor对象,并将其与我们的嵌入匹配。我们将k ,以找到与我们的输入词最接近的单个词。

k = 1nn = NearestNeighbors(n_neighbors=k)nn.fit(vectors)

最后,我们使用我们训练好的模型为输入词生成一个嵌入,并在嵌入空间中找到最近的词。

input_word = 'word'input_vector = embedding_model.predict({'input_ids': tokenizer.encode(input_word, add_special_tokens=True, return_tensors='tf'), 'attention_mask': tf.ones((1, len(tokenizer.encode(input_word))))})[0]distances, indices = nn.kneighbors([input_vector])nearest_word = vocabulary[indices[0][0]]print(f'Nearest word to "{input_word}" is "{nearest_word}"')

这种方法在各种自然语言处理任务中都很有用,如信息检索和推荐系统。通过为单词生成嵌入并找到其最近的邻居,我们可以根据嵌入空间的相似性进行预测和推荐。

总之,使用BERT来训练自定义词嵌入可以成为自然语言处理中的一个强大工具。通过利用预训练的BERT模型,并在我们的特定数据上对其进行微调,我们可以生成捕捉我们语言的细微差别和复杂性的嵌入。此外,通过使用分布式策略和优化我们的代码以适应GPU的使用,我们可以加速训练过程并处理大型数据集。最后,通过使用嵌入来寻找最近的邻居,我们可以根据嵌入空间的相似性进行预测和推荐。