I want to measure the time that KMColourSegmenter, in OpenIMAJ library, takes to perform the clustering.
If I didn't make the initial centroids fixed, rather than random, I can't make the measure the performance; because it will change every time, give different number of iterations , and vary in time to execute the clustering.
So how to make the initial centroids fixed i.e. setting them manually?
Update:
@Jon Thanks for the answer, I am trying to implement what you said. Could you check it, especially the "clusters" array I think this array doesn't make sense to initialize. Please, correct me if I am wrong.
public class MyFloatKMeansInit extends FloatKMeansInit{
@Override
public void initKMeans(DataSource<float[]> bds, float[][] clusters) throws IOException {
// TODO Auto-generated method stub
for (int i = 0; i < bds.size(); i++) {
for (int j = 0; j < bds.getData(i).length; j++) {
clusters[i][j]=bds.getData(i)[j];
}
}
}
}
public class MyKMColourSegmenter extends KMColourSegmenter{
public MyKMColourSegmenter(FloatArrayBackedDataSource bds, ColourSpace colourSpace, int K) throws IOException {
super(colourSpace, K);
MyFloatKMeansInit myFloatKMeansInit = new MyFloatKMeansInit();
float[][] clusters = new float[K][];//#######I think there is something wrong here
myFloatKMeansInit.initKMeans(bds, clusters);
this.kmeans.setInit(myFloatKMeansInit);
// TODO Auto-generated constructor stub
}
}
You'll have to implement this yourself; create a subclass of KMColourSegmenter
and create a constructor that takes in the centroids, as well as any parameters needed by your choice of constructor in the KMColourSegmenter
super class. Then in your constructor, after the call to super
, use the this.kmeans.setInit()
method to set a initialisation to use you predefined centroids. You'll need to implement a custom FloatKMeansInit
subclass that lets you set the centroids externally, but this should be trivial as it only requires implementing a single method.
Update in response to amended question:
You shouldn't call initKMeans
directly; that happens behind the scenes when you run the algorithm. You also need to populate the centroids array with the centroids initial centroids you want rather than from the bds
. For example (untested):
public class MyFloatKMeansInit extends FloatKMeansInit{
private float [][] mycentroids;
public MyFloatKMeansInit(float [][] mycentroids) {//modifying data type here
this.mycentroids = mycentroids;
}
@Override
public void initKMeans(DataSource<float[]> bds, float[][] clusters) throws IOException {
for (int i = 0; i < mycentroids.length; i++) {
for (int j = 0; j < mycentroids[i].length; j++) {
clusters[i][j]=mycentroids[i][j]; //could use arraycopy instead
}
}
}
}
public class MyKMColourSegmenter extends KMColourSegmenter{
public MyKMColourSegmenter(ColourSpace colourSpace, float[][] mycentroids) throws IOException {
super(colourSpace, mycentroids.length);
MyFloatKMeansInit myFloatKMeansInit = new MyFloatKMeansInit(mycentroids);
this.kmeans.setInit(myFloatKMeansInit);
}
}