基于相似度分数的可视化聚类

Posted

技术标签:

【中文标题】基于相似度分数的可视化聚类【英文标题】:Visualizing clustering based on similarity score 【发布时间】:2016-01-29 00:22:35 【问题描述】:

我有以下交叉表数据:

            biz   user1  user2  user3  user4
    user
    A         1      1      0      0
    B         1      1      0      0
    C         1      1      1      0
    D         1      0      0      0
    E         0      0      1      1
    F         0      0      1      1
    G         0      0      1      1
    J         0      0      0      1
    M         0      1      0      0

并使用协方差将其变为:

   [ 1.  ,  0.75,  0.25,  0.  ],
   [ 0.75,  1.  ,  0.25,  0.  ],
   [ 0.25,  0.25,  1.  ,  0.75],
   [ 0.  ,  0.  ,  0.75,  1.  ]

使用以下代码,我尝试绘制这些数据:

   import pandas as pd
   import numpy as np
   import networkx as nx

    users=[]
    user_s=[(x+',')*4 for x in ['user1', 'user2', 'user3', 'user4']]
    for s in user_s:
        users.extend([e for e in s.split(',') if e!=''])

    X=[]
    user_s=[(x+',')*4 for x in ['32.5', '32.2', '30.4', '31.5']]
    for s in user_s:
        X.extend([float(e) for e in s.split(',') if e!=''])

    Y=[]
    user_s=[(x+',')*4 for x in ['-110', '-110', '-115', '-114']]
    for s in user_s:
        Y.extend([float(e) for e in s.split(',') if e!=''])    

    dat=pd.DataFrame('user':users, 
        'biz':['A', 'B', 'C', 'D', 'A', 'B', 'C', 'M', 'C', 'E', 'F', 'G', 'E', 'F', 'G', 'J'],
        'X':X, 'Y':Y)

    rel=pd.crosstab(dat.user, dat.biz, rownames=['biz'], colnames=['user']).transpose()
    cov=np.dot(rel.transpose(), rel)/np.diag(np.dot(rel.transpose(), rel))
    dat.groupby('user').mean()[['X', 'Y']]
    dat.groupby('user').mean()[['X', 'Y']]
    G=nx.Graph()
    for i in rel.columns.tolist():
        G.add_node(i, X=dat.loc[dat.user==i, 'X'].mean(), Y=dat.loc[dat.user==i, 'Y'].mean())


    for i in np.arange(0, cov.shape[0]):
        idx=np.where(cov[i,]>.0)[0].tolist() ##for column i, get index of cov values above quantile p
        for j in idx:
            if i!=j: #eliminates (0,0) as an edge bc its redundant
                G.add_edge(rel.columns[i],
                rel.columns[j],weight=cov[i,j],length=1/cov[i,j], width=cov[i,j])

    centrality=nx.degree_centrality(G)    
    pos=nx.spring_layout(G)
    nx.draw(G,pos, node_size=[centrality[key]*500 for key in centrality.keys()],
        cm=plt.cm.Spectral,edge_cm=plt.cm.Blues,
        width=[(x[2]['width']*2)**2 for x in G.edges(data=True)], alpha=.5)  
    nx.draw_networkx_labels(G,pos,fontsize=16) 

graph produced by above code

注意 user1 和 user2 是如何高度相关的,user3 和 user4 也是如此;而两个集群之间的关系较弱。

我想做两件事:

让两个组有相同的颜色(告诉集群的成员) 让 user1 和 user2 之间的距离小于 user1 和 user3 之间的距离。对于 user3 和 user4 也是如此。

我是绘图新手,所以如果您能建议一种有助于聚类的算法,我将不胜感激。

我的主要目标是在更大的数据集(10k 用户)上对此进行可视化

【问题讨论】:

【参考方案1】:

您可能还想考虑dendrogram。

您可以使用scipy 生成一个。

【讨论】:

【参考方案2】:

在问题的图表中,连接由用户之间的非零权重决定;因此,要检查高度 类似的组,我将需要计为连接的权重定义为相关性高于 0.75 的权重。这会产生岛屿 并且可以使用以下函数绘制为不同的组:

    G=nx.Graph()
    G.add_nodes_from(['u1', 'u2', 'u3', 'u4', 'u5', 'u6', 'u7', 'u8'])
    G.add_edges_from([
    ('u1', 'u2', 'weight':.75),  ('u1','u5', 'weight':1),('u2', 'u5', 'weight':.75),
    ('u3', 'u6', 'weight':.8), ('u4', 'u6', 'weight':.65),('u3', 'u4', 'weight':.75),
    #('u3', 'u7', 'weight':.5),
    #('u2', 'u4', 'weight':.3),
    ('u7', 'u8', 'weight':.9)])

    def draw_group_graph(graph, edge_cmap=plt.cm.Blues,node_cmap=plt.cm.jet, w_pwr=3):
        plt.figure()
        pos=nx.spring_layout(graph)

        nx.draw_networkx_edges(graph,pos,
        width=[nx.get_edge_attributes(graph,'weight')[i]*w_pwr for i in  G.edges()],
        edge_cmap=edge_cmap, 
        edge_color=[nx.get_edge_attributes(graph,'weight')[i] for i in  G.edges()])

        nx.draw_networkx_edge_labels(G, pos, labels=[str(i) for i in weights])

        g_list=[j for j in nx.connected_component_subgraphs(graph) if len(j.edges())>0]

        col_val=np.linspace(0,1,num=len(g_list)).tolist()
        i=0; print(len(g_list))
        for g in g_list:
            print(i, "color:",node_cmap(col_val[i]) )
            nx.draw_networkx_nodes(g, pos, node_color=node_cmap(col_val[i]), alpha=.6,
            node_size=[nx.degree_centrality(g)[i]*1000 for i in  g.nodes()])
            nx.draw_networkx_labels(g, pos, fontsize=16)
            i=i+1

Above defined graph plotted using different groups

【讨论】:

你从哪里得到“权重”? @ethanenglish 权重来自归一化协方差矩阵;以上是加权图。

以上是关于基于相似度分数的可视化聚类的主要内容,如果未能解决你的问题,请参考以下文章

给定单词相似度推断句子相似度

余弦相似度聚类

AP聚类算法介绍

有没有一种根据 Jaccard 相似度对图进行聚类的有效方法?

使用 Jaccard 相似度对分类数据进行聚类

聚类算法(相似度与性能度量)