Word Embedding的几种模型和示例

介绍

人类有能力理解单词并轻松地从中获取含义。然而,在当今世界,大多数任务都是由计算机执行的。例如,如果您想知道今天是晴天还是下雨天,则必须在 Google 中输入文本查询。现在的问题是,机器将如何频繁地理解和处理文本中呈现的如此大量的信息?答案是词嵌入。

Word Embeddings 基本上是向量(文本转换为数字),用于捕获单词的含义、各种上下文和语义关系。嵌入本质上是使用预定义字典将单词映射到其对应向量。

例如,

句子: It will rain heavily today.

字典:{“it”:[1,0,0,0,0],“will”:[0,1,0,0,0],“rain”:[0,0,1,0,0] , “ heavily ”: [0,0,0,1,0], “today”: [0,0,0,0,1]}

在这里,每个单词都被分配了一个唯一的向量(例如),以便区分所有单词。

Let the corpus comprise three sentences.

S1 = In monsoon, it will rain.

S2 = rain rain come again.

S3 = sun is visible in summer. In the monsoon, the sun is hidden by clouds.

Let N be the list of unique words = [‘monsoon’, ‘rain’, ‘come’, ‘again’, ‘sun’, ‘visible’, ‘summer’, ‘hidden’, ‘clouds’]

计数矩阵的维度将是 3X9,因为语料库中有 3 个文档和 9 个唯一词。
计数矩阵如下所示:

优点:由于只考虑单词的频率,因此计算成本较低。


缺点:由于计算只是基于计数并且没有考虑单词的上下文,因此该方法证明不太有用。
代码:

#Importing libraries
from sklearn.feature_extraction.text import CountVectorizer
import nltk 
from nltk.corpus import stopwords 
from nltk.tokenize import word_tokenize 

#Downloading stopwords and punkt packages
nltk.download('stopwords') 
nltk.download('punkt') 

#Initialising stopwords for english
set(stopwords.words('english')) 

#sample sentences
text = ["In monsoon, it will rain", "rain rain come again", "sun is visible in summer. In the monsoon, the sun is hidden by clouds"]

#set of stop words
stop_words = set(stopwords.words('english')) 
all_sentences = []

#Logic for removing stop words and obtaining filtered sentences from the list 

for i in range(len(text)):
  word_tokens[i] = word_tokenize(text[i]) 
  tokenized_sentence = []

  for j in word_tokens[i]: 
      if j not in stop_words: 
          tokenized_sentence.append(j) 
  all_sentences.append(" ".join(tokenized_sentence))

#Initialising the CountVectorizer
countvectorizer = CountVectorizer()

#Applying CountVectorizer to the list of sentences
X = countvectorizer.fit_transform(all_sentences)

#Converting output to array
result = X.toarray()

print("Sentences after removing stop words", all_sentences)
print("Count Vector:", result)

2.TF-IDF:

TF-IDF 代表词频-逆文档频率。 该方法是对 Count Vector 方法的即兴创作,因为特定单词的频率被考虑在整个语料库中,而不仅仅是单个文档。 主要思想是对某些文档非常具体的词给予更多的权重,而对更普遍且在大多数文档中出现的词给予较少的权重。

例如,诸如“is”、“the”、“and”之类的通用词会经常出现,而诸如“Donald Trump”或“Indira Gandhi”之类的词将特定于特定文档。

数学上,

词频 (TF) = 词条在文档中出现的次数 / 文档中词条的总数

逆文档频率 (IDF) = log(N/n) 其中 N 是文档总数,n 是一个术语出现的文档数。

考虑以下示例。
给出了两个文档——D1 和 D2。

TF(Today, Document 1) = 1/8

TF(Today, Document 2) = 1/8

TF(sunny, Document 1) = 4/8

IDF(Today) = log(2/2) = log(1) = 0

IDF(sunny) = log(2/1) = log(2) = 0.301

Therefore,

TF-IDF(Today, Document 1) = 1/8 * 0 = 0

TF-IDF(Today, Document 2) = 1/8 * 0 = 0

TF-IDF(sunny, Document 1) = 4/8 * 0.301 = 0.1505

