2012-05-24 71 views
1

我在SAS IML中有一個矩陣。對於每一對行(說矢量AB),我想計算的cosine similarity,計算SAS/IML中的餘弦相似度

A . B/(||A|| x ||B||)

所以結果應該是一個與初始矩陣行數相同的方陣。

如果我將一個向量傳遞給Euclid函數,我得到一個向量,所以函數似乎分別作用於向量的每個元素。事實上,SAS文檔says

如果你調用一個基地,以矩陣 說法SAS功能,該功能通常會 德[原文]矩陣中的每個元素採取行動的elementwise。

這很奇怪 - 爲什麼會有人想爲矢量的每個元素計算彙總統計?他們將始終只返回元素。有一種方法可以獲得矢量的歐幾里德準則嗎?

我的代碼如下。儘管歐幾里得規範,是否有更有效的方法來做到這一點?

proc iml; 
use fundstr; 
read all var _all_ into wgts; 

nrows=nrow(wgts); 
d=j(nrows,nrows,0); 

do i = 1 to nrows; 
    do j = i to nrows; 

    tmp = wgts[i,]*wgts[j,]`; /** need to divide by norms each vector **/ 
    d[i,j] = tmp; 
    d[j,i] = tmp; 

    end; 
end; 
quit; 

回答

2

使用矩陣運算並將此問題看作(A/|| A ||)*(B/|| B ||)。

第一步是將每一行的歐幾里得範數除以sqrt(ssq(wgts [i,])))。您可以使用「平方和」下標縮減運算符(##)來爲所有行一次計算此值,而無需編寫循環:sqrt(wgts [,##]); (參見http://blogs.sas.com/content/iml/2012/05/23/compute-statistics-for-each-row-by-using-subscript-operators/關於下標歸約算子的解釋和示例。)

行的成對點積相當於矩陣乘法A * A`,其中A是標度矩陣。把所有這些一起導致瞭解決方案:

wgts = ranuni(j(5,5));   
norm = sqrt(wgts[ ,##]); /* Euclidean norm */ 
A = wgts/norm; 
d = A*A`; 
print d; 

如果你想與此相比,使用循環的(低效率)的解決方案,那就是:

nrows=nrow(wgts); 
d=j(nrows,nrows,0); 
do i = 1 to nrows; 
    normi = sqrt(wgts[i,##]); 
    do j = i to nrows; 
     normj = sqrt(wgts[j,##]); 
     tmp = wgts[i,]*wgts[j,]`/(normi * normj); 
     d[i,j] = tmp; 
     d[j,i] = tmp; 
    end; 
end; 
print d; 

順便問一下,你會很高興聽到在SAS/IML的下一個版本中,文檔中的輸入錯誤是固定的:-)

1

爲了提供參考,我認爲裏克的this article可能是一個很好的閱讀。將矢量轉換爲逗號分隔字符串的方法非常方便。