From Word Embeddings To Document Distances

From Word Embeddings To Document Distances

1. Word Mover’s Distance (WMD) 能解决的具体问题及本文的背景

这是一篇2015年发表的文章,主要是基于word embedding以及一个在运输领域使用很广的Word Mover’s Distance (WMD)来计算文档之间的距离(相似性)。 首先我们知道,从文本中提取摘应用是很广泛的,比如自动生成新闻题目,文档分类,不同语言的文本匹配等等(其实还能用来找同领域的文献,这样你阅读的论文就会成指数级增长:P)。 但是传统的NLP方法,比如计算文档中的词频(TF-IDF)或者a bag of words (BOW)没有考虑语义的影响。比如对Obama和American President其实是一个意思,但是如果只计算词频的话是没办法说这两个词是相近的。 传统的改进方法是对feature space进行改进,比如Latent Semantic Indexing (LSI) 对 BOW feature space做特征值分解, and Latent Dirichlet Allocation (LDA) 用概率的方法把相近的词group在一起,然后把文档表示为关于topic的概率分布。不过这些方法没有在计算文档之间距离(相似性)的任务上做改进。 而基于word to vec 算出来的word embedding之间的距离就可以考虑语义的影响,因此本文的工作是把两个文档之间距离表示为文档中从一个词到另一个词的最小距离之和,见图1(其实思想挺简单的但在当时word2vec刚出来,所以在此基础上做的工作还是值得肯定的)。 很明显这是一个最优化问题,并且还是一个在运输领域研究的很完备的问题,所以可以利用针对这个问题开发好的求解器来求解。事实上,WMD其实是earth mover’s distance metric的一个特例。跟前一篇类似,本文中也使用了一些lower bounds来近似和裁剪从而达到优化速度的效果。 作者还介绍了EMD在图像提取中的早期应用,以及在此领域对earth mover's distance metric(EMD)的一些优化,比如并行计算等。但那些优化有前提假设,即提取出的矩阵大小并不太大,这对NLP问题并不适用,因此作者本文对EMD进行了针对文档相似性计算的优化。

image

Fig.1 An illustration of the word mover's distance. All non-stop words (bold) of both documents are embedded into a word2vec space. The distance between the two documents is the minimum cumulative distance that all words in document 1 need to travel to exactly match document

1.1 Earth Mover’s Distance (EMD) 的背景

要了解WMD,首先要了解搬土问题,英文为EMD(earth mover distance)。假设有北京上海两地各有土250吨和300吨,现在有三个仓库分别需要土100, 250, 270吨,北京上海运输每吨土到三个仓库一共有6种不同的成本,问如果规划可以让成本最小,见图2。很明显,这是一个线性规划问题。 设从北京运t_1, t_2, t_3到仓库1,2,3,成本为c_1, c_2, c_3,从上海运t_4, t_5, t_6到仓库1,2,3,成本为c_4, c_5, c_6,则EMD问题可写作:

image

Fig.2 An example of the earth mover's distance.

Minimize 总成本 = t_{1}c_{1}+t_{2} c_{2}+t_{3} c_{3}+t_{4} c_{4}+t_{5} c_{5}+t_{6} c_{6},

Subject to (t_{1}+t_{2}+t_{3})/250 \leq 1 (t_{4}+t_{5}+t_{6})/300 \leq 1

t_{1}+t_{4} = 100 t_{2}+t_{5} = 250 t_{3}+t_{6} = 270 (仓库轴和地点轴分别的constraint)

写成矩阵,T_{ij}是从 T_{i} 搬到 T_{j} 的土的重量。这个线性规划模型很容易解,有很多solver可以求解。 (在WMD中由于这个矩阵被归一化了,所以 T_{ij} 是搬多少word_{i}去第二篇文章的word_{j}的权重,并且由于word_{i}用到是BOW的表示比如文章中个word_i是“nice”,在文中出现了5次,所有的词加起来一共20次,则这个word的总重是d_i = 0.25,所以\sum_{j=1}^{n}\mathbf T_{ij} = d_i

image

Fig.3 An example of flow matrix.

\min_{\mathbf T>=0} \sum_{i,j=1}^{n}\mathbf T_{ij}c(i,j) \sum_{j=1}^{n}\mathbf T_{ij} = d_1 \hspace{1cm} \forall_i \in {1,\dots,n} \hspace{1cm} (1)

\sum_{i=1}^{n}\mathbf T_{ij} = d_2 \hspace{1cm} \forall_i \in {1,\dots,n} \hspace{1cm} (2)

1.2 Word Mover’s Distance (WMD) 介绍

联系刚刚的例子,上海北京是一篇文章,仓库1,2,3是另一篇文章。上海,北京分别是文章1中的两个词,用BOW的一个长度为N的词库,比如在一个长度为5的词库{仓库1,北京,仓库2,上海,仓库3}里,文章1可以表示为『0,0.5,0,0.5,0』,文章2可以表示为『0.33,0,0.33,0,0.33』。c_{i,j}word_iword_j的word2vec的embedding向量的距离,可以认为是从文章1的word_i到文章word_j的cost。 跟EMD相似的,从数学上正式定义这个问题的话可以写作:

\min_{\mathbf T>=0} \sum_{i,j=1}^{n}\mathbf T_{ij}c(i,j)

\sum_{j=1}^{n}\mathbf T_{ij} = d_1 \hspace{1cm} \forall_i \in {1,\dots,n} \hspace{1cm} (1)

\sum_{i=1}^{n}\mathbf T_{ij} = d_2 \hspace{1cm} \forall_i \in {1,\dots,n} \hspace{1cm} (2)

在WMD中由于这个T_{ij}矩阵被归一化了,所以 T_{ij} 是搬多少word_{i}去第二篇文章的word_{j}的权重,并且由于word_{i}用到是BOW的表示比如文章中个word_i是“nice”,在文中出现了5次,所有的词在文章1加起来一共20次,则这个word的总重是d_i = 0.25,所以\sum_{j=1}^{n}\mathbf T_{ij} = d_i) 这里横轴纵轴也有constrain,跟EMD一样理解。

