各クラスターのポイント数が等しいクラスタリング手順?


25

にいくつかのポイントがあり、ポイントをクラスター化して次のようにします。X={x1,...,xn}Rp

  1. 各クラスターには、等しい数のの要素が含まれます。(クラスターの数が分割すると仮定します。)Xn

  2. 各クラスターは、平均のクラスターのように、ある意味で「空間的に凝集」しています。k

これらのいずれかを満たす多くのクラスタリング手順を考えるのは簡単ですが、誰もが両方を一度に取得する方法を知っていますか?


2
クラスターサイズも指定されていますか?そして、述べたように、問題は私には解決できないようです。して以下の場合考える:。2つのクラスターが必要な場合は、サイズが異なるか、「空間的に凝集」していません。または、「可能な限り空間的に凝集性」のようなものが必要ですか?クラスター内の最大距離などを最小化しますか?もう1つの解決策は、クラスターサイズとして約数を許可することですが、サイズクラスターの些細なソリューションが常に存在します。n=4p=1バツ={10.9911.01}nn1
エリックP.

1
いい視点ね。理想的には、等しいカーディナリティー制約を満たしながら、「可能な限り空間的に凝集性のある」何かが欲しいです。しかし、ここで他のトレードオフを行う手順についても聞いてみたいと思います。それらは適応できる可能性があるからです。
ダレットではない

データを変位値で分割するだけで十分ですか?値が互いに単調でない場合、他の値がどのように「空間的に凝集性」であるかを確認できません。
セレニウス

4
制約付きクラスタリングに関する最近の研究がいくつかあります。Googleはgoogle.com/search?q=constrained+k-means
whuber

テストされていないアイデアだけです。クラスタリングでは、いわゆるSilhouette統計がよく使用されます。オブジェクトがどれだけうまくクラスター化されているか、どのオブジェクトが登録可能な他の最良の近隣クラスターであるかを示します。したがって、K-MEANSまたは異なるクラスターnの他の分類から始めることができます。次に、(統計によると)あまりよく分類されていないオブジェクトを、等しいnが得られるまで、nがより小さい最適な近隣クラスターに移動します。いくつかのオブジェクトを移動したり、統計を再計算したり、オブジェクトを移動したりするなどの反復を期待しています。これはトレードオフプロセスになります。
ttnphns

回答:


6

2段階のアプローチをお勧めします。

  1. クラスタの中心の適切な初期推定を取得します。たとえば、ハードまたはファジーK平均を使用します。

  2. Global Nearest Neighbor割り当てを使用してポイントをクラスター中心に関連付けます:各ポイントと各クラスター中心間の距離行列を計算し(合理的な距離を計算するだけで問題を少し小さくすることができます)、各クラスター中心をX回複製し、線形を解きます課題問題。各クラスターセンターについて、データポイントと完全にXが一致するため、グローバルにデータポイントとクラスターセンター間の距離が最小化されます。

手順2の後にクラスター中心を更新し、手順2を繰り返して基本的にクラスターごとに固定数のポイントでK-meansを実行できることに注意してください。それでも、最初に適切な初期推測を取得することをお勧めします。


4

このk-meansバリエーションを試してください。

初期化

  • kデータセットからセンターをランダムに選択するか、kmeans ++戦略を使用してさらに良い
  • 各ポイントについて、その最も近いクラスター中心までの距離を計算し、このためのヒープを構築します
  • クラスターが既にいっぱいになっていない限り、ヒープからポイントを描画し、それらを最も近いクラスターに割り当てます。その場合、次に最も近いクラスター中心を計算し、ヒープに再挿入します

最終的に、クラスターごとに+ -1個の同じオブジェクト数の要件を満たすパーティションを作成する必要があります(最後のいくつかのクラスターにも正しい数があることを確認してmください。最初のクラスターにはceilオブジェクトがあり、残りは正確にfloorオブジェクトです)

反復ステップ

必要条件:「スワップ提案」(異なるクラスターにあることを好むオブジェクト)を持つ各クラスターのリスト。

Eステップ:通常のk-meansのように、更新されたクラスター中心を計算します

Mステップ:すべてのポイントを反復処理する(1つだけ、または1つのバッチですべて)

オブジェクトに最も近いクラスター中心/現在のクラスターより近いすべてのクラスター中心を計算します。別のクラスターの場合:

  • 他のクラスターが現在のクラスターよりも小さい場合は、新しいクラスターに移動するだけです
  • 他のクラスター(または距離の短いクラスター)からスワップの提案がある場合、2つの要素クラスターの割り当てをスワップします(複数のオファーがある場合、改善度が最も高いものを選択します)
  • そうでない場合は、他のクラスターのスワップ提案を示します

クラスターサイズは不変(+-天井/床の差)のままであり、オブジェクトは、推定値が改善される限り、あるクラスターから別のクラスターにのみ移動します。したがって、k-meansのようなある点で収束するはずです。ただし、少し遅い(つまり、繰り返しが多い)場合があります。

これが以前に公開または実装されたかどうかはわかりません。それは私が試してみただけです(k-meansを試してみると、はるかに優れたクラスタリングアルゴリズムがあります)。

開始するのに適した場所は、3つの異なる初期化(k-means ++を含む)を既にサポートしているように見えるELKIの k-means実装です。著者は、さまざまな一般的なモジュラー形式のバリアント(たとえば、ロイド、マックイーンなど)。


2
同様のアプローチがELKIのチュートリアルおよびチュートリアルの「拡張」モジュールに含まれています。elki.dbs.ifi.lmu.de / wiki
Erich Schubert

3

