aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGertjan van den Burg <gertjanvandenburg@gmail.com>2017-02-17 19:02:52 -0500
committerGertjan van den Burg <gertjanvandenburg@gmail.com>2017-02-17 19:02:52 -0500
commit3a30e992cf022f4ec3c76506c070e59d093951d4 (patch)
treefe14713d50876c1d37f1acec40b9a77875d2bba3 /src
parentminor code clarification (diff)
downloadgensvm-3a30e992cf022f4ec3c76506c070e59d093951d4.tar.gz
gensvm-3a30e992cf022f4ec3c76506c070e59d093951d4.zip
Remove kernelparam array in favour of explicit kernel parameters
This simplifies a lot of the code and will make it easier to link to other languages.
Diffstat (limited to 'src')
-rw-r--r--src/GenSVMtraintest.c29
-rw-r--r--src/gensvm_base.c10
-rw-r--r--src/gensvm_consistency.c2
-rw-r--r--src/gensvm_copy.c25
-rw-r--r--src/gensvm_gridsearch.c44
-rw-r--r--src/gensvm_kernel.c94
-rw-r--r--src/gensvm_task.c51
7 files changed, 83 insertions, 172 deletions
diff --git a/src/GenSVMtraintest.c b/src/GenSVMtraintest.c
index 0da45ec..285be2a 100644
--- a/src/GenSVMtraintest.c
+++ b/src/GenSVMtraintest.c
@@ -278,9 +278,6 @@ void parse_command_line(int argc, char **argv, struct GenModel *model,
char **prediction_outputfile)
{
int i;
- double gamma = 1.0,
- degree = 2.0,
- coef = 0.0;
GENSVM_OUTPUT_FILE = stdout;
GENSVM_ERROR_FILE = stderr;
@@ -294,10 +291,10 @@ void parse_command_line(int argc, char **argv, struct GenModel *model,
}
switch (argv[i-1][1]) {
case 'c':
- coef = atof(argv[i]);
+ model->coef = atof(argv[i]);
break;
case 'd':
- degree = atof(argv[i]);
+ model->degree = atof(argv[i]);
break;
case 'e':
model->epsilon = atof(argv[i]);
@@ -305,7 +302,7 @@ void parse_command_line(int argc, char **argv, struct GenModel *model,
exit_invalid_param("epsilon", argv);
break;
case 'g':
- gamma = atof(argv[i]);
+ model->gamma = atof(argv[i]);
break;
case 'k':
model->kappa = atof(argv[i]);
@@ -369,24 +366,4 @@ void parse_command_line(int argc, char **argv, struct GenModel *model,
(*testing_inputfile) = Malloc(char, strlen(argv[i])+1);
strcpy((*testing_inputfile), argv[i+1]);
}
-
- // set kernel parameters
- switch (model->kerneltype) {
- case K_LINEAR:
- break;
- case K_POLY:
- model->kernelparam = Calloc(double, 3);
- model->kernelparam[0] = gamma;
- model->kernelparam[1] = coef;
- model->kernelparam[2] = degree;
- break;
- case K_RBF:
- model->kernelparam = Calloc(double, 1);
- model->kernelparam[0] = gamma;
- break;
- case K_SIGMOID:
- model->kernelparam = Calloc(double, 1);
- model->kernelparam[0] = gamma;
- model->kernelparam[1] = coef;
- }
}
diff --git a/src/gensvm_base.c b/src/gensvm_base.c
index 6b979fd..79e5f45 100644
--- a/src/gensvm_base.c
+++ b/src/gensvm_base.c
@@ -53,7 +53,9 @@ struct GenData *gensvm_init_data()
// set default values
data->kerneltype = K_LINEAR;
- data->kernelparam = NULL;
+ data->gamma = -1;
+ data->coef = -1;
+ data->degree = -1;
return data;
}
@@ -82,7 +84,6 @@ void gensvm_free_data(struct GenData *data)
free(data->Z);
free(data->RAW);
}
- free(data->kernelparam);
free(data->y);
free(data->Sigma);
free(data);
@@ -108,8 +109,10 @@ struct GenModel *gensvm_init_model()
model->epsilon = 1e-6;
model->kappa = 0.0;
model->weight_idx = 1;
+ model->gamma = 1.0;
+ model->coef = 0.0;
+ model->degree = 2.0;
model->kerneltype = K_LINEAR;
- model->kernelparam = NULL;
model->kernel_eigen_cutoff = 1e-8;
model->V = NULL;
@@ -213,7 +216,6 @@ void gensvm_free_model(struct GenModel *model)
free(model->Q);
free(model->H);
free(model->rho);
- free(model->kernelparam);
free(model->data_file);
free(model);
diff --git a/src/gensvm_consistency.c b/src/gensvm_consistency.c
index bf8cf9a..07ff7a6 100644
--- a/src/gensvm_consistency.c
+++ b/src/gensvm_consistency.c
@@ -256,8 +256,6 @@ void gensvm_consistency_repeats(struct GenQueue *q, long repeats,
}
free(cv_idx);
- // make sure no double free occurs with the copied kernelparam
- model->kernelparam = NULL;
gensvm_free_model(model);
gensvm_free_queue(nq);
diff --git a/src/gensvm_copy.c b/src/gensvm_copy.c
index 43a1107..28642c7 100644
--- a/src/gensvm_copy.c
+++ b/src/gensvm_copy.c
@@ -45,26 +45,7 @@ void gensvm_copy_model(struct GenModel *from, struct GenModel *to)
to->lambda = from->lambda;
to->kerneltype = from->kerneltype;
- switch (to->kerneltype) {
- case K_LINEAR:
- break;
- case K_POLY:
- if (to->kernelparam) free(to->kernelparam);
- to->kernelparam = Malloc(double, 3);
- to->kernelparam[0] = from->kernelparam[0];
- to->kernelparam[1] = from->kernelparam[1];
- to->kernelparam[2] = from->kernelparam[2];
- break;
- case K_RBF:
- if (to->kernelparam) free(to->kernelparam);
- to->kernelparam = Malloc(double, 1);
- to->kernelparam[0] = from->kernelparam[0];
- break;
- case K_SIGMOID:
- if (to->kernelparam) free(to->kernelparam);
- to->kernelparam = Malloc(double, 2);
- to->kernelparam[0] = from->kernelparam[0];
- to->kernelparam[1] = from->kernelparam[1];
- break;
- }
+ to->gamma = from->gamma;
+ to->coef = from->coef;
+ to->degree = from->degree;
}
diff --git a/src/gensvm_gridsearch.c b/src/gensvm_gridsearch.c
index 387ebc1..e6adf8b 100644
--- a/src/gensvm_gridsearch.c
+++ b/src/gensvm_gridsearch.c
@@ -80,8 +80,6 @@ void gensvm_fill_queue(struct GenGrid *grid, struct GenQueue *queue,
task->test_data = test_data;
task->folds = grid->folds;
task->kerneltype = grid->kerneltype;
- task->kernelparam = Calloc(double, grid->Ng +
- grid->Nc + grid->Nd);
queue->tasks[i] = task;
}
@@ -140,8 +138,7 @@ void gensvm_fill_queue(struct GenGrid *grid, struct GenQueue *queue,
while (i < N) {
for (j=0; j<grid->Ne; j++) {
for (k=0; k<cnt; k++) {
- queue->tasks[i]->epsilon =
- grid->epsilons[j];
+ queue->tasks[i]->epsilon = grid->epsilons[j];
i++;
}
}
@@ -152,8 +149,7 @@ void gensvm_fill_queue(struct GenGrid *grid, struct GenQueue *queue,
while (i < N && grid->Ng > 0) {
for (j=0; j<grid->Ng; j++) {
for (k=0; k<cnt; k++) {
- queue->tasks[i]->kernelparam[0] =
- grid->gammas[j];
+ queue->tasks[i]->gamma = grid->gammas[j];
i++;
}
}
@@ -164,8 +160,7 @@ void gensvm_fill_queue(struct GenGrid *grid, struct GenQueue *queue,
while (i < N && grid->Nc > 0) {
for (j=0; j<grid->Nc; j++) {
for (k=0; k<cnt; k++) {
- queue->tasks[i]->kernelparam[1] =
- grid->coefs[j];
+ queue->tasks[i]->coef = grid->coefs[j];
i++;
}
}
@@ -176,8 +171,7 @@ void gensvm_fill_queue(struct GenGrid *grid, struct GenQueue *queue,
while (i < N && grid->Nd > 0) {
for (j=0; j<grid->Nd; j++) {
for (k=0; k<cnt; k++) {
- queue->tasks[i]->kernelparam[2] =
- grid->degrees[j];
+ queue->tasks[i]->degree = grid->degrees[j];
i++;
}
}
@@ -200,24 +194,27 @@ void gensvm_fill_queue(struct GenGrid *grid, struct GenQueue *queue,
*/
bool gensvm_kernel_changed(struct GenTask *newtask, struct GenTask *oldtask)
{
- int i;
if (oldtask == NULL)
return true;
if (newtask->kerneltype != oldtask->kerneltype) {
return true;
} else if (newtask->kerneltype == K_POLY) {
- for (i=0; i<3; i++)
- if (newtask->kernelparam[i] != oldtask->kernelparam[i])
- return true;
+ if (newtask->gamma != oldtask->gamma)
+ return true;
+ if (newtask->coef != oldtask->coef)
+ return true;
+ if (newtask->degree != oldtask->degree)
+ return true;
return false;
} else if (newtask->kerneltype == K_RBF) {
- if (newtask->kernelparam[0] != oldtask->kernelparam[0])
+ if (newtask->gamma != oldtask->gamma)
return true;
return false;
} else if (newtask->kerneltype == K_SIGMOID) {
- for (i=0; i<2; i++)
- if (newtask->kernelparam[i] != oldtask->kernelparam[i])
- return true;
+ if (newtask->gamma != oldtask->gamma)
+ return true;
+ if (newtask->coef != oldtask->coef)
+ return true;
return false;
}
return false;
@@ -331,8 +328,6 @@ void gensvm_train_queue(struct GenQueue *q)
note("\nTotal elapsed training time: %8.8f seconds\n",
gensvm_elapsed_time(&main_s, &main_e));
- // make sure no double free occurs with the copied kernelparam
- model->kernelparam = NULL;
gensvm_free_model(model);
for (f=0; f<folds; f++) {
gensvm_free_data(train_folds[f]);
@@ -365,15 +360,12 @@ void gensvm_gridsearch_progress(struct GenTask *task, long N, double perf,
char buffer[GENSVM_MAX_LINE_LENGTH];
sprintf(buffer, "(%03li/%03li)\t", task->ID+1, N);
if (task->kerneltype == K_POLY)
- sprintf(buffer + strlen(buffer), "d = %2.2f\t",
- task->kernelparam[2]);
+ sprintf(buffer + strlen(buffer), "d = %2.2f\t", task->degree);
if (task->kerneltype == K_POLY || task->kerneltype == K_SIGMOID)
- sprintf(buffer + strlen(buffer), "c = %2.2f\t",
- task->kernelparam[1]);
+ sprintf(buffer + strlen(buffer), "c = %2.2f\t", task->coef);
if (task->kerneltype == K_POLY || task->kerneltype == K_SIGMOID ||
task->kerneltype == K_RBF)
- sprintf(buffer + strlen(buffer), "g = %3.3f\t",
- task->kernelparam[0]);
+ sprintf(buffer + strlen(buffer), "g = %3.3f\t", task->gamma);
sprintf(buffer + strlen(buffer), "eps = %g\tw = %i\tk = %2.2f\t"
"l = %f\tp = %2.2f\t", task->epsilon,
task->weight_idx, task->kappa, task->lambda, task->p);
diff --git a/src/gensvm_kernel.c b/src/gensvm_kernel.c
index 8f0b6da..a25fcfd 100644
--- a/src/gensvm_kernel.c
+++ b/src/gensvm_kernel.c
@@ -46,29 +46,10 @@
void gensvm_kernel_copy_kernelparam_to_data(struct GenModel *model,
struct GenData *data)
{
- int i;
data->kerneltype = model->kerneltype;
-
- free(data->kernelparam);
- data->kernelparam = NULL;
-
- switch (model->kerneltype) {
- case K_LINEAR:
- break;
- case K_POLY:
- data->kernelparam = Calloc(double, 3);
- for (i=0; i<3; i++)
- data->kernelparam[i] = model->kernelparam[i];
- break;
- case K_RBF:
- data->kernelparam = Calloc(double, 1);
- data->kernelparam[0] = model->kernelparam[0];
- break;
- case K_SIGMOID:
- data->kernelparam = Calloc(double, 2);
- data->kernelparam[0] = model->kernelparam[0];
- data->kernelparam[1] = model->kernelparam[1];
- }
+ data->gamma = model->gamma;
+ data->coef = model->coef;
+ data->degree = model->degree;
}
@@ -188,14 +169,16 @@ void gensvm_kernel_compute(struct GenModel *model, struct GenData *data,
x1 = &data->RAW[i*(data->m+1)+1];
x2 = &data->RAW[j*(data->m+1)+1];
if (model->kerneltype == K_POLY)
- value = gensvm_kernel_dot_poly(x1, x2,
- model->kernelparam, data->m);
+ value = gensvm_kernel_dot_poly(x1, x2, data->m,
+ model->gamma, model->coef,
+ model->degree);
else if (model->kerneltype == K_RBF)
- value = gensvm_kernel_dot_rbf(x1, x2,
- model->kernelparam, data->m);
+ value = gensvm_kernel_dot_rbf(x1, x2, data->m,
+ model-> gamma);
else if (model->kerneltype == K_SIGMOID)
- value = gensvm_kernel_dot_sigmoid(x1, x2,
- model->kernelparam, data->m);
+ value = gensvm_kernel_dot_sigmoid(x1, x2,
+ data->m, model->gamma,
+ model->coef);
else {
// LCOV_EXCL_START
err("[GenSVM Error]: Unknown kernel type in "
@@ -342,14 +325,15 @@ double *gensvm_kernel_cross(struct GenModel *model, struct GenData *data_train,
x1 = &data_test->RAW[i*(m+1)+1];
x2 = &data_train->RAW[j*(m+1)+1];
if (model->kerneltype == K_POLY)
- value = gensvm_kernel_dot_poly(x1, x2,
- model->kernelparam, m);
+ value = gensvm_kernel_dot_poly(x1, x2, m,
+ model->gamma, model->coef,
+ model->degree);
else if (model->kerneltype == K_RBF)
- value = gensvm_kernel_dot_rbf(x1, x2,
- model->kernelparam, m);
+ value = gensvm_kernel_dot_rbf(x1, x2, m,
+ model->gamma);
else if (model->kerneltype == K_SIGMOID)
- value = gensvm_kernel_dot_sigmoid(x1, x2,
- model->kernelparam, m);
+ value = gensvm_kernel_dot_sigmoid(x1, x2, m,
+ model->gamma, model->coef);
else {
// LCOV_EXCL_START
err("[GenSVM Error]: Unknown kernel type in "
@@ -482,20 +466,18 @@ void gensvm_kernel_testfactor(struct GenData *testdata,
*
* @param[in] x1 first vector
* @param[in] x2 second vector
- * @param[in] kernelparam array of kernel parameters (gamma is first
- * element)
* @param[in] n length of the vectors x1 and x2
+ * @param[in] gamma gamma parameter of the kernel
* @returns kernel evaluation
*/
-double gensvm_kernel_dot_rbf(double *x1, double *x2, double *kernelparam,
- long n)
+double gensvm_kernel_dot_rbf(double *x1, double *x2, long n, double gamma)
{
long i;
double value = 0.0;
for (i=0; i<n; i++)
value += (x1[i] - x2[i]) * (x1[i] - x2[i]);
- value *= -kernelparam[0];
+ value *= -gamma;
return exp(value);
}
@@ -506,23 +488,26 @@ double gensvm_kernel_dot_rbf(double *x1, double *x2, double *kernelparam,
* The polynomial kernel is computed between two vectors. This kernel is
* defined as
* @f[
- * k(x_1, x_2) = ( \gamma \langle x_1, x_2 \rangle + c)^d
+ * k(x_1, x_2) = ( \gamma \langle x_1, x_2 \rangle + coef)^{degree}
* @f]
- * where @f$ \gamma @f$, @f$ c @f$ and @f$ d @f$ are kernel parameters.
+ * where @f$ \gamma @f$, @f$ coef @f$ and @f$ degree @f$ are kernel
+ * parameters.
*
* @param[in] x1 first vector
* @param[in] x2 second vector
- * @param[in] kernelparam array of kernel parameters (gamma, c, d)
* @param[in] n length of the vectors x1 and x2
+ * @param[in] gamma gamma parameter of the kernel
+ * @param[in] coef coef parameter of the kernel
+ * @param[in] degree degree parameter of the kernel
* @returns kernel evaluation
*/
-double gensvm_kernel_dot_poly(double *x1, double *x2, double *kernelparam,
- long n)
+double gensvm_kernel_dot_poly(double *x1, double *x2, long n, double gamma,
+ double coef, double degree)
{
double value = cblas_ddot(n, x1, 1, x2, 1);
- value *= kernelparam[0];
- value += kernelparam[1];
- return pow(value, kernelparam[2]);
+ value *= gamma;
+ value += coef;
+ return pow(value, degree);
}
/**
@@ -532,22 +517,23 @@ double gensvm_kernel_dot_poly(double *x1, double *x2, double *kernelparam,
* The sigmoid kernel is computed between two vectors. This kernel is defined
* as
* @f[
- * k(x_1, x_2) = \tanh( \gamma \langle x_1 , x_2 \rangle + c)
+ * k(x_1, x_2) = \tanh( \gamma \langle x_1 , x_2 \rangle + coef)
* @f]
- * where @f$ \gamma @f$ and @f$ c @f$ are kernel parameters.
+ * where @f$ \gamma @f$ and @f$ coef @f$ are kernel parameters.
*
* @param[in] x1 first vector
* @param[in] x2 second vector
- * @param[in] kernelparam array of kernel parameters (gamma, c)
* @param[in] n length of the vectors x1 and x2
+ * @param[in] gamma gamma parameter of the kernel
+ * @param[in] coef coef parameter of the kernel
* @returns kernel evaluation
*/
-double gensvm_kernel_dot_sigmoid(double *x1, double *x2, double *kernelparam,
- long n)
+double gensvm_kernel_dot_sigmoid(double *x1, double *x2, long n, double gamma,
+ double coef)
{
double value = cblas_ddot(n, x1, 1, x2, 1);
- value *= kernelparam[0];
- value += kernelparam[1];
+ value *= gamma;
+ value += coef;
return tanh(value);
}
diff --git a/src/gensvm_task.c b/src/gensvm_task.c
index 468705a..1526936 100644
--- a/src/gensvm_task.c
+++ b/src/gensvm_task.c
@@ -47,7 +47,9 @@ struct GenTask *gensvm_init_task()
t->kappa = 0.0;
t->lambda = 1.0;
t->epsilon = 1e-6;
- t->kernelparam = NULL;
+ t->gamma = 1.0;
+ t->coef = 0.0;
+ t->degree = 2.0;
t->train_data = NULL;
t->test_data = NULL;
t->performance = 0.0;
@@ -59,16 +61,14 @@ struct GenTask *gensvm_init_task()
* @brief Free the GenTask struct
*
* @details
- * Freeing the allocated memory of the GenTask means freeing _only_ the
- * kernelparam array, and the task itself. The datasets are not freed, as
- * these are shared between all tasks.
+ * Freeing the allocated memory of the GenTask means freeing _only_ the task
+ * itself. The datasets are not freed, as these are shared between all tasks.
*
* @param[in] t GenTask to be freed
*
*/
void gensvm_free_task(struct GenTask *t)
{
- free(t->kernelparam);
free(t);
t = NULL;
}
@@ -77,9 +77,8 @@ void gensvm_free_task(struct GenTask *t)
* @brief Deepcopy a GenTask struct
*
* @details
- * Create a deep copy of a GenTask struct. The kernelparameters are copied to
- * a new array. Note that the datasets belonging to the tasks are not copied,
- * only the pointers to the datasets.
+ * Create a deep copy of a GenTask struct. Note that the datasets belonging to
+ * the tasks are not copied, only the pointers to the datasets.
*
* @param[in] t input GenTask struct to copy
*
@@ -100,21 +99,9 @@ struct GenTask *gensvm_copy_task(struct GenTask *t)
nt->performance = t->performance;
nt->kerneltype = t->kerneltype;
- if (nt->kerneltype == K_LINEAR) {
- nt->kernelparam = NULL;
- } else if (nt->kerneltype == K_RBF) {
- nt->kernelparam = Malloc(double, 1);
- nt->kernelparam[0] = t->kernelparam[0];
- } else if (nt->kerneltype == K_POLY) {
- nt->kernelparam = Malloc(double, 3);
- nt->kernelparam[0] = t->kernelparam[0];
- nt->kernelparam[1] = t->kernelparam[1];
- nt->kernelparam[2] = t->kernelparam[2];
- } else if (nt->kerneltype == K_SIGMOID) {
- nt->kernelparam = Malloc(double, 2);
- nt->kernelparam[0] = t->kernelparam[0];
- nt->kernelparam[1] = t->kernelparam[1];
- }
+ nt->gamma = t->gamma;
+ nt->coef = t->coef;
+ nt->degree = t->degree;
return nt;
}
@@ -140,19 +127,7 @@ void gensvm_task_to_model(struct GenTask *task, struct GenModel *model)
// copy kernel parameters
model->kerneltype = task->kerneltype;
- if (model->kerneltype == K_LINEAR) {
- model->kernelparam = NULL;
- } else if (model->kerneltype == K_RBF) {
- model->kernelparam = Malloc(double, 1);
- model->kernelparam[0] = task->kernelparam[0];
- } else if (model->kerneltype == K_POLY) {
- model->kernelparam = Malloc(double, 3);
- model->kernelparam[0] = task->kernelparam[0];
- model->kernelparam[1] = task->kernelparam[1];
- model->kernelparam[2] = task->kernelparam[2];
- } else if (model->kerneltype == K_SIGMOID) {
- model->kernelparam = Malloc(double, 2);
- model->kernelparam[0] = task->kernelparam[0];
- model->kernelparam[1] = task->kernelparam[1];
- }
+ model->gamma = task->gamma;
+ model->coef = task->coef;
+ model->degree = task->degree;
}