代碼在網上可以找到,savemodel.c與loadmodel.c 我把網上的引用放在下面
最近一直在用matlab和libsvm,發現libsvm庫用起來還是很方便的,就是沒有模型直接保存到文件和讀取模型的matlab接口(C++的接口有)。由於有會用的Opencv等C/C++庫,所以數據交換比較麻煩。看了一下libsvm的svm.h、svm.cpp文件,發現有svm_save_model(),svm_load_model()等函數。於是乎用mex小做封裝,寫了兩個matlab可以直接調用的接口。
保存svm model到文件:(savemodel.c)
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include "svm.h"
- #include "mex.h"
- #include "svm_model_matlab.h"
- void exit_with_help()
- {
- mexPrintf(
- "Usage: savemodel('filename', model);\n"
- );
- }
- int savemodel(const char *filename, const mxArray *matlab_struct)
- {
- const char *error_msg;
- struct svm_model* model;
- int result;
- model = matlab_matrix_to_model(matlab_struct, &error_msg);
- if (model == NULL)
- {
- mexPrintf("Error: can't read model: %s\n", error_msg);
- }
- result = svm_save_model(filename, model);
- if( result != 0 )
- {
- mexPrintf("Error: can't write model to file!\n");
- }
- return result;
- }
- void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
- {
- if(nrhs == 2)
- {
- char filename[256];
- int *result;
- mxGetString(prhs[0], filename, mxGetN(prhs[0])+1);
- plhs[0] = mxCreateNumericMatrix(1, 1, mxINT8_CLASS, 0);
- result = mxGetPr(plhs[0]);
- *result = savemodel(filename, prhs[1]);
- }
- else
- {
- exit_with_help();
- return;
- }
- }
讀取文件中的svm model:( loadmodel.c )
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include "svm.h"
- #include "mex.h"
- #include "svm_model_matlab.h"
- void exit_with_help()
- {
- mexPrintf(
- "Usage: model = loadmodel('filename', num_of_feature);\n"
- );
- }
- void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
- {
- if(nrhs == 2)
- {
- char filename[256];
- int num_of_feature;
- struct svm_model* model;
- int featurenum;
- const char *error_msg;
- mxGetString(prhs[0], filename, mxGetN(prhs[0])+1);
- model = svm_load_model(filename);
- if(model == NULL)
- {
- mexPrintf("Error: can't read the model file!\n");
- return;
- }
- featurenum = *(mxGetPr(prhs[1]));
- error_msg = model_to_matlab_structure(plhs, featurenum, model);
- if(error_msg)
- mexPrintf("Error: can't convert libsvm model to matrix structure: %s\n", error_msg);
- svm_free_and_destroy_model(&model);
- }
- else
- {
- exit_with_help();
- return;
- }
- }
這兩個文件放入libsvm-3.1/matlab目錄下,然後打開同目錄下的make.m文件,添加如下兩行(紅色部分):
mex -O -largeArrayDims -I..\ -c ..\svm.cpp
mex -O -largeArrayDims -I..\ -c svm_model_matlab.c
mex -O -largeArrayDims -I..\ svmtrain.c svm.obj svm_model_matlab.obj
mex -O -largeArrayDims -I..\ svmpredict.c svm.obj svm_model_matlab.obj
mex -O -largeArrayDims -I..\ savemodel.c svm.obj svm_model_matlab.obj
mex -O -largeArrayDims -I..\ loadmodel.c svm.obj svm_model_matlab.obj
最後在matlab中,libsvm-3.1/matlab目錄下運行“make”,等到編譯完成後,生成savemodel.mexw32、loadmodel.mexw32兩個文件。(64位的系統生成的兩個文件擴展名不一樣)
此時就可以在matlab中使用savemodel('filename', model)和model = loadmodel('filename', num)來讀取和保存訓練好的svm模型了。
注意:loadmodel接口中的第二個參數num是向量的維度(特徵數),即500個30維的樣本,num=30.
(貌似多了這個參數是因爲matlab調用了model_to_matlab_structure這個接口的緣故,在c/c++中讀寫模型就不需用num這個參數了)
如果需要在c/c++程序中調用libsvm的模型文件,就直接用svm_save_model(),svm_load_model()等函數進行操作了。
我用的版本是libsvm 2.91,savemodel.c沒有問題,loadmodel需要做如下修改
svm_free_and_destroy_model(&model); 修改爲 svm_destroy_model(model);
完美運行