通过 KMeans 聚类确定双峰分布的阈值

Posted

技术标签:

【中文标题】通过 KMeans 聚类确定双峰分布的阈值【英文标题】:Determining a threshold value for a bimodal distribution via KMeans clustering 【发布时间】:2017-06-28 05:55:01 【问题描述】:

我想找到双峰分布的阈值。例如,双峰分布可能如下所示:

import numpy as np
import matplotlib.pyplot as plt
np.random.seed(45)
n = 1000; b = n//10; i = np.random.randint(0,2,n)
x = i*np.random.normal(-2.0,0.8,n) + (1-i)*np.random.normal(2.0,0.8,n)
_ = plt.hist(x,bins=b)

寻找聚类中心的尝试没有奏效,因为我不确定矩阵 h 应该如何格式化:

from sklearn.cluster import KMeans
h = np.histogram(x,bins=b)
h = np.vstack((0.5*(h[1][:-1]+h[1][1:]),h[0])).T  # because h[0] and h[1] have different sizes.
kmeans = KMeans(n_clusters=2).fit(h)

我希望能够在 -2 和 2 附近找到聚类中心。阈值将是两个聚类中心的中点。

【问题讨论】:

【参考方案1】:

您的问题让我有点困惑,所以如果我的解释有误,请告诉我。我认为您基本上是在尝试进行 1D kmeans,并尝试将频率作为第二维引入以使 KMeans 工作,但真的很高兴 [-2,2] 作为中心的输出而不是 [(-2,y1), (2,y2)]

要进行一维 kmeans,您只需将数据重塑为 1 长度向量的 n(类似问题:Scikit-learn: How to run KMeans on a one-dimensional array?)

代码:

import numpy as np
import matplotlib.pyplot as plt
np.random.seed(45)
n = 1000;
b = n//10;
i = np.random.randint(0,2,n)
x = i*np.random.normal(-2.0,0.8,n) + (1-i)*np.random.normal(2.0,0.8,n)
_ = plt.hist(x,bins=b)

from sklearn.cluster import KMeans
h = np.histogram(x,bins=b)
h = np.vstack((0.5*(h[1][:-1]+h[1][1:]),h[0])).T  # because h[0] and h[1] have different sizes.

kmeans = KMeans(n_clusters=2).fit(x.reshape(n,1))
print kmeans.cluster_centers_

输出:

[[-1.9896414]
 [ 2.0176039]]

【讨论】:

以上是关于通过 KMeans 聚类确定双峰分布的阈值的主要内容,如果未能解决你的问题,请参考以下文章

关于k-means算法的聚类分析

matlab 图像处理 二值化

用 r 在双峰分布中找到局部最小值

基于K-means聚类算法的图像分割

MATLAB教程案例23基于MATLAB图像分割算法仿真——阈值分割法Otsu阈值分割法K均值聚类分割法等

自适应阈值化操作:adaptiveThreshold()函数