#include #include #include #include "../svm.h" #include "mex.h" #include "svm_model_matlab.h" #ifdef MX_API_VER #if MX_API_VER < 0x07030000 typedef int mwIndex; #endif #endif #define CMD_LEN 2048 int print_null(const char *s,...) {} int (*info)(const char *fmt,...) = &mexPrintf; void read_sparse_instance(const mxArray *prhs, int index, struct svm_node *x) { int i, j, low, high; mwIndex *ir, *jc; double *samples; ir = mxGetIr(prhs); jc = mxGetJc(prhs); samples = mxGetPr(prhs); // each column is one instance j = 0; low = (int)jc[index], high = (int)jc[index+1]; for(i=low;iparam.kernel_type == PRECOMPUTED) { // precomputed kernel requires dense matrix, so we make one mxArray *rhs[1], *lhs[1]; rhs[0] = mxDuplicateArray(prhs[1]); if(mexCallMATLAB(1, lhs, 1, rhs, "full")) { mexPrintf("Error: cannot full testing instance matrix\n"); fake_answer(nlhs, plhs); return; } ptr_instance = mxGetPr(lhs[0]); mxDestroyArray(rhs[0]); } else { mxArray *pprhs[1]; pprhs[0] = mxDuplicateArray(prhs[1]); if(mexCallMATLAB(1, pplhs, 1, pprhs, "transpose")) { mexPrintf("Error: cannot transpose testing instance matrix\n"); fake_answer(nlhs, plhs); return; } } } if(predict_probability) { if(svm_type==NU_SVR || svm_type==EPSILON_SVR) info("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma=%g\n",svm_get_svr_probability(model)); else prob_estimates = (double *) malloc(nr_class*sizeof(double)); } tplhs[0] = mxCreateDoubleMatrix(testing_instance_number, 1, mxREAL); if(predict_probability) { // prob estimates are in plhs[2] if(svm_type==C_SVC || svm_type==NU_SVC) tplhs[2] = mxCreateDoubleMatrix(testing_instance_number, nr_class, mxREAL); else tplhs[2] = mxCreateDoubleMatrix(0, 0, mxREAL); } else { // decision values are in plhs[2] if(svm_type == ONE_CLASS || svm_type == EPSILON_SVR || svm_type == NU_SVR || nr_class == 1) // if only one class in training data, decision values are still returned. tplhs[2] = mxCreateDoubleMatrix(testing_instance_number, 1, mxREAL); else tplhs[2] = mxCreateDoubleMatrix(testing_instance_number, nr_class*(nr_class-1)/2, mxREAL); } ptr_predict_label = mxGetPr(tplhs[0]); ptr_prob_estimates = mxGetPr(tplhs[2]); ptr_dec_values = mxGetPr(tplhs[2]); x = (struct svm_node*)malloc((feature_number+1)*sizeof(struct svm_node) ); for(instance_index=0;instance_indexparam.kernel_type != PRECOMPUTED) // prhs[1]^T is still sparse read_sparse_instance(pplhs[0], instance_index, x); else { for(i=0;i 3 || nrhs > 4 || nrhs < 3) { exit_with_help(); fake_answer(nlhs, plhs); return; } if(!mxIsDouble(prhs[0]) || !mxIsDouble(prhs[1])) { mexPrintf("Error: label vector and instance matrix must be double\n"); fake_answer(nlhs, plhs); return; } if(mxIsStruct(prhs[2])) { const char *error_msg; // parse options if(nrhs==4) { int i, argc = 1; char cmd[CMD_LEN], *argv[CMD_LEN/2]; // put options in argv[] mxGetString(prhs[3], cmd, mxGetN(prhs[3]) + 1); if((argv[argc] = strtok(cmd, " ")) != NULL) while((argv[++argc] = strtok(NULL, " ")) != NULL) ; for(i=1;i=argc) && argv[i-1][1] != 'q') { exit_with_help(); fake_answer(nlhs, plhs); return; } switch(argv[i-1][1]) { case 'b': prob_estimate_flag = atoi(argv[i]); break; case 'q': i--; info = &print_null; break; default: mexPrintf("Unknown option: -%c\n", argv[i-1][1]); exit_with_help(); fake_answer(nlhs, plhs); return; } } } model = matlab_matrix_to_model(prhs[2], &error_msg); if (model == NULL) { mexPrintf("Error: can't read model: %s\n", error_msg); fake_answer(nlhs, plhs); return; } if(prob_estimate_flag) { if(svm_check_probability_model(model)==0) { mexPrintf("Model does not support probabiliy estimates\n"); fake_answer(nlhs, plhs); svm_free_and_destroy_model(&model); return; } } else { if(svm_check_probability_model(model)!=0) info("Model supports probability estimates, but disabled in predicton.\n"); } predict(nlhs, plhs, prhs, model, prob_estimate_flag); // destroy model svm_free_and_destroy_model(&model); } else { mexPrintf("model file should be a struct array\n"); fake_answer(nlhs, plhs); } return; }