diff options
| author | Gertjan van den Burg <burg@ese.eur.nl> | 2016-12-05 11:19:24 +0100 |
|---|---|---|
| committer | Gertjan van den Burg <burg@ese.eur.nl> | 2016-12-05 11:19:24 +0100 |
| commit | 238110891d8cd0b95aae0b273c8b627580a9274a (patch) | |
| tree | ad01cf6a119a66cb702d217e09dd34c7d738d8a7 | |
| parent | Improvements and tests for tasks and gridsearch (diff) | |
| download | gensvm-238110891d8cd0b95aae0b273c8b627580a9274a.tar.gz gensvm-238110891d8cd0b95aae0b273c8b627580a9274a.zip | |
Tests and documentation kernel module
| -rw-r--r-- | include/gensvm_kernel.h | 23 | ||||
| -rw-r--r-- | src/gensvm_kernel.c | 248 | ||||
| -rw-r--r-- | tests/Makefile | 2 | ||||
| -rw-r--r-- | tests/src/test_gensvm_kernel.c | 153 |
4 files changed, 334 insertions, 92 deletions
diff --git a/include/gensvm_kernel.h b/include/gensvm_kernel.h index 44b3555..c24426e 100644 --- a/include/gensvm_kernel.h +++ b/include/gensvm_kernel.h @@ -39,19 +39,22 @@ void gensvm_kernel_preprocess(struct GenModel *model, struct GenData *data); void gensvm_kernel_postprocess(struct GenModel *model, struct GenData *traindata, struct GenData *testdata); -void gensvm_make_kernel(struct GenModel *model, struct GenData *data, +void gensvm_kernel_compute(struct GenModel *model, struct GenData *data, double *K); -long gensvm_make_eigen(double *K, long n, double **P, double **Sigma); -void gensvm_make_crosskernel(struct GenModel *model, - struct GenData *data_train, struct GenData *data_test, - double **K2); -void gensvm_make_trainfactor(struct GenData *data, double *P, double *Sigma, +long gensvm_kernel_eigendecomp(double *K, long n, double **P_ret, + double **Sigma_ret); +double *gensvm_kernel_cross(struct GenModel *model, struct GenData *data_train, + struct GenData *data_test); +void gensvm_kernel_trainfactor(struct GenData *data, double *P, double *Sigma, long r); -void gensvm_make_testfactor(struct GenData *testdata, +void gensvm_kernel_testfactor(struct GenData *testdata, struct GenData *traindata, double *K2); -double gensvm_dot_rbf(double *x1, double *x2, double *kernelparam, long n); -double gensvm_dot_poly(double *x1, double *x2, double *kernelparam, long n); -double gensvm_dot_sigmoid(double *x1, double *x2, double *kernelparam, long n); +double gensvm_kernel_dot_rbf(double *x1, double *x2, double *kernelparam, + long n); +double gensvm_kernel_dot_poly(double *x1, double *x2, double *kernelparam, + long n); +double gensvm_kernel_dot_sigmoid(double *x1, double *x2, double *kernelparam, + long n); int dsyevx(char JOBZ, char RANGE, char UPLO, int N, double *A, int LDA, double VL, double VU, int IL, int IU, double ABSTOL, int *M, double *W, double *Z, int LDZ, double *WORK, int LWORK, diff --git a/src/gensvm_kernel.c b/src/gensvm_kernel.c index 7dcfb4e..d236553 100644 --- a/src/gensvm_kernel.c +++ b/src/gensvm_kernel.c @@ -27,16 +27,37 @@ You should have received a copy of the GNU General Public License along with GenSVM. If not, see <http://www.gnu.org/licenses/>. - */ +*/ #include "gensvm_kernel.h" #include "gensvm_print.h" +#ifndef GENSVM_EIGEN_CUTOFF + /** + * Mimimum ratio between an eigenvalue and the largest eigenvalue for it to + * be included in the reduced eigendecomposition + */ + #define GENSVM_EIGEN_CUTOFF 1e-8 +#endif + /** * @brief Do the preprocessing steps needed to perform kernel GenSVM * * @details - * tdb + * To achieve nonlinearity through kernels in GenSVM, a preprocessing step is + * needed. This preprocessing step computes the full kernel matrix, and an + * eigendecomposition of this matrix. Next, it computes a matrix @f$\textbf{M} + * = \textbf{P}\boldsymbol{\Sigma}@f$ which takes the role as data matrix in + * the optimization algorithm. + * + * @sa + * gensvm_kernel_compute(), gensvm_kernel_eigendecomp(), + * gensvm_kernel_trainfactor(), gensvm_kernel_postprocess() + * + * @param[in] model input GenSVM model + * @param[in,out] data input structure with the data. On exit, + * contains the training factor in GenData::Z, + * and the original data in GenData::RAW * */ void gensvm_kernel_preprocess(struct GenModel *model, struct GenData *data) @@ -47,21 +68,20 @@ void gensvm_kernel_preprocess(struct GenModel *model, struct GenData *data) } int i; - long r, - n = data->n; + long r, n = data->n; double *P = NULL, *Sigma = NULL, *K = NULL; // build the kernel matrix K = Calloc(double, n*n); - gensvm_make_kernel(model, data, K); + gensvm_kernel_compute(model, data, K); // generate the eigen decomposition - r = gensvm_make_eigen(K, n, &P, &Sigma); + r = gensvm_kernel_eigendecomp(K, n, &P, &Sigma); // build M and set to data (leave RAW intact) - gensvm_make_trainfactor(data, P, Sigma, r); + gensvm_kernel_trainfactor(data, P, Sigma, r); // Set Sigma to data->Sigma (need it again for prediction) if (data->Sigma != NULL) { @@ -98,6 +118,19 @@ void gensvm_kernel_preprocess(struct GenModel *model, struct GenData *data) free(P); } +/** + * @brief Compute the kernel postprocessing factor + * + * @details + * This function computes the postprocessing factor needed to do predictions + * with kernels in GenSVM. This is a wrapper around gensvm_kernel_cross() and + * gensvm_kernel_testfactor(). + * + * @param[in] model a GenSVM model + * @param[in] traindata the training dataset + * @param[in,out] testdata the test dataset. On exit, GenData::Z + * contains the testfactor + */ void gensvm_kernel_postprocess(struct GenModel *model, struct GenData *traindata, struct GenData *testdata) { @@ -107,11 +140,10 @@ void gensvm_kernel_postprocess(struct GenModel *model, } // build the cross kernel matrix between train and test - double *K2 = NULL; - gensvm_make_crosskernel(model, traindata, testdata, &K2); + double *K2 = gensvm_kernel_cross(model, traindata, testdata); // generate the data matrix N = K2 * M * Sigma^{-2} - gensvm_make_testfactor(testdata, traindata, K2); + gensvm_kernel_testfactor(testdata, traindata, K2); free(K2); } @@ -120,10 +152,10 @@ void gensvm_kernel_postprocess(struct GenModel *model, * @brief Compute the kernel matrix * * @details - * This function computes the kernel matrix of a data matrix based on the - * requested kernel type and the kernel parameters. The potential types of - * kernel functions are document in KernelType. This function uses a naive - * multiplication and computes the entire upper triangle of the kernel matrix, + * This function computes the kernel matrix of a data matrix based on the + * requested kernel type and the kernel parameters. The potential types of + * kernel functions are document in KernelType. This function uses a naive + * multiplication and computes the entire upper triangle of the kernel matrix, * then copies this over to the lower triangle. * * @param[in] model a GenModel structure with the model @@ -131,8 +163,8 @@ void gensvm_kernel_postprocess(struct GenModel *model, * @param[out] K an nxn preallocated kernel matrix * */ -void gensvm_make_kernel(struct GenModel *model, struct GenData *data, - double *K) +void gensvm_kernel_compute(struct GenModel *model, struct GenData *data, + double *K) { long i, j; long n = data->n; @@ -145,13 +177,13 @@ void gensvm_make_kernel(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_dot_poly(x1, x2, + value = gensvm_kernel_dot_poly(x1, x2, model->kernelparam, data->m); else if (model->kerneltype == K_RBF) - value = gensvm_dot_rbf(x1, x2, + value = gensvm_kernel_dot_rbf(x1, x2, model->kernelparam, data->m); else if (model->kerneltype == K_SIGMOID) - value = gensvm_dot_sigmoid(x1, x2, + value = gensvm_kernel_dot_sigmoid(x1, x2, model->kernelparam, data->m); else { err("[GenSVM Error]: Unknown kernel type in " @@ -167,23 +199,30 @@ void gensvm_make_kernel(struct GenModel *model, struct GenData *data, /** * @brief Find the (reduced) eigendecomposition of a kernel matrix * - * @todo - * Document this function + * @details + * Compute the reduced eigendecomposition of the kernel matrix. This uses the + * LAPACK function dsyevx to do the computation. Only those + * eigenvalues/eigenvectors are kept for which the ratio between the + * eigenvalue and the largest eigenvalue is larger than GENSVM_EIGEN_CUTOFF. + * This function uses the highest precision eigenvalues, twice the underflow + * threshold (see dsyevx documentation). * - * @param[in] K - * @param[in] n - * @param[out] P - * @param[out] Sigma + * @param[in] K the kernel matrix + * @param[in] n the dimension of the kernel matrix + * @param[out] P on exit contains the eigenvectors + * @param[out] Sigma on exit contains the eigenvalues * - * @return + * @return the number of eigenvalues kept */ -long gensvm_make_eigen(double *K, long n, double **P, double **Sigma) +long gensvm_kernel_eigendecomp(double *K, long n, double **P_ret, + double **Sigma_ret) { - int M, status, LWORK, - *IWORK = NULL, + int M, status, LWORK, *IWORK = NULL, *IFAIL = NULL; long i, j, num_eigen, cutoff_idx; - double max_eigen, abstol, *WORK = NULL; + double max_eigen, abstol, *WORK = NULL, + *Sigma = NULL, + *P = NULL; double *tempSigma = Malloc(double, n); double *tempP = Malloc(double, n*n); @@ -216,26 +255,26 @@ long gensvm_make_eigen(double *K, long n, double **P, double **Sigma) max_eigen = tempSigma[n-1]; cutoff_idx = 0; - for (i=0; i<n; i++) - if (tempSigma[i]/max_eigen > 1e-8 ) { + for (i=0; i<n; i++) { + if (tempSigma[i]/max_eigen > GENSVM_EIGEN_CUTOFF) { cutoff_idx = i; break; } + } num_eigen = n - cutoff_idx; - *Sigma = Calloc(double, num_eigen); - + Sigma = Calloc(double, num_eigen); for (i=0; i<num_eigen; i++) { - (*Sigma)[i] = tempSigma[n-1 - i]; + Sigma[i] = tempSigma[n-1 - i]; } // revert P to row-major order and copy only the the columns // corresponding to the selected eigenvalues - *P = Calloc(double, n*num_eigen); + P = Calloc(double, n*num_eigen); for (j=n-1; j>n-1-num_eigen; j--) { for (i=0; i<n; i++) { - (*P)[i*num_eigen + (n-1)-j] = tempP[i + j*n]; + P[i*num_eigen + (n-1)-j] = tempP[i + j*n]; } } @@ -245,51 +284,83 @@ long gensvm_make_eigen(double *K, long n, double **P, double **Sigma) free(IFAIL); free(WORK); + *Sigma_ret = Sigma; + *P_ret = P; + return num_eigen; } -void gensvm_make_crosskernel(struct GenModel *model, - struct GenData *data_train, struct GenData *data_test, - double **K2) +/** + * @brief Compute the kernel crossproduct between two datasets + * + * @details + * Given a training set @f$\textbf{X}@f$ with feature space mapping + * @f$\boldsymbol{\Phi}@f$ and a test set @f$\textbf{X}_2@f$ with feature + * space mapping @f$\boldsymbol{\Phi}_2@f$, the crosskernel @f$\textbf{K}_2@f$ + * is given by @f$\textbf{K}_2 = \boldsymbol{\Phi}_2 \boldsymbol{\Phi}'@f$. + * Thus, an element in row @f$i@f$ and column @f$j@f$ in @f$\textbf{K}_2@f$ + * equals the kernel product between the @f$i@f$-th row of @f$\textbf{X}_2@f$ + * and the @f$j@f$-th row of @f$\textbf{X}@f$. + * + * @param[in] model the GenSVM model + * @param[in] data_train the training dataset + * @param[in] data_test the test dataset + * + * @return the matrix @f$\textbf{K}_2@f$ + */ +double *gensvm_kernel_cross(struct GenModel *model, struct GenData *data_train, + struct GenData *data_test) { long i, j; long n_train = data_train->n; long n_test = data_test->n; long m = data_test->m; - double value; - double *x1 = NULL, - *x2 = NULL; - - *K2 = Calloc(double, n_test*n_train); + double value, *x1 = NULL, + *x2 = NULL, + *K2 = Calloc(double, n_test * n_train); for (i=0; i<n_test; i++) { for (j=0; j<n_train; j++) { x1 = &data_test->RAW[i*(m+1)+1]; x2 = &data_train->RAW[j*(m+1)+1]; if (model->kerneltype == K_POLY) - value = gensvm_dot_poly(x1, x2, - model->kernelparam, - m); + value = gensvm_kernel_dot_poly(x1, x2, + model->kernelparam, m); else if (model->kerneltype == K_RBF) - value = gensvm_dot_rbf(x1, x2, - model->kernelparam, - m); + value = gensvm_kernel_dot_rbf(x1, x2, + model->kernelparam, m); else if (model->kerneltype == K_SIGMOID) - value = gensvm_dot_sigmoid(x1, x2, - model->kernelparam, - m); + value = gensvm_kernel_dot_sigmoid(x1, x2, + model->kernelparam, m); else { err("[GenSVM Error]: Unknown kernel type in " "gensvm_make_crosskernel\n"); exit(EXIT_FAILURE); } - matrix_set((*K2), n_train, i, j, value); + matrix_set(K2, n_train, i, j, value); } } + return K2; } -void gensvm_make_trainfactor(struct GenData *data, double *P, double *Sigma, - long r) +/** + * @brief Compute the training factor as part of kernel preprocessing + * + * @details + * This function computes the matrix product @f$\textbf{M} = + * \textbf{P}\boldsymbol{\Sigma}@f$ and stores the result in GenData::Z, + * preceded by a column of ones. It also sets GenData::r to the number of + * eigenvectors that were includedin P and Sigma. Note that P and Sigma + * correspond to the reduced eigendecomposition of the kernel matrix. + * + * @param[in,out] data a GenData structure. On exit, GenData::Z and + * GenData::r are updated as described above. + * @param[in] P the eigenvectors + * @param[in] Sigma the eigenvalues + * @param[in] r the number of eigenvalues and eigenvectors + */ +void gensvm_kernel_trainfactor(struct GenData *data, double *P, double *Sigma, + long r) { long i, j, n = data->n; double value; @@ -311,12 +382,29 @@ void gensvm_make_trainfactor(struct GenData *data, double *P, double *Sigma, data->r = r; } -void gensvm_make_testfactor(struct GenData *testdata, - struct GenData *traindata, double *K2) +/** + * @brief Calculate the matrix product for the testfactor + * + * @details + * To predict class labels when kernels are used, a transformation of the + * testdata has to be performed to get the simplex space vectors. This + * transformation is based on the matrix @f$\textbf{K}_2@f$ (as calculated by + * gensvm_make_crosskernel()) and the matrices @f$\textbf{M} = + * \textbf{P}*\boldsymbol{\Sigma}@f$) and @f$\boldsymbol{\Sigma}@f$. The + * testfactor is equal to @f$\textbf{K}_2 \textbf{M} + * \boldsymbol{\Sigma}^{-2}@f$. + * + * @param[out] testdata a GenData struct with the testdata, contains + * the testfactor in GenData::Z on exit preceded + * by a column of ones. + * @param[in] traindata a GenData struct with the training data + * @param[in] K2 crosskernel between the train and test data + */ +void gensvm_kernel_testfactor(struct GenData *testdata, + struct GenData *traindata, double *K2) { long n1, n2, r, i, j; - double value, - *N = NULL, + double value, *N = NULL, *M = NULL; n1 = traindata->n; @@ -328,10 +416,12 @@ void gensvm_make_testfactor(struct GenData *testdata, // copy M from traindata->Z because we need it in dgemm without column // of 1's. - for (i=0; i<n1; i++) - for (j=0; j<r; j++) - matrix_set(M, r, i, j, - matrix_get(traindata->Z, r+1, i, j+1)); + for (i=0; i<n1; i++) { + for (j=0; j<r; j++) { + value = matrix_get(traindata->Z, r+1, i, j+1); + matrix_set(M, r, i, j, value); + } + } // Multiply K2 with M and store in N cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, n2, r, n1, 1.0, @@ -377,7 +467,8 @@ void gensvm_make_testfactor(struct GenData *testdata, * @param[in] n length of the vectors x1 and x2 * @returns kernel evaluation */ -double gensvm_dot_rbf(double *x1, double *x2, double *kernelparam, long n) +double gensvm_kernel_dot_rbf(double *x1, double *x2, double *kernelparam, + long n) { long i; double value = 0.0; @@ -405,15 +496,13 @@ double gensvm_dot_rbf(double *x1, double *x2, double *kernelparam, long n) * @param[in] n length of the vectors x1 and x2 * @returns kernel evaluation */ -double gensvm_dot_poly(double *x1, double *x2, double *kernelparam, long n) +double gensvm_kernel_dot_poly(double *x1, double *x2, double *kernelparam, + long n) { - long i; - double value = 0.0; - for (i=0; i<n; i++) - value += x1[i]*x2[i]; + double value = cblas_ddot(n, x1, 1, x2, 1); value *= kernelparam[0]; value += kernelparam[1]; - return pow(value, ((int) kernelparam[2])); + return pow(value, kernelparam[2]); } /** @@ -433,12 +522,10 @@ double gensvm_dot_poly(double *x1, double *x2, double *kernelparam, long n) * @param[in] n length of the vectors x1 and x2 * @returns kernel evaluation */ -double gensvm_dot_sigmoid(double *x1, double *x2, double *kernelparam, long n) +double gensvm_kernel_dot_sigmoid(double *x1, double *x2, double *kernelparam, + long n) { - long i; - double value = 0.0; - for (i=0; i<n; i++) - value += x1[i]*x2[i]; + double value = cblas_ddot(n, x1, 1, x2, 1); value *= kernelparam[0]; value += kernelparam[1]; return tanh(value); @@ -454,18 +541,17 @@ double gensvm_dot_sigmoid(double *x1, double *x2, double *kernelparam, long n) * See the LAPACK documentation at: * http://www.netlib.org/lapack/explore-html/d2/d97/dsyevx_8f.html * - * */ int dsyevx(char JOBZ, char RANGE, char UPLO, int N, double *A, int LDA, - double VL, double VU, int IL, int IU, double ABSTOL, int *M, + double VL, double VU, int IL, int IU, double ABSTOL, int *M, double *W, double *Z, int LDZ, double *WORK, int LWORK, int *IWORK, int *IFAIL) { extern void dsyevx_(char *JOBZ, char *RANGE, char *UPLO, int *Np, double *A, int *LDAp, double *VLp, double *VUp, - int *ILp, int *IUp, double *ABSTOLp, int *M, + int *ILp, int *IUp, double *ABSTOLp, int *M, double *W, double *Z, int *LDZp, double *WORK, - int *LWORKp, int *IWORK, int *IFAIL, int *INFOp); + int *LWORKp, int *IWORK, int *IFAIL, int *INFOp); int INFO; dsyevx_(&JOBZ, &RANGE, &UPLO, &N, A, &LDA, &VL, &VU, &IL, &IU, &ABSTOL, M, W, Z, &LDZ, WORK, &LWORK, IWORK, IFAIL, &INFO); diff --git a/tests/Makefile b/tests/Makefile index 11a0022..febe7be 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -3,7 +3,7 @@ CFLAGS=-Wall -g -rdynamic -DNDEBUG $(OPTFLAGS) INCLUDE=-I../include/ -I./include LIB=-L../lib -override LDFLAGS+=-lgensvm -lm -lcblas -llapack -latlas +override LDFLAGS+=-lm -lcblas -llapack -latlas -lgensvm TEST_SRC=$(wildcard src/test_*.c) TESTS=$(patsubst src/%.c,bin/%,$(TEST_SRC)) diff --git a/tests/src/test_gensvm_kernel.c b/tests/src/test_gensvm_kernel.c new file mode 100644 index 0000000..47eb8b1 --- /dev/null +++ b/tests/src/test_gensvm_kernel.c @@ -0,0 +1,153 @@ +/** + *@file test_gensvm_kernel.c + *@author G.J.J. van den Burg + *@date 2016-11-09 + *@brief Unit tests for gensvm_kernel.c + * + *@copyright + Copyright 2016, G.J.J. van den Burg. + + This file is part of GenSVM. + + GenSVM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + GenSVM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GenSVM. If not, see <http://www.gnu.org/licenses/>. + + */ + +#include "minunit.h" +#include "gensvm_kernel.h" + +char *test_dot_rbf() +{ + double dot; + double *a = Malloc(double, 5); + double *b = Malloc(double, 5); + double *kernelparam = Malloc(double, 1); + + a[0] = 0.5203363837176203; + a[1] = 0.3860628599460129; + a[2] = 0.3592536954640216; + a[3] = 0.6824659760765744; + a[4] = 0.5390520090020700; + + b[0] = 0.1782643262351465; + b[1] = 0.0314270210724957; + b[2] = 0.5887219369641497; + b[3] = 0.7710042954911620; + b[4] = 0.8805451245738238; + + // start test code // + kernelparam[0] = 1.0; + dot = gensvm_kernel_dot_rbf(a, b, kernelparam, 5); + mu_assert(fabs(dot - 0.657117701533133) < 1e-14, "Incorrect dot (1)"); + + kernelparam[0] = 5.0; + dot = gensvm_kernel_dot_rbf(a, b, kernelparam, 5); + mu_assert(fabs(dot - 0.122522495044048) < 1e-14, "Incorrect dot (2)"); + + // end test code // + free(a); + free(b); + free(kernelparam); + + return NULL; +} + +char *test_dot_poly() +{ + double dot; + double *a = Malloc(double, 5); + double *b = Malloc(double, 5); + double *kernelparam = Malloc(double, 3); + + a[0] = 0.5203363837176203; + a[1] = 0.3860628599460129; + a[2] = 0.3592536954640216; + a[3] = 0.6824659760765744; + a[4] = 0.5390520090020700; + + b[0] = 0.1782643262351465; + b[1] = 0.0314270210724957; + b[2] = 0.5887219369641497; + b[3] = 0.7710042954911620; + b[4] = 0.8805451245738238; + + // start test code // + kernelparam[0] = 1.0; + kernelparam[1] = 1.0; + kernelparam[2] = 1.0; + dot = gensvm_kernel_dot_poly(a, b, kernelparam, 5); + mu_assert(fabs(dot - 2.31723456944910) < 1e-14, "Incorrect dot (1)"); + + kernelparam[0] = 1.5; + kernelparam[1] = 2.5; + kernelparam[2] = 3.5; + dot = gensvm_kernel_dot_poly(a, b, kernelparam, 5); + mu_assert(fabs(dot - 189.6989652572890179) < 1e-14, "Incorrect dot (2)"); + + // end test code // + free(a); + free(b); + free(kernelparam); + return NULL; +} + +char *test_dot_sigmoid() +{ + double dot; + double *a = Malloc(double, 5); + double *b = Malloc(double, 5); + double *kernelparam = Malloc(double, 2); + + a[0] = 0.5203363837176203; + a[1] = 0.3860628599460129; + a[2] = 0.3592536954640216; + a[3] = 0.6824659760765744; + a[4] = 0.5390520090020700; + + b[0] = 0.1782643262351465; + b[1] = 0.0314270210724957; + b[2] = 0.5887219369641497; + b[3] = 0.7710042954911620; + b[4] = 0.8805451245738238; + + // start test code // + kernelparam[0] = 1.0; + kernelparam[1] = 1.0; + dot = gensvm_kernel_dot_sigmoid(a, b, kernelparam, 5); + mu_assert(fabs(dot - 0.9807642810850747) < 1e-14, "Incorrect dot (1)"); + + kernelparam[0] = 1.5; + kernelparam[1] = 2.5; + dot = gensvm_kernel_dot_sigmoid(a, b, kernelparam, 5); + mu_assert(fabs(dot - 0.9997410009167159) < 1e-14, "Incorrect dot (2)"); + + // end test code // + free(a); + free(b); + free(kernelparam); + + return NULL; +} + +char *all_tests() +{ + mu_suite_start(); + mu_run_test(test_dot_rbf); + mu_run_test(test_dot_poly); + mu_run_test(test_dot_sigmoid); + + return NULL; +} + +RUN_TESTS(all_tests); |
