机器学习——KMeans聚类

  1. KMeans 是最常用的聚类算法.
  2. 数据任然使用iris.arff数据,不使用最后一项属性。
  3. getRandomIndices() 和 kMeans 的完全相同, 拷贝过来.
  4. distance() 和 KMeans 的相似, 注意不要用决策属性, 而且参数不同. 第 2 个参数为实数向量, 这是类为中心可能为虚拟的, 而中心点那里并没有对象.
    代码:
package machinelearning.kmeans;

import weka.core.Instance;
import weka.core.Instances;

import java.io.FileReader;
import java.util.Arrays;
import java.util.Random;

public class KMeans {
    /**
     * Manhattan distance.
     */
    public static final int MANHATTAN = 0;

    /**
     * Euclidean distance.
     */
    public static final int EUCLIDEAN = 1;

    /**
     * The distance measure.
     */
    public int distanceMeasure = EUCLIDEAN;

    /**
     * A random instance;
     */
    public static final Random random = new Random();
    /**
     * The data.
     */
    Instances dataset;
    /**
     * The number of clusters.
     */
    int numClusters = 2;

    /**
     * The clusters.
     */
    int[][] clusters;

    public KMeans(String paraFilename) {
        dataset = null;
        try {
            FileReader fileReader = new FileReader(paraFilename);
            dataset = new Instances(fileReader);
            fileReader.close();
        } catch (Exception e) {
            System.out.println("Cannot read the file: " + paraFilename + "\r\n" + e);
            System.exit(0);
        }// of try
    }// of the first constructor.

    public void setNumClusters(int paraNumClusters) {
        this.numClusters = paraNumClusters;
    }

    /**
     * Get a random indices for data randomization.
     * @param paraLength thr length of the sequence.
     * @return An array of indices.
     */
    public static int[] getRandomIndices(int paraLength) {
        int[] resultIndices = new int[paraLength];

        // Step 1. Initialize.
        for (int i = 0; i < paraLength; i++) {
            resultIndices[i] = i;
        } // Of for i

        // Step 2. Randomly swap.
        int tempFirst, tempSecond, tempValue;
        for (int i = 0; i < paraLength; i++) {
            // Generate two random indices.
            tempFirst = random.nextInt(paraLength);
            tempSecond = random.nextInt(paraLength);

            // Swap.
            tempValue = resultIndices[tempFirst];
            resultIndices[tempFirst] = resultIndices[tempSecond];
            resultIndices[tempSecond] = tempValue;
        } // Of for i

        return resultIndices;
    }// Of getRandomIndices

    public double distance(int paraI,double[] paraArray) {
        int resultDistance = 0;
        double tempDifference;
        switch (distanceMeasure) {
            case MANHATTAN:
                for (int i = 0; i < dataset.numAttributes() - 1; i++) {
                    tempDifference = dataset.instance(paraI).value(i) - paraArray[i];
                    if (tempDifference < 0) {
                        resultDistance -= tempDifference;
                    } else {
                        resultDistance += tempDifference;
                    }// of if
                }// of for i
                break;

            case EUCLIDEAN:
                for (int i = 0; i < dataset.numAttributes() - 1; i++) {
                    tempDifference = dataset.instance(paraI).value(i) - paraArray[i];
                    resultDistance += tempDifference * tempDifference;
                }// of for i
                break;
            default:
                System.out.println("Unsupported distance measure: " + distanceMeasure);
        }// of switch
        return resultDistance;
    }// of distance
    public void clustering() {
        int[] tempOldClusterArray = new int[dataset.numInstances()];
        tempOldClusterArray[0] = -1;
        int[] tempClusterArray = new int[dataset.numInstances()];
        Arrays.fill(tempClusterArray,0);
        double[][] tempCenters = new double[numClusters][dataset.numAttributes() - 1];

        //Step 1. Initialize centers.
        int[] tempRandomOrders = getRandomIndices(dataset.numInstances());
        for (int i = 0; i < numClusters; i++) {
            for (int j = 0; j < tempCenters[0].length; j++) {
                tempCenters[i][j] = dataset.instance(tempRandomOrders[i]).value(j);
            }// of for j
        }// of for i

        int[] tempClusterLengths = null;
        while(!Arrays.equals(tempOldClusterArray,tempClusterArray)) {
            System.out.println("New loop ...");
            tempOldClusterArray = tempClusterArray;
            tempClusterArray = new int[dataset.numInstances()];

            // Step 2.1 Minimization. Assign cluster to each instance.
            int tempNearestCenter;
            double tempNearestDistance;
            double tempDistance;

            for (int i = 0; i < dataset.numInstances(); i++) {
                tempNearestCenter = -1;
                tempNearestDistance = Double.MAX_VALUE;

                for (int j = 0; j < numClusters; j++) {
                    tempDistance = distance(i,tempCenters[j]);
                    if(tempNearestDistance > tempDistance) {
                        tempNearestDistance = tempDistance;
                        tempNearestCenter = j;
                    }// of if
                }// of for j
                tempClusterArray[i] = tempNearestCenter;
            }// of for i

            //Step 2.2 Mean. Find new centers.
            tempClusterLengths = new int[numClusters];
            Arrays.fill(tempClusterLengths,0);
            double[][] tempNewCenters = new double[numClusters][dataset.numAttributes() - 1];

            for (int i = 0; i < dataset.numInstances(); i++) {
                for (int j = 0; j < tempNewCenters[0].length; j++) {
                    tempNewCenters[tempClusterArray[i]][j] += dataset.instance(i).value(j);
                }// of for j
                tempClusterLengths[tempClusterArray[i]]++;
            }// of for i

            //Step 2.3 Now average
            for (int i = 0; i < tempNewCenters.length; i++) {
                for (int j = 0; j < tempNewCenters[0].length; j++) {
                    tempNewCenters[i][j] /= tempClusterLengths[i];
                }
            }// of for i
            //tempNewCenters = tempRealCenters(tempNewCenters);//*****
            System.out.println("Now the new centers are: " + Arrays.deepToString(tempNewCenters));
            tempCenters = tempNewCenters;

        }// of while

        // Step 3. Form clusters.
        clusters = new int[numClusters][];
        int[] tempCounters = new int[numClusters];
        for(int i = 0; i < numClusters; i++) {
            clusters[i] = new int[tempClusterLengths[i]];

        }// of for i

        for (int i = 0; i < tempClusterArray.length; i++) {
            clusters[tempClusterArray[i]][tempCounters[tempClusterArray[i]]] = i;
            tempCounters[tempClusterArray[i]]++;
        }
        System.out.println("The clusters are: " + Arrays.deepToString(clusters));

    }// of clustering

    
    public static void testClustering() {
        KMeans tempKMeans = new KMeans("D:\\研究生学习\\测试文件\\iris.arff");
        tempKMeans.setNumClusters(3);
        tempKMeans.clustering();
    }// of testClustering

