ClusteringΒΆ

Example of how to cluster a set of points. The points are randomly drawn from three different distributions. The clustering algorithm will attempt to dermine which points belong to the same set.

Clusters

Output from example. Each cluster has its own color and each point is colorized to show the cluster it belongs to.

ExampleClustering.java

  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
 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
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// if true it will create the clusters from a gaussian distribution.
// Otherwise an uniform distribution is used.
public static boolean gaussian = true;
public static Random rand = new Random(324);
public static boolean clicked = false;

public static void main(String[] args) {
    List<double[]> points = new ArrayList<double[]>();

    // create 3 clusters drawn from a uniform square distribution
    points.addAll( createCluster(5,7,2,100) );
    points.addAll( createCluster(1,2,1,120) );
    points.addAll( createCluster(4,5,1.5,300) );

    // remove any structure from the point's ordering
    Collections.shuffle(points);

    ComputeClusters<double[]> cluster = FactoryClustering.kMeans_F64(null,1000,100, 1e-8);
    // ComputeClusters<double[]> cluster = FactoryClustering.gaussianMixtureModelEM_F64(1000, 1e-8);

    cluster.init(2, rand.nextLong());

    // visualization stuff
    Gui gui = new Gui(points);

    JFrame frame = new JFrame();
    frame.add(gui,BorderLayout.CENTER);
    frame.pack();
    frame.setVisible(true);
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

    // Run the cluster algorithm again each time the user clicks the window
    // This allows you to see how stable the clusters are
    while( true ) {

        cluster.process(points, 3);

        AssignCluster<double[]> assignment = cluster.getAssignment();
        gui.update(assignment);

        while( !clicked ) {
            Thread.yield();
        }
        clicked = false;
    }
}

public static List<double[]> createCluster( double x , double y , double width , int N ) {

    List<double[]> points = new ArrayList<double[]>();

    for (int i = 0; i < N; i++) {
        double[] p = new double[2];

        if ( gaussian ) {
            p[0] = rand.nextGaussian()*width/3+x;
            p[1] = rand.nextGaussian()*width/3+y;
        } else {
            p[0] = rand.nextDouble()*width-width/2+x;
            p[1] = rand.nextDouble()*width-width/2+y;
        }

        points.add(p);
    }

    return points;
}

/**
 * Basic visualization which draws the points in a window.  Each color is assigned a different random color
 */
public static class Gui extends JPanel implements MouseListener {
    AssignCluster<double[]> assignment;
    List<double[]> points;
    Color colors[];

    public Gui( List<double[]> points) {

        this.points = points;

        setPreferredSize(new Dimension(300,300));
        setBackground(Color.WHITE);

        addMouseListener(this);
    }

    public synchronized void update( AssignCluster<double[]> assignment ) {
        this.assignment = assignment;
        colors = new Color[ assignment.getNumberOfClusters() ];
        for (int i = 0; i < colors.length; i++) {
            colors[i] = new Color(rand.nextInt() | 0x080808);
        }
        repaint();
    }

    @Override
    public synchronized void paintComponent(Graphics g) {
        if( assignment == null )
            return;

        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D)g;

        double scaleX = getWidth()/10.0;
        double scaleY = getHeight()/10.0;


        for (int i = 0; i < points.size(); i++) {
            double[] p = points.get(i);
            int x = (int)(p[0]*scaleX+0.5);
            int y = (int)(p[1]*scaleY+0.5);

            g2.setColor(colors[assignment.assign(p)]);
            g2.fillOval(x-2,y-2,5,5);
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        clicked = true;
    }

    @Override public void mousePressed(MouseEvent e) {}
    @Override public void mouseReleased(MouseEvent e) {}
    @Override public void mouseEntered(MouseEvent e) {}
    @Override public void mouseExited(MouseEvent e) {}
}