R:计算两个稀疏矩阵的行之间的余弦距离

时间:2016-09-06 13:41:03

标签: r sparse-matrix cosine-similarity

我有两个相同 MxN维度的稀疏矩阵A和B(slam::simple_triplet_matrix),其中M = ~100K,N = ~150K。

我希望计算每对行之间的余弦距离(即矩阵A的行1和矩阵B的行1,矩阵A的行2和矩阵B的行2等)。

我可以使用for循环或使用apply函数来执行此操作,但这样做太慢了,例如:

library(slam)

A <- simple_triplet_matrix(1:3, 1:3, 1:3)
B <- simple_triplet_matrix(1:3, 3:1, 1:3)

cosine <- NULL
for (i in 1:(dim(A)[1])) {
    a <- as.vector(A[i,])
    b <- as.vector(B[i, ])
    cosine[i] <- a %*% b / sqrt(a%*%a * b%*%b)
}

我理解this先前提出的问题可能有助于我,但是:

a)这不是我想要的,我只想要M行的M余弦距离,而不是给定稀疏矩阵的行之间的所有成对相关。

b)我承认没有完全理解这个“矢量化”解决方案背后的数学原理,所以也许有些解释可以派上用场。

谢谢。

编辑:这也不是this问题的重复,因为我不仅仅对两个简单向量的常规余弦计算感兴趣(我清楚地知道如何做到这一点,见上文),我是对更大规模的情况感兴趣,特别是涉及大量稀疏矩阵。

2 个答案:

答案 0 :(得分:3)

根据文档,simple_triplet_matrices的兼容row_sumssimple_triplet_matrices的逐个元素(数组)乘法是可用的。使用这些运算符/函数,计算结果为:

cosineDist <- function(A, B){
  row_sums(A * B) / sqrt(row_sums(A * A) * row_sums(B * B)) 
}

注意:

  1. row_sums(A * B)计算A中每一行及其B中相应行的点积,这是cosine中的分子项。结果是一个向量(非稀疏),其元素是A和B中每个对应行的这些点积。
  2. row_sums(A * A)计算A中每行的平方2范数。结果是一个向量(非稀疏),其元素是A中每行的平方2范数。
  3. 同样,row_sums(B * B)计算B中每行的平方2范数。结果是一个向量(非稀疏),其元素是B中每行的2平方。
  4. 计算的其余部分对这些向量进行操作,其元素用于A和/或B的每一行。

答案 1 :(得分:0)

cosineDist <- function(x){
  as.dist(1 - x%*%t(x)/(sqrt(rowSums(x^2) %*% t(rowSums(x^2))))) 
}