作者 |ARAVIND PAI
编译 |VK
起源 |Analytics Vidhya
概述
- 了解预训练词嵌入的重要性
- 理解两种风行的预训练词嵌入类型:Word2Vec 和 GloVe
- 预训练词嵌入与从头学习嵌入的性能比拟
介绍
咱们如何让机器了解文本数据?咱们晓得机器十分善于解决和解决数字数据,但如果咱们向它们提供原始文本数据,它们是不能了解的。
这个想法是创立一个词汇的示意,捕获它们的含意、语义关系和它们所应用的不同类型的上下文。这就是词嵌入的想法,将文本用数字示意。
预训练词嵌入是当今自然语言解决(NLP)畛域中的一个重要组成部分。
然而,问题依然存在——预训练的单词嵌入是否为咱们的 NLP 模型提供了额定的劣势?这是一个重要的问题,你应该晓得答案。
因而在本文中,我将说明预训练词嵌入的重要性。对于一个情感剖析问题,咱们还将比拟预训练词嵌入和从头学习嵌入的性能。
目录
- 什么是预训练词嵌入?
- 为什么咱们须要预训练的词嵌入?
-
预训练词嵌入的不同模型?
- 谷歌的 Word2vec
- 斯坦福的 GloVe
- 案例钻研:从头开始学习嵌入与预训练词嵌入
什么是预训练词嵌入?
让咱们间接答复一个大问题——预训练词嵌入到底是什么?
预训练词嵌入是在一个工作中学习到的词嵌入,它能够用于解决另一个工作。
这些嵌入在大型数据集上进行训练,保留,而后用于解决其余工作。这就是为什么预训练词嵌入是迁徙学习的一种模式。
迁徙学习,顾名思义,就是把一项工作的学习成绩转移到另一项工作上。学习既能够是权重,也能够是嵌入。在咱们这里,学习的是嵌入。因而,这个概念被称为预训练词嵌入。在权重的状况下,这个概念被称为预训练模型。
然而,为什么咱们首先须要预训练词嵌入呢?为什么咱们不能从零开始学习咱们本人的嵌入呢?我将在下一节答复这些问题。
为什么咱们须要预训练词嵌入?
预训练词嵌入在大数据集上训练时捕捉单词的语义和句法意义。它们可能进步自然语言解决(NLP)模型的性能。这些单词嵌入在比赛数据中很有用,当然,在事实世界的问题中也很有用。
然而为什么咱们不学习咱们本人的嵌入呢?好吧,从零开始学习单词嵌入是一个具备挑战性的问题,次要有两个起因:
- 训练数据稠密
- 大量可训练参数
训练数据稠密
不这样做的次要起因之一是训练数据稀少。大多数事实世界的问题都蕴含一个蕴含大量罕见单词的数据集。从这些数据集中学习到的嵌入无奈失去单词的正确示意。
为了实现这一点,数据集必须蕴含丰盛的词汇表。
大量可训练参数
其次,从零开始学习嵌入时,可训练参数的数量减少。这会导致训练过程变慢。从零开始学习嵌入也可能会使你对单词的示意形式处于不分明的状态。
因而,解决上述问题的办法是预训练词嵌入。让咱们在下一节探讨不同的预训练词嵌入。
预训练词嵌入的不同模型
我将把嵌入大抵分为两类:单词级嵌入和字符级嵌入。ELMo 和 Flair 嵌入是字符级嵌入的示例。在本文中,咱们将介绍两种风行的单词级预训练词嵌入:
- 谷歌的 Word2vec
- 斯坦福的 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 向量输出到模型中:
斯坦福的 GloVe
GloVe 嵌入的根本思维是从全局统计中导出单词之间的关系。
然而,统计数字怎么能代表意义呢?让我解释一下。
最简略的办法之一是看共现矩阵。共现矩阵通知咱们一对特定的词在一起呈现的频率。共现矩阵中的每个值都是一对词同时呈现的计数。
例如,思考一个语料库:“play cricket, I love cricket and I love football”。语料库的共现矩阵如下所示:
当初,咱们能够很容易地计算出一对词的概率。为了简略起见,让咱们把重点放在“cricket”这个词上:
p(cricket/play)=1
p(cricket/love)=0.5
接下来,咱们计算概率比:
p(cricket/play) / p(cricket/love) = 2
当比率大于 1 时,咱们能够推断板球最相干的词是“play”,而不是“love”。同样,如果比率靠近 1,那么这两个词都与板球无关。
咱们能够用简略的统计办法得出这些词之间的关系。这就是 GLoVE 预训练词嵌入的想法。
案例钻研:从头开始学习嵌入与预训练词嵌入
让咱们通过一个案例来比拟从头开始学习咱们本人的嵌入和预训练词嵌入的性能。咱们还将理解应用预训练词嵌入是否会进步 NLP 模型的性能?
所以,让咱们抉择一个文本分类问题 - 电影评论的情感剖析。从这里下载电影评论数据集 (https://www.kaggle.com/columb…。
将数据集加载到 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.h5', monitor='val_acc', mode='max', save_best_only=True,verbose=1)
#输入模型
print(model.summary())
输入:
模型中可训练参数总数为 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.h5')
#评估
_,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.h5', monitor='val_acc', mode='max', save_best_only=True,verbose=1)
#输入模型
print(model.summary())
输入:
如你所见,可训练参数的数量仅为 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.h5')
#评估
_,val_acc = model.evaluate(x_val_seq,y_val, batch_size=128)
print(val_acc)
输入:88.49
与从头学习嵌入相比,应用预训练词嵌入的性能有所提高。
结尾
预训练词嵌入是无力的文本示意形式,因为它们往往捕获单词的语义和句法意义。
在本文中,咱们理解了预训练词嵌入的重要,并探讨了两种风行的预训练词嵌入:Word2Vec 和 gloVe。
原文链接:https://www.analyticsvidhya.c…
欢送关注磐创 AI 博客站:
http://panchuang.net/
sklearn 机器学习中文官网文档:
http://sklearn123.com/
欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/