當前位置:
首頁 > 科技 > 「詞嵌入」在NLP中扮演什麼角色?一文搞懂Word Embeddings背後原理

「詞嵌入」在NLP中扮演什麼角色?一文搞懂Word Embeddings背後原理

原文來源:DATASCIENCE

作者:Ruslana Dalinina

「機器人圈」編譯:嗯~阿童木呀、多啦A亮

「機器人圈」正式更名為「雷克世界」,後台回復「雷克世界」查看更多詳情。

介紹

相信大家都清楚,自然語言處理(NLP)所涉及的廣闊領域使得我們能夠理解從在線評論到音頻錄製這樣大量語言數據的模式。但在數據科學家真正挖掘出一個NLP問題之前,他或她必須為此奠定基礎,從而幫助模型對即將遇到的不同語言單位有所了解。

詞嵌入(Word embeddings)是一組廣泛應用於預測NLP建模的特徵工程技術,特別是在深度學習應用中的使用更為顯著。詞嵌入是將詞的稀疏向量表示轉換為密集、連續的向量空間,使你能夠識別單詞和短語之間的相似性,而這一點很大程度上依賴於它們的語境。

在本文中,我將詳細闡述一下詞嵌入背後的原理,並演示如何使用這些技術對來自亞馬遜的500000份評論數據創建相似辭彙的集群。你可以下載數據集(https://www.kaggle.com/snap/amazon-fine-food-reviews)來進行追蹤。

詞嵌入:它們是如何運作的?

在典型的詞袋(bag-of-words)模型中,每個單詞都被認為是一個唯一的標記,與其他單詞毫無關聯。例如,即使「salt(鹽)」和「seasoning(調味料)」平時都是高頻地出現在相同的語境或是句子中,也將被分配一個唯一的ID。詞嵌入是一系列特徵工程技術,它將稀疏的詞向量映射到基於周圍語境的連續空間中。話句話說,你可以將此過程視為將高維向量詞表示嵌入到一個較低維的空間中。

而這樣的向量表示比較單詞或短語提供了便利屬性。例如,如果「salt」和「seasoning」出現在相同的語境中,那麼模型將表明「salt」在概念上更接近於「seasoning」,而不是「chair(椅子)」。

現如今有幾種用於構建詞嵌入表示的模型。谷歌的word2vec是最為廣泛使用的實現之一,而這主要得益於它的訓練速度和性能。Word2vec是一個預測模型,這意味著它並不是像LDA(latent Dirichlet allocation)那樣需要進行單詞計數,而是被訓練為從鄰近詞的語境中預測目標詞。該模型首先使用獨熱編碼(one-hot-encoding)對每個單詞進行編碼,然後使用權重矩陣將其饋送到隱藏層;該過程的輸出則是目標單詞。詞嵌入向量實際上是該擬合模型的權重。為了更好地進行說明,這裡有一個簡單的視覺圖:

實際上,Word2vec有兩種「風格」的詞嵌入模型:連續的詞袋(CBOW)和跳格式。CBOW實現會在目標單詞周圍出現一個滑動窗口,以便於做出預測。而另一方面,跳格式模型則是截然相反的——它會預測出給定目標單詞的語境周邊的單詞。有關跳格式模型的更多信息,請查閱此篇學術論文(https://arxiv.org/abs/1310.4546)。

入門

為什麼有那麼多人對詞嵌入如此感興趣呢?這主要是因為詞嵌入在深度學習的多種任務中有著非常廣泛的應用,如情緒分析、語法分析、命名稱識別等。除此之外,它們還可以用於:

?通過基於語境的保存單詞與單詞之間的相似性,提供一種更為複雜的方法來表示數字空間中的單詞。

?提供單詞或短語之間的相似度的衡量標準。

?用作分類任務中的特徵。

?提高模型性能。

使用詞嵌入可以發現許多有趣的關係,最著名的例子莫過於此了:king - man + woman = queen。所以,請繼續在Amazon Fine Foods評論數據集中進行詞嵌入操作吧!

可以先從越多語料庫開始,我將使用一個面向DataScience.com客戶的模塊,該模塊被稱之為「客戶手冊」,其中包含常見文本處理和建模任務的代碼,例如刪除或阻止不良字元。它也可以用於主題建模和意見挖掘任務。

# imports

%matplotlib inline

import os

import pandas as pd

import numpy

import matplotlib.pyplot as plt

import string

import re

from gensim import corpora

from gensim.models import Phrases

from nltk.corpus import stopwords

from ds_voc.text_processing import TextProcessing

# sample for speed

raw_df = raw_df.sample(frac=0.1, replace=False)

print raw_df.shape

# grab review text

raw = list(raw_df['Text'])

print len(raw)

先標註我們的樣本,並做一般的清理步驟:刪除不好的字元,過濾單詞和干擾:

# word2vec expexts a list of list: each document is a list of tokens

te = TextProcessing()

cleaned = [te.default_clean(d) for d in raw]

sentences = [te.stop_and_stem(c) for c in cleaned]

現在我們已經準備好適應一個模型了。這裡我們使用gensim實現:

from gensim.models import Word2Vec

model = Word2Vec(sentences=sentences, # tokenized senteces, list of list of strings

size=300, # size of embedding vectors

workers=4, # how many threads?

min_count=20, # minimum frequency per token, filtering rare words

sample=0.05, # weight of downsampling common words

sg = 0, # should we use skip-gram? if 0, then cbow

iter=5,

hs = 0

)

瞧!這很簡單。現在,你可以問這個模型有什麼問題?回想一下,在相似情景下發生的詞將被認為是相似的,從而形成「集群」。 從簡單的例子開始,通過檢查模型認為類似於「花生」的什麼樣的詞語:

print (model.most_similar('peanut'))

[(u'butter', 0.9887357950210571), (u'fruit', 0.9589880108833313), (u'crunchi', 0.9448184967041016), (u'potato', 0.9327490329742432), (u'textur', 0.9302218556404114), (u'nut', 0.9176014065742493), (u'tasti', 0.9175000190734863), (u'sweet', 0.9135239124298096), (u'appl', 0.9122942686080933), (u'soft', 0.9103059768676758)]

不錯,最相似的標記當然是「黃油」,其他的標記也很直觀。然而,「水果」和「蘋果」可能是客戶提到果醬和花生醬時擴展的結果。讓我們再舉幾個例子:

print (model.most_similar('coffee'))

print (model.most_similar('spice'))

請注意,即使「焦糖蘋果香料」是一個受歡迎的組合,但與「香料」最相似的詞語是「刷新」和「焦糖」。你可以擴展類比,不僅可以在上下文中包含多個詞,還可以排除某些詞。我對富含蛋白質的零食很感興趣,但我不想服用蛋白質補充劑:

print (model.most_similar(['snack', 'protein'], negative=['supplement']))

這是模型得出來的結果:

該模型發現,「薯條」,「酒吧」,「花生」,「堅果」和「健康」等辭彙與「零食」和「蛋白質」相同處在同一詞群中,但與「補充品」的詞群不同。

當然,這些都是簡單的例子,但別忘了我們在一個小樣本的評論中訓練了該模型。我建議你擴展數據集,以構建更強大的詞嵌入。

可視化詞向量

為了可視化所得到的單詞嵌入,我們可以使用降維技術t-SNE,它可以將所得到的嵌入向量投影到二維中:

# visualize food data

from sklearn.manifold import TSNE

tsne = TSNE(n_components=2)

X_tsne = tsne.fit_transform(X)

plt.rcParams['figure.figsize'] = [10, 10]

plt.scatter(X_tsne[:, 0], X_tsne[:, 1])

plt.show()

我們可以看到一些集群形成。我們來標記每一個點,看看所得到的集群。你還可以使用散景庫(bokeh library)https://bokeh.pydata.org/en/latest/進行互動式繪圖,以便進行縮放。

from bokeh.plotting import figure, show

from bokeh.io import push_notebook, output_notebook

from bokeh.models import ColumnDataSource, LabelSet

def interactive_tsne(text_labels, tsne_array):

'''makes an interactive scatter plot with text labels for each point'''

# define a dataframe to be used by bokeh context

bokeh_df = pd.DataFrame(tsne_array, text_labels, columns=['x','y'])

bokeh_df['text_labels'] = bokeh_df.index

# interactive controls to include to the plot

TOOLS="hover, zoom_in, zoom_out, box_zoom, undo, redo, reset, box_select"

p = figure(tools=TOOLS, plot_width=700, plot_height=700)

# define data source for the plot

source = ColumnDataSource(bokeh_df)

# scatter plot

p.scatter('x', 'y', source=source, fill_alpha=0.6,

fill_color="#8724B5",

line_color=None)

# text labels

labels = LabelSet(x='x', y='y', text='text_labels', y_offset=8,

text_font_size="8pt", text_color="#555555",

source=source, text_align='center')

p.add_layout(labels)

# show plot inline

output_notebook()

show(p)

其中一些更具直觀的意義,如左下角包含decaf,bean和french的集群:

附加提示

我們還可以通過在模型中添加二進位和/或部分語音標籤來改進詞嵌入。在同一個單詞可能具有多重含義的情況下,詞性標註可能很有用。例如,seasoning可以是名詞也可以是動詞,並且根據詞性的不同而具有不同的含義。

sent_w_pos = [nltk.pos_tag(d) for d in sentences]

sents = [[tup[0]+tup[1] for tup in d] for d in sent_w_pos]

model_pos = Word2Vec(sentences=sents,

size=300,

workers=4,

min_count=20,

sample=0.05,

sg = 0,

hs=0,

iter=5

)

我們還可以在我們的模型中添加二進位對象,以便將頻繁的單詞對分組:

bigrams = Phrases(sentences)

model = Word2Vec(sentences=bigrams[sentences],

size=300,

workers=4,

min_count=20,

sample=0.05,

sg = 0,

iter=5,

hs = 0

)

結論

現在,你對詞嵌入有了一些基本的了解,並可以使用gensim中的word2vec生成向量。這個有用的技術應該在你的NLP工具箱中,因為它可以在各種建模任務中派上用場。欲了解更多信息,請看DataScience.com平台的演示,查看我們的客戶手冊,如客戶手冊的語音和建模資源。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 雷克世界 的精彩文章:

他是吳恩達導師,被馬雲聘為「達摩院」首座
DeepMind最新論文提出「Rainbow」,將深度強化學習組合改進

TAG:雷克世界 |