1. 程式人生 > >R+NLP︱text2vec包——四類文字挖掘相似性指標 RWMD、cosine、Jaccard 、Euclidean (三,相似距離)

R+NLP︱text2vec包——四類文字挖掘相似性指標 RWMD、cosine、Jaccard 、Euclidean (三,相似距離)

要學的東西太多,無筆記不能學~~ 歡迎關注公眾號,一起分享學習筆記,記錄每一顆“貝殼”~

———————————————————————————


   在之前的開篇提到了text2vec,筆者將其定義為R語言文字分析"No.1",她是一個文字分析的生態系統。筆者在學習之後發現開發者簡直牛!基於分享精神,將自學筆記記錄出來。開篇內容參考:

  text2vec中包括了四大類距離:

  • Cosine
  • Jaccard
  • Relaxed Word Mover's Distance
  • Euclidean

—————————————————————————————————————————————

一、文字分析常見三大距離——cosine/jaccard/Euclidean

      1、Euclidean,歐氏距離是最易於理解的一種距離計算方法,源自歐氏空間中兩點間的距離公式。

      2、cosine, 有沒有搞錯,又不是學幾何,怎麼扯到夾角餘弦了?各位看官稍安勿躁。幾何中夾角餘弦可用來衡量兩個向量方向的差異,機器學習中借用這一概念來衡量樣本向量之間的差異。

      3、jaccard,傑卡德相似係數,  兩個集合A和B的交集元素在A,B的並集中所佔的比例,稱為兩個集合的傑卡德相似係數,用符號J(A,B)表示。

      不展開描述,因為很常見,其中文字分析還有Hamming距離

—————————————————————————————————————————————

二、文字分析相似性距離——Relaxed Word Mover's Distance(RWMD)

      本節內容轉載於IR實驗室,《劉龍飛 From Word Embeddings To Document Distance》。

      1、Earth Mover’s Distance (EMD)

      Earth Mover’s Distance (EMD),和歐氏距離一樣,他們都是一種距離度量的定義,可以用來測量某分佈之間的距離。EMD主要應用在影象處理和語音訊號處理領域。


      EMD 實際上是線性規劃運輸問題的最優解。首先,簡要描述下運輸問題。我們假設這個例子是從多個工廠運輸貨物到多個倉庫。在上圖左側,P從在P1 到 Pm代表m座工廠,工廠Pi有重量為wPi的貨物。在上圖右側,Q從Q1到Qn代表n個倉庫,倉庫Qj最大容量為wQj。

      貨物之間沒有什麼區別,都是同一類東西。每個倉庫都希望裝儘可能多的貨物。如何儘可能高效把所有貨物(實際上不一定是所有貨物,部分也OK)從P運送到Q,就是運輸問題的優化目標。在本例中,P、Q都是離散的,那麼EMD可以用運輸問題的Hungarian演算法來計算它們之間的距離。挖個坑而已,這裡不具體討論。

2、EMD演算法在自然語言處理領域的應用

      通過詞嵌入(Word Embedding),我們可以得到詞語的分散式低維實數向量表示,我們可以計算詞語之間的距離,即我們可以得到dij,因此可以將EMD引入自然語言處理領域。

      Matt等人[2]將詞嵌入與EMD相聯絡,用來度量文件距離。提出了WMD(word mover’s distance)演算法,以及WCD(word centroid distance)、RWMD(relaxed word mover’s distance)兩種犧牲精度降低複雜度的演算法。


       如何將一個文件變為分佈P這種形式?

      用歸一化的詞袋模型(nBOW, normalized bag-of-words)表示。其中P1表示詞語,用計算該詞的權重,其中表示詞語i在文件中出現了次,P1的特徵量用該詞語的詞向量表示。一個nBOW文件向量是比較稀疏的,因為大部分的詞語不會出現在該文件中,且在生成文件向量時,去掉的停用詞。用歐式距離計算詞語與詞語之間的距離。

      假定資料集中只有兩個文件,則這兩個文件生成的歸一化nBOW向量如下圖所示。


      轉移量用矩陣T表示,生成的矩陣T如下圖所示


      表示詞語i有多少轉移到了詞語j,

      綜上,Matt等人提出了WMD演算法,WMD是EMD的一個特殊形式。

