温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

python怎么实现预训练词嵌入

发布时间:2021-12-27 13:42:25 来源:亿速云 阅读:188 作者:iii 栏目:大数据

这篇文章主要讲解了“python怎么实现预训练词嵌入”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“python怎么实现预训练词嵌入”吧!

什么是预训练词嵌入?

让我们直接回答一个大问题——预训练词嵌入到底是什么?

预训练词嵌入是在一个任务中学习到的词嵌入,它可以用于解决另一个任务。

这些嵌入在大型数据集上进行训练,保存,然后用于解决其他任务。这就是为什么预训练词嵌入是迁移学习的一种形式。

python怎么实现预训练词嵌入

迁移学习,顾名思义,就是把一项任务的学习成果转移到另一项任务上。学习既可以是权重,也可以是嵌入。在我们这里,学习的是嵌入。因此,这个概念被称为预训练词嵌入。在权重的情况下,这个概念被称为预训练模型。

但是,为什么我们首先需要预训练词嵌入呢?为什么我们不能从零开始学习我们自己的嵌入呢?我将在下一节回答这些问题。

为什么我们需要预训练词嵌入?

预训练词嵌入在大数据集上训练时捕获单词的语义和句法意义。它们能够提高自然语言处理(NLP)模型的性能。这些单词嵌入在竞赛数据中很有用,当然,在现实世界的问题中也很有用。

但是为什么我们不学习我们自己的嵌入呢?好吧,从零开始学习单词嵌入是一个具有挑战性的问题,主要有两个原因:

  • 训练数据稀疏

  • 大量可训练参数

训练数据稀疏

不这样做的主要原因之一是训练数据稀少。大多数现实世界的问题都包含一个包含大量稀有单词的数据集。从这些数据集中学习到的嵌入无法得到单词的正确表示。

为了实现这一点,数据集必须包含丰富的词汇表。

大量可训练参数

其次,从零开始学习嵌入时,可训练参数的数量增加。这会导致训练过程变慢。从零开始学习嵌入也可能会使你对单词的表示方式处于不清楚的状态。

因此,解决上述问题的方法是预训练词嵌入。让我们在下一节讨论不同的预训练词嵌入。

预训练词嵌入的不同模型

我将把嵌入大致分为两类:单词级嵌入和字符级嵌入。ELMo和Flair嵌入是字符级嵌入的示例。在本文中,我们将介绍两种流行的单词级预训练词嵌入:

  1. 谷歌的Word2vec

  2. 斯坦福的GloVe

让我们了解一下Word2Vec和GloVe的工作原理。

谷歌的Word2vec

Word2Vec是Google开发的最流行的预训练词嵌入工具之一。Word2Vec是在Google新闻数据集(约1000亿字)上训练的。它有几个用例,如推荐引擎、单词相似度和不同的文本分类问题。

Word2Vec的架构非常简单。它是一个只有一个隐藏层的前馈神经网络。因此,它有时被称为浅层神经网络结构。

根据嵌入的学习方式,Word2Vec分为两种方法:

  • 连续词袋模型(CBOW)

  • Skip-gram 模型

连续词袋(CBOW)模型在给定相邻词的情况下学习焦点词,而Skip-gram模型在给定词的情况下学习相邻词。

连续词袋模型模型和Skip-gram 模型是相互颠倒的。

例如,想想这句话:““I have failed at times but I never stopped trying”。假设我们想学习“failed”这个词的嵌入。所以,这里的焦点词是“failed”。

第一步是定义上下文窗口。上下文窗口是指出现在焦点词左右的单词数。出现在上下文窗口中的单词称为相邻单词(或上下文)。让我们将上下文窗口固定为2

  • 连续词袋模型:Input=[I,have,at,times],Output=failed

  • Skip-gram 模型跳:Input = failed, Output = [I, have, at, times ]

如你所见,CBOW接受多个单词作为输入,并生成一个单词作为输出,而Skip gram接受一个单词作为输入,并生成多个单词作为输出。

因此,让我们根据输入和输出定义体系结构。但请记住,每个单词作为一个one-hot向量输入到模型中:

python怎么实现预训练词嵌入

斯坦福的GloVe

GloVe嵌入的基本思想是从全局统计中导出单词之间的关系。

但是,统计数字怎么能代表意义呢?让我解释一下。

最简单的方法之一是看共现矩阵。共现矩阵告诉我们一对特定的词在一起出现的频率。共现矩阵中的每个值都是一对词同时出现的计数。

例如,考虑一个语料库:“play cricket, I love cricket and I love football”。语料库的共现矩阵如下所示:

python怎么实现预训练词嵌入

现在,我们可以很容易地计算出一对词的概率。为了简单起见,让我们把重点放在“cricket”这个词上:

p(cricket/play)=1

p(cricket/love)=0.5

接下来,我们计算概率比:

p(cricket/play) / p(cricket/love) = 2

当比率大于1时,我们可以推断板球最相关的词是“play”,而不是“love”。同样,如果比率接近1,那么这两个词都与板球有关。

我们可以用简单的统计方法得出这些词之间的关系。这就是GLoVE预训练词嵌入的想法。

python怎么实现预训练词嵌入

案例研究:从头开始学习嵌入与预训练词嵌入

让我们通过一个案例来比较从头开始学习我们自己的嵌入和预训练词嵌入的性能。我们还将了解使用预训练词嵌入是否会提高NLP模型的性能?

