如何将核密度估计用作 scikit 学习中的一维聚类方法?
How would one use Kernel Density Estimation as a 1D clustering method in scikit learn?
我需要将一个简单的单变量数据集聚类到预设数量的聚类中。从技术上讲,它更接近于对数据进行分箱或排序,因为它只是一维的,但我的老板称其为聚类,所以我将坚持使用该名称。
我所使用的系统当前使用的方法是 K-means,但这似乎有点矫枉过正。
是否有更好的方法来执行此任务?
其他一些帖子的答案提到了KDE(内核密度估计),但这是一种密度估计方法,它是如何工作的?
我看到 KDE 如何 returns 一个密度,但我如何告诉它把数据分成 bins?
如何拥有独立于数据的固定数量的 bin(这是我的要求之一)?
更具体地说,如何使用 scikit learn 实现这一目标?
我的输入文件如下所示:
str ID sls
1 10
2 11
3 9
4 23
5 21
6 11
7 45
8 20
9 11
10 12
我想将 sls 编号分组到集群或容器中,这样:
Cluster 1: [10 11 9 11 11 12]
Cluster 2: [23 21 20]
Cluster 3: [45]
我的输出文件将如下所示:
str ID sls Cluster ID Cluster centroid
1 10 1 10.66
2 11 1 10.66
3 9 1 10.66
4 23 2 21.33
5 21 2 21.33
6 11 1 10.66
7 45 3 45
8 20 2 21.33
9 11 1 10.66
10 12 1 10.66
自己写代码。那么它最适合你的问题!
样板文件:永远不要假设您从网上下载的代码是正确的或最佳的...确保在使用它之前完全理解它。
%matplotlib inline
from numpy import array, linspace
from sklearn.neighbors.kde import KernelDensity
from matplotlib.pyplot import plot
a = array([10,11,9,23,21,11,45,20,11,12]).reshape(-1, 1)
kde = KernelDensity(kernel='gaussian', bandwidth=3).fit(a)
s = linspace(0,50)
e = kde.score_samples(s.reshape(-1,1))
plot(s, e)
from scipy.signal import argrelextrema
mi, ma = argrelextrema(e, np.less)[0], argrelextrema(e, np.greater)[0]
print "Minima:", s[mi]
print "Maxima:", s[ma]
> Minima: [ 17.34693878 33.67346939]
> Maxima: [ 10.20408163 21.42857143 44.89795918]
因此您的集群是
print a[a < mi[0]], a[(a >= mi[0]) * (a <= mi[1])], a[a >= mi[1]]
> [10 11 9 11 11 12] [23 21 20] [45]
在视觉上,我们做了这样的拆分:
plot(s[:mi[0]+1], e[:mi[0]+1], 'r',
s[mi[0]:mi[1]+1], e[mi[0]:mi[1]+1], 'g',
s[mi[1]:], e[mi[1]:], 'b',
s[ma], e[ma], 'go',
s[mi], e[mi], 'ro')
我们在红色标记处切入。绿色标记是我们对聚类中心的最佳估计。
@Has QUIT 接受的答案有一点错误--Anony-Mousse(由于我的声誉,我不能评论也不能建议修改)。
行:
print(a[a < mi[0]], a[(a >= mi[0]) * (a <= mi[1])], a[a >= mi[1]])
应编辑为:
print(a[a < s[mi][0]], a[(a >= s[mi][0]) * (a <= s[mi][1])], a[a >= s[mi][1]])
那是因为mi
和ma
是一个索引,其中s[mi]
和s[ma]
是值。如果您使用 mi[0]
作为限制,如果您的上限和下限 linspace >> 您的上限和下限数据,您将面临分裂的风险和错误。例如,运行这段代码,看拆分结果的区别:
import numpy as np
from numpy import array, linspace
from sklearn.neighbors import KernelDensity
from matplotlib.pyplot import plot
from scipy.signal import argrelextrema
a = array([10,11,9,23,21,11,45,20,11,12]).reshape(-1, 1)
kde = KernelDensity(kernel='gaussian', bandwidth=3).fit(a)
s = linspace(0,100)
e = kde.score_samples(s.reshape(-1,1))
mi, ma = argrelextrema(e, np.less)[0], argrelextrema(e, np.greater)[0]
print('Grouping by HAS QUIT:')
print(a[a < mi[0]], a[(a >= mi[0]) * (a <= mi[1])], a[a >= mi[1]])
print('Grouping by yasirroni:')
print(a[a < s[mi][0]], a[(a >= s[mi][0]) * (a < s[mi][1])], a[a >= s[mi][1]])
结果:
Grouping by Has QUIT:
[] [10 11 9 11 11 12] [23 21 45 20]
Grouping by yasirroni:
[10 11 9 11 11 12] [23 21 20] [45]
我需要将一个简单的单变量数据集聚类到预设数量的聚类中。从技术上讲,它更接近于对数据进行分箱或排序,因为它只是一维的,但我的老板称其为聚类,所以我将坚持使用该名称。 我所使用的系统当前使用的方法是 K-means,但这似乎有点矫枉过正。
是否有更好的方法来执行此任务?
其他一些帖子的答案提到了KDE(内核密度估计),但这是一种密度估计方法,它是如何工作的?
我看到 KDE 如何 returns 一个密度,但我如何告诉它把数据分成 bins?
如何拥有独立于数据的固定数量的 bin(这是我的要求之一)?
更具体地说,如何使用 scikit learn 实现这一目标?
我的输入文件如下所示:
str ID sls
1 10
2 11
3 9
4 23
5 21
6 11
7 45
8 20
9 11
10 12
我想将 sls 编号分组到集群或容器中,这样:
Cluster 1: [10 11 9 11 11 12]
Cluster 2: [23 21 20]
Cluster 3: [45]
我的输出文件将如下所示:
str ID sls Cluster ID Cluster centroid
1 10 1 10.66
2 11 1 10.66
3 9 1 10.66
4 23 2 21.33
5 21 2 21.33
6 11 1 10.66
7 45 3 45
8 20 2 21.33
9 11 1 10.66
10 12 1 10.66
自己写代码。那么它最适合你的问题!
样板文件:永远不要假设您从网上下载的代码是正确的或最佳的...确保在使用它之前完全理解它。
%matplotlib inline
from numpy import array, linspace
from sklearn.neighbors.kde import KernelDensity
from matplotlib.pyplot import plot
a = array([10,11,9,23,21,11,45,20,11,12]).reshape(-1, 1)
kde = KernelDensity(kernel='gaussian', bandwidth=3).fit(a)
s = linspace(0,50)
e = kde.score_samples(s.reshape(-1,1))
plot(s, e)
from scipy.signal import argrelextrema
mi, ma = argrelextrema(e, np.less)[0], argrelextrema(e, np.greater)[0]
print "Minima:", s[mi]
print "Maxima:", s[ma]
> Minima: [ 17.34693878 33.67346939]
> Maxima: [ 10.20408163 21.42857143 44.89795918]
因此您的集群是
print a[a < mi[0]], a[(a >= mi[0]) * (a <= mi[1])], a[a >= mi[1]]
> [10 11 9 11 11 12] [23 21 20] [45]
在视觉上,我们做了这样的拆分:
plot(s[:mi[0]+1], e[:mi[0]+1], 'r',
s[mi[0]:mi[1]+1], e[mi[0]:mi[1]+1], 'g',
s[mi[1]:], e[mi[1]:], 'b',
s[ma], e[ma], 'go',
s[mi], e[mi], 'ro')
我们在红色标记处切入。绿色标记是我们对聚类中心的最佳估计。
@Has QUIT 接受的答案有一点错误--Anony-Mousse(由于我的声誉,我不能评论也不能建议修改)。
行:
print(a[a < mi[0]], a[(a >= mi[0]) * (a <= mi[1])], a[a >= mi[1]])
应编辑为:
print(a[a < s[mi][0]], a[(a >= s[mi][0]) * (a <= s[mi][1])], a[a >= s[mi][1]])
那是因为mi
和ma
是一个索引,其中s[mi]
和s[ma]
是值。如果您使用 mi[0]
作为限制,如果您的上限和下限 linspace >> 您的上限和下限数据,您将面临分裂的风险和错误。例如,运行这段代码,看拆分结果的区别:
import numpy as np
from numpy import array, linspace
from sklearn.neighbors import KernelDensity
from matplotlib.pyplot import plot
from scipy.signal import argrelextrema
a = array([10,11,9,23,21,11,45,20,11,12]).reshape(-1, 1)
kde = KernelDensity(kernel='gaussian', bandwidth=3).fit(a)
s = linspace(0,100)
e = kde.score_samples(s.reshape(-1,1))
mi, ma = argrelextrema(e, np.less)[0], argrelextrema(e, np.greater)[0]
print('Grouping by HAS QUIT:')
print(a[a < mi[0]], a[(a >= mi[0]) * (a <= mi[1])], a[a >= mi[1]])
print('Grouping by yasirroni:')
print(a[a < s[mi][0]], a[(a >= s[mi][0]) * (a < s[mi][1])], a[a >= s[mi][1]])
结果:
Grouping by Has QUIT:
[] [10 11 9 11 11 12] [23 21 45 20]
Grouping by yasirroni:
[10 11 9 11 11 12] [23 21 20] [45]