使用Python視覺化Word2vec的結果
作者|Mate Pocs 編譯|VK 來源|Towards Data Science
Word2vec絕對是我在自然語言處理研究中遇到的最有趣的概念。想象一下,有一種演算法可以成功地模擬理解單詞的含義及其在語言中的功能,它可以在不同的主題內來衡量單詞之間的接近程度。
我認為視覺化地表示word2vec向量會很有趣:本質上,我們可以獲取國家或城市的向量,應用主成分分析來減少維度,並將它們放在二維圖表上。然後,我們可以觀察視覺化的結果。
在本文中,我們將:
從廣義上討論word2vec理論;
下載原始的預訓練向量;
看看一些有趣的應用程式:比如對一些單詞進行算術運算,比如著名的king-man+woman=queen等式
根據word2vec向量看看我們能多精確地來繪製歐洲的首都。
word2vec的原始研究論文和預訓練模型來自2013年,考慮到NLP文獻的擴充套件速度,目前它是老技術。較新的方法包括GloVe(更快,可以在較小的語料庫上訓練)和fastText(能夠處理字元級的n-gram)。
Quick Word2Vec簡介
自然語言處理的核心概念之一是如何量化單詞和表示式,以便能夠在模型環境中使用它們。語言元素到數值表示的這種對映稱為詞嵌入。
Word2vec是一個詞嵌入過程。這個概念相對簡單:通過一個句子一個句子地在語料庫中迴圈去擬合一個模型,根據預先定義的視窗中的相鄰單詞預測當前單詞。
為此,它使用了一個神經網路,但實際上最後我們並不使用預測的結果。一旦模型被儲存,我們只儲存隱藏層的權重。在我們將要使用的原始模型中,有300個權重,因此每個單詞都由一個300維向量表示。
請注意,兩個單詞不必彼此接近的地方才被認為是相似的。如果兩個詞從來沒有出現在同一個句子中,但它們通常被相同的包圍,那麼可以肯定它們有相似的意思。
word2vec中有兩種建模方法:skip-gram和continuous bag of words,這兩種方法都有各自的優點和對某些超引數的敏感性……但是你知道嗎?我們將不擬合我們自己的模型,所以我不會花時間在它上面。
當然,你得到的詞向量取決於你訓練模型的語料庫。一般來說,你確實需要一個龐大的語料庫,有維基百科上訓練過的版本,或者來自不同來源的新聞文章。我們將要使用的結果是在Google新聞上訓練出來的。
如何下載和安裝
首先,你需要下載預訓練word2vec向量。你可以從各種各樣的模型中進行選擇,這些模型是針對不同型別的文件進行訓練的。
我用的是最初的模型,在Google新聞上受過訓練,你可以從很多來源下載,只需搜尋“Google News vectors negative 300”。或者, 在這裡下載:https://github.com/mmihaltz/word2vec-GoogleNews-vectors。
注意,這個檔案是1.66gb,但它包含了30億字的300維表示。
當談到在Python中使用word2vec時,再一次,你有很多包可供選擇,我們將使用gensim庫。假設檔案儲存在word2vec_pretrained資料夾中,可以用Python載入,程式碼如下所示:
from gensim.models.keyedvectors import KeyedVectors
word_vectors = KeyedVectors.load_word2vec_format(\
'./word2vec_pretrained/GoogleNews-vectors-negative300.bin.gz', \
binary = True, limit = 1000000)
limit引數定義了要匯入的單詞數,100萬對於我來說已經足夠了。
探索Word2vec
現在我們已經有了word2vec向量,我們可以檢視它的一些相關有趣的用法。
首先,你可以實際檢查任何單詞的向量表示:
word_vectors['dog']
結果,正如我們預期的,是一個300維的向量,並且這個向量很難解釋。我們通過對這些向量的加和減來計算新向量,然後計算餘弦相似度來找到最接近的匹配詞。
你可以使用most_similar函式找到同義詞,topn引數定義要列出的單詞數:
word_vectors.most_similar(positive = ['nice'], topn = 5)
結果
[('good', 0.6836092472076416),
('lovely', 0.6676311492919922),
('neat', 0.6616737246513367),
('fantastic', 0.6569241285324097),
('wonderful', 0.6561347246170044)]
現在,你可能認為用類似的方法,你也可以找到反義詞,你可能認為只需要把“nice”這個詞作為negative
輸入。但結果卻是
[('J.Gordon_###-###', 0.38660115003585815),
('M.Kenseth_###-###', 0.35581791400909424),
('D.Earnhardt_Jr._###-###', 0.34227001667022705),
('G.Biffle_###-###', 0.3420777916908264),
('HuMax_TAC_TM', 0.3141660690307617)]
這些詞實際上表示離“nice”這個詞最遠的詞。
使用doesnt_match
函式可以找出異常詞:
word_vectors.doesnt_match(
['Hitler', 'Churchill', 'Stalin', 'Beethoven'])
返回Beethoven
。我想這很方便。
最後,讓我們看看一些操作的例子,這些操作通過賦予演算法一種虛假的智慧感而出名。如果我們想合併father和woman這兩個詞的向量,並且減去man這個詞的向量,程式碼如下
word_vectors.most_similar(
positive = ['father', 'woman'], negative = ['man'], topn = 1)
我們得到:
[('mother', 0.8462507128715515)]
腦子先轉一轉,想象一下我們只有兩個維度:親子關係和性別。“女人”這個詞可以用這個向量來表示:[0,1],“男人”是[0,-1],“父親”是[1,-1],“母親”是[1,1]。現在,如果我們做同樣的運算,我們得到同樣的結果。當然,區別在於我們有300個維度,而不是示例中僅有的2個維度,維度的含義幾乎無法解釋。
在word2vec操作中,有一個著名的性別偏見例子,“doctor”這個詞的女性版本過去被計算為“nurse”。我試著複製,但沒有得到同樣的結果:
word_vectors.most_similar(
positive = ['doctor', 'woman'], negative = ['man'], topn = 1)
[('gynecologist', 0.7093892097473145)]
我們得到了婦科醫生,所以,我想這可能是進步吧?
好吧,現在我們已經檢查了一些基本的函式,讓我們來研究我們的視覺化吧!
Map函式
首先,我們需要一個Map函式。假設我們有一個要視覺化的字串列表和一個詞嵌入,我們希望:
找到列表中每個單詞的詞向量表示;
利用主成分分析法將維數降到2;
建立散點圖,將單詞作為每個資料點的標籤;
另外一個額外的好處是,可以從任何維度“旋轉”結果——主成分分析的向量是任意方向的,當我們繪製地理單詞時,我們可能想要改變這個方向,看是否可以與現實世界的方向一致。
我們需要以下庫:
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.decomposition import PCA
import adjustText
列表中不常用的一個庫是adjustText,這是一個非常方便的包,它使得在散點圖中編寫圖例變得簡單,而不會重疊。對於我來說,找到這個解決方案非常困難,而且據我所知,在matplotlib或seaborn中沒有辦法做到這一點。
無需進一步說明,此函式將完全滿足我們的需要:
def plot_2d_representation_of_words(
word_list,
word_vectors,
flip_x_axis = False,
flip_y_axis = False,
label_x_axis = "x",
label_y_axis = "y",
label_label = "city"):
pca = PCA(n_components = 2)
word_plus_coordinates=[]
for word in word_list:
current_row = []
current_row.append(word)
current_row.extend(word_vectors[word])
word_plus_coordinates.append(current_row)
word_plus_coordinates = pd.DataFrame(word_plus_coordinates)
coordinates_2d = pca.fit_transform(
word_plus_coordinates.iloc[:,1:300])
coordinates_2d = pd.DataFrame(
coordinates_2d, columns=[label_x_axis, label_y_axis])
coordinates_2d[label_label] = word_plus_coordinates.iloc[:,0]
if flip_x_axis:
coordinates_2d[label_x_axis] = \
coordinates_2d[label_x_axis] * (-1)
if flip_y_axis:
coordinates_2d[label_y_axis] = \
coordinates_2d[label_y_axis] * (-1)
plt.figure(figsize = (15,10))
p1=sns.scatterplot(
data=coordinates_2d, x=label_x_axis, y=label_y_axis)
x = coordinates_2d[label_x_axis]
y = coordinates_2d[label_y_axis]
label = coordinates_2d[label_label]
texts = [plt.text(x[i], y[i], label[i]) for i in range(len(x))]
adjustText.adjust_text(texts)
現在是測試函式的時候了。我畫出了歐洲國家的首都。你可以使用任何列表,例如總統或其他歷史人物的名字,汽車品牌,烹飪原料,搖滾樂隊等等,只要在word_list引數中傳遞它。很有意思的是看到一堆堆的東西在兩個軸後面形成一個意思。
如果你想重現結果,以下是城市:
capitals = [
'Amsterdam', 'Athens', 'Belgrade', 'Berlin', 'Bern',
'Bratislava', 'Brussels', 'Bucharest', 'Budapest',
'Chisinau', 'Copenhagen','Dublin', 'Helsinki', 'Kiev',
'Lisbon', 'Ljubljana', 'London', 'Luxembourg','Madrid',
'Minsk', 'Monaco', 'Moscow', 'Nicosia', 'Nuuk', 'Oslo',
'Paris','Podgorica', 'Prague', 'Reykjavik', 'Riga',
'Rome', 'San_Marino', 'Sarajevo','Skopje', 'Sofia',
'Stockholm', 'Tallinn', 'Tirana', 'Vaduz', 'Valletta',
'Vatican', 'Vienna', 'Vilnius', 'Warsaw', 'Zagreb']
假設你仍然有我們在上一節中建立的word_vectors物件,可以這樣呼叫函式:
plot_2d_representation_of_words(
word_list = capitals,
word_vectors = word_vectors,
flip_y_axis = True)
(翻轉y軸是為了建立更像真實貼圖的表示。)
結果是:
我不知道你的感受,當我第一次看到地圖的時候,我真不敢相信結果會有多好!是的,當然,你看得越久,你發現的“錯誤”就越多,一個不好的結果就是莫斯科離東方的距離並不像它應該的那麼遠……儘管如此,東西方几乎完全分離,斯堪的納維亞和波羅的海國家被很好地組合在一起,義大利周圍的首都也是如此。
需要強調的是,這絕不是純粹的地理位置,例如,雅典離西方很遠,但這是有原因的。讓我們回顧一下上面的地圖是如何匯出的,這樣我們就可以充分理解它了:
谷歌的一組研究人員訓練了一個龐大的神經網路,根據上下文預測單詞;
他們將每個單詞的權重儲存在一個300維的向量表示中;
我們計算歐洲各國首都的向量;
利用主成分分析法將維數降到2;
把計算出的成分放在圖表上。
所以,語義的資訊不能代表真實地理資訊。但我覺得這個嘗試很有趣。
參考引用
Hobson, L. & Cole, H. & Hannes, H. (2019). Natural Language Processing in Action: Understanding, Analyzing, and Generating Text with Python. Manning Publications, 2019.
原文連結:https://towardsdatascience.com/how-to-draw-a-map-using-python-and-word2vec-e9627b4eae34
歡迎關注磐創AI部落格站: http://panchuang.net/
sklearn機器學習中文官方文件: http://sklearn123.com/
歡迎關注磐創部落格資源彙總站: http://docs.panchuang.net/
相關文章
- Tableau視覺化結果的優化小技巧(二)視覺化優化
- ICML:2019論文接收結果視覺化視覺化
- Python視覺化神器Yellowbrick使用Python視覺化
- 使用 Python 進行資料視覺化Python視覺化
- 【Python視覺化】使用Pyecharts進行奧運會視覺化分析~Python視覺化Echarts
- 12個流行的Python資料視覺化庫總結Python視覺化
- Pytorch使用Tensorboard視覺化網路結構PyTorchORB視覺化
- 如何使用Python 進行資料視覺化Python視覺化
- CNN視覺化技術總結(三)--類視覺化CNN視覺化
- python資料視覺化——echartsPython視覺化Echarts
- python 資料視覺化利器Python視覺化
- Python繪圖與視覺化Python繪圖視覺化
- Python視覺化-氣泡圖Python視覺化
- Python視覺化-折線圖Python視覺化
- Python視覺化-地圖染色Python視覺化地圖
- python資料視覺化-matplotlib入門(7)-從網路載入資料及資料視覺化的小總結Python視覺化
- 資料視覺化的知識總結視覺化
- 視覺化執行Python的神器Jupyter Notebook視覺化Python
- 資料視覺化——Matpoltlib庫的使用視覺化
- Pytorch網路結構視覺化PyTorch視覺化
- Python資料視覺化matplotlib庫Python視覺化
- Python視覺化(1):折線圖Python視覺化
- 基於python----影像的表示和視覺化Python視覺化
- 分割結果視覺化,把標籤mask輪廓顯示在原圖上視覺化
- 視覺化學習:WebGL的基礎使用視覺化Web
- Python視覺化圖系列(1)-----jupyter notebookPython視覺化
- Python資料視覺化---pygal模組Python視覺化
- Python 如何實現資料視覺化Python視覺化
- 在PyTorch中使用tensorboard視覺化PyTorchORB視覺化
- Docker使用Portainer搭建視覺化介面DockerAI視覺化
- 如何使用Android視覺化埋點Android視覺化
- CNN視覺化技術總結(四)--視覺化工具與專案CNN視覺化
- 5 種使用 Python 程式碼輕鬆實現資料視覺化的方法Python視覺化
- 視覺化視覺化
- Python——視覺化神器pyecharts的正確開啟方式Python視覺化Echarts
- 【推薦】常見的Python資料視覺化庫Python視覺化
- 常見的6個Python資料視覺化庫!Python視覺化
- Docker-視覺化管理工具總結-推薦使用PortainerDocker視覺化AI