QUESTION SUMMARY:
I have a [5 x 72580] matrix. I am trying to fit a Gaussian Mixture Model (GMM) to this data using the gmm_diag.learn() method with random_subset as the initial seeding mode. Why does Armadillo display "gmm_diag::learn(): no existing means" and fail to learn the model?
PROBLEM DETAILS:
I am working on a machine learning algorithm, the aim of which is to identify a writer from their handwriting. I am using supervised learning to train our model with a GMM.
All the training data is read from XML files. After calculating the features, their values are stored into a linked list. After this, the number of elements in the list is counted and is used to initialize an Armadillo mat(rix) variable at runtime as shown below:
int totFeatureVectors = CountPointClusterElements(TRAINING_CLUSTER_LIST_INDEX);
printf("\n%d elements added to list\n",totFeatureVectors);
mat F = mat(NUM_POINT_BASED_FEATURES, totFeatureVectors, fill::zeros);
Here TRAINING_CLUSTER_LIST_INDEX and NUM_POINT_BASED_FEATURES are a couple of configurable, project level constants; for my program NUM_POINT_BASED_FEATURES = 5 and totFeatureVectors = 72580. So the variable F is a [5 x 72580] dimensional matrix of double values. After initialization, I am reading the feature values from the linked list into F as follows:
int rowInd=0, colInd=0;
PointClusterElement *iterator = allClusterPointsList;
while(iterator!=NULL)
{
F(rowInd,colInd)=iterator->pointSample.speed;
rowInd += 1;
F(rowInd,colInd)=iterator->pointSample.dirn.cosComponent;
rowInd += 1;
F(rowInd,colInd)=iterator->pointSample.dirn.sinComponent;
rowInd += 1;
F(rowInd,colInd)=iterator->pointSample.curv.cosComponent;
rowInd += 1;
F(rowInd,colInd)=iterator->pointSample.curv.sinComponent;
rowInd += 1;
if(rowInd==NUM_POINT_BASED_FEATURES)
{
rowInd=0;
colInd += 1;
}
iterator=iterator->nextClusterElement;
}
The assignment of feature values to locations in F is being made in a column major manner i.e. each column of F represents a feature vector post assignment. I am even writing the values of F into a text file to verify that all the feature values have been properly set and yes, it is happening without any problems
FILE *fp = fopen(PROGRAM_DATA_OUTPUT_PATH,"w");
if(fp!=NULL)
{
int r,c;
for(c=0; c<totFeatureVectors; c++)
{
for(r=0; r<NUM_POINT_BASED_FEATURES; r++)
{
fprintf(fp,"%lf\t",F(r,c));
}
fprintf(fp,"\n");
}
}
fclose(fp);
So far, so good. But after this, when I declare a gmm_diag variable and try to fit a GMM to F using its learn() method, the program displays a warning "gmm_diag::learn(): no existing means" and quits, thus failing to learn the GMM (here the VARIANCE_FLOORING_FACTOR = 0.001)
gmm_diag writerModel;
bool result = writerModel.learn(F, 20, maha_dist, random_subset, 100, 100, VARIANCE_FLOORING_FACTOR, true);
writerModel.dcovs.print("covariances:\n");
writerModel.hefts.print("weights:\n");
writerModel.means.print("means:\n");
if(result==true)
{
printf("\nModel learnt");
}
else if(result==false)
{
printf("\nModel not learnt");
}
I opened up the learn() method on my IDE and from what I could make out, this error (warning) message is displayed only when the initial seeding mode is keep_existing. The source file I referred to is at /usr/include/armadillo_bits/gmm_diag_meat.hpp
My question is - why would this happen even when my seeding is done using the random_subset mode? How exactly should I proceed to get my model to learn? Not sure what I am missing here... The documentation and code samples provided at http://arma.sourceforge.net/docs.html#gmm_diag were not too helpful (the short program here works even without initializing the means of the GMM). The code is given below
int main(int argc, char** argv) {
int totFeatureVectors = CountPointClusterElements(TRAINING_CLUSTER_LIST_INDEX);
printf("\n%d elements added to list\n",totFeatureVectors);
mat F = mat(NUM_POINT_BASED_FEATURES, totFeatureVectors, fill::zeros);
int rowInd=0, colInd=0;
PointClusterElement *iterator = allClusterPointsList;
while(iterator!=NULL)
{
F(rowInd,colInd)=iterator->pointSample.speed;
rowInd += 1;
F(rowInd,colInd)=iterator->pointSample.dirn.cosComponent;
rowInd += 1;
F(rowInd,colInd)=iterator->pointSample.dirn.sinComponent;
rowInd += 1;
F(rowInd,colInd)=iterator->pointSample.curv.cosComponent;
rowInd += 1;
F(rowInd,colInd)=iterator->pointSample.curv.sinComponent;
rowInd += 1;
if(rowInd==NUM_POINT_BASED_FEATURES)
{
rowInd=0;
colInd += 1;
}
iterator=iterator->nextClusterElement;
}
FILE *fp = fopen(PROGRAM_DATA_OUTPUT_PATH,"w");
if(fp!=NULL)
{
int r,c;
for(c=0; c<totFeatureVectors; c++)
{
for(r=0; r<NUM_POINT_BASED_FEATURES; r++)
{
fprintf(fp,"%lf\t",F(r,c));
}
fprintf(fp,"\n");
}
}
fclose(fp);
gmm_diag writerModel;
bool result = writerModel.learn(F, 20, maha_dist, random_subset, 100, 100, VARIANCE_FLOORING_FACTOR, true);
writerModel.dcovs.print("covariances:\n");
writerModel.hefts.print("weights:\n");
writerModel.means.print("means:\n");
if(result==true)
{
printf("\nModel learnt");
}
else if(result==false)
{
printf("\nModel not learnt");
}
getchar();
return 0;}
TECHNICAL DETAILS:
The program is being run on a Ubuntu 14.04 OS using a Netbeans 8.0.2 IDE. The project is a C/C++ application
Any help would be most appreciated! Thanks in advance ~ Sid