【问题标题】:Problem with creating bar plots for KMeans-based clustering algorithm为基于 KMeans 的聚类算法创建条形图的问题
【发布时间】:2021-12-03 13:00:28
【问题描述】:

我正在努力为基于 KMeans 的聚类算法绘制条形图。问题是我想以这样的方式演示集群,即可以在 x 轴的末端描绘非常异常的集群,而其余的集群保持相对相邻。我认为问题是xsticks,它们在x轴上平均分布:

---|---|---|-----------------> x-axis
0  1   2   3 

在这种情况下,我想证明这一点,例如基于 Score 标记为 3 的集群预测的位置有点远,需要对 bin 宽度进行一些调整,可能如下所示:

---|---|--------------|------> x-axis
0  1   2              3 

到目前为止,我得到了以下结果来展示基于 KM 的算法在异常值检测方面的结果:

from sklearn.cluster import KMeans
import seaborn as sns
import numpy as np
from pandas import DataFrame
from math import pow
import math

class ODKM:
    
    def __init__(self,n_clusters=15,effectiveness=500,max_iter=2):
        self.n_clusters=n_clusters
        self.effectiveness=effectiveness
        self.max_iter=max_iter
        self.kmeans = {}
        self.cluster_score = {}
        #self.labels = {}
        
    def fit(self, data):
        length = len(data)
        for column in data.columns:
            kmeans = KMeans(n_clusters=self.n_clusters,max_iter=self.max_iter)
            self.kmeans[column]=kmeans
            kmeans.fit(data[column].values.reshape(-1,1))
            assign = DataFrame(kmeans.predict(data[column].values.reshape(-1,1)),columns=['cluster'])
            cluster_score=assign.groupby('cluster').apply(len).apply(lambda x:x/length)
            ratio=cluster_score.copy()
        
            sorted_centers = sorted(kmeans.cluster_centers_)
            max_distance = ( sorted_centers[-1] - sorted_centers[0] )[ 0 ]
        
            for i in range(self.n_clusters):
                for k in range(self.n_clusters):
                    if i != k:
                        dist = abs(kmeans.cluster_centers_[i] - kmeans.cluster_centers_[k])/max_distance
                        effect = ratio[k]*(1/pow(self.effectiveness,dist))
                        cluster_score[i] = cluster_score[i]+effect
                        
            self.cluster_score[column] = cluster_score
                    
    def predict(self, data):
        length = len(data)
        score_array = np.zeros(length)
        for column in data.columns:
            kmeans = self.kmeans[ column ]
            cluster_score = self.cluster_score[ column ]
            #labels = kmeans.labels_ 
            assign = kmeans.predict( data[ column ].values.reshape(-1,1) )
            #print(assign)
            
            for i in range(length):
                score_array[i] = score_array[i] + math.log10( cluster_score[assign[i]] )
            
        return score_array #,labels
    
    def fit_predict(self,data):
        self.fit(data)
        return self.predict(data)

测试结果:

import pandas as pd

df = pd.DataFrame(data={'attr1':[1,1,1,1,2,2,2,2,2,2,2,2,3,5,5,6,6,7,7,7,7,7,7,7,15],
                        'attr2':[1,1,1,1,2,2,2,2,2,2,2,2,3,5,5,6,6,7,7,7,13,13,13,14,15]})

#generate score from KM-based algorithm via class ODKM
odkm_model = ODKM(n_clusters=3, max_iter=1)
result = odkm_model.fit_predict(df)

#include generated scores to the main frame to reach desired plot
df['ODKM_Score']= result 
df

#for i in result:
#    print(round(i,2))

#results
#-0.51, -0.51 , -0.51 , -0.51, -0.51, -0.51, -0.51, -0.51, -0.51, -0.51, -0.51, -0.51, -0.51
#-0.78, -0.78, -0.78, -0.78, -0.78, -0.78, -0.78
#-0.99, -0.99, -0.99, -0.99
#-1.99

您可以在colab notebook 中找到我的整个代码,包括这个基于 KM 的算法,以便快速调试。如果您需要,请随时在笔记本上实施您的解决方案或在单元格上发表评论,或者 ODKM 算法本身(执行 KM 集群的地方​​)的一些更改已被脚本化,可以以 @class ODKM 的形式访问。也许最好提取预测的集群标签并在 Cluster_label 的标题下添加一个新列 ODKM 算法 Score 以便更好地访问条形图。

预期的输出应该是这样的(相同集群中更好的 bin 具有相同的颜色,例如 1st cluster C1):

更新:除了条形图解决方案之外,我还可以绘制 Hist 和分布图,但我不知道如何着色和传递聚类标签以按预期在直方图中的 bin 上反映聚类结果.

