如何使用SAS計算Word Mover的距離

Word Mover的距離(WMD)是用於衡量兩個文檔之間差別的距離度量,它在文本分析中的應用是由華盛頓大學的一個研究小組在2015年引入的。該小組的論文「 從Word嵌入到文檔距離」發表了在第32屆國際機器學習大會(ICML)上。在本文中,他們證實了WMD度量致使8個真實世界文檔分類數據集中史無前例的低k-最近鄰文檔分類錯誤率。node

他們利用單詞嵌入和WMD對文檔進行分類,這種方法相對於傳統方法的最大優勢是它可以將單個單詞對(例如總統和奧巴馬)之間的語義類似性合併到文檔距離度量中。以傳統方式,操縱語義類似單詞的一種方法是提供同義詞表,以便算法在測量文檔距離以前能夠將具備相同含義的單詞合併到表明性單詞中,不然您將沒法得到準確的相異性結果。然而,維護同義詞表須要人類專家的不斷努力,所以耗時且很是昂貴。此外,單詞的語義含義取決於域,而通用同義詞表不適用於不一樣的域。算法

Word Mover距離的定義

WMD是兩個文檔之間的距離,做爲將全部單詞從一個文檔移動到另外一個文檔所需的最小(加權)累積成本。經過解決如下線性程序問題來計算距離。sql

T ij表示文檔d中的單詞i在文檔d '中移動到單詞j的多少;app

c(i; j)表示從文件d中的單詞i到文件d '中的單詞j「行進」的費用; 這裏的成本是word2vec嵌入空間中的兩個詞'歐幾里德距離;機器學習

若是字我出現Ç 我在文檔d次,咱們記ide

WMD是地球移動器距離度量(EMD)的一個特例,這是一個衆所周知的運輸問題。工具

如何用SAS計算地球移動器的距離?
SAS / OR是解決運輸問題的工具。圖1顯示了一個帶有四個節點和節點之間距離的傳輸示例,我從這個Earth Mover的Distance文檔中複製了這些節點。目標是找出從{x1,x2}到{y1,y2}的最小流量。如今讓咱們看看如何使用SAS / OR解決這個運輸問題。學習

節點的權重和節點之間的距離以下。ui

clipboard.png

圖-1運輸問題idea

datax_set;input_node_ $ _sd_;datalines;x10.74x20.26;datay_set;input_node_ $ _sd_;datalines;y10.23y20.51;dataarcdata;input_tail_ $ _head_ $ _cost_;datalines;x1 y1155.7x1 y2252.3x2 y1292.9x2 y2198.2;proc optmodel;setxNODES;num w{xNODES};setyNODES;num u{yNODES};set ARCS;num arcCost{ARCS}; readdatax_setintoxNODES=[_node_]w=_sd_;readdatay_setintoyNODES=[_node_]u=_sd_;readdataarcdataintoARCS=[_tail_ _head_]arcCost=_cost_;varflow{inARCS}>=0;impvar sumY =sum{jinyNODES}u[j];minobj =(sum{inARCS}arcCost[i,j]* flow[i,j])/sumY;con con_y{jinyNODES}:sum{inARCS}flow[i,j]= u[j];con con_x{iinxNODES}:sum{<(i),j>inARCS}flow[i,j]<= w[i]; solve with lp / algorithm=ns scale=none logfreq=1;print flow;quit;

SAS / OR的解決方案如表-1所示,EMD是目標值:203.26756757。

clipboard.png

表-1 EMD用SAS / OR計算

我用SAS / OR表2獲得的流量數據顯示以下,與上述地球移動器距離文檔中公佈的圖表相同。

clipboard.png

表-2 SAS / OR的流量數據

clipboard.png

圖-2運輸問題流程圖

如何用SAS計算Word Mover的距離

本文從Word嵌入到文檔距離,經過刪除WMD的第二個約束來減小計算,提出了一個名爲Relaxed Word Mover Distance(RWMD)的新度量。因爲咱們須要讀取文字嵌入數據,所以我將向您展現如何使用SAS Viya計算兩個文檔的RWMD。

/* start CAS server */cas casauto host="host.example.com"port=5570;libnamesascas1 cas;/* load documents into CAS */datasascas1.documents;infiledatalines delimiter='|'missover;lengthtext varchar(300);inputtext$ did;datalines;Obama speaks to the mediainIllinois.|1The President greets the pressinChicago.|2;run;/* create stop list*/datasascas1.stopList;infiledatalines missover;lengthterm $20;inputterm$;datalines;thetoin;run;/* load word embedding model */proc cas;loadtable path='datasources/glove_100d_tab_clean.txt'caslib="CASTestTmp"importOptions={fileType="delimited",delimiter='\t',getNames=True,guessRows=2.0,varChars=True}casOut={name='glove'replace=True};run;quit;%macrocalculateRWMD(textDS=documents,documentID=did,text=text,language=English,stopList=stopList,word2VectDS=glove,doc1_id=1,doc2_id=2);/* text parsing and aggregation */proc cas;textParse.tpParse/table={name="&textDS",where="&documentID=&doc1_id or &documentID=&doc2_id"}docId="&documentID",language="&language",stemming=False,nounGroups=False,tagging=False,offset={name="outpos",replace=1},text="&text";run; textparse.tpaccumulate/parent={name="outparent1",replace=1}language="&language",offset='outpos',stopList={name="&stoplist"},terms={name="outterms1",replace=1},child={name="outchild1",replace=1},reduce=1,cellweight='none',termWeight='none';run;quit;/* terms of the two test documents */proc cas;loadactionset"fedsql";execdirect casout={name="doc_terms",replace=true}query="