これは最適化の問題です。この問題を解決するオープンソースのJavaライブラリがあります(クラスタごとの数量が設定範囲内にある必要があるクラスタリング)。ただし、ポイントの合計数は最大で数千である必要があります-5000以下、または10000以下。

ライブラリは次のとおりです。

https://github.com/PGWelch/territorium/tree/master/territorium.core

ライブラリ自体は、地理的/ GISタイプの問題用に設定されているため、XとY、緯度と経度、顧客、距離と時間などへの参照が表示されます。ただし、「地理」要素は無視してもかまいません。クラスター。

それぞれが最小および最大の目標数量を持つ、最初は空の入力クラスターのセットを提供します。クラスタリングは、ヒューリスティックベースの最適化アルゴリズム(スワップ、移動など)を使用して、入力クラスターにポイントを割り当てます。最適化では、最初に各クラスターを最小および最大数量範囲内に維持することを優先し、次にクラスター内のすべてのポイントとクラスターの中心点間の距離を最小化するため、クラスターは空間的に凝集性があります。

このインターフェイスを使用して、ソルバーにポイント間のメトリック関数(距離関数)を与えます。

https://github.com/PGWelch/territorium/blob/master/territorium.core/src/main/java/com/opendoorlogistics/territorium/problem/TravelMatrix.java

メトリックは、実際には距離と「時間」の両方を返すように構成されています。これは、旅行ベースの地理的問題用に設計されているためですが、任意のクラスタリング問題では、「時間」をゼロに設定し、距離を実際のメトリックに設定するだけですポイント。

このクラスで問題を設定します:

https://github.com/PGWelch/territorium/blob/master/territorium.core/src/main/java/com/opendoorlogistics/territorium/problem/Problem.java

ポイントは「顧客」であり、その数量は1です。顧客クラスでは、TravelMatrixによって返される「距離」フィールドにメトリック距離を返すと仮定して、costPerUnitTime = 0およびcostPerUnitDistance = 1を設定します。

https://github.com/PGWelch/territorium/blob/master/territorium.core/src/main/java/com/opendoorlogistics/territorium/problem/Customer.java

ソルバーの実行例については、こちらをご覧ください:

https://github.com/PGWelch/territorium/blob/master/territorium.core/src/test/java/com/opendoorlogistics/territorium/TestSolver.java



2

最近、あまり大きくないデータセットにこれを自分で必要としました。私の答えは、実行時間が比較的長いにもかかわらず、ローカル最適に収束することが保証されています。

def eqsc(X, K=None, G=None):
    "equal-size clustering based on data exchanges between pairs of clusters"
    from scipy.spatial.distance import pdist, squareform
    from matplotlib import pyplot as plt
    from matplotlib import animation as ani    
    from matplotlib.patches import Polygon   
    from matplotlib.collections import PatchCollection
    def error(K, m, D):
        """return average distances between data in one cluster, averaged over all clusters"""
        E = 0
        for k in range(K):
            i = numpy.where(m == k)[0] # indeces of datapoints belonging to class k
            E += numpy.mean(D[numpy.meshgrid(i,i)])
        return E / K
    numpy.random.seed(0) # repeatability
    N, n = X.shape
    if G is None and K is not None:
        G = N // K # group size
    elif K is None and G is not None:
        K = N // G # number of clusters
    else:
        raise Exception('must specify either K or G')
    D = squareform(pdist(X)) # distance matrix
    m = numpy.random.permutation(N) % K # initial membership
    E = error(K, m, D)
    # visualization
    #FFMpegWriter = ani.writers['ffmpeg']
    #writer = FFMpegWriter(fps=15)
    #fig = plt.figure()
    #with writer.saving(fig, "ec.mp4", 100):
    t = 1
    while True:
        E_p = E
        for a in range(N): # systematically
            for b in range(a):
                m[a], m[b] = m[b], m[a] # exchange membership
                E_t = error(K, m, D)
                if E_t < E:
                    E = E_t
                    print("{}: {}<->{} E={}".format(t, a, b, E))
                    #plt.clf()
                    #for i in range(N):
                        #plt.text(X[i,0], X[i,1], m[i])
                    #writer.grab_frame()
                else:
                    m[a], m[b] = m[b], m[a] # put them back
        if E_p == E:
            break
        t += 1           
    fig, ax = plt.subplots()
    patches = []
    for k in range(K):
        i = numpy.where(m == k)[0] # indeces of datapoints belonging to class k
        x = X[i]        
        patches.append(Polygon(x[:,:2], True)) # how to draw this clock-wise?
        u = numpy.mean(x, 0)
        plt.text(u[0], u[1], k)
    p = PatchCollection(patches, alpha=0.5)        
    ax.add_collection(p)
    plt.show()

if __name__ == "__main__":
    N, n = 100, 2    
    X = numpy.random.rand(N, n)
    eqsc(X, G=3)

1
@ user2341646、この貢献に感謝します。このソリューションが何であるか、どのように機能するのか、なぜソリューションであるのかを説明する説明を追加していただけますか?
GUNG -復活モニカ

OK。基本的に、アルゴリズムはランダムなメンバーシップ割り当てから始まりますが、クラスター内にはGメンバーに近く、全体でKクラスターがあります。1つのクラスター内のデータ間の平均距離をすべてのクラスターで平均して測定するエラー関数を定義します。データのすべてのペアを体系的に調べて、これらの2つのデータのメンバーシップを交換すると、エラーが少なくなるかどうかを確認します。存在する場合は、可能な限り最小のエラーを更新し、存在しない場合はメンバーシップの切り替えを取り消します。1回のパス全体でこれ以上の動きがなくなるまでこれを行います。
アレクサンダーケイン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.