    public static void main(String[] args) {
        testClustering();
    }
}// of class KMeans

运行结果:

New loop ...
Now the new centers are: [[5.044230769230769, 3.4000000000000004, 1.5942307692307693, 0.29999999999999993], [5.21, 2.3600000000000003, 3.38, 1.02], [6.387499999999997, 2.9284090909090916, 5.0806818181818185, 1.7500000000000007]]
New loop ...
Now the new centers are: [[5.005999999999999, 3.4180000000000006, 1.464, 0.2439999999999999], [5.556, 2.612, 3.892, 1.2080000000000002], [6.49733333333333, 2.9586666666666672, 5.244000000000002, 1.832]]
New loop ...
Now the new centers are: [[5.005999999999999, 3.4180000000000006, 1.464, 0.2439999999999999], [5.758139534883719, 2.730232558139535, 4.176744186046512, 1.3232558139534882], [6.642105263157891, 2.9789473684210517, 5.456140350877192, 1.9421052631578946]]
New loop ...
Now the new centers are: [[5.005999999999999, 3.4180000000000006, 1.464, 0.2439999999999999], [5.89344262295082, 2.750819672131147, 4.391803278688525, 1.4327868852459016], [6.838461538461538, 3.0615384615384604, 5.7102564102564095, 2.056410256410256]]
New loop ...
Now the new centers are: [[5.005999999999999, 3.4180000000000006, 1.464, 0.2439999999999999], [5.95735294117647, 2.7720588235294112, 4.463235294117647, 1.486764705882353], [6.909375000000001, 3.084374999999999, 5.846874999999999, 2.0781249999999996]]
New loop ...
Now the new centers are: [[5.007843137254902, 3.400000000000001, 1.4941176470588236, 0.2607843137254901], [6.0126760563380275, 2.7985915492957747, 4.525352112676057, 1.523943661971831], [6.935714285714286, 3.0714285714285707, 5.939285714285714, 2.082142857142857]]
New loop ...
Now the new centers are: [[5.007843137254902, 3.400000000000001, 1.4941176470588236, 0.2607843137254901], [6.035135135135134, 2.808108108108108, 4.564864864864864, 1.5391891891891891], [6.980000000000001, 3.0759999999999996, 5.991999999999998, 2.1039999999999996]]
New loop ...
Now the new centers are: [[5.007843137254902, 3.400000000000001, 1.4941176470588236, 0.2607843137254901], [6.035135135135134, 2.808108108108108, 4.564864864864864, 1.5391891891891891], [6.980000000000001, 3.0759999999999996, 5.991999999999998, 2.1039999999999996]]
The clusters are: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 98], [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 99, 101, 106, 110, 111, 112, 113, 114, 115, 116, 119, 121, 123, 126, 127, 133, 137, 138, 139, 141, 142, 145, 146, 147, 148, 149], [100, 102, 103, 104, 105, 107, 108, 109, 117, 118, 120, 122, 124, 125, 128, 129, 130, 131, 132, 134, 135, 136, 140, 143, 144]]

你可能感兴趣的:(聚类,机器学习,kmeans)