Quick addition to libsvm matlab binding

Some people, myself included, make use of the libsvm package for whatever classification problem they happen to be working on. There are lots of additional goodies available at the same site, including tools that will perform different diagnostics or exploratory analyses of the model, as long as you have it contained in a libsvm model file. I tried to use one such tool recently, but since I was working from Matlab, I couldn’t figure out how to get the model (saved as a struct array in Matlab) into a libsvm formatted file.

If you find yourself in a similar position, you can try compiling this MEX file that I put together, which will do just that. Here’s the file (I called it svmsave.c):

#include "svm.h"
#include "mex.h"
#include "svm_model_matlab.h"
#define CMD_LEN 2048
#define FILENAME_LEN 256

void exit_with_help(){ }

static void fake_answer(mxArray *plhs[]) { plhs[0] = mxCreateDoubleMatrix(0, 0, mxREAL); }

void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) {
struct svm_model *model;
if (nrhs > 3 || nrhs < 1) {
exit_with_help();
fake_answer(plhs);
return;
}
if (mxIsStruct(prhs[0])){
const char *error_msg;
//model = (struct svm_model *) malloc(sizeof(struct svm_model));
model = matlab_matrix_to_model(prhs[0], &error_msg);
if (*error_msg) {
mexPrintf("Error: can't read model: %s\n", *error_msg);
//svm_destroy_model(model);
fake_answer(plhs);
//return;
}
if (mxIsChar(prhs[1])) {
long unsigned int buflen,status;
char filename[FILENAME_LEN];
buflen = (mxGetM(prhs[1]) * mxGetN(prhs[1])) + 1;
//filename = mxCalloc(buflen, sizeof(char));
status = mxGetString(prhs[1], filename, buflen);
if (status != 0) mexWarnMsgTxt("Not enough space. String is truncated.");
svm_save_model(filename,model);
}
else {
mexPrintf("filename should be given as char(s)\n");
}
svm_destroy_model(model);
}
else {
mexPrintf("model file should be a struct array\n");
fake_answer(plhs);
}
return;
}

Then all you need to do is add another target to the Makefile that comes with libsvm for Matlab, like so:

svmsave.$(MEX_EXT): svmsave.c svm.h svm_model_matlab.h svm.o svm_model_matlab.o
$(MEX) $(MEX_OPTION) svmsave.c svm.o svm_model_matlab.o

and make sure that target gets built as part of the build rule for the binary target. Then to save your libsvm model, just use
>svmsave(model,'model_file_name.ext') where the model file and file name are replaced appropriately.

Advertisements