【问题标题】:Clustering items from matrix从矩阵中聚类项目
【发布时间】:2013-10-10 00:20:52
【问题描述】:

我有一本这种格式的字典

items = {"0":'lorem ipsum', "1":'blah blah', "2":'blah", "3":'lorem',.....}

假设len(items) = 70

我有一个 70x70 矩阵,其中包含每对字典的值。例如,matrix[4][20] 表示字典中第 4 项和第 20 项之间的值。

我想对字典项进行聚类,并将所有值超过某个阈值的项放在同一个组中。我不知道我的方法是不是最好的方法。也许有一个图书馆可以比我的更快地完成同样的事情。因为我的矩阵可能是 10000x10000。

size = range(0,len(items))
t = 1
mydict = {}
for i in size:
    mylist = items[i]
    size.remove(i)
    for j in size:
        if items[j] in lis:
            pass
        elif matrix[i][j] > 0.50:
            mylist.append(items[j])
            size.remove(j)
    mydict[t] = mylist
    t = t + 1
    mylist = [] 

然后我打印所有超过 5 个项目的组。

for i in mydict:
    if len(mydict[i]) > 5:
        print mydict[i]
        print ""

您是否发现任何错误?知道任何库或更好的算法来做到这一点吗?

更新 这是一个更好的例子:

items = {"0": 'item 0', "1":'item 1', "2":'item 2', "3":'item 3', "4":'item 4', "5":'item 5'}

matrix = [[1.0 0.2 0.7 0.8 0.3 0.1],
          [0.2 1.0 0.2 0.3 0.6 0.2],
          [0.7 0.2 1.0 0.7 0.2 0.3],
          [0.8 0.3 0.7 1.0 0.2 0.4],
          [0.3 0.6 0.2 0.2 1.0 0.1],
          [0.1 0.2 0.3 0.4 0.1 1.0]]

**The results:**

[item 0, item 2, item 3]

[item 1, item 4]

[item 5]

矩阵是三角形的,对角线上的所有点都是1。

【问题讨论】:

  • 您能否提供一个传入字典和所需结果的说明性示例?
  • 传入的字典与示例相同,但值不同。关键是一个从 0 到 len(items) 的 int。现在的输出是每个组的列表。我将尝试使用 dic、矩阵和结果创建一个示例
  • @J0HN 我用一个例子更新了这个问题。
  • 矩阵是对字典或只是输入/配置参数的一些计算的产物?
  • 是字典的值的文本相似度。

标签: python cluster-analysis


【解决方案1】:

这听起来像您正在尝试使用单链接进行层次链接聚类,然后使用给定的阈值进行切割。

这基本上等同于最小生成树 (MST) 问题,而且速度也差不多:O(n^2) 其中n 是项目数。

所以我相信你的算法是合理的。请注意,层次聚类的 SciPy 实现仅支持 Ward 链接,不支持单链接,并且可能具有O(n^3) 复杂度。

如果您想让事情变得更快,请尽量不要首先构建矩阵。但是保留一组集群,并通过一次添加一个元素来适当地加入这些集群。本质上,对于每个新项目,找到所有高于阈值的项目。那么你可以得到三种情况: 1. 附近没有其他集群。然后使用当前项目启动一个新集群。 2.正好有一个簇,把当前项加入这个簇。 3. 集群不止一个。合并所有这些,然后添加当前项。

class cluster:
    def __init__(self, first):
        self.members = [first]

mydict = {}
for i in range(0,len(items)):
    nearby = set()
    for j in range(0, i):
        if matrix[i][j] > 0.5: nearby.add(mydict[j])
    if len(nearby) == 0:
        mydict[i] = cluster(i)
    else:
        mydict[i] = nearby.pop()
        mydict[i].members.append(i)
        for other in nearby: # merge other clusters
            mydict[i].members.extend(other.members)
            for k in other.members: mydict[k] = mydict[i]

请注意,我故意只跟踪整数。节省内存是处理大型数据集的关键,而整数正是您拥有的最有效的实体。

【讨论】:

  • 我喜欢你的想法。我已经用 scipy 实现了分层聚类,但它比我的方式慢。今天下午我会试试你的方法,如果有人提出任何建议,我会等待,否则,我会选择你的答案作为最佳答案:)
猜你喜欢
  • 2014-12-18
  • 2023-03-12
  • 1970-01-01
  • 2014-01-12
  • 2015-01-07
  • 1970-01-01
  • 2017-08-06
  • 2016-10-01
相关资源
最近更新 更多