计算SAS / IML中的余弦相似度

时间:2012-05-24 16:14:39

标签: sas

我在SAS IML中有一个矩阵。对于每对行(例如向量AB),我想计算cosine similarity

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

因此,结果应该是一个方形矩阵,其行数与初始矩阵相同。

如果我将向量传递给Euclid函数,我会返回一个向量,因此该函数似乎分别对向量的每个元素起作用。确实,SAS文档says

  

如果使用矩阵调用Base SAS功能   参数,该函数通常将元素作用于每个元素   teh [sic]矩阵。

这很奇怪 - 为什么有人想要计算向量的每个元素的摘要统计数据?他们将永远只返回元素。有没有办法获得向量的欧几里德范数?

我的代码如下。尽管有欧几里德规范,还有更有效的方法吗?

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 个答案:

答案 0 :(得分: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 :(得分:1)

为了提供参考,我认为Rick的this article可能是一本很好的读物。将向量转换为逗号分隔字符串的方法非常方便。