R:使用tm和代理计算与术语 - 文档矩阵的余弦距离

时间:2015-04-20 14:22:14

标签: r matrix proxy tm

我想计算语料库作者之间的余弦距离。让我们采用20个文档的语料库。

require(tm)
data("crude")
length(crude)
# [1] 20

我想找出这20个文件中的余弦距离(相似度)。我用

创建了一个术语 - 文档矩阵
tdm <- TermDocumentMatrix(crude,
                          control = list(removePunctuation = TRUE,
                                         stopwords = TRUE))

然后我必须将其转换为矩阵才能将其传递给代理包的dist()

tdm <- as.matrix(tdm)
require(proxy)
cosine_dist_mat <- as.matrix(dist(t(tdm), method = "cosine"))

最后,我删除余弦距离矩阵的对角线(因为我对文档与其自身之间的距离不感兴趣)并计算每个文档与语料库的另外19个文档之间的平均距离

diag(cosine_dist_mat) <- NA
cosine_dist <- apply(cosine_dist_mat, 2, mean, na.rm=TRUE)

cosine_dist
# 127       144       191       194 
# 0.6728505 0.6788326 0.7808791 0.8003223 
# 211       236       237       242 
# 0.8218699 0.6702084 0.8752164 0.7553570 
# 246       248       273       349 
# 0.8205872 0.6495110 0.7064158 0.7494145 
# 352       353       368       489 
# 0.6972964 0.7134836 0.8352642 0.7214411 
# 502       543       704       708 
# 0.7294907 0.7170188 0.8522494 0.8726240

到目前为止一直很好(有小型语料库)。问题是这种方法对于较大的文档集不能很好地扩展。由于两次调用as.matrix(),将tdm tm 传递到代理并最终计算平均值,因此效果似乎效率低下。

是否有可能设想一种更聪明的方法来获得相同的结果?

2 个答案:

答案 0 :(得分:14)

由于tm的术语文档矩阵只是稀疏的&#34;简单的三元组矩阵&#34;从slam包中,您可以使用那里的函数直接计算余弦相似度定义的距离:

library(slam)
cosine_dist_mat <- 1 - crossprod_simple_triplet_matrix(tdm)/(sqrt(col_sums(tdm^2) %*% t(col_sums(tdm^2))))

这利用了稀疏矩阵乘法。在我手中,220个文档中有2963个术语,97%稀疏度的tdm只花了几秒钟。

我还没想过这个,所以我不知道它是否比proxy::dist()更快。

注意:要使其正常工作,您应强制将tdm强制转换为常规矩阵,即不要tdm <- as.matrix(tdm)

答案 1 :(得分:9)

首先。伟大的代码MAndrecPhD!但我相信他的意思是写:

cosine_dist_mat <- crossprod_simple_triplet_matrix(tdm)/(sqrt(col_sums(tdm^2) %*% t(col_sums(tdm^2))))

他编写的代码返回相异度分数。我们希望对角线上的1是余弦相似度,而不是0。 https://en.wikipedia.org/wiki/Cosine_similarity。我可能会弄错,你们真的想要不同的分数,但我想我会提到它,因为我花了一点时间思考它。