diff options
| author | Gertjan van den Burg <gertjanvandenburg@gmail.com> | 2017-02-17 19:02:52 -0500 |
|---|---|---|
| committer | Gertjan van den Burg <gertjanvandenburg@gmail.com> | 2017-02-17 19:02:52 -0500 |
| commit | 3a30e992cf022f4ec3c76506c070e59d093951d4 (patch) | |
| tree | fe14713d50876c1d37f1acec40b9a77875d2bba3 /src | |
| parent | minor code clarification (diff) | |
| download | gensvm-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.c | 29 | ||||
| -rw-r--r-- | src/gensvm_base.c | 10 | ||||
| -rw-r--r-- | src/gensvm_consistency.c | 2 | ||||
| -rw-r--r-- | src/gensvm_copy.c | 25 | ||||
| -rw-r--r-- | src/gensvm_gridsearch.c | 44 | ||||
| -rw-r--r-- | src/gensvm_kernel.c | 94 | ||||
| -rw-r--r-- | src/gensvm_task.c | 51 |
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; } |
