15

私は単純な単変量データセットを予め設定された数のクラスタにクラスタリングする必要があります。技術的にはデータが1Dなのでビニングやソートに近づくでしょうが、私の上司はそれをクラスタリングと呼んでいますので、その名前に固執します。 私が使用しているシステムで使用されている現在の方法はK平均ですが、それは過度のようです。scikitでカーネル密度推定を1Dクラスタリング方法としてどのように使うのでしょうか?

このタスクを実行するより良い方法はありますか?

KDE(Kernel Density Estimation)について言及していますが、それは密度推定方法です。どのように機能しますか?

KDEがどのように密度を返すかを見ていますが、データをビンに分割する方法を教えてください。

私の要件の1つであるデータとは独立した固定数のビンを持つにはどうすればよいですか?

具体的には、scikitを使ってこれをどのように取り除きますか?

私の入力ファイルは次のようになります。私は、このようなことを、クラスタまたはビンにSLS番号グループにしたい

str ID  sls 
1   10 
2   11 
3   9 
4   23 
5   21 
6   11 
7   45 
8   20 
9   11 
10   12 

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 
+0

k-meansの関心事は何ですか?パフォーマンス? –

+0

kmeansがkdeより効率的です – lejlot

+0

@DavidMaust 1)単変量データでsklearnのk-meansを実行しようとしたとき、エラーが発生しました。元の1dデータと同一のコピーである2dデータにクラスタリングすることで、それを騙さなければなりませんでした。 2)この[投稿](http://stackoverflow.com/a/11516590/3967806)によると、それは悪い考えです。 –

答えて

24

自分でコードを書いてください。それはあなたの問題に一番合っています!

定型文:ネットからダウンロードしたコードは、正しいか最適かを決して想定しないでください。使用する前に十分に理解してください。

%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) 

enter image description here

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') 

enter image description here

赤いマーカーでカットします。緑のマーカは、クラスタセンターのための最良の推定値です。

+0

私はこの方法をk-meansよりも良く呼ぶことを躊躇します。任意の帯域幅を選択し、次に50個の密度推定値を計算することを含む。カーネル密度の推定では、より良い方法があるかどうかはわかりません。 –

+4

あなたはkを知る必要はありません。あなたはより良いセンター(外れ値の影響を受けにくい)だけでなく、音の分割ポイント(半分だけでなく)を取得します。シルバーマンのルールのような帯域幅に関する文献はたくさんあります。また、 50の密度推定値を計算することに誰が気をつけますか?あなたはカーネルをあらかじめ計算し、これを高速コンボリューションで行うことができます。 –

+0

これは、1Dクラスタリングに対して特に高速で非線形のスケーリング方法であるとも付け加えます。 – Matthew

関連する問題