R:计算两个稀疏矩阵行之间的余弦距离
R: Calculate cosine distance between rows of two sparse matrices
我有两个 相同 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) 我承认我没有完全理解这个 'vectorized' 解决方案背后的数学原理,所以也许一些解释会派上用场。
谢谢。
编辑:这也不是 this 问题的重复,因为我不仅对两个简单向量的常规余弦计算感兴趣(我清楚地知道如何做到这一点,见上文),我我对更大规模的情况感兴趣,特别是涉及 slam 稀疏矩阵。
cosineDist <- function(x){
as.dist(1 - x%*%t(x)/(sqrt(rowSums(x^2) %*% t(rowSums(x^2)))))
}
根据文档,simple_triplet_matrices
的兼容 simple_triplet_matrices
和 row_sums
的逐个元素(数组)乘法是可用的。使用这些 operators/functions,计算结果为:
cosineDist <- function(A, B){
row_sums(A * B) / sqrt(row_sums(A * A) * row_sums(B * B))
}
备注:
row_sums(A * B)
计算 A
中每一行与其在 B
中对应行的点积,这是 cosine
中的分子项。结果是一个向量(非稀疏),其元素是 A 和 B 中每个对应行的这些点积。
row_sums(A * A)
计算 A
中每一行的平方 2 范数。结果是一个向量(非稀疏),其元素是 A 中每一行的这些平方 2 范数。
- 类似地,
row_sums(B * B)
计算 B
中每一行的平方 2 范数。结果是一个向量(非稀疏),其元素是 B 中每一行的这些平方 2 范数。
- 其余的计算对这些向量进行操作,这些向量的元素是 A and/or B 的每一行。
我有两个 相同 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) 我承认我没有完全理解这个 'vectorized' 解决方案背后的数学原理,所以也许一些解释会派上用场。
谢谢。
编辑:这也不是 this 问题的重复,因为我不仅对两个简单向量的常规余弦计算感兴趣(我清楚地知道如何做到这一点,见上文),我我对更大规模的情况感兴趣,特别是涉及 slam 稀疏矩阵。
cosineDist <- function(x){
as.dist(1 - x%*%t(x)/(sqrt(rowSums(x^2) %*% t(rowSums(x^2)))))
}
根据文档,simple_triplet_matrices
的兼容 simple_triplet_matrices
和 row_sums
的逐个元素(数组)乘法是可用的。使用这些 operators/functions,计算结果为:
cosineDist <- function(A, B){
row_sums(A * B) / sqrt(row_sums(A * A) * row_sums(B * B))
}
备注:
row_sums(A * B)
计算A
中每一行与其在B
中对应行的点积,这是cosine
中的分子项。结果是一个向量(非稀疏),其元素是 A 和 B 中每个对应行的这些点积。row_sums(A * A)
计算A
中每一行的平方 2 范数。结果是一个向量(非稀疏),其元素是 A 中每一行的这些平方 2 范数。- 类似地,
row_sums(B * B)
计算B
中每一行的平方 2 范数。结果是一个向量(非稀疏),其元素是 B 中每一行的这些平方 2 范数。 - 其余的计算对这些向量进行操作,这些向量的元素是 A and/or B 的每一行。