乐趣区

关于人工智能:使用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/w…。

留神,这个文件是 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 函数。假如咱们有一个要可视化的字符串列表和一个词嵌入,咱们心愿:

  1. 找到列表中每个单词的词向量示意;
  2. 利用主成分分析法将维数降到 2;
  3. 创立散点图,将单词作为每个数据点的标签;
  4. 另外一个额定的益处是,能够从任何维度“旋转”后果——主成分剖析的向量是任意方向的,当咱们绘制天文单词时,咱们可能想要扭转这个方向,看是否能够与事实世界的方向统一。

咱们须要以下库:

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://en.wikipedia.org/wiki…
  • https://adjusttext.readthedoc…

原文链接:https://towardsdatascience.co…

欢送关注磐创 AI 博客站:
http://panchuang.net/

sklearn 机器学习中文官网文档:
http://sklearn123.com/

欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/

退出移动版