1. 程式人生 > >「詞嵌入」在自然語言處理中扮演什麼角色?一文搞懂Word Embeddings的背後原理

「詞嵌入」在自然語言處理中扮演什麼角色?一文搞懂Word Embeddings的背後原理

0?wx_fmt=gif&wxfrom=5&wx_lazy=1

640?wx_fmt=png&wxfrom=5&wx_lazy=1

原文來源:DATASCIENCE

作者:Ruslana Dalinina

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

「機器人圈」正式更名為「雷克世界」,後臺回覆「雷克世界」檢視更多詳情。

0?wx_fmt=png介紹

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

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

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

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

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

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

0?wx_fmt=png

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

https://arxiv.org/abs/1310.4546)。

入門

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

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

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

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

•提高模型效能。

可以先從越多語料庫開始,我將使用一個面向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 nltk.stem.porter import PorterStemmer

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

        )

X = model[model.wv.vocab]

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

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'))

[(u'k', 0.8691866397857666), (u'starbuck', 0.862629771232605), (u'keurig', 0.85813969373703), (u'decaf', 0.8456668853759766), (u'blend', 0.840221643447876), (u'bold', 0.8374124765396118), (u'cup', 0.8330360651016235), (u'brew', 0.8262926340103149), (u'espresso', 0.8225802183151245), (u'roast', 0.812541127204895)]

print (model.most_similar('spice'))

[(u'refresh', 0.9925233721733093), (u'caramel', 0.9756978750228882), (u'pepper', 0.9739495515823364), (u'cherri', 0.9737452268600464), (u'slightli', 0.9729464054107666), (u'cinnamon', 0.9727376699447632), (u'lemon', 0.9724155068397522), (u'blueberri', 0.9717040061950684), (u'sour', 0.971449613571167), (u'cocoa', 0.9712052345275879)]

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

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

這是模型得出來的結果:

[(u'chip', 0.7655218839645386), (u'bar', 0.7496042251586914), (u'potato', 0.7473998069763184), (u'peanut', 0.741823136806488), (u'feel', 0.7318717241287231), (u'cereal', 0.7217452526092529), (u'nut', 0.716484546661377), (u'butter', 0.7104200124740601), (u'healthi', 0.7084594964981079), (u'low', 0.7055443525314331)]

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

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

視覺化詞向量

為了視覺化所得到的單詞嵌入,我們可以使用降維技術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()

0?wx_fmt=png

我們可以看到一些叢集形成。我們來標記每一個點,看看所得到的叢集。你還可以使用散景庫(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的叢集:

0?wx_fmt=png

附加提示

我們還可以通過在模型中新增二進位制和/或部分語音標籤來改進詞嵌入。在同一個單詞可能具有多重含義的情況下,詞性標註可能很有用。例如,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

        )

X = model_pos[model_pos.wv.vocab]

我們還可以在我們的模型中新增二進位制物件,以便將頻繁的單詞對分組:

bigrams = Phrases(sentences)

model = Word2Vec(sentences=bigrams[sentences],

                 size=300,

                 workers=4,

                 min_count=20,

                 sample=0.05,

                 sg = 0,

                 iter=5,

                 hs = 0

        )

X = model[model.wv.vocab]

結論

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

回覆「轉載」獲得授權,微信搜尋「ROBO_AI」關注公眾號

中國人工智慧產業創新聯盟於2017年6月21日成立,超200家成員共推AI發展,相關動態:

640.png點選下圖加入聯盟

0.png

0?wx_fmt=gif

關注“雷克世界”後不要忘記置頂

我們還在搜狐新聞、雷克世界官網、騰訊新聞、網易新聞、一點資訊、天天快報、今日頭條、雪球財經……

↓↓↓點選閱讀原文檢視中國人工智慧產業創新聯盟手冊