為了降低模型的計算複雜度,Matt等人提出了WCD和RWMD兩個演算法,這兩個演算法是WMD的兩個不同下限,通過降低精度來降低計算複雜度。

      Relaxed word moving distance(RWMD),通過放鬆限制條件,得到WMD的下限。通過去掉條件2,保留條件1。

作者:From word embeddings to document distances, Matt J. kusner et al.

連結:http://ir.dlut.edu.cn/news/detail/362

—————————————————————————————————————————————

三、R語言︱text2vec包中的四大相似性距離

      text2vec環境中有這麼四個求距離的函式:

      sim2(x, y, method):分別計算x*y個相似性;

      psim2(x, x, method):平行地求資料的相似性,x個相似性;

      dist2(x, y, method):跟sim2相反,分別計算x*y個距離;

      pdist2(x, x, method),平行地求資料的距離,x個距離。

      注意到的是,sim2與psim2一個是生成了x*y個數值,一個是生成了x個數值,區別顯而易見。

來看一個官方案例:

      先準備好資料,還是之前的那個電影簡述資料。

library(stringr)
library(text2vec)
data("movie_review")
# select 500 rows for faster running times
movie_review = movie_review[1:500, ]
prep_fun = function(x) {
  x %>% 
    # make text lower case
    str_to_lower %>% 
    # remove non-alphanumeric symbols
    str_replace_all("[^[:alnum:]]", " ") %>% 
    # collapse multiple spaces
    str_replace_all("\\s+", " ")
}
movie_review$review_clean = prep_fun(movie_review$review)

定義兩個文件:

doc_set_1 = movie_review[1:300, ]
it1 = itoken(doc_set_1$review_clean, progressbar = FALSE)

# specially take different number of docs in second set
doc_set_2 = movie_review[301:500, ]
it2 = itoken(doc_set_2$review_clean, progressbar = FALSE)

1、Jaccard距離

dtm1 = create_dtm(it1, vectorizer)
dtm2 = create_dtm(it2, vectorizer)
d1_d2_jac_sim = sim2(dtm1, dtm2, method = "jaccard", norm = "none")
      生成了一個300*200的相似性矩陣。
dtm1_2 = dtm1[1:200, ]
dtm2_2 = dtm2[1:200, ]
d1_d2_jac_psim = psim2(dtm1_2, dtm2_2, method = "jaccard", norm = "none")
str(d1_d2_jac_psim)
      生成了一個200個數值的相似性係數。

2、cosine距離

d1_d2_cos_sim = sim2(dtm1, dtm2, method = "cosine", norm = "l2")

3、Euclidean 距離

x = dtm_tfidf_lsa[1:300, ]
y = dtm_tfidf_lsa[1:200, ]
m1 = dist2(x, y, method = "euclidean")

4、RWMD距離

data("movie_review")
tokens = movie_review$review %>%
  tolower %>%
  word_tokenizer
v = create_vocabulary(itoken(tokens)) %>%
  prune_vocabulary(term_count_min = 5, doc_proportion_max = 0.5)
corpus = create_corpus(itoken(tokens), vocab_vectorizer(v, skip_grams_window = 5))
dtm = get_dtm(corpus)
tcm = get_tcm(corpus)
glove_model = GloVe$new(word_vectors_size = 50, vocabulary = v, x_max = 10)
wv = glove_model$fit(tcm, n_iter = 10)
rwmd_model = RWMD(wv)
rwmd_dist = dist2(dtm[1:10, ], dtm[1:100, ], method = rwmd_model, norm = 'none')