从上面的计算可以看出,与文档 1 的上下文中的重要词“sunny”相比,常用词“Today”的权重较低。

优点:

它在计算上很容易。
文档中最重要的单词是通过基本计算提取的,不需要太多努力。

缺点:

它无法捕捉单词的语义,只能像词汇级别的特征一样工作。
代码:

from sklearn.feature_extraction.text import TfidfVectorizer 
import pandas as pd

#Declaring the list of sentences
documents = ['Today is sunny day', 'Today is rainy day']

#Initialising Tfidf Vectorizer
vectorizer = TfidfVectorizer()

#Fitting the Vectorizer to the list
X = vectorizer.fit_transform(documents)
print(X)

#Printing the feature names
print(vectorizer.get_feature_names()) 

matrix = X.todense()
tfidf_list = matrix.tolist()
tfidf_df = pd.DataFrame(tfidf_list, columns = vectorizer.get_feature_names())

print(tfidf_df)

3.Word2Vec:

Word2Vec 是一种基于预测的词嵌入方法。 与确定性方法不同,它是一个浅层的两层神经网络,能够预测单词之间的语义和相似性。 Word2Vec 是两种不同模型的组合——(i)CBOW(连续词袋)和(ii)Skip-gram。

模型概述 – CBOW(连续词袋)和 Skip-gram。

word_2_vec

3.1 CBOW(连续词袋):

该模型是一个浅层神经网络,可以在给定上下文的情况下预测单词的概率。 这里,上下文是指围绕要预测的单词的单词的输入。
CBOW模型的架构:

Architecture of CBOW model

作为第一步,输入是通过为给定文本形成一个词袋来创建的。
例如,

Sentence 1 = All work and no play make Jack a dull boy.

Sentence 2 = Jack and Jill went up the hill.

Bag of Words: {“All”:1, “work”:1, “no”:1, “play”:1, “makes”:1, “Jack”:2, “dull”:1, “boy”:1, “Jill”:1, “went”:1, “up”:1, “hill”:1} (after removing the stop words)

这个由单词及其出现频率组成的输入作为向量发送到输入层。对于 X 个单词,输入将是 X[1XV] 个向量,其中 V 是向量的最大长度。

接下来,输入隐藏层矩阵由维数 VXN 组成,其中 N 是表示单词的维数。输出隐藏层矩阵由维数 NXV 组成。在这里,这些值是通过将输入乘以隐藏输入权重来计算的。

在输出层,通过将隐藏输入乘以隐藏输出权重来计算输出。在隐藏层和输出层之间计算的权重给出了单词的表示。作为一个连续的中间步骤,通过对输出和目标值之间计算的误差使用反向传播来调整权重。
优点:

与确定性方法相比,概率性方法给出了更好的结果。
由于不需要计算巨大的矩阵,因此内存需求较少。
缺点:

优化非常重要,否则培训将需要很长时间才能完成。


3.2 Skip-gram :

Skip-gram 模型预测给定单词的上下文,与 CBOW 所做的正好相反。 Skip-gram 模型的架构:

Architecture of Skip-gram model:

输入层大小:[1XV],输入隐藏权重矩阵大小:[VXN],输出隐藏权重矩阵:[NXV],输出层大小:C[1XV]

模型的输入和直到隐藏层的进一步步骤将类似于 CBOW。 输出目标变量的数量取决于上下文窗口的大小。 例如,如果上下文窗口的大小为 2,那么将有四个目标变量,两个词在给定词之前,两个词在给定词之后。

将针对四个目标变量计算四个单独的误差,并通过执行元素相加获得最终向量。 然后反向传播这个最终向量以更新权重。 对于训练,输入和隐藏层之间的权重用于单词表示。

优点:

Skip-gram 模型可以捕获单词的不同上下文信息,因为每个上下文都有不同的向量表示。
对于不常用的术语更准确,并且适用于更大的数据库。
缺点:

它需要更多的 内存 进行处理。
代码:

要使用 genism 库中预训练的 Word2Vec 模型:

import gensim 
import gensim.downloader as api
from gensim.models.keyedvectors import KeyedVectors

#loading pretrained model
nlp_w2v = api.load("word2vec-google-news-300") 

