Hi,
This is my first post, so hello to everybody, happy to start sharing ideas with all of you.
I am trying to use a separate dll library to perform regression with Support Vector Machine in Zorro. The library is libsvm.dll and contains several functions. It is a C++ library with a C-API (compiled with EXTERN C).
I declare and initialise the required dll functions prototypes in my header, for example :
const char* __cdecl svm_check_parameter(const svm_problem *prob, const svm_parameter *param);
#define PRAGMA_API svm_check_parameter;libsvm!svm_check_parameter
I am able to call the dll functions in the run (or main) script, however the functions seems not to recognise some struct components (variables) passed through the function argument as a pointer, and so doesn’t work properly.My header SVM.h with the structs :
#ifndef SVM_h
#define SVM_h
//---------------------------------------------------------------------------------------------------
// Some definitions
//Svm_type
#define C_SVC 0
#define NU_SV 1
#define ONE_CLASS 2
#define EPSILON_SVR 3
#define NU_SVR 4
//Kernel_type
#define LINEAR 0
#define POLY 1
#define RBF 2
#define SIGMOID 3
#define PRECOMPUTED 4
//---------------------------------------------------------------------------------------------------
//Struct definitions
typedef struct
{
int index;
double value;
} svm_node;
typedef struct
{
int l;
double *y;
svm_node **x;
} svm_problem;
typedef struct
{
int svm_type;
int kernel_type;
int degree; // for poly
double gamma; // for poly/rbf/sigmoid
double coef0; // for poly/sigmoid
// these are for training only
float cache_size; // in MB
double eps; // stopping criteria
double C; // for C_SVC, EPSILON_SVR and NU_SVR
int nr_weight; // for C_SVC
int *weight_label; // for C_SVC
double* weight; // for C_SVC
double nu; // for NU_SVC, ONE_CLASS, and NU_SVR
double p; // for EPSILON_SVR
int shrinking; // use the shrinking heuristics
int probability; // do probability estimates
} svm_parameter;
// svm_model
typedef struct
{
svm_parameter param; // parameter
int nr_class; // number of classes, = 2 in regression/one class svm
int l; // total #SV
svm_node **SV; // SVs (SV[l])
double **sv_coef; // coefficients for SVs in decision functions (sv_coef[k-1][l])
double *rho; // constants in decision functions (rho[k*(k-1)/2])
double *probA; // pariwise probability information
double *probB;
int *sv_indices; // sv_indices[0,...,nSV-1] are values in [1,...,num_traning_data] to indicate SVs in the training set */
// for classification only
int *label; // label of each class (label[k])
int *nSV; // number of SVs for each class (nSV[k])
// nSV[0] + nSV[1] + ... + nSV[k-1] = l
// XXX
int free_sv; // 1 if svm_model is created by svm_load_model
// 0 if svm_model is created by svm_train
} svm_model;
//---------------------------------------------------------------------------------------------------
// Train and predict functions
svm_model* __cdecl svm_train(const svm_problem *prob, const svm_parameter *param); //return a pointer to a SVM model
#define PRAGMA_API svm_train;libsvm!svm_train
double __cdecl svm_predict(const svm_model *model, const svm_node *x);
#define PRAGMA_API svm_predict;libsvm!svm_predict
//Check function
const char* __cdecl svm_check_parameter(const svm_problem *prob, const svm_parameter *param);
#define PRAGMA_API svm_check_parameter;libsvm!svm_check_parameter
#endif
My main function :
//---------------------------------------------------------------------------------+
// Preprocessors +
//---------------------------------------------------------------------------------+
#include <default.c>
#include <SVM.h>
//---------------------------------------------------------------------------------+
//Run +
//---------------------------------------------------------------------------------+
function main()
{
// SVM variables----------------------------------------------+
int i,m,j;
double norm_x;
svm_parameter param;/
svm_problem prob;
svm_node* x_space;
//Fill in a parameter structure
param.svm_type = EPSILON_SVR;
param.kernel_type = LINEAR;
param.degree = 1; // for poly
param.gamma = 0.5; //default 1/number of features
param.coef0 = 0; // for poly/sigmoid
param.cache_size = 100.0; // in MB defaut 100
param.eps = 0.001; //default 0.001
param.C= 1.0; //default 1
param.nr_weight = 0; // for C_SVC
param.weight_label = NULL; // for C_SVC
param.weight = NULL; // for C_SVC
param.nu = 0.5; // for NU_SVC, ONE_CLASS, and NU_SVR
param.p = 0.1; //the epsilon for SVR default 0.1
param.shrinking = 0; // use the shrinking heuristics
param.probability = 0; // do probability estimates
//Problem structure definition and filling
prob.l = 11; // number of training data
// INPUT and DATA preparation--------------------------------------------------------------------------------------+
//Input target
int feat = 1;
int elements = prob.l * (feat+1);
prob.y = malloc(sizeof(double)*prob.l);
prob.x = malloc(sizeof(svm_node*)*prob.l);
x_space = malloc(sizeof(svm_node)*elements);
j=0;
for(i=0; i<prob.l; i++){ // lines
(prob.x)[i] = &x_space[j];
x_space[j].index = 1; // only one indice
norm_x = (double)i/(prob.l-1.0);
x_space[j].value = norm_x;
//next col j
++j; // here same as j++
x_space[j].index = -1;
++j;
}
(prob.y)[0] = 1;
(prob.y)[1] = 6;
(prob.y)[2] = 4;
(prob.y)[3] = 8;
(prob.y)[4] = 15;
(prob.y)[5] = 12;
(prob.y)[6] = 18;
(prob.y)[7] = 20;
(prob.y)[8] = 19;
(prob.y)[9] = 22;
(prob.y)[10] = 25;
//************Here param.C value is not correctly passed
char* err;
err = svm_check_parameter(&prob, ¶m);
if(*err!=NULL) watch("Check: ", err); // returns me C<=0 by the external function
watch("C: ", param.C); // returns me correctly 1.0
free(prob.y);
free(x_space);
free(prob.x);
}
For example when I initialise param.C and call svm_check_parameter(&prob, ¶m) the functions returns me an error : C<=0 , however when I check param.C with “watch” it gives me 1.0.
Strangely, I also hade the same problem with param.cache_size whose value was not recognised by the same dll function. But I resolve it by changing it to a float, whereas a double is expected in the original dll function.
I also tried to declare my struct as global, but this doesn’t change anything.
Does anyone have any idea how to make this work?
Thank you for your help or comments.
Niels