boolean train(MatrixDouble data) {
        trained = false;

        if (numClusters == 0) {
            System.err.println("train_(MatrixDouble &data) - Failed to train model. NumClusters is zero!");
            return false;
        }

        if (data.getNumRows() == 0 || data.getNumCols() == 0) {
            System.err.println("train_(MatrixDouble &data) - The number of rows or columns in the data is zero!");
            return false;
        }

        numTrainingSamples = data.getNumRows();
        numInputDimensions = data.getNumCols();

//            /* DEBUG!!! */
//    System.out.println( "numTrainingSamples" + numTrainingSamples );
//    System.out.println( "numInputDimensions" + numInputDimensions );
  
        clusters.resize(numClusters, numInputDimensions);
        assign = new int[numTrainingSamples];
        count = new int[numClusters];

        //Randomly pick k data points as the starting clusters
        int[] randIndexs = new int[numTrainingSamples];
        for (int i = 0; i < numTrainingSamples; i++) {
            randIndexs[i] = i;
        }

        Random rand = new Random();

        for (int i = 0; i < numTrainingSamples; i++) {
            int change = i + rand.nextInt(numTrainingSamples - i);

            int temp = randIndexs[i];
            randIndexs[i] = randIndexs[change];
            randIndexs[change] = temp;
        }

        //Copy the clusters
        for (int k = 0; k < numClusters; k++) {
            for (int j = 0; j < numInputDimensions; j++) {

                double val = data.get(randIndexs[k], j);
                clusters.set(val, k, j);
            }
        }
        
//        /* DEBUG! */

        try {
            clusters.loadDataTxt("clusters.txt");
        } catch (Exception ex) {
            System.err.println(ex);
        }
        System.out.println("\nClusters:");
        clusters.print();
        
        return trainModel(data);
    }