##left output
# just plot 'Score' column (not all columsn in 1st phase) to simply the problem
#cols_ = df.columns[-1:] 
ax1 = plt.subplot2grid((1,1), (0,0))
df['Score'].plot(kind='hist', ax=ax1 , color='b', alpha=0.4)
df['Score'].plot(kind='kde', ax=ax1, secondary_y=True, label='distribution', color='b', lw=2)

##Right output
sns.distplot(df['Score'] , color='b')

尽管在图表上反映了聚类结果,但我注意到存在一些差异,正如我在下图中强调的那样,这两个图 e。 G。 y 轴的比例和靠近 x 轴原点的主要 bin 之间的间隙问题:

我也发现了这个post,但我无法适应@class ODKM 来动态解决我的问题。 我最近也可以做到这一点:

df['Score'] = df['Score'].abs()
sns.displot(df, 
            x='Score',
            hue='Cluster_labels',
            palette=["#00f0f0","#ff0000","#00ff00"],
             alpha=1)

【问题讨论】:

  • 您想仅根据分数值分配集群标签,还是还想包括其他列?
  • 这个问题和KMeans或聚类有什么关系吗?我建议您简化有关绘图的问题。
  • @warped Right,仅适用于 Score 列上的所有列。但在此之前,我们需要使用.labels_ 属性返回@class ODKM: 内部的预测标签,就像docs 中一样。
  • @mwaskom 我指的是 KM 聚类方法,如果有机会通过使用聚类计算以 条形图 达到所需的输出 e。 g,在 x 轴上操作以突出显示 out cluster(s) 的刻度。

标签: python matplotlib seaborn cluster-analysis k-means


【解决方案1】:
import pandas as pd


df = pd.DataFrame(data={'attr1':[1,1,1,1,2,2,2,2,2,2,2,2,3,5,5,6,6,7,7,7,7,7,7,7,15],
                        'attr2':[1,1,1,1,2,2,2,2,2,2,2,2,3,5,5,6,6,7,7,7,13,13,13,14,15]
                        })

import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN

def kmeans_scatterplot(df):

    column_i = 'attr1'
    column_j = 'attr2'

    df_temp = df[[column_i, column_j]]
    
    # model
    y_pred = DBSCAN(eps = 3, min_samples = 1).fit_predict(df_temp)
    
    # plot
    plt.scatter(df_temp[column_i], df_temp[column_j], c=y_pred, cmap='rainbow', alpha=0.7, edgecolors='b')

    plt.show()
kmeans_scatterplot(df)

这个聚类只需要指定距离,然后我们就可以根据类别标注颜色了。

帮助你快速了解这个算法的原理:https://www.naftaliharris.com/blog/visualizing-dbscan-clustering/

【讨论】:

  • 我理解您的观点,但 class ODKM 是基于 KMeas 的。这个想法是在ODKM_Score Histot-distribution 上反映class ODKM 内的KMeans 聚类结果(如条形图,例如displotdistplot)。请查看您的解决方案 outputODKM_Score 的分布比较。起初我以为你提供使用 DBSCAN 方法来可视化和反映 ODKM_Score 上的 ODKM 类的结果,但问题是如何收集 KMeans 聚类信息 within class ODKM 以反映 @987654332 @ 输出是ODKM_Score
【解决方案2】:

对于一维情况,您可以使用簇的中心作为条形的 x 位置。

n_clusters=3

km = KMeans(init='k-means++', n_clusters=n_clusters).fit(df[['Score']])

counts = np.bincount(km.labels_)

for center, count, label in zip(km.cluster_centers_, counts, range(n_clusters)):
    print(center, count)
    plt.bar(center, count, width=0.2, label=label)

【讨论】:

  • 感谢您的意见。我稍微编辑了您的答案并添加了一个图例,但我尝试更改 color argumenet 以突出显示 离群值集群栏,但未成功。第二个问题是@class ODKM 我可以检索聚类信息centercountlabel?你检查了colab notebook 的第一个单元格吗?
  • 我没有看你的 colab 笔记本。请编辑您的问题,使其重现您的问题并包含相关部分,并且请不要链接到外部内容。
  • 我进行了编辑,以便您可以检查它并在 class ODKM 中检索 KM 信息,并在可能的情况下返回它,并希望绘制 class ODKM 的结果,即来自 @987654331 的所谓 'ODKM_Score' @
猜你喜欢
  • 2020-11-18
  • 1970-01-01
  • 2020-02-04
  • 2013-03-24
  • 2011-10-24
  • 2021-11-21
  • 1970-01-01
  • 2017-04-07
  • 1970-01-01
相关资源
最近更新 更多