所以,让我们选择一个文本分类问题-电影评论的情感分析。

将数据集加载到Jupyter:

#导入库
import pandas as pd
import numpy as np

#读取csv文件
train = pd.read_csv('Train.csv')
valid = pd.read_csv('Valid.csv')             

#训练测试集分离
x_tr, y_tr = train['text'].values, train['label'].values
x_val, y_val = valid['text'].values, valid['label'].values

准备数据:

from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences

tokenizer = Tokenizer()

#准备词汇表
tokenizer.fit_on_texts(list(x_tr))

#将文本转换为整数序列
x_tr_seq  = tokenizer.texts_to_sequences(x_tr) 
x_val_seq = tokenizer.texts_to_sequences(x_val)

#填充以准备相同长度的序列
x_tr_seq  = pad_sequences(x_tr_seq, maxlen=100)
x_val_seq = pad_sequences(x_val_seq, maxlen=100)

让我们看一下训练数据中的单词个数:

size_of_vocabulary=len(tokenizer.word_index) + 1 #+1用于填充
print(size_of_vocabulary)

Output: 112204

我们将构建两个相同架构的不同NLP模型。第一个模型从零开始学习嵌入,第二个模型使用预训练词嵌入。

定义架构从零开始学习嵌入:

#深度学习库
from keras.models import *
from keras.layers import *
from keras.callbacks import *

model=Sequential()

#嵌入层
model.add(Embedding(size_of_vocabulary,300,input_length=100,trainable=True)) 

#lstm层
model.add(LSTM(128,return_sequences=True,dropout=0.2))

#Global Max池化
model.add(GlobalMaxPooling1D())

#Dense层
model.add(Dense(64,activation='relu')) 
model.add(Dense(1,activation='sigmoid')) 

#添加损失函数、度量、优化器
model.compile(optimizer='adam', loss='binary_crossentropy',metrics=["acc"]) 

#添加回调
es = EarlyStopping(monitor='val_loss', mode='min', verbose=1,patience=3)  
mc=ModelCheckpoint('best_model.h6', monitor='val_acc', mode='max', save_best_only=True,verbose=1)  

#输出模型
print(model.summary())

输出:

python怎么实现预训练词嵌入

模型中可训练参数总数为33889169。其中,嵌入层贡献了33661200个参数。参数太多了!

训练模型:

history = model.fit(np.array(x_tr_seq),np.array(y_tr),batch_size=128,epochs=10,validation_data=(np.array(x_val_seq),np.array(y_val)),verbose=1,callbacks=[es,mc])

评估模型的性能:

#加载最佳模型
from keras.models import load_model
model = load_model('best_model.h6')

#评估
_,val_acc = model.evaluate(x_val_seq,y_val, batch_size=128)
print(val_acc)

输出:0.865

现在,是时候用GLoVE预训练的词嵌入来构建第二版了。让我们把GLoVE嵌入到我们的环境中:

# 将整个嵌入加载到内存中
embeddings_index = dict()
f = open('../input/glove6b/glove.6B.300d.txt')

for line in f:
    values = line.split()
    word = values[0]
    coefs = np.asarray(values[1:], dtype='float32')
    embeddings_index[word] = coefs

f.close()
print('Loaded %s word vectors.' % len(embeddings_index))

输出:Loaded 400,000 word vectors.

通过为词汇表分配预训练的词嵌入,创建嵌入矩阵:

# 为文档中的单词创建权重矩阵
embedding_matrix = np.zeros((size_of_vocabulary, 300))

for word, i in tokenizer.word_index.items():
    embedding_vector = embeddings_index.get(word)
    if embedding_vector is not None:
        embedding_matrix[i] = embedding_vector

定义架构-预训练嵌入:

model=Sequential()

#嵌入层
model.add(Embedding(size_of_vocabulary,300,weights=[embedding_matrix],input_length=100,trainable=False)) 

#lstm层
model.add(LSTM(128,return_sequences=True,dropout=0.2))

#Global Max池化
model.add(GlobalMaxPooling1D())

#Dense层
model.add(Dense(64,activation='relu')) 
model.add(Dense(1,activation='sigmoid')) 

#添加损失函数、度量、优化器
model.compile(optimizer='adam', loss='binary_crossentropy',metrics=["acc"]) 

#添加回调
es = EarlyStopping(monitor='val_loss', mode='min', verbose=1,patience=3)  
mc=ModelCheckpoint('best_model.h6', monitor='val_acc', mode='max', save_best_only=True,verbose=1)  

#输出模型
print(model.summary())

输出:

python怎么实现预训练词嵌入

如你所见,可训练参数的数量仅为227969。与嵌入层相比,这是一个巨大的下降。

训练模型:

history = model.fit(np.array(x_tr_seq),np.array(y_tr),batch_size=128,epochs=10,validation_data=(np.array(x_val_seq),np.array(y_val)),verbose=1,callbacks=[es,mc])

评估模型的性能:

#加载最佳模型
from keras.models import load_model
model = load_model('best_model.h6')

#评估
_,val_acc = model.evaluate(x_val_seq,y_val, batch_size=128)
print(val_acc)

输出:88.49

与从头学习嵌入相比,使用预训练词嵌入的性能有所提高。

感谢各位的阅读,以上就是“python怎么实现预训练词嵌入”的内容了,经过本文的学习后,相信大家对python怎么实现预训练词嵌入这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI