http://blog.csdn.net/baimafujinji/article/details/77836142
一、数学上的“嵌入”(Embedding)
Embed这个词,英文的释义为, fix (an object) firmly and deeply in a surrounding mass, 也就是“嵌入”之意。例如:One of the bullets passed through Andrea's chest before embedding itself in a wall.
另外,这个词(的分词形式)在数学上也是一个专有名词,Embedding,它广泛存在于包括代数、拓扑与几何等诸多数学领域。它主要表征某个数学结构中的一个实例被包含在另外一个实例中,例如一个group它同时又是一个subgroup。
当我们说某个对象 X 被嵌入到另外一个对象 Y 中, 那么 embedding 就由一个单射的、结构保持的(structure-preserving)映射 f : X → Y 来给定的。此处的结构保持的具体含义要依赖于X 和 Y 是哪种数学结构的实例而定。
举个例子:我们可以把整数“嵌入”进有理数之中。显然,整数是一个group,同时它又是有理数的一个subgroup。整数集合中的每个整数,在有理数集合中都能找到一个唯一的对应(其实就是它本身)。同时,整数集合中的每个整数所具有的性质,在有理数中同样得到了保持。同理,我们也可以把有理数“嵌入”到实数中去。
二、词嵌入(Word Embedding)
John likes to watch movies. Mary likes movies too.
John also likes to watch football games.
把上述语料中的词汇表整理出来并排序(具体的排序原则可以有很多,例如可以根据字母表顺序,也可以根据出现在语料库中的先后顺序)
假设我们的词汇表排序结果如下:
{"John": 1, "likes": 2, "to": 3, "watch": 4, "movies": 5, "also":6, "football": 7, "games": 8, "Mary": 9, "too": 10}
[1, 2, 1, 1, 2, 0, 0, 0, 1, 1]
[1, 1, 1, 1, 0, 1, 1, 1, 0, 0]
One-hot方法很简单,但是它的问题也很明显:
1)它没有考虑单词之间相对位置的关系;
2)词向量可能非常非常长!
针对第一个问题,你可能会想到n-gram方法,这确实是一个策略,但是它可能会导致计算量的急剧增长。因为n-gram已经在之前的文章中解释过了,下面我们来看另外一个方法:共现矩阵 (Cocurrence matrix)。
一个非常重要的思想是,我们认为某个词的意思跟它临近的单词是紧密相关的。这是我们可以设定一个窗口(大小一般是5~10),如下窗口大小是2,那么在这个窗口内,与rests 共同出现的单词就有life、he、in、peace。然后我们就利用这种共现关系来生成词向量。
例如,现在我们的语料库包括下面三份文档资料:
I like deep learning.
I like NLP.
I enjoy flying.
作为示例,我们设定的窗口大小为1,也就是只看某个单词周围紧邻着的那个单词。此时,将得到一个对称矩阵——共现矩阵。因为在我们的语料库中,I 和 like做为邻居同时出现在窗口中的次数是2,所以下表中I 和like相交的位置其值就是2。这样我们也实现了将word变成向量的设想,在共现矩阵每一行(或每一列)都是对应单词的一个向量表示。
- “国王” – “王后” ≈ “男” – “女”
- “英国” – “伦敦” ≈ “法国” – “巴黎” ≈ “首都”
- import gensim, logging, os
- logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
- import nltk
- corpus = nltk.corpus.brown.sents()
- fname = 'brown_skipgram.model'
- if os.path.exists(fname):
- # load the file if it has already been trained, to save repeating the slow training step below
- model = gensim.models.Word2Vec.load(fname)
- else:
- # can take a few minutes, grab a cuppa
- model = gensim.models.Word2Vec(corpus, size=100, min_count=5, workers=2, iter=50)
- model.save(fname)
- words = "woman women man girl boy green blue did".split()
- for w1 in words:
- for w2 in words:
- print(w1, w2, model.similarity(w1, w2))
- woman woman 1.0
- woman women 0.3451595268
- woman man 0.607956254336
- woman girl 0.761190251497
- woman boy 0.558522930154
- woman green 0.24118403927
- woman blue 0.178044251325
- woman did 0.0751838683173
- women woman 0.3451595268
- women women 1.0
- women man 0.126646555737
- women girl 0.292825346454
- women boy 0.298552943639
- women green 0.104096393379
- women blue 0.0930137564485
- women did 0.152766770859
- 注意:输出内容较长,这里不全部列出,读者可以执行尝试并观察输出结果... ...
- import numpy as np
- import matplotlib.pyplot as plt
- %matplotlib inline
- M = np.zeros((len(words), len(words)))
- for i, w1 in enumerate(words):
- for j, w2 in enumerate(words):
- M[i,j] = model.similarity(w1, w2)
- plt.imshow(M, interpolation='nearest')
- plt.colorbar()
- ax = plt.gca()
- ax.set_xticklabels([''] + words, rotation=45)
- ax.set_yticklabels([''] + words)
- model.most_similar(positive=['woman'], topn=10)
- [('girl', 0.7611901760101318),
- ('man', 0.6079562902450562),
- ('lady', 0.6069421768188477),
- ('boy', 0.5585228800773621),
- ('child', 0.5556907653808594),
- ('person', 0.5444432497024536),
- ('young', 0.5219132900238037),
- ('pair', 0.5211296081542969),
- ('she', 0.5175711512565613),
- ('fellow', 0.5115353465080261)]
现在你也可以试着来玩一下Word2Vec啦!