2. Word Mover’s Distance (WMD) 的优化方法

2.1. Word centroid distance

与2012 KDD best paper 那篇优化DTW算法的方法一样,一个很有效的办法是通过计算WMD的lower bound来prune掉大部分距离比较大的document。即需要找到一个lower bound,算出来的距离始终比WMD小。那么在本文里,一个很明显的lower bound是根据三角形不等式,即两边之和大于第三边得到的。可以见下列的数学公式,或者用一张更明显的几何图来表示,如图4。公式左边是距离的和,右边是向量之和的距离。左边大于右边,严格证明的话可以把point连起来形成若干个三角形根据两边之和大于第三边来证。后面把公式右边那个比较小的距离做了一些变换得到word centroid distance,就是每个词的质心距离。

image
image

Fig.4 公式的几何表示

2.2. Relaxed word moving distance

WMD虽然计算很快但是不tight,还有一种优化方式就是去掉一个constraint。

image

由于不像EMD我们分一些北京的土到三个不同的仓库,对于词向量来说最优的情况是把一个词全部移动到与他距离最近词上去,因此T^*可以重新定义为:

\mathbf{T}{i j}^{*}=\left{\begin{array}{l}{d{i} \text { if } j=\operatorname{argmin}_{j} c(i, j)} \ {0 \text { otherwise. }}\end{array}\right. 具体可以根据以下公式证明:

image

与之前那篇用DTW来做trillion时序comparison的优化方式一样,本文作者也是做了两个lower bound组合的方式来prune,并且也做了sorting和缓存计算好的距离。就不赘述了,具体可以看前一篇。

KDD2012 best paper

3. 关于此文的一些思考

  1. 本文通过word2vec得到有semantic的word embedding,然后通过转化文档相似性问题为一个在运筹领域研究的很透彻的EMD问题来解决,这种思想值得借鉴。

  2. 找lower bound看来是一种加速算法的通用方法,最好找到一些计算速度比较快的lower bound,然后做瀑布式的裁剪,同时sorting和存一些变量也是比较好的方法。

4\ WMD代码实现

  1. 下载用glove训练好的word embedding
    https://nlp.stanford.edu/projects/glove/
import cvxopt
import numpy as np
import string
from collections import Counter
from scipy.optimize import linprog

glovefile = open("glove.6B.100d.txt","r",encoding="utf-8")
em = glovefile.readlines()
dic = {}
for i in range(len(em)):
    s = em[i].strip("\n").split(" ")
    dic[s[0]] = np.loadtxt(s[1:])

def WMD (sent1, sent2):
    def get_words_counts(sent):
        """
        given a sent, return its unique words and words count
        Args: 
            sent: str
        Return:
            words: list of unique words in the sentence
            freq_vector: array of normalized frequency of corresponding words, shape (len(words))
        """
        words = sent.translate(str.maketrans('', '', string.punctuation)).lower().split(" ")
        from collections import Counter
        words1dict = Counter(words)
        words1unique = list(words1dict.keys())
        wordvector = [words1dict[i]/len(words) for i in words1unique]
        return words1unique, wordvector
    
    def flat_and_index(matr):
        """
        given a matr with shape m x n,
        after flat the matr, return original
        row-wise coefficient matrix and column-wise coefficient matrix
        Args:
            matr: array like
        Return: 
            A1: m x(m*n) row wise coefficient matrix
            A2: n x(m*n) column wise coefficient matrix
        """
        m, n = np.shape(matr)
        A1 = np.zeros((m, m*n))
        counter =0
        for i in range(m):
            A1[i, counter:counter+n] =1
            counter = counter + n
        A2 = np.zeros((n, m*n))
        for i in range(n):
            for j in range(m):
                A2[i, i+j*n] =1
        return A1, A2
    
    
    
    words1unique, counter_vector1 = get_words_counts(sent1)
    words2unique, counter_vector2 = get_words_counts(sent2)
    words1_arrays = [dic[i] for i in words1unique]
    words2_arrays = [dic[i] for i in words2unique]
    
    
    dist_matrix = np.zeros((len(words1_arrays), len(words2_arrays)))

    for i in range(len(words1unique)):
        for j in range(len(words2unique)):
            dist_matrix[i,j] = np.linalg.norm(words1_arrays[i]-words2_arrays[j])

    A1, A2 = flat_and_index(dist_matrix) 
    assert len(A1) == len(counter_vector1)
    assert len(A2) == len(counter_vector2)        
    A = np.vstack((A1, A2))
    c = dist_matrix.flatten()
    B = np.asarray(counter_vector1+counter_vector2)
    sol  = linprog(c, A_eq =A, b_eq=B, bounds=(0,None))
    wmd =  np.dot(sol.x, c)
    return wmd
  1. 测试
print(WMD("people like this car", "those guys enjoy driving that"))
print(WMD("I love my home it is in a good place", "Believe it or not I like you"))
print(WMD("That is it, stop it!", "I hate it, do not do it right now"))
print(WMD("my leader is giving a speech", "Our president is presenting"))

4.271249445939769
3.6289936834376237
3.342944295085508
3.9697731866077657

References:

[1] M. J. Kusner, Y. Sun, N. I. Kolkin和K. Q. Weinberger, 《From Word Embeddings To Document Distances》, p10.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容