我写了一个函数,它在正态分布上做kmeans聚类。该函数可用于一维和二维正态分布。绘制1d kmeans集群很容易,可以使用以下方法完成:

    plot(data[idx==0,0],data[idx==0,1],'ob',
         data[idx==1,0],data[idx==1,1],'or',
         data[idx==2,0],data[idx==2,1],'og',
         data[idx==3,0],data[idx==3,1],'oy',
         data[idx==4,0],data[idx==4,1],'oc')

    plot(centroids[:,0],centroids[:,1],'sg',markersize=8)
    show()

会有这样的情节:
二维正态分布图如下:
二维正态分布有mean = [a b]var = [[p q],[r s]]
二维分布聚类得到的质心形状也与点的均值和方差相同(明显)。我面临的问题是绘制这些数据。如何使用python和matplotlib将其可视化。因此,一维情况下的点将被椭圆代替,质心也将是椭圆。集群应该类似于:
其中黑色椭圆是二维分布,红色椭圆是二维质心。
im用于绘制单个二维分布的绘图函数为:
def plot2DND(mean, variance):
    mean1 = mean.flatten()
    cov1 = variance

    nobs = 2500
    rvs1 = np.random.multivariate_normal(mean1, cov1, size=nobs)

    plt.plot(rvs1[:, 0], rvs1[:, 1], '.')
    plt.axis('equal')
    plt.show()

下图给出了需求的更好可视化(从:http://www.lix.polytechnique.fr/~nielsen/pdf/2008-C-ClusteringNormal-ETVC.pdf
是否可以使用python和matplotlib(或其他lib)实现类似的功能。或者,对于这种类型的数据,更好的可视化是可能的吗?

最佳答案

首先需要做的是更改绘图函数,以便它只绘制一个等高线,而不是所有点。您可以使用Ellipse来完成这项工作,并使用方差矩阵的特征值和特征向量来找到角度(我希望我做得对,可能需要方差是对称的)。

from matplotlib.patches import Ellipse

def plot_ellipse(mean, var, ec='k', alpha=1):
    evals, evecs = np.linalg.eig(var)
    ang = np.degrees(np.arctan2(*evecs[1]))
    ell = Ellipse(mean, *np.abs(evals), angle=ang, fc='None', ec=ec, alpha=alpha)
    plt.gca().add_artist(ell)

所以,假设你已经对数据做了任何你需要的处理,最后得到了类似于mean_centroidsvariance_centroids的东西,它们会有(k, 2)(k, 2, 2)形状。
colors = ['r', 'g', 'b'] # length of this should be `k`

for i, (m, v) in enumerate(zip(mean_centroids, variance_centroids)):
    plot_ellipse(m, v, ec=colors[i])

您可能有一个包含大量均值和方差的数据数组,因此您可以循环遍历所有这些数据,并按标签着色,这将从centroids, labels = kmeans2(data, k)中获得:
for i, m, v in zip(labels, means, variances):
    plot_ellipse(m, v, ec=colors[i], alpha=.5)

顺便说一下,您可以将第一个散点图示例替换为:
colors = ['b', 'r', 'g', 'y', 'c']
plt.scatter(*data.T, c=np.choose(ids, colors))

plt.plot(centroids[:,0],centroids[:,1],'sg',markersize=8)
show()

关于python - 以k均值绘制二维簇,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20566987/

10-11 15:22