分かりやすいデータに X-means を適用した結果

下記のプログラムに示すように,4クラスから成るデータに対して,クラスタ数の下限を2,上限を5として X-means 法によるクラスタリングを行った.
(参考:下限・上限を指定しない場合のデフォルト値は「下限 2,上限 4」である)

// 配列データを Weka のインスタンスとして x-means 法を適用する.
/*
test.txt の内容は以下のとおり.2次元空間において,4クラスから成ると想定する.
----------------------------
1.0,1.0,label
1.1,1.0,label
1.0,1.1,label
4.0,1.0,label
4.1,1.0,label
4.1,1.1,label
1.0,4.0,label
1.0,4.1,label
1.1,4.1,label
4.0,4.0,label
4.1,4.0,label
4.1,4.1,label
----------------------------
 */

// [コンパイル&実行]
// javac -cp weka.jar WekaXmeans.java
// java -cp weka.jar:. WekaXmeans

import java.io.*;
import weka.core.*;
import weka.clusterers.*;
import weka.core.neighboursearch.KDTree;

public class WekaXmeans {
    public static void main(String[] args) throws Exception {

	//属性名の設定
	FastVector attributes = new FastVector();
	attributes.addElement(new Attribute("attribute1"));
	attributes.addElement(new Attribute("attribute2"));

	//インスタンス集合の定義
	Instances dataClusterer = new Instances("test", attributes, 0);

	/// iris.txt からのデータ読み込み & インスタンス集合の生成(ここから) ///
	try {
	    BufferedReader fin = new BufferedReader(
						    new FileReader("test.txt"));
	    String s;
	    while((s = fin.readLine()) != null){
		String[] ss = s.split(",");

		//インスタンス1個分のデータを配列に入れておいて・・・
		int dimension = 2;
		double[] data = new double[dimension];
		for(int i = 0; i < dimension; i++) data[i] = Double.parseDouble(ss[i]);

		//インスタンスを作り・・・
		Instance instance = new Instance(1.0, data);

		//インスタンス集合に追加(登録)する
		dataClusterer.add(instance);
	    }
	    
	    fin.close();
	} catch(Exception e){
	    System.err.println("データ読み込み中にエラー");
	    System.exit(1);
	}
	/// iris.txt からのデータ読み込み & インスタンス集合の生成(ここまで) ///

	
	////////// clusterer(クラスタリングモデル)を作る //////////
	// クラスタリング手法として x-means 法を用いる
	XMeans clusterer = new XMeans();
	clusterer.setMinNumClusters(2);
	clusterer.setMaxNumClusters(5);

	//setOptions メソッドを用いてオプションを設定する場合,以下のようにする.
	/*
	String[] options = {"-L", "2",
			    "-H", "7",
			    "-use-kdtree",
			    "-K", "weka.core.neighboursearch.KDTree -P"};
	clusterer.setOptions(options);
	*/

	clusterer.buildClusterer(dataClusterer); //学習データを与えて clusterer を構築

	////////// clusterer(クラスタリングモデル)の評価 //////////
	ClusterEvaluation eval = new ClusterEvaluation();
	eval.setClusterer(clusterer);  // 評価したい clusterer を設定
	eval.evaluateClusterer(dataClusterer);  // テストデータとして元データを与える

	////////// clusterer の評価結果(サマリ)を出力 //////////
	System.out.println(eval.clusterResultsToString());

	// クラスタリングの結果として割り当てられたクラス番号を得る
	double[] assignment = eval.getClusterAssignments();
	for(int i = 0; i < assignment.length; i++){
	    System.out.print((int)assignment[i] + " ");
	}
    }
}

実行結果は以下のとおりで,4個のクラスタを検出できた.

XMeans
======
Requested iterations            : 1
Iterations performed            : 1
Splits prepared                 : 2
Splits performed                : 2
Cutoff factor                   : 0.5
Percentage of splits accepted 
by cutoff factor                : 0 %
------
Cutoff factor                   : 0.5
------

Cluster centers                 : 4 centers

Cluster 0
            4.066666666666666 4.033333333333333
Cluster 1
            4.066666666666666 1.0333333333333334
Cluster 2
            1.0333333333333334 4.066666666666666
Cluster 3
            1.0333333333333334 1.0333333333333334

Distortion: 5.841547
BIC-Value : -8.862267
Clustered Instances

0       3 ( 25%)
1       3 ( 25%)
2       3 ( 25%)
3       3 ( 25%)

3 3 3 1 1 1 2 2 2 0 0 0

ちなみに,Iris データでも試してみたが,(相変わらず)2個のクラスタしか得られなかった.