【问题标题】:Text clustering with Levenshtein distances具有 Levenshtein 距离的文本聚类
【发布时间】:2014-02-26 00:29:53
【问题描述】:

我有一组 (2k - 4k) 小字符串(3-6 个字符),我想对它们进行聚类。由于我使用字符串,How does clustering (especially String clustering) work? 上的先前答案告诉我 Levenshtein distance 很适合用作字符串的距离函数。另外,由于我事先不知道集群的数量,hierarchical clustering 是要走的路,而不是 k-means。

虽然我以抽象的形式解决了这个问题,但我不知道实际解决问题的简单方法是什么。例如,对于使用自定义函数(Levenshtein 距离)实际实现层次聚类,MATLAB 还是 R 是更好的选择。 对于这两种软件,人们都可以轻松找到 Levenshtein 距离实现。聚类部分似乎更难。例如Clustering text in MATLAB 计算所有字符串的距离数组,但我不明白如何使用距离数组来实际获得聚类。你们中的任何一位大师能否向我展示如何使用自定义函数在 MATLAB 或 R 中实现层次聚类的方法?

【问题讨论】:

  • 这取决于您使用的层次聚类类型。 Single linkage & complete linkage HC 可以只用一个距离矩阵来执行,所以一旦你通过任何方法获得了它,正常的聚类函数(例如,hclust)应该可以正常工作。 OTOH、average 链接或 Ward 方法需要在每一步重新计算距离,因此实现起来会更加复杂。
  • 因此在 MATLAB 中 Z = linkage(Y,method) 将使用计算的距离矩阵和完整的方法。对吗?
  • 我只能猜测答案是“是”。自从我使用 MATLAB 以来已经有很长时间了,而且我从未使用它进行任何聚类。

标签: r matlab cluster-analysis levenshtein-distance hierarchical-clustering


【解决方案1】:

ELKI 包括 Levenshtein 距离,并提供多种高级聚类算法选择,例如 OPTICS 聚类。

Felix Stahlberg 贡献了文本聚类支持,作为他工作的一部分:

Stahlberg, F.、Schlippe, T.、Vogel, S. 和 Schultz, T.
通过跨语言单词到音素对齐的分词。
口语语言技术研讨会 (SLT),2012 年 IEEE。 IEEE,2012。

我们当然会感谢其他贡献。

【讨论】:

  • +1。我听说过 ELKI,我的许多同事都在使用它。如果您想投入必要的时间,ELKI 是一个有效的选择。但是在 Elki 中,R 代码有 10 行长,我必须重载许多 Java 类才能初步了解结果。最好快速查看初始结果,即使基于非最优算法也比浪费 15-30 天来学习框架只是为了看看我的方法不正确。所以,R现在很好。以后,ELKI 可能是更好的解决方案。
  • ELKI 需要一个脚本 API,我一直在考虑添加 Groovy,但还没有时间这样做。有了 R,我并没有因为性能而太高兴。任何不是矩阵的东西都很慢,并且矩阵运算以O(n^2) 或更差的方式扩展。如果我想快速尝试一些东西,我发现 scipy 通常是最好的脚本语言,而且由于 Cython 代码,它的速度通常非常快。
【解决方案2】:

如果您想清楚地了解如何使用分区聚类(肯定会更快)来解决您的问题,请查看这篇论文:使用聚类算法的有效拼写检查方法。 https://www.researchgate.net/publication/255965260_Effective_Spell_Checking_Methods_Using_Clustering_Algorithms?ev=prf_pub

作者解释了如何使用 iK-Means 的修改(类似 PAM)版本对字典进行聚类。

祝你好运!

【讨论】:

  • 那么,R 是否实现了 iK-Means 的这个修改(类似 PAM)版本?此方法是否自动提取聚类数?如果没有,即使它真的是最先进的,我也没有办法实际实现聚类算法。此外,慢速部分必须是距离矩阵,而不是聚类。
  • ...仍然为您的贡献 +1
  • 是的,它会自动获取集群的数量。据我所知,它没有 R 版本,但是,它应该不难实现(在 Matlab 中它只有大约 80 行)。
