summaryrefslogtreecommitdiff
path: root/OASIS/C/src
diff options
context:
space:
mode:
authorEric Dao <eric@erickhangdao.com>2023-05-12 14:09:07 -0400
committerEric Dao <eric@erickhangdao.com>2023-05-12 14:09:07 -0400
commit191e4bd8beae134295d481773823142d2fdc6a98 (patch)
treeaaca4e7f8e229f9bd551d9bb1583b8ecd7a59d4a /OASIS/C/src
parent186daed7e179241377c117e9d208ccd301d4d712 (diff)
downloadura-master.tar.gz
ura-master.tar.bz2
ura-master.zip
refactored tool chain setup, able to debug and run from vscode nowHEADmaster
Diffstat (limited to 'OASIS/C/src')
-rw-r--r--OASIS/C/src/ekd_blas.c191
-rw-r--r--OASIS/C/src/ekd_cv.c90
-rw-r--r--OASIS/C/src/ekd_pca.c286
-rw-r--r--OASIS/C/src/ekd_svm.c259
-rw-r--r--OASIS/C/src/main.c108
5 files changed, 0 insertions, 934 deletions
diff --git a/OASIS/C/src/ekd_blas.c b/OASIS/C/src/ekd_blas.c
deleted file mode 100644
index 8555fbf..0000000
--- a/OASIS/C/src/ekd_blas.c
+++ /dev/null
@@ -1,191 +0,0 @@
-#include "ekd_blas.h"
-
-void print_vector(float* vector, uint32_t size) {
- for (uint32_t i=0; i<size; i++) printf("%.2f ", vector[i]);
-}
-
-void print_matrix(float** matrix, uint32_t rows, uint32_t cols) {
- for (uint32_t i=0; i<rows; i++) {
- printf("\n");
- for (uint32_t j=0; j<cols; j++) printf("%.2f ", matrix[i][j]);
- }
-}
-
-void copy_vector(float* input_vector, float* resultant_vector, uint32_t size) {
- for (uint32_t i=0; i<size; i++) resultant_vector[i] = input_vector[i];
-}
-
-void copy_matrix(float** input_matrix, float** resultant_matrix, uint32_t rows, uint32_t cols) {
- for (uint32_t i=0; i<rows; i++){
- for (uint32_t j=0; j<cols; j++) resultant_matrix[i][j] = input_matrix[i][j];
- }
-}
-
-float trace_matrix(float** input_matrix, uint32_t size) {
- float trace = 0.0f;
- for (uint32_t i=0; i<size; i++) {
- for (uint32_t j=0; j< size; j++) {
- if (i == j) trace += input_matrix[i][j];
- }
- }
-
- return trace;
-}
-
-void shift_matrix(float** input_matrix, uint32_t size, float trace, shift_matrix_operation_e operation) {
- for (uint32_t i=0; i<size; i++) {
- for (uint32_t j=0; j<size; j++) {
- if (i == j) {
- if (operation == SHIFT_ADD) {
- input_matrix[i][j] += trace;
- } else if (operation == SHIFT_SUBTRACT) {
- input_matrix[i][j] -= trace;
- }
- }
- }
- }
-}
-
-void eye(float** input_matrix, uint32_t size) {
- for (uint32_t i=0; i<size; i++) {
- for (uint32_t j=0; j<size; j++) input_matrix[i][j] = (i == j) ? 1 : 0;
- }
-}
-
-void outer_product(float* input_vector, uint32_t size, float** resultant_matrix) {
- // for (uint32_t i=0; i<size; i++) {
- // for (uint32_t j=0; j<size; j++) resultant_matrix[i][j] = input_vector[i] * input_vector[j];
- // }
- for (uint32_t i = 0; i < size; i++) {
- for (uint32_t j = i; j < size; j++) {
- float value = input_vector[i] * input_vector[j];
- resultant_matrix[i][j] = value;
- resultant_matrix[j][i] = value;
- }
- }
-}
-
-float inner_product(float* input_vector_1, float* input_vector_2, uint32_t size) {
- float resultant_scalar = 0.0;
- for (uint32_t i=0; i<size; i++) resultant_scalar += input_vector_1[i] * input_vector_2[i];
- return resultant_scalar;
-}
-
-void transpose(float** input_matrix, uint32_t rows, uint32_t cols, float** transposed_matrix) {
- for (uint32_t i=0; i<rows; i++){
- for (uint32_t j=0; j<cols; j++) transposed_matrix[j][i] = input_matrix[i][j];
- }
-}
-
-void matrix_operation(float** input_matrix_A, uint32_t rows_A, uint32_t cols_A, float** input_matrix_B, uint32_t rows_B, uint32_t cols_B, float** resultant_matrix, matrix_matrix_operation_e operation) {
- if (operation == MM_ADD) {
- for (uint32_t i=0; i<rows_A; i++) {
- for (uint32_t j=0; j<cols_A; j++) resultant_matrix[i][j] = input_matrix_A[i][j] + input_matrix_B[i][j];
- }
- } else if (operation == MM_SUBTRACT) {
- for (uint32_t i=0; i<rows_A; i++) {
- for (uint32_t j=0; j<cols_A; j++) resultant_matrix[i][j] = input_matrix_A[i][j] - input_matrix_B[i][j];
- }
- } else if (operation == MM_MULTIPLY) {
- for (uint32_t i=0; i<rows_A; i++) {
- for (uint32_t j=0; j<cols_B; j++) {
- resultant_matrix[i][j] = 0;
- for (uint32_t k=0; k<cols_A; k++) resultant_matrix[i][j] += input_matrix_A[i][k] * input_matrix_B[k][j];
- }
- }
- } else if (operation == MM_MULTIPLY_OMP) {
- uint32_t a, b, c;
- #pragma omp parallel for private(a, b, c) shared(input_matrix_A, input_matrix_B, resultant_matrix)
- for (a=0; a<rows_A; a++) {
- for (b=0; b<cols_B; b++) {
- resultant_matrix[a][b] = 0;
- for (c=0; c<cols_A; c++) resultant_matrix[a][b] += input_matrix_A[a][c] * input_matrix_B[c][b];
- }
- }
- } else if (operation == MM_MULTIPLY_GEMM) {
- float* temp_matrix_A = malloc(rows_A * cols_A * sizeof(float));
- float* temp_matrix_B = malloc(rows_B * cols_B * sizeof(float));
- float* temp_resultant_matrix = malloc(rows_A * cols_B * sizeof(float));
-
- for (uint32_t i = 0; i < rows_A; i++) {
- for (uint32_t j = 0; j < cols_A; j++) {
- temp_matrix_A[i * cols_A + j] = input_matrix_A[i][j];
- }
- }
-
- for (uint32_t i = 0; i < rows_B; i++) {
- for (uint32_t j = 0; j < cols_B; j++) {
- temp_matrix_B[i * cols_B + j] = input_matrix_B[i][j];
- }
- }
-
- cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, rows_A, cols_B, cols_A, 1.0, temp_matrix_A, cols_A, temp_matrix_B, cols_B, 0.0, temp_resultant_matrix, cols_B);
-
- for (uint32_t i = 0; i < rows_A; i++) {
- for (uint32_t j = 0; j < cols_B; j++) {
- resultant_matrix[i][j] = temp_resultant_matrix[i * cols_B + j];
- }
- }
-
- free(temp_matrix_A);
- free(temp_matrix_B);
- free(temp_resultant_matrix);
- }
-}
-
-uint8_t sign(float num) {
- return (num > 0) - (num < 0);
-}
-
-void vector_normalize(float* vector, uint32_t size) {
- float norm = 0.0;
- for (uint32_t i=0; i<size; i++) norm += vector[i] * vector[i];
- norm = sqrt(norm);
- for (uint32_t i=0; i<size; i++) vector[i] = (norm == 0) ? 0 : vector[i]/norm;
-}
-
-float vector_norm(float* vector, uint32_t size) {
- float norm = 0.0;
- for (uint32_t i=0; i<size; i++) norm += vector[i] * vector[i];
-
- return sqrt(norm);
-}
-
-float matrix_norm(float** input_matrix_A1, float** input_matrix_A, uint32_t rows, uint32_t cols) {
- float norm = 0.0;
- for (uint32_t i=0; i<rows; i++) {
- for (uint32_t j=0; j<cols; j++) norm += fabs(input_matrix_A1[i][j] - input_matrix_A[i][j]) * fabs(input_matrix_A1[i][j] - input_matrix_A[i][j]);
- }
-
- return sqrt(norm);
-}
-
-float cosine_similarity(float* curr_vector, float* new_vector, uint32_t size) {
- float dot_product = 0.0f;
- for (uint32_t i=0; i<size; i++) dot_product += curr_vector[i] * new_vector[i];
-
- return (vector_norm(curr_vector, size) == 0 || vector_norm(new_vector, size) == 0) ? 1e-6 : dot_product / (vector_norm(curr_vector, size) * vector_norm(new_vector, size));
-}
-
-void matrix_vector_multiply(float** input_matrix, uint32_t rows, uint32_t cols, float* input_vector, float* resultant_vector, matrix_vector_operation_e operation) {
- if (operation == MV_MULTIPLY) {
- for (uint32_t i=0; i<rows; i++) {
- resultant_vector[i] = 0;
- for (uint32_t j=0; j<cols; j++) {
- resultant_vector[i] += input_matrix[i][j] * input_vector[j];
- }
- }
- } else if (operation == MV_MULTIPLY_GEMV) {
- float* temp_matrix = malloc(rows * cols * sizeof(float));
-
- for (uint32_t i = 0; i < rows; i++) {
- for (uint32_t j = 0; j < cols; j++) {
- temp_matrix[i * cols + j] = input_matrix[i][j];
- }
- }
-
- cblas_sgemv(CblasRowMajor, CblasNoTrans, rows, cols, 1.0f, temp_matrix, cols, input_vector, 1, 0.0f, resultant_vector, 1);
-
- free(temp_matrix);
- }
-} \ No newline at end of file
diff --git a/OASIS/C/src/ekd_cv.c b/OASIS/C/src/ekd_cv.c
deleted file mode 100644
index 1f9afad..0000000
--- a/OASIS/C/src/ekd_cv.c
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "ekd_cv.h"
-
-void read_bmp(char* filename, uint8_t** data) {
- bmp_header_t header;
- bmp_info_t info;
-
- FILE* file = fopen(filename, "rb");
- if (file == NULL) {
- printf("Unable to open file.\n");
- return;
- }
-
- fread(&header.signature, sizeof(uint16_t), 1, file);
- fread(&header.file_size, sizeof(uint32_t), 1, file);
- fread(&header.reserved, sizeof(uint32_t), 1, file);
- fread(&header.data_offset, sizeof(uint32_t), 1, file);
-
- fread(&info.size, sizeof(uint32_t), 1, file);
- fread(&info.width, sizeof(uint32_t), 1, file);
- fread(&info.height, sizeof(uint32_t), 1, file);
- fread(&info.planes, sizeof(uint16_t), 1, file);
- fread(&info.bit_depth, sizeof(uint16_t), 1, file);
- fread(&info.compression, sizeof(uint32_t), 1, file);
- fread(&info.image_size, sizeof(uint32_t), 1, file);
- fread(&info.x_pixels_per_meter, sizeof(uint32_t), 1, file);
- fread(&info.y_pixels_per_meter, sizeof(uint32_t), 1, file);
- fread(&info.colours_used, sizeof(uint32_t), 1, file);
- fread(&info.important_colours, sizeof(uint32_t), 1, file);
-
- uint8_t* raw_data = (uint8_t*) malloc(info.width * info.height * sizeof(uint8_t));
-
- fseek(file, header.data_offset, SEEK_SET);
- fread(raw_data, sizeof(uint8_t), info.width * info.height, file);
-
- fclose(file);
-
- for (uint8_t i=0; i<info.height; i++) {
- for (uint8_t j=0; j < info.width; j++) data[i][j] = raw_data[(i * info.width) + j];
- }
-
- free(raw_data);
-}
-
-void read_dir(char* dneg_path, char* dpos_path, char** file_name_arr) {
- DIR* dneg_dir = opendir(dneg_path);
- DIR* dpos_dir = opendir(dpos_path);
- struct dirent *entry;
- uint8_t item_id = 0;
-
- while ((entry = readdir(dneg_dir)) != NULL) {
- if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
- continue;
- }
- strcat(file_name_arr[item_id], entry->d_name);
- item_id++;
- }
-
- while ((entry = readdir(dpos_dir)) != NULL) {
- if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
- continue;
- }
- strcat(file_name_arr[item_id], entry->d_name);
- item_id++;
- }
-
- closedir(dneg_dir);
- closedir(dpos_dir);
-}
-
-void flatten_image(uint8_t** image, float* image_flattened) {
- for (uint8_t i=0; i<IMAGE_HEIGHT; i++) {
- for (uint8_t j=0; j<IMAGE_WIDTH; j++) image_flattened[(i*IMAGE_WIDTH)+j] = (float)image[i][j];
- }
-}
-
-void shuffle_data_labels(float** data, int32_t* labels, uint8_t num_images) {
- srand(time(NULL)); // initialize random seed
- for (int i = num_images - 1; i > 0; i--) {
- // Generate a random index between 0 and i (inclusive)
- int j = rand() % (i + 1);
-
- // Swap the rows of data_flatten and labels at indices i and j
- float* temp_data = data[i];
- data[i] = data[j];
- data[j] = temp_data;
- int32_t temp_label = labels[i];
- labels[i] = labels[j];
- labels[j] = temp_label;
- }
-} \ No newline at end of file
diff --git a/OASIS/C/src/ekd_pca.c b/OASIS/C/src/ekd_pca.c
deleted file mode 100644
index f76d20e..0000000
--- a/OASIS/C/src/ekd_pca.c
+++ /dev/null
@@ -1,286 +0,0 @@
-#include "ekd_pca.h"
-
-void centre_scale(float** input_matrix, uint32_t rows, uint32_t cols, centre_scale_operation_e operation) {
- float* means = (float*) malloc(cols * sizeof(float));
- float* std_devs = (float*) malloc(cols * sizeof(float));
-
- // Iterating column by column
- for (uint32_t j = 0; j<cols; j++) {
- float col_sum = 0.0;
- for (uint32_t i = 0; i<rows; i++){
- col_sum += input_matrix[i][j];
- }
- means[j] = col_sum / (float)rows;
-
- float variance = 0.0;
- for (uint32_t i = 0; i<rows; i++) variance += (input_matrix[i][j] - means[j]) * (input_matrix[i][j] - means[j]);
- std_devs[j] = (variance < 1e-6) ? 1e-6 : sqrtf(variance / (float)rows);
- }
-
- // Centering -> subtract means, Scaling -> Divide by std_devs
- for (uint32_t j=0; j<cols; j++) {
- for (uint32_t i=0; i<rows; i++) {
- if (operation == MEAN_UNIT_VARIANCE) {
- input_matrix[i][j] = (input_matrix[i][j] - means[j]) / std_devs[j];
- } else if (operation == MEAN) {
- input_matrix[i][j] = (input_matrix[i][j] - means[j]);
- }
- }
- }
-
- free(means);
- free(std_devs);
-}
-
-void covariance(float** input_matrix, uint32_t rows, uint32_t cols, float** covariance_matrix) {
- float** transposed_matrix = (float**) malloc(cols * sizeof(float*));
- for (uint32_t i=0; i<cols; i++) transposed_matrix[i] = (float*) malloc(rows * sizeof(float));
-
- transpose(input_matrix, rows, cols, transposed_matrix);
-
- matrix_operation(transposed_matrix, cols, rows, input_matrix, rows, cols, covariance_matrix, MM_MULTIPLY_GEMM);
-
- // Divide by n since we have full population
- for (uint32_t i=0; i<cols; i++) {
- for (uint32_t j=0; j<cols; j++) covariance_matrix[i][j] /= rows-1;
- }
-
- for (uint32_t i=0; i<cols; i++) free(transposed_matrix[i]);
- free(transposed_matrix);
-}
-
-void house_holder_vector(float* vector, uint32_t size) {
-
- // Computes the norm of the input vector
- float norm_input_vector = 0.0;
- for (uint32_t i=0; i<size; i++) norm_input_vector += vector[i] * vector[i];
- norm_input_vector = sqrt(norm_input_vector);
-
- // Since the rest of output vector already is the input vector, change the first index
- vector[0] = vector[0] + sign(vector[0]) * norm_input_vector;
-}
-
-void house_holder_transformation(float* house_holder_vector, uint32_t size, float** house_holder_matrix) {
- float** identity_matrix = (float**) malloc(size * sizeof(float*));
- for (uint32_t i=0; i<size; i++) identity_matrix[i] = (float*) malloc(size * sizeof(float));
-
- float** numerator = (float**) malloc(size * sizeof(float*));
- for (uint32_t i=0; i<size; i++) numerator[i] = (float*) malloc(size * sizeof(float));
-
- eye(identity_matrix, size);
-
- float denominator = inner_product(house_holder_vector, house_holder_vector, size);
-
- outer_product(house_holder_vector, size, numerator);
-
- for (uint32_t i=0; i<size; i++) {
- for (uint32_t j=0; j<size; j++) numerator[i][j] = (denominator == 0) ? 0 : (2 / denominator) * numerator[i][j];
- }
-
- matrix_operation(identity_matrix, size, size, numerator, size, size, house_holder_matrix, MM_SUBTRACT);
-
- for (uint32_t i=0; i<size; i++){
- free(numerator[i]);
- free(identity_matrix[i]);
- }
- free(numerator);
- free(identity_matrix);
-}
-
-void qr_decomposition(float** input_matrix, uint32_t size, float** resultant_matrix) {
- float** matrix_Q = (float**) malloc(size * sizeof(float*)); // Has size x size dimensions
- float** matrix_Q_prime = (float**) malloc(size * sizeof(float*)); // Has size x size dimensions
- float** matrix_R = (float**) malloc(size * sizeof(float*)); // Has size x size dimensions
- float** matrix_R_prime = (float**) malloc(size * sizeof(float*)); // Has size x size dimensions
- for(uint32_t i=0; i<size; i++) {
- matrix_Q[i] = (float*) malloc(size * sizeof(float));
- matrix_Q_prime[i] = (float*) malloc(size * sizeof(float));
- matrix_R[i] = (float*) malloc(size * sizeof(float));
- matrix_R_prime[i] = (float*) malloc(size * sizeof(float));
- }
-
- for (uint32_t i=0; i<size; i++) memcpy(matrix_R[i], input_matrix[i], size * sizeof(float));
-
- eye(matrix_Q, size);
-
- for (uint32_t i=0; i<size; i++) {
- float* current_house_holder_vector = (float*) malloc((size - i) * sizeof(float));
-
- float** current_house_holder_matrix = (float**) malloc((size - i) * sizeof(float*)); // Has (size-i)x(size-i) dimensions
- for (uint32_t j=0; j<(size - i); j++) current_house_holder_matrix[j] = (float*) malloc((size - i) * sizeof(float));
-
- float** matrix_H = (float**) malloc(size * sizeof(float*)); // Has size x size dimensions
- for (uint32_t j=0; j<size; j++) matrix_H[j] = (float*) malloc(size * sizeof(float));
-
- eye(matrix_H, size);
-
- for(uint32_t j=0; j<(size - i); j++) current_house_holder_vector[j] = matrix_R[j+i][i];
-
- house_holder_vector(current_house_holder_vector, (size - i));
-
- house_holder_transformation(current_house_holder_vector, (size - i), current_house_holder_matrix);
-
- // Starting from the ith ith sub matrix
- for (uint32_t j=i; j<size; j++) {
- for (uint32_t k=i; k<size; k++) matrix_H[j][k] = current_house_holder_matrix[j-i][k-i];
- }
-
- matrix_operation(matrix_H, size, size, matrix_R, size, size, matrix_R_prime, MM_MULTIPLY_GEMM);
- matrix_operation(matrix_Q, size, size, matrix_H, size, size, matrix_Q_prime, MM_MULTIPLY_GEMM);
-
- // print_matrix(matrix_H, size, size);
-
- for (uint32_t j=0; j<size; j++) memcpy(matrix_Q[j], matrix_Q_prime[j], size * sizeof(float));
- for (uint32_t j=0; j<size; j++) memcpy(matrix_R[j], matrix_R_prime[j], size * sizeof(float));
-
- for (uint32_t j=0; j<size; j++) free(matrix_H[j]);
- free(matrix_H);
- for (uint32_t j=0; j<(size - i); j++) free(current_house_holder_matrix[j]);
- free(current_house_holder_matrix);
- free(current_house_holder_vector);
- }
-
- matrix_operation(matrix_R, size, size, matrix_Q, size, size, resultant_matrix, MM_MULTIPLY_GEMM);
- matrix_operation(matrix_Q, size, size, matrix_R, size, size, resultant_matrix, MM_MULTIPLY_GEMM);
-
- print_matrix(matrix_R, size, size);
-
- for (uint32_t i=0; i<size; i++) {
- free(matrix_R[i]);
- free(matrix_R_prime[i]);
- free(matrix_Q_prime[i]);
- free(matrix_Q[i]);
- }
- free(matrix_R_prime);
- free(matrix_R);
- free(matrix_Q_prime);
- free(matrix_Q);
-}
-
-void qr_algorithm(float** input_matrix, uint32_t rows, uint32_t cols, float** resultant_matrix) {
- float** covariance_matrix = (float**) malloc(cols * sizeof(float*)); // Has feature x feature dimensions
- for (uint32_t i=0; i<cols; i++) covariance_matrix[i] = (float*) malloc(cols * sizeof(float));
-
- float** covariance_matrix_prime = (float**) malloc(cols * sizeof(float*)); // Has feature x feature dimensions
- for (uint32_t i=0; i<cols; i++) covariance_matrix_prime[i] = (float*) malloc(cols * sizeof(float));
-
- centre_scale(input_matrix, rows, cols, MEAN);
- covariance(input_matrix, rows, cols, covariance_matrix);
-
- qr_decomposition(covariance_matrix, cols, covariance_matrix_prime);
- while (matrix_norm(covariance_matrix_prime, covariance_matrix, cols, cols) > TOLERANCE) {
- for (uint32_t i=0; i<cols; i++) {
- for (uint32_t j=0; j<cols; j++) {
- if (i == j) printf("%.2f ", covariance_matrix[i][j]);
- }
- }
-
- memcpy(covariance_matrix, covariance_matrix_prime, cols);
- qr_decomposition(covariance_matrix, cols, covariance_matrix_prime);
-
- for (uint32_t i=0; i<cols; i++) free(covariance_matrix[i]);
- free(covariance_matrix);
- }
-}
-
-void power_iteration(float** input_matrix, uint32_t size, float* eigen_vector) {
- // Initialize first guess vector
- float* new_vector = (float*) malloc(size * sizeof(float));
- float* curr_vector = (float*) malloc(size * sizeof(float));
- for (uint32_t i=0; i<size; i++) curr_vector[i] = (float) rand() / RAND_MAX;
-
- // MAX_INTERATIONS in case the singular vector doesn't converge
- for (uint32_t i=0; i<MAX_ITERATIONS; i++) {
- matrix_vector_multiply(input_matrix, size, size, curr_vector, new_vector, MV_MULTIPLY);
- vector_normalize(curr_vector, size);
- vector_normalize(new_vector, size);
- if (fabs(fabs(cosine_similarity(new_vector, curr_vector, size))-1.0) < TOLERANCE) break;
- memcpy(curr_vector, new_vector, size * sizeof(float));
- }
-
- memcpy(eigen_vector, new_vector, size * sizeof(float));
- free(curr_vector);
- free(new_vector);
-}
-
-float eigen_value_compute(float* eigen_vector, float** input_matrix, uint32_t size) {
- if (vector_norm(eigen_vector, size) == 0) return 0;
-
- float lambda = 0.0f;
- for (uint32_t i=0; i<size; i++) {
- lambda += input_matrix[i][i] * eigen_vector[i] * eigen_vector[i];
- for (uint32_t j=0; j<size; j++) {
- if (i != j) {
- lambda += input_matrix[i][j] * eigen_vector[i] * eigen_vector[j];
- }
- }
- }
- lambda /= vector_norm(eigen_vector, size) * vector_norm(eigen_vector, size);
- return lambda;
-}
-
-void subtract_eigen(float* eigen_vector, float** input_matrix, float** resultant_matrix, float eigen_value, uint32_t size) {
- float** outer_product_matrix = (float**) malloc(size * sizeof(float*));
- for (uint32_t i=0; i<size; i++) outer_product_matrix[i] = (float*) malloc(size * sizeof(float));
-
- outer_product(eigen_vector, size, outer_product_matrix);
-
- for (uint32_t i=0; i<size; i++) {
- for (uint32_t j=0; j<size; j++) outer_product_matrix[i][j] *= eigen_value;
- }
-
- matrix_operation(input_matrix, size, size, outer_product_matrix, size, size, resultant_matrix, MM_SUBTRACT);
-
- for (uint32_t i=0 ; i<size; i++) free(outer_product_matrix[i]);
- free(outer_product_matrix);
-}
-
-void pca_covariance_method(float** input_matrix, uint32_t rows, uint32_t cols, float** resultant_matrix, uint32_t components) {
- float** input_matrix_original = (float**) malloc(rows * sizeof(float*)); // Has sample x feature dimensions
- for (uint32_t i=0; i<rows; i++) input_matrix_original[i] = (float*) malloc(cols * sizeof(float));
-
- float* eigen_vector = (float*) malloc(cols * sizeof(float)); // Has feature dimensions
-
- float** covariance_matrix = (float**) malloc(cols * sizeof(float*)); // Has feature x feature dimensions
- float** covariance_matrix_prime = (float**) malloc(cols * sizeof(float*));
- float** projection_matrix = (float**) malloc(cols * sizeof(float*)); // Has features x components dimensions
-
- for (uint32_t i=0; i<cols; i++) {
- projection_matrix[i] = (float*) malloc(components * sizeof(float));
- covariance_matrix[i] = (float*) malloc(cols * sizeof(float));
- covariance_matrix_prime[i] = (float*) malloc(cols * sizeof(float));
- }
-
- copy_matrix(input_matrix, input_matrix_original, rows, cols);
-
- centre_scale(input_matrix, rows, cols, MEAN);
- covariance(input_matrix, rows, cols, covariance_matrix);
-
- for (uint32_t i=0; i<components; i++) {
- power_iteration(covariance_matrix, cols, eigen_vector);
- float eigen_value = eigen_value_compute(eigen_vector, covariance_matrix, cols);
- subtract_eigen(eigen_vector, covariance_matrix, covariance_matrix_prime, eigen_value, cols);
- for (uint32_t j=0; j<cols; j++) projection_matrix[j][i] = eigen_vector[j];
-
- copy_matrix(covariance_matrix_prime, covariance_matrix, cols, cols);
- }
-
- matrix_operation(input_matrix_original, rows, cols, projection_matrix, cols, components, resultant_matrix, MM_MULTIPLY_GEMM); // Has sample x components dimensions
-
- free(eigen_vector);
-
- for (uint32_t i=0; i<cols; i++) {
- free(projection_matrix[i]);
- free(covariance_matrix_prime[i]);
- free(covariance_matrix[i]);
- }
-
- for (uint32_t i=0; i<rows; i++) {
- free(input_matrix_original[i]);
- }
-
- free(covariance_matrix_prime);
- free(covariance_matrix);
- free(input_matrix_original);
- free(projection_matrix);
-}
diff --git a/OASIS/C/src/ekd_svm.c b/OASIS/C/src/ekd_svm.c
deleted file mode 100644
index 13c155d..0000000
--- a/OASIS/C/src/ekd_svm.c
+++ /dev/null
@@ -1,259 +0,0 @@
-#include "ekd_svm.h"
-
-void svm_preprocess(float** input_matrix, uint32_t rows, uint32_t cols) {
- centre_scale(input_matrix, rows, cols, MEAN_UNIT_VARIANCE);
-}
-
-float rbf_kernel(float* sample_1, float* sample_2, uint32_t features, float gamma) {
- float distance = 0.0f;
- for (uint32_t i=0; i<features; i++) distance += pow(sample_1[i] - sample_2[i], 2);
- return exp(-gamma * distance);
-}
-
-void kernel_matrix_transform(float** input_matrix, float** resultant_matrix, uint32_t samples, uint32_t features, float gamma) {
- for (uint32_t i=0; i<samples; i++) {
- for (uint32_t j=0; j<samples; j++) {
- float kernel = rbf_kernel(input_matrix[i], input_matrix[j], features, gamma);
- resultant_matrix[i][j] = kernel;
- }
- }
-}
-
-void kernel_row_transform(float** input_matrix, float* query_row, float* resultant_row, uint32_t samples, uint32_t features, float gamma) {
- for (uint32_t i=0; i<samples; i++) {
- float kernel = rbf_kernel(input_matrix[i], query_row, features, gamma);
- resultant_row[i] = kernel;
- }
-}
-
-float get_error(uint32_t index, float* alphas, float** kernel_matrix, int32_t* labels, uint32_t samples) {
- float error = 0.0f;
-
- for (uint32_t i=0; i<samples; i++) error += alphas[i] * labels[i] * kernel_matrix[i][index];
-
- error -= labels[index];
- return error;
-}
-
-uint32_t find_second_alpha(uint32_t first_index, float first_error_val, float* alphas, float** kernel_matrix, int32_t* labels, uint32_t samples) {
- int32_t second_index = -1;
- float max_error_diff = 0;
-
- for (uint32_t i=0; i<samples; i++) {
- if (i == first_index) continue;
-
- float second_error_val = get_error(i, alphas, kernel_matrix, labels, samples);
- float error_diff = fabs(first_error_val - second_error_val);
- if (error_diff > max_error_diff) {
- max_error_diff = error_diff;
- second_index = i;
- }
- }
- return second_index;
-}
-
-void calculate_bounds(float first_label, float second_label, float first_alpha, float second_alpha, float penalty, float* lower_bound, float* upper_bound) {
- if (first_label != second_label) {
- *lower_bound = fmax(0, second_alpha - first_alpha);
- *upper_bound = fmin(penalty, penalty + second_alpha - first_alpha);
- } else {
- *lower_bound = fmax(0, second_alpha + first_alpha - penalty);
- *upper_bound = fmin(penalty, second_alpha + first_alpha);
- }
-}
-
-float clip_second_alpha_new(float second_alpha_new, float lower_bound, float upper_bound) {
- if (second_alpha_new < lower_bound) {
- return lower_bound;
- } else if (second_alpha_new > upper_bound) {
- return upper_bound;
- } else {
- return second_alpha_new;
- }
-}
-
-void update_alphas(float first_alpha_new, float second_alpha_new, float* alphas, uint32_t first_index, uint32_t second_index) {
- alphas[first_index] = first_alpha_new;
- alphas[second_index] = second_alpha_new;
-}
-
-float calculate_bias(float first_error_val, float second_error_val, float first_alpha_new, float first_alpha, float second_alpha_new, float second_alpha, float kernel_val_ii, float kernel_val_ij, float kernel_val_jj, float first_label, float second_label, float penalty) {
- float first_bias = first_error_val + first_label * (first_alpha_new - first_alpha) * kernel_val_ii + second_label * (second_alpha_new - second_alpha) * kernel_val_ij;
- float second_bias = first_error_val + first_label * (first_alpha_new - first_alpha) * kernel_val_ij + second_label * (second_alpha_new - second_alpha) * kernel_val_jj;
- float bias;
- if (first_alpha_new > 0 && first_alpha_new < penalty) {
- bias = first_bias;
- } else if (second_alpha_new > 0 && second_alpha_new < penalty) {
- bias = second_bias;
- } else {
- bias = (first_bias + second_bias) / 2;
- }
- return bias;
-}
-
-void update_errors(float* errors, uint32_t samples, uint32_t first_index, uint32_t second_index, float first_label, float second_label, float first_alpha_new, float first_alpha, float second_alpha_new, float second_alpha, float* bias, float** kernel_matrix) {
- float bias_temp = *bias;
- for (uint32_t i=0; i<samples; i++) {
- if (i == first_index || i == second_index) continue;
- float error = errors[i];
- error += first_label * (first_alpha_new - first_alpha) * kernel_matrix[first_index][i];
- error -= bias_temp - *bias;
- errors[i] = error;
- }
-}
-
-uint8_t optimize_alphas(uint32_t first_index, uint32_t second_index, float* alphas, float* bias, float* errors, float** kernel_matrix, int32_t* labels, uint32_t samples, float penalty) {
- if (first_index == second_index) return 0;
-
- float first_label = (float) labels[first_index];
- float second_label = (float) labels[second_index];
-
- float first_alpha = alphas[first_index];
- float second_alpha = alphas[second_index];
-
- float first_error_val = errors[first_index];
- float second_error_val = errors[second_index];
-
- float kernel_val_ii = kernel_matrix[first_index][first_index];
- float kernel_val_jj = kernel_matrix[second_index][second_index];
- float kernel_val_ij = kernel_matrix[first_index][second_index];
-
- // Second derivative of objective function
- float learning_rate = 2 * kernel_val_ij - kernel_val_ii - kernel_val_jj;
- if (learning_rate >= 0) return 0;
-
- float second_alpha_new = second_alpha - (second_label * (first_error_val - second_error_val) / learning_rate);
-
- float lower_bound, upper_bound;
- calculate_bounds(first_label, second_label, first_alpha, second_alpha, penalty, &lower_bound, &upper_bound);
- second_alpha_new = clip_second_alpha_new(second_alpha_new, lower_bound, upper_bound);
-
- if (fabs(second_alpha_new - second_alpha) < SVM_TOLERANCE * (second_alpha_new + second_alpha + SVM_TOLERANCE)) return 0;
-
- float first_alpha_new = first_alpha + first_label * second_label * (second_alpha - second_alpha_new);
-
- update_alphas(first_alpha_new, second_alpha_new, alphas, first_index, second_index);
-
- float bias_new = calculate_bias(first_error_val, second_error_val, first_alpha_new, first_alpha, second_alpha_new, second_alpha, kernel_val_ii, kernel_val_ij, kernel_val_jj, first_label, second_label, penalty);
- *bias = bias_new;
-
- update_errors(errors, samples, first_index, second_index, first_label, second_label, first_alpha_new, first_alpha, second_alpha_new, second_alpha, bias, kernel_matrix);
-
- return 1;
-}
-
-uint8_t verify_kkt(uint32_t first_index, float tolerance, float* alphas, float* bias, float* errors, float** kernel_matrix, int32_t* labels, uint32_t samples, float penalty) {
- float first_label = (float) labels[first_index];
- float first_alpha = alphas[first_index];
- float first_error_val = errors[first_index];
- float first_residual_error = first_error_val * first_label;
-
- if ((first_residual_error < -tolerance && first_alpha < penalty) || (first_residual_error > tolerance && first_alpha > 0)) {
- // Alpha is able be optimized, now find second alpha using heuristic method
- uint32_t second_index = find_second_alpha(first_index, first_error_val, alphas, kernel_matrix, labels, samples);
- // If the alphas have been optimized, return
- if (optimize_alphas(first_index, second_index, alphas, bias, errors, kernel_matrix, labels, samples, penalty)) return 1;
-
- // Could not find second alpha or couldn't optimize alphas values
- uint32_t max_index = -1;
- float max_error = -FLT_MAX;
- for (uint32_t i=0; i<samples; i++) {
- if (alphas[i] > 0 && alphas[i] < penalty) {
- float error = errors[i];
- if (fabs(error - first_error_val) > max_error) {
- max_index = i;
- max_error = fabs(error - first_error_val);
- }
- }
- }
-
- if (max_index != -1 && optimize_alphas(first_index, max_index, alphas, bias, errors, kernel_matrix, labels, samples, penalty) == 1) return 1;
-
- // Still couldn't optimize alpha values:w
- return 0;
- }
-
- // Alpha values do not need to be optimized
- return 0;
-}
-
-void train_svm(float** data_matrix, uint32_t samples, uint32_t features, float* alphas, float* bias, int32_t* labels, float penalty) {
- // Centre and scale reduced_dimension_matrix
- svm_preprocess(data_matrix, samples, features);
-
- float** kernel_matrix = (float**) malloc(samples * sizeof(float*));
- for (uint32_t i=0; i<samples; i++) kernel_matrix[i] = (float*) malloc(samples * sizeof(float));
-
- // Compute kernel matrix using RBF
- kernel_matrix_transform(data_matrix, kernel_matrix, samples, features, GAMMA);
-
- // Initialize bias to 0, alphas/errors to random numbers between -1 and 1
- *bias = 0;
-
- float* errors = (float*) malloc(samples * sizeof(float));
- for (uint32_t i=0; i<samples; i++) {
- errors[i] = (float) rand() / (float) RAND_MAX * 2 - 1;
- alphas[i] = (float) rand() / (float) RAND_MAX * 2 - 1;
- }
-
- uint32_t num_changed_alphas = 0;
- uint32_t search_passes = 0;
- uint8_t searched_all_flag = 1;
-
- while ((search_passes < MAX_SVM_PASSES && num_changed_alphas > 0) || searched_all_flag) {
- num_changed_alphas = 0;
-
- if (searched_all_flag) {
- // Loops over all samples
- for (uint32_t sample_index=0; sample_index<samples; sample_index++)
- num_changed_alphas += verify_kkt(sample_index, SVM_TOLERANCE, alphas, bias, errors, kernel_matrix, labels, samples, penalty);
- } else {
- // Loops over non support vector samples (not 0 and not C -> penalty parameter)
- for (uint32_t sample_index=0; sample_index<samples; sample_index++) {
- if (alphas[sample_index] > 0 && alphas[sample_index] < penalty)
- num_changed_alphas += verify_kkt(sample_index, SVM_TOLERANCE, alphas, bias, errors, kernel_matrix, labels, samples, penalty);
- }
- }
-
- if (searched_all_flag) {
- searched_all_flag = 0;
- } else if (num_changed_alphas == 0) {
- searched_all_flag = 1;
- }
- search_passes++;
- }
-
- for (uint32_t i=0; i<samples; i++) free (kernel_matrix[i]);
- free(kernel_matrix);
- free(errors);
-}
-
-int32_t svm_predict(float** test_data, int32_t* labels_test, uint32_t num_test, uint32_t num_components, float* alphas, float bias, float gamma) {
- int num_correct = 0;
- for (int i=0; i<num_test; i++) {
- float transformed_row[num_test];
- kernel_row_transform(test_data, test_data[i], transformed_row, num_test, num_components, gamma);
- float prediction = bias;
- for (int j = 0; j<num_test; j++) {
- prediction += alphas[j] * transformed_row[j];
- }
- if (prediction >= 0 && labels_test[i] == 1) {
- num_correct++;
- } else if (prediction < 0 && labels_test[i] == -1) {
- num_correct++;
- }
- }
- return num_correct;
-}
-
-float test_svm(float** data_test, int32_t* labels_test, uint32_t num_test, uint32_t num_components, float* alphas, float bias) {
- uint32_t num_correct = 0;
- float* prediction = (float*) malloc(num_test * sizeof(float));
- for (uint8_t i=0; i<num_test; i++) {
- prediction[i] = svm_predict(data_test, labels_test, num_test, num_components, alphas, bias, GAMMA);
- if (prediction[i] * labels_test[i] > 0) num_correct++;
- }
- float accuracy = ((float) num_correct / num_test) * 100;
- free(prediction);
- return accuracy;
-} \ No newline at end of file
diff --git a/OASIS/C/src/main.c b/OASIS/C/src/main.c
deleted file mode 100644
index b84e29f..0000000
--- a/OASIS/C/src/main.c
+++ /dev/null
@@ -1,108 +0,0 @@
-#include "main.h"
-
-uint64_t seconds() {
- struct timespec start;
- clock_gettime(CLOCK_MONOTONIC_RAW, &start);
- return start.tv_sec;
-}
-
-int main() {
- uint64_t start = seconds();
- // Allocate memory
- char** file_names = (char**) malloc((NUM_IMAGES) * sizeof(char*));
- for (uint8_t i=0; i<NUM_IMAGES; i++) {
- file_names[i] = (char*) malloc(FILE_NAME_SIZE * sizeof(char));
- // Populate file name array with file path
- file_names[i] = (i < NUM_DNEG_IMAGES) ? strcpy(file_names[i], DNEG_FOLDER_PATH) : strcpy(file_names[i], DPOS_FOLDER_PATH);
- }
- uint8_t*** data = (uint8_t***) malloc((NUM_IMAGES) * sizeof(uint8_t**));
- for (uint8_t i=0; i<NUM_IMAGES; i++) {
- data[i] = (uint8_t**) malloc(IMAGE_HEIGHT * sizeof(uint8_t*));
- for (uint8_t j=0; j<IMAGE_HEIGHT; j++) data[i][j] = (uint8_t*)malloc(IMAGE_WIDTH * sizeof(uint8_t));
- }
-
- float** data_flatten = (float**) malloc((NUM_IMAGES) * sizeof(float*));
- for (uint8_t i=0; i<NUM_IMAGES; i++) data_flatten[i] = (float*) malloc(FEATURE_VECTOR_SIZE * sizeof(float));
-
- int32_t* labels = (int32_t*) malloc((NUM_IMAGES) * sizeof(int32_t));
-
- uint8_t num_train = (uint8_t) (0.8 * NUM_IMAGES);
- uint8_t num_test = NUM_IMAGES - num_train;
-
- float** data_train = (float**) malloc (num_train * sizeof(float*));
- float** data_test = (float**) malloc (num_test * sizeof(float*));
-
- int32_t* labels_train = (int32_t*) malloc(num_train * sizeof(int32_t));
- int32_t* labels_test = (int32_t*) malloc(num_test * sizeof(int32_t));
-
- float** data_reduced_dimensions = (float**) malloc((NUM_IMAGES) * sizeof(float*));
- for (uint32_t i=0; i<NUM_IMAGES; i++) data_reduced_dimensions[i] = (float*) malloc(NUM_COMPONENTS * sizeof(float));
-
- float* alphas = (float*) malloc((NUM_IMAGES) * sizeof(float));
-
- // Concatenate the file name array with the image name
- read_dir(DNEG_FOLDER_PATH, DPOS_FOLDER_PATH, file_names);
- printf("read\n");
-
- // Read in an array of 2D images, then flatten
- for (uint8_t i=0; i<NUM_IMAGES; i++) {
- labels[i] = (i < NUM_DNEG_IMAGES) ? -1 : 1;
- read_bmp(file_names[i], data[i]);
- flatten_image(data[i], data_flatten[i]);
- }
-
- printf("flattened\n");
-
- // PCA Transform
- pca_covariance_method(data_flatten, NUM_IMAGES, FEATURE_VECTOR_SIZE, data_reduced_dimensions, NUM_COMPONENTS);
- printf("pca\n");
-
- // Shuffle data and labels
- shuffle_data_labels(data_reduced_dimensions, labels, NUM_IMAGES);
- printf("shuffled\n");
-
- // Populate the training and testing data
- for (uint8_t i=0; i<num_train; i++) {
- data_train[i] = data_reduced_dimensions[i];
- labels_train[i] = labels[i];
- }
-
- for (uint8_t i=num_train; i<NUM_IMAGES; i++) {
- data_test[i - num_train] = data_reduced_dimensions[i];
- labels_test[i - num_train] = labels[i];
- }
-
- printf("split\n");
-
- // Train SVM
- float bias;
- train_svm(data_train, num_train, NUM_COMPONENTS, alphas, &bias, labels, PENALTY_PARAM);
- printf("trained\n");
-
- // Test SVM
- float accuracy = test_svm(data_test, labels_test, num_test, NUM_COMPONENTS, alphas, bias);
- printf("Accuracy: %.2f%%\n", accuracy);
-
- // Free memory
- for (uint8_t i=0; i<NUM_IMAGES; i++) {
- free(file_names[i]);
- free(data_flatten[i]);
- free(data_reduced_dimensions[i]);
- for (uint8_t j=0; j<IMAGE_HEIGHT; j++) free(data[i][j]);
- free(data[i]);
- }
- free(file_names);
- free(data);
- free(data_flatten);
- free(data_reduced_dimensions);
- free(labels);
- free(labels_train);
- free(labels_test);
- free(data_train);
- free(data_test);
- free(alphas);
-
- uint64_t end = seconds();
- printf("Time Elapsed: %lds\n", end-start);
- return 0;
-} \ No newline at end of file