select outparent1.*,_term_

from outparent1

left join outterms1

on outparent1._termnum_ = outterms1._termnum_

where _Document_=&doc1_id or _Document_=&doc2_id;

";run;quit;/* term vectors and counts of the two test documents */proc cas;loadactionset"fedsql";execdirect casout={name="doc1_termvects",replace=true}query="

select word2vect.*

from &word2VectDS word2vect, doc_terms

where _Document_=&doc2_id and lowcase(term) = _term_;

";run; execdirect casout={name="doc1_terms",replace=true}query="

select doc_terms.*

from &word2VectDS, doc_terms

where _Document_=&doc2_id and lowcase(term) = _term_;

";run; simple.groupBy /table={name="doc1_terms"}inputs={"_Term_","_Count_"}aggregator="n"casout={name="doc1_termcount",replace=true};run;quit;proc cas;loadactionset"fedsql";execdirect casout={name="doc2_termvects",replace=true}query="

select word2vect.*

from &word2VectDS word2vect, doc_terms

where _Document_=&doc1_id and lowcase(term) = _term_;

";run; execdirect casout={name="doc2_terms",replace=true}query="

select doc_terms.*

from &word2VectDS, doc_terms

where _Document_=&doc1_id and lowcase(term) = _term_;

";run; simple.groupBy /table={name="doc2_terms"}inputs={"_Term_","_Count_"}aggregator="n"casout={name="doc2_termcount",replace=true};run;quit;/* calculate Euclidean distance between words */datadoc1_termvects;setsascas1.doc1_termvects;run;datadoc2_termvects;setsascas1.doc2_termvects;run;proc iml;use doc1_termvects;read allvar_char_intolterm;read allvar_num_intox;closedoc1_termvects; use doc2_termvects;read allvar_char_intorterm;read allvar_num_intoy;closedoc2_termvects; d = distance(x,y); lobs=nrow(lterm);robs=nrow(rterm);d_out=j(lobs*robs, 3, ' ');doi=1to lobs;doj=1to robs;d_out[(i-1)*robs+j,1]=lterm[i];d_out[(i-1)*robs+j,2]=rterm[j];d_out[(i-1)*robs+j,3]=cats(d[i,j]);end;end;createdistancefromd_out;appendfromd_out;closedistance;run;quit;/* calculate RWMD between documents */datax_set;setsascas1.doc1_termcount;rename_term_=_node_;_weight_=_count_;run;datay_set;setsascas1.doc2_termcount;rename_term_=_node_;_weight_=_count_;run;dataarcdata;setdistance;renamecol1=_tail_;renamecol2=_head_;length_cost_8;_cost_= col3;run;proc optmodel;setxNODES;num w{xNODES};setyNODES;num u{yNODES};set ARCS;num arcCost{ARCS}; readdatax_setintoxNODES=[_node_]w=_weight_;readdatay_setintoyNODES=[_node_]u=_weight_;readdataarcdataintoARCS=[_tail_ _head_]arcCost=_cost_;varflow{inARCS}>=0;impvar sumY =sum{jinyNODES}u[j];minobj =(sum{inARCS}arcCost[i,j]* flow[i,j])/sumY;con con_y{jinyNODES}:sum{inARCS}flow[i,j]= u[j];/* con con_x {i in xNODES}: sum {<(i),j> in ARCS} flow[i,j] <= w[i];*/solve with lp / algorithm=ns scale=none logfreq=1;callsymput('obj', strip(put(obj,best.)));createdataflowDatafrom[i j]={inARCS: flow[i,j].sol >0}col("cost")=arcCost[i,j]col("flowweight")=flow[i,j].sol;run;quit;%putRWMD=&obj;%mendcalculateRWMD; %calculateRWMD(textDS=documents,documentID=did,text=text,language=English,stopList=stopList,word2VectDS=glove,doc1_id=1,doc2_id=2);



proc printdata=flowdata;run;quit;

WMD方法不只能夠測量文檔的類似性,還能夠經過可視化流數據來解釋爲何這兩個文檔是類似的。

相關文章
相關標籤/搜索