You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何删除语料库中的相似文档?余弦相似度去重方案求助

解决重复文档删除问题:从余弦相似度到保留唯一文档

我懂你现在的困境:已经用余弦相似度找出了那些只有页眉页脚差异的重复新闻,但嵌套循环删除的方法总是出问题。其实不用纠结复杂的循环,我们可以用更高效的方式来分组并保留唯一文档。

先确认你的前期处理是对的

首先,你之前生成余弦相似度矩阵并转换为二值矩阵的代码没问题,先贴出来确认:

# 构建文档特征矩阵
myDfm <- dfm(as.character(docs$text_main), verbose=FALSE)
# 计算文档间余弦相似度
cosinesim <- textstat_simil(x=myDfm, selection=docnames(myDfm), margin="documents", method="cosine")
cosinemat <- as.matrix(cosinesim)

# 处理矩阵:对角线设为0,按阈值转换为二值矩阵
diag(cosinemat) <- 0
cosinemat[cosinemat >= 0.9] <- 1
cosinemat[cosinemat < 0.9] <- 0

方案1:用连通分量分组(推荐,高效处理多重复文档)

这种方法把相似文档看作图中的节点,相似的节点连在一起,然后把每个连通的节点组视为重复集合,每组只留一个文档。我们可以用igraph包来实现:

# 安装并加载igraph(如果没装的话)
if (!require(igraph)) {
  install.packages("igraph")
  library(igraph)
}

# 把二值相似度矩阵转换成无向图
g <- graph_from_adjacency_matrix(cosinemat, mode = "undirected", weighted = NULL)

# 获取每个文档所属的分组ID
doc_groups <- components(g)$membership

# 每组只保留第一个出现的文档,得到唯一文档集合
unique_docs <- docs[!duplicated(doc_groups), ]

这个方法的优势是不管一组里有多少个重复文档,都能一次性处理,不会出现循环中修改数据框导致的索引混乱问题。

方案2:基础R标记法(不用额外包)

如果你不想装新包,可以用标记法:先标记要保留的文档,最后再筛选,避免循环中修改原数据框:

# 初始化保留标记,默认全部保留
keep <- rep(TRUE, nrow(docs))

# 遍历每个文档
for (i in 1:nrow(cosinemat)) {
  if (!keep[i]) next  # 如果已经标记为删除,直接跳过
  
  # 找到所有和当前文档相似的文档
  duplicate_indices <- which(cosinemat[i, ] == 1)
  
  # 把这些重复项标记为不保留,只保留当前文档
  keep[duplicate_indices] <- FALSE
  keep[i] <- TRUE
}

# 筛选出保留的文档
unique_docs <- docs[keep, ]

额外优化:预处理去掉页眉页脚

其实你可以先预处理去掉页眉页脚,这样余弦相似度的计算会更准确,避免页眉的干扰:

# 用正则表达式去掉开头到"Body"的页眉部分,只留正文
docs$text_clean <- gsub("^.*Body", "", docs$text_main)

# 用清理后的正文构建dfm,再计算相似度
myDfm <- dfm(as.character(docs$text_clean), verbose=FALSE)

这样处理后,相似度的计算会更聚焦于正文内容,阈值设置也会更精准。

内容的提问来源于stack exchange,提问作者lispang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:07:57