#save the Word2Vec model
nlp_w2v.wv.save_word2vec_format('model.bin', binary=True)

#load the Word2Vec model 
model = KeyedVectors.load_word2vec_format('model.bin', binary=True)

#Printing the most similar words to New York from vocabulary of pretrained model
model.most_similar('New_York')

从头开始训练 Word2Vec 模型:

import gensim 
'''
Data for training Word2Vec
train: A data frame comprising of text samples
'''

#training data
corpus = train

#creates a list for a list of words for every training sample
w2v_corpus = []
for document in corpus:
   w2v_words = document.split()
   w2v_grams = [" ".join(w2v_words[i:i+1]) 
               for i in range(0, len(w2v_words), 1)]
   w2v_corpus.append(w2v_grams)

#initialising and training the custom Word2Vec model 
'''
size: dimensions of word embeddings 
window: context window for words 
min_count: words which appear less number of times than this count will be ignored 
sg: To choose skip-gram model 
iter: Number of epochs for training
'''

word2vec_model = gensim.models.word2vec.Word2Vec(w2v_corpus, size=300,   
            window=8, min_count=1, sg=1, iter=30)

#vector size of the model
print(word2vec_model.vector_size)

#vocabulary contained by the model
print(len(word2vec_model.wv.vocab))

4.GloVE:

GloVe 代表词表示的全局向量。 该算法是对 Word2Vec 方法的改进,因为它考虑全局统计而不是局部统计。 在这里,全局统计数据意味着从整个语料库中考虑的单词。 GloVe 基本上试图解释特定单词对在文档中出现的频率。 为此,构建了一个共现矩阵,该矩阵将表示特定单词相对于另一个单词的存在。

例如,

Corpus – It is rainy today, tomorrow it will be sunny and the day after will be windy.

上面的矩阵表示一个共现矩阵,其值表示在给定示例语料库中一起出现的每对单词的计数。

在计算给定“today”、p(rainy/today) 和给定“tomorrow”、p(rainy/tomorrow) 的单词“rainy”的出现概率后,结果是与“rainy”最相关的单词 与“明天”相比,“今天”是“今天”。

代码:

#Import statements
from numpy import array
from numpy import asarray
from numpy import zeros
from keras.preprocessing.text import Tokenizer 

#Download the pretrained GloVe data files
!wget http://nlp.stanford.edu/data/glove.6B.zip

#Unzipping the zipped folder
!unzip glove*.zip

#Initialising a tokenizer and fitting it on the training dataset
'''
train: a dataframe comprising of rows containing text data
'''
tokenizer = Tokenizer(num_words=5000)
tokenizer.fit_on_texts(train)

#Creating a dictionary to store the embeddings
embeddings_dictionary = dict()

#Opening GloVe file
glove_file = open('glove.6B.50d.txt', encoding="utf8")

#Filling the dictionary of embeddings by reading data from the GloVe file
for line in glove_file:
    records = line.split()
    word = records[0]
    vector_dimensions = asarray(records[1:], dtype='float32')
    embeddings_dictionary[word] = vector_dimensions
glove_file.close()

#Parsing through all the words in the input dataset and fetching their corresponding vectors from the dictionary and storing them in a matrix 
embedding_matrix = zeros((vocab_size, 50))
for word, index in tokenizer.word_index.items():
    embedding_vector = embeddings_dictionary.get(word)
    if embedding_vector is not None:
        embedding_matrix[index] = embedding_vector

#Displaying embedding matrix 
print(embedding_matrix) 

结论:

在这篇博客中,我们回顾了一些方法——Count Vector、TF-IDF、Word2Vec 和 GloVe,用于从原始文本数据创建词嵌入。 预处理文本然后发送预处理数据以创建词嵌入总是一个好习惯。 作为进一步的步骤,这些词嵌入可以发送到机器学习或深度学习模型,用于各种任务,例如文本分类或机器翻译。

关注公众号“大模型全栈程序员”回复“小程序”获取1000个小程序打包源码。更多免费资源在http://www.gitweixin.com/?p=2627

发表评论

邮箱地址不会被公开。 必填项已用*标注