【解决方案3】:

这可能有点简单,但这里有一个代码示例,它使用基于 R 中的 Levenshtein 距离的层次聚类。

set.seed(1)
rstr <- function(n,k){   # vector of n random char(k) strings
  sapply(1:n,function(i){do.call(paste0,as.list(sample(letters,k,replace=T)))})
}

str<- c(paste0("aa",rstr(10,3)),paste0("bb",rstr(10,3)),paste0("cc",rstr(10,3)))
# Levenshtein Distance
d  <- adist(str)
rownames(d) <- str
hc <- hclust(as.dist(d))
plot(hc)
rect.hclust(hc,k=3)
df <- data.frame(str,cutree(hc,k=3))

在本例中,我们人工创建了一组 30 个随机 char(5) 字符串,分为 3 组(以“aa”、“bb”和“cc”开头)。我们使用adist(...) 计算 Levenshtein 距离矩阵,并使用hclust(...) 运行层次聚类。然后我们用cutree(...)将树状图分成三个簇,并将簇ID附加到原始字符串中。

【讨论】:

  • 那么,d sj) 的 levenshtein 吗?另外,我是否需要包含一个 R 包才能使其工作?
  • adist(...) 位于 utils 包中,当您启动 R 会话时,该包通常默认加载。它计算一个完整的距离矩阵,这就是为什么您需要 as.dist(d) 将其转换为 hclust(...) 理解为距离对象的东西。为文档键入 ?adist
  • 有没有办法用这个解决方案找出集群的数量?
【解决方案4】:

虽然答案在一定程度上取决于字符串的含义,但一般而言,您的问题可以通过序列分析系列技术来解决。更具体地说,最佳匹配分析 (OMA)。

OMA 通常分三个步骤进行。首先,你定义你的序列。根据您的描述,我可以假设每个字母都是一个单独的“状态”,是一个序列中的构建块。其次,您将使用几种算法之一来计算数据集中所有序列之间的距离,从而获得距离矩阵。最后,您将该距离矩阵输入聚类算法,例如层次聚类或围绕中心点分区 (PAM),由于有关聚类质量的附加信息,该算法似乎越来越受欢迎。后者指导您选择簇数,这是序列分析中的几个主观步骤之一。

R中,最方便的功能丰富的包是TraMineR,网址可以找到here。它的用户指南非常易于访问,开发人员也或多或少地活跃在 SO 上。

您可能会发现聚类并不是最困难的部分,除了聚类数量的决定。 TraMineR 的指南表明语法非常简单,并且基于视觉序列图很容易解释结果。以下是用户指南中的示例:

clusterward1 <- agnes(dist.om1, diss = TRUE, method = "ward")

dist.om1 是 OMA 获得的距离矩阵,集群成员包含在 clusterward1 对象中,您可以做任何您想做的事情:绘图、重新编码为变量等。diss=TRUE 选项表示数据object 是相异(或距离)矩阵。容易吧?最困难的选择(不是语法上,而是方法上)是选择适合您特定应用的正确距离算法。一旦你有了这个,能够证明选择的合理性,剩下的就很容易了。祝你好运!

【讨论】:

  • 我看过序列模式匹配,但定义字母表似乎有点过头了,因为距离(abc,abd)=距离(abc,abf)。那么为什么要定义字典,因为我们只检查不等式 f!=c 与 e!=c 相同。不过,为您的努力 +1。
  • 字母表是自动定义的,对所有可能的状态进行采样。当然,您可以更改它。常规 OM 算法将在 (abc,abd) 和 (abc,abf) 之间分配完全相同的距离。在这两种情况下,距离都基于一个替换,并且它的成本是相同的,假设您没有为这些特定字母分配差异成本。当然,如果您的问题与其他解决方案一样简单,那完全没问题。您也可以使用 PAM 代替 HC。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-16
  • 2016-08-09
  • 1970-01-01
  • 1970-01-01
  • 2014-04-20
  • 1970-01-01
  • 2016-11-18
相关资源
最近更新 更多