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

332 阅读4分钟

可以肯定的是,人类之间自然互动的方式是计算机最难理解的任务之一。对于计算机来说,一切都是和数字打交道,所以我们说的语言,造的句子,用的词,所指的相关上下文,都需要转换成数字。然后我们在这些数值表示上训练 ML/DL 模型来完成我们的任务。

image.png

词的向量表示

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

BERT 和自定义词嵌入

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

BERT 的好处之一是它可以针对特定任务进行微调,从而为该任务创建自定义嵌入。这是因为 BERT 使用掩码语言建模任务进行训练,它学习预测句子中缺失的单词。通过针对特定任务微调 BERT,我们可以创建适合该任务的嵌入。

通过以下代码,您可以针对手头的特定任务在数据集上微调 bert。

使用 TensorFlow 和 Hugging Face 转换器库,我们可以轻松加载预训练的 BERT 模型和分词器:

将tensorflow作为tf
从transformers导入BertTokenizer, TFBertModel 

bert_model = TFBertModel.from_pretrained( 'bert-base-uncased' ) 
tokenizer = BertTokenizer.from_pretrained( 'bert-base-uncased' )

您还可以使用“bert-large-uncased”代替“bert-base-uncased”。它是一个更大的 Bert 模型,具有更多的参数,因此需要更多的时间和资源来训练。但预计会给出更好的结果。

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

打开 (' data.txt '' r ' )作为f :text_data =     f.readlines () _

然后我们可以将输入数据转换为 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, GlobalAveragePooling1D 
from tensorflow.keras.models import Model 

input_ids = Input(shape=( None ,), dtype=tf.int32, name= 'input_ids' ) 
attention_mask = Input(shape=(无, ), 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)

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

从tensorflow.keras.callbacks导入EarlyStopping

嵌入模型。编译(optimizer=tf.optimizers.Adam(), loss=tf.losses.CosineSimilarity(), metrics=[tf.metrics.CosineSimilarity()]) 

early_stopping = EarlyStopping(monitor= 'loss' , patience= 3 , restore_best_weights=真) 
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) 

# 如下面的代码所示,我们可以使用“nn.kneighbor” 
# 找到最近的单词

接下来,我们创建一个 NearestNeighbor 对象并将其拟合到我们的嵌入中。我们设置k为 1 以查找与我们的输入词最接近的单个词。

# 构建最近邻模型
k = 1 
nn = 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} " 是 " {nearest_word} "' )

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

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