#include #include #include "../svm.h" #include "mex.h" #ifdef MX_API_VER #if MX_API_VER < 0x07030000 typedef int mwIndex; #endif #endif #define NUM_OF_RETURN_FIELD 11 #define Malloc(type,n) (type *)malloc((n)*sizeof(type)) static const char *field_names[] = { "Parameters", "nr_class", "totalSV", "rho", "Label", "sv_indices", "ProbA", "ProbB", "nSV", "sv_coef", "SVs" }; const char *model_to_matlab_structure(mxArray *plhs[], int num_of_feature, struct svm_model *model) { int i, j, n; double *ptr; mxArray *return_model, **rhs; int out_id = 0; rhs = (mxArray **)mxMalloc(sizeof(mxArray *)*NUM_OF_RETURN_FIELD); // Parameters rhs[out_id] = mxCreateDoubleMatrix(5, 1, mxREAL); ptr = mxGetPr(rhs[out_id]); ptr[0] = model->param.svm_type; ptr[1] = model->param.kernel_type; ptr[2] = model->param.degree; ptr[3] = model->param.gamma; ptr[4] = model->param.coef0; out_id++; // nr_class rhs[out_id] = mxCreateDoubleMatrix(1, 1, mxREAL); ptr = mxGetPr(rhs[out_id]); ptr[0] = model->nr_class; out_id++; // total SV rhs[out_id] = mxCreateDoubleMatrix(1, 1, mxREAL); ptr = mxGetPr(rhs[out_id]); ptr[0] = model->l; out_id++; // rho n = model->nr_class*(model->nr_class-1)/2; rhs[out_id] = mxCreateDoubleMatrix(n, 1, mxREAL); ptr = mxGetPr(rhs[out_id]); for(i = 0; i < n; i++) ptr[i] = model->rho[i]; out_id++; // Label if(model->label) { rhs[out_id] = mxCreateDoubleMatrix(model->nr_class, 1, mxREAL); ptr = mxGetPr(rhs[out_id]); for(i = 0; i < model->nr_class; i++) ptr[i] = model->label[i]; } else rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL); out_id++; // sv_indices if(model->sv_indices) { rhs[out_id] = mxCreateDoubleMatrix(model->l, 1, mxREAL); ptr = mxGetPr(rhs[out_id]); for(i = 0; i < model->l; i++) ptr[i] = model->sv_indices[i]; } else rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL); out_id++; // probA if(model->probA != NULL) { rhs[out_id] = mxCreateDoubleMatrix(n, 1, mxREAL); ptr = mxGetPr(rhs[out_id]); for(i = 0; i < n; i++) ptr[i] = model->probA[i]; } else rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL); out_id ++; // probB if(model->probB != NULL) { rhs[out_id] = mxCreateDoubleMatrix(n, 1, mxREAL); ptr = mxGetPr(rhs[out_id]); for(i = 0; i < n; i++) ptr[i] = model->probB[i]; } else rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL); out_id++; // nSV if(model->nSV) { rhs[out_id] = mxCreateDoubleMatrix(model->nr_class, 1, mxREAL); ptr = mxGetPr(rhs[out_id]); for(i = 0; i < model->nr_class; i++) ptr[i] = model->nSV[i]; } else rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL); out_id++; // sv_coef rhs[out_id] = mxCreateDoubleMatrix(model->l, model->nr_class-1, mxREAL); ptr = mxGetPr(rhs[out_id]); for(i = 0; i < model->nr_class-1; i++) for(j = 0; j < model->l; j++) ptr[(i*(model->l))+j] = model->sv_coef[i][j]; out_id++; // SVs { int ir_index, nonzero_element; mwIndex *ir, *jc; mxArray *pprhs[1], *pplhs[1]; if(model->param.kernel_type == PRECOMPUTED) { nonzero_element = model->l; num_of_feature = 1; } else { nonzero_element = 0; for(i = 0; i < model->l; i++) { j = 0; while(model->SV[i][j].index != -1) { nonzero_element++; j++; } } } // SV in column, easier accessing rhs[out_id] = mxCreateSparse(num_of_feature, model->l, nonzero_element, mxREAL); ir = mxGetIr(rhs[out_id]); jc = mxGetJc(rhs[out_id]); ptr = mxGetPr(rhs[out_id]); jc[0] = ir_index = 0; for(i = 0;i < model->l; i++) { if(model->param.kernel_type == PRECOMPUTED) { // make a (1 x model->l) matrix ir[ir_index] = 0; ptr[ir_index] = model->SV[i][0].value; ir_index++; jc[i+1] = jc[i] + 1; } else { int x_index = 0; while (model->SV[i][x_index].index != -1) { ir[ir_index] = model->SV[i][x_index].index - 1; ptr[ir_index] = model->SV[i][x_index].value; ir_index++, x_index++; } jc[i+1] = jc[i] + x_index; } } // transpose back to SV in row pprhs[0] = rhs[out_id]; if(mexCallMATLAB(1, pplhs, 1, pprhs, "transpose")) return "cannot transpose SV matrix"; rhs[out_id] = pplhs[0]; out_id++; } /* Create a struct matrix contains NUM_OF_RETURN_FIELD fields */ return_model = mxCreateStructMatrix(1, 1, NUM_OF_RETURN_FIELD, field_names); /* Fill struct matrix with input arguments */ for(i = 0; i < NUM_OF_RETURN_FIELD; i++) mxSetField(return_model,0,field_names[i],mxDuplicateArray(rhs[i])); /* return */ plhs[0] = return_model; mxFree(rhs); return NULL; } struct svm_model *matlab_matrix_to_model(const mxArray *matlab_struct, const char **msg) { int i, j, n, num_of_fields; double *ptr; int id = 0; struct svm_node *x_space; struct svm_model *model; mxArray **rhs; num_of_fields = mxGetNumberOfFields(matlab_struct); if(num_of_fields != NUM_OF_RETURN_FIELD) { *msg = "number of return field is not correct"; return NULL; } rhs = (mxArray **) mxMalloc(sizeof(mxArray *)*num_of_fields); for(i=0;irho = NULL; model->probA = NULL; model->probB = NULL; model->label = NULL; model->sv_indices = NULL; model->nSV = NULL; model->free_sv = 1; // XXX ptr = mxGetPr(rhs[id]); model->param.svm_type = (int)ptr[0]; model->param.kernel_type = (int)ptr[1]; model->param.degree = (int)ptr[2]; model->param.gamma = ptr[3]; model->param.coef0 = ptr[4]; id++; ptr = mxGetPr(rhs[id]); model->nr_class = (int)ptr[0]; id++; ptr = mxGetPr(rhs[id]); model->l = (int)ptr[0]; id++; // rho n = model->nr_class * (model->nr_class-1)/2; model->rho = (double*) malloc(n*sizeof(double)); ptr = mxGetPr(rhs[id]); for(i=0;irho[i] = ptr[i]; id++; // label if(mxIsEmpty(rhs[id]) == 0) { model->label = (int*) malloc(model->nr_class*sizeof(int)); ptr = mxGetPr(rhs[id]); for(i=0;inr_class;i++) model->label[i] = (int)ptr[i]; } id++; // sv_indices if(mxIsEmpty(rhs[id]) == 0) { model->sv_indices = (int*) malloc(model->l*sizeof(int)); ptr = mxGetPr(rhs[id]); for(i=0;il;i++) model->sv_indices[i] = (int)ptr[i]; } id++; // probA if(mxIsEmpty(rhs[id]) == 0) { model->probA = (double*) malloc(n*sizeof(double)); ptr = mxGetPr(rhs[id]); for(i=0;iprobA[i] = ptr[i]; } id++; // probB if(mxIsEmpty(rhs[id]) == 0) { model->probB = (double*) malloc(n*sizeof(double)); ptr = mxGetPr(rhs[id]); for(i=0;iprobB[i] = ptr[i]; } id++; // nSV if(mxIsEmpty(rhs[id]) == 0) { model->nSV = (int*) malloc(model->nr_class*sizeof(int)); ptr = mxGetPr(rhs[id]); for(i=0;inr_class;i++) model->nSV[i] = (int)ptr[i]; } id++; // sv_coef ptr = mxGetPr(rhs[id]); model->sv_coef = (double**) malloc((model->nr_class-1)*sizeof(double)); for( i=0 ; i< model->nr_class -1 ; i++ ) model->sv_coef[i] = (double*) malloc((model->l)*sizeof(double)); for(i = 0; i < model->nr_class - 1; i++) for(j = 0; j < model->l; j++) model->sv_coef[i][j] = ptr[i*(model->l)+j]; id++; // SV { int sr, elements; int num_samples; mwIndex *ir, *jc; mxArray *pprhs[1], *pplhs[1]; // transpose SV pprhs[0] = rhs[id]; if(mexCallMATLAB(1, pplhs, 1, pprhs, "transpose")) { svm_free_and_destroy_model(&model); *msg = "cannot transpose SV matrix"; return NULL; } rhs[id] = pplhs[0]; sr = (int)mxGetN(rhs[id]); ptr = mxGetPr(rhs[id]); ir = mxGetIr(rhs[id]); jc = mxGetJc(rhs[id]); num_samples = (int)mxGetNzmax(rhs[id]); elements = num_samples + sr; model->SV = (struct svm_node **) malloc(sr * sizeof(struct svm_node *)); x_space = (struct svm_node *)malloc(elements * sizeof(struct svm_node)); // SV is in column for(i=0;iSV[i] = &x_space[low+i]; for(j=low;jSV[i][x_index].index = (int)ir[j] + 1; model->SV[i][x_index].value = ptr[j]; x_index++; } model->SV[i][x_index].index = -1; } id++; } mxFree(rhs); return model; }