From cf8b0a8b949edc00b929271c96170bf11a558690 Mon Sep 17 00:00:00 2001 From: Thomas Date: Sun, 24 Sep 2023 12:22:28 +0200 Subject: [PATCH] Clean up (1) --- image/image.c | 3 +- image/image.h | 15 +-- main.c | 61 ++++++++--- matrix/matrix.c | 255 +------------------------------------------- matrix/matrix.h | 19 +--- matrix/operations.c | 232 ++++++++++++++++++++++++++++++++++++++++ matrix/operations.h | 26 ++++- neuronal_network.c | 3 +- 8 files changed, 312 insertions(+), 302 deletions(-) diff --git a/image/image.c b/image/image.c index fb1cdfc..419620d 100644 --- a/image/image.c +++ b/image/image.c @@ -159,7 +159,6 @@ Image** import_images(char* image_file_string, char* label_file_string, int* _nu } void img_print (Image* img) { - //print the image matrix_print(img->pixel_values); //print the number of the image @@ -183,7 +182,7 @@ void img_free (Image* img) { free(img); } -void images_free (Image** images, int quantity){ +void images_free(Image** images, int quantity) { //frees every single image for(int i=0;ipixel_values); -// matrix_print(images[1]->pixel_values); + /* + * Create a new network and randomize the weights + */ - Neural_Network* nn = new_network(28*28, 50, 3, 10, 0.1); - randomize_network(nn, 1); -// Neural_Network* nn = load_network("../networks/newest_network.txt"); + Neural_Network* network = new_network(input_size, hidden_layer_size, hidden_layer_count, 10, learning_rate); + randomize_network(network, 1); - for (int i = 0; i < 60000; ++i) { - train_network(nn, images[i], images[i]->label); + /* + * Training + */ + + for (int i = 0; i < amount_of_images_used_to_train; i++) { + train_network(network, images[i], images[i]->label); } -// batch_train(nn, images, 30000, 2); + // Batch training works if you change the train_network method, but the results are not that good (needs further testing) + // batch_train(nn, images, 30000, 2); + printf("Trinaing Done!\n"); -// save_network(nn); + /* + * Saving and Loading + */ - printf("%lf\n", measure_network_accuracy(nn, images, 10000)); +// save_network(network); +// Neural_Network* network = load_network("../networks/newest_network.txt"); -} \ No newline at end of file + /* + * Measure Accuracy & predict single images + */ + + printf("Accuracy: %lf\n", measure_network_accuracy(network, images, amount_of_images_used_to_test)); + +// matrix_print(predict_image(network, images[0])); + + images_free(images, amount_of_images_to_load); + free_network(network); + + return 0; +} diff --git a/matrix/matrix.c b/matrix/matrix.c index 84e07e9..bec2425 100644 --- a/matrix/matrix.c +++ b/matrix/matrix.c @@ -1,12 +1,9 @@ #include "matrix.h" #include #include -#include -#include + #define MAX_BYTES 100 -static int RANDOMIZED = 0; -// operational functions Matrix* matrix_create(int rows, int columns) { // allocate memory for the matrix @@ -80,175 +77,6 @@ Matrix* matrix_copy(Matrix *matrix) { return copy_of_matrix; } -// mathematical functions - -/* - * These methods won't change or free the input matrix. - * It creates a new matrix, which is modified and then returned. - * If we don't need the original matrix, we should consider just changing the original matrix and changing the method signature to void. - */ - -Matrix* multiply(Matrix* matrix1, Matrix* matrix2) { - - // check if the two matrices are of the same size - if(matrix1->rows != matrix2->rows || matrix1->columns != matrix2->columns) { - printf("ERROR: Size of matrices are not compatible! (Multiply)"); - exit(1); - } - - // create result matrix - Matrix* result_matrix = matrix_create(matrix1->rows, matrix1->columns); - - // multiply the values and save them into the result matrix - for (int i = 0; i < matrix1->rows; i++) { - for (int j = 0; j < matrix1->columns; j++) { - result_matrix->numbers[i][j] = matrix1->numbers[i][j] * matrix2->numbers[i][j]; - } - } - - // return resulting matrix - return result_matrix; -} - -Matrix* add(Matrix* matrix1, Matrix* matrix2) { - - // check if the two matrices are of the same size - if(matrix1->rows != matrix2->rows || matrix1->columns != matrix2->columns) { - printf("ERROR: Size of matrices are not compatible! (Add)"); - exit(1); - } - - // create result matrix - Matrix* result_matrix = matrix_create(matrix1->rows, matrix1->columns); - - // add the value of the number in matrix 1 to the value of the number in matrix 2 - for (int i = 0; i < matrix1->rows; i++) { - for (int j = 0; j < matrix1->columns; j++) { - result_matrix->numbers[i][j] = matrix1->numbers[i][j] + matrix2->numbers[i][j]; - } - } - - // return the result matrix - return result_matrix; -} - -Matrix* subtract(Matrix* matrix1, Matrix* matrix2) { - - // check if the two matrices are of the same size - if(matrix1->rows != matrix2->rows || matrix1->columns != matrix2->columns) { - printf("ERROR: Size of matrices are not compatible! (Subtract)"); - exit(1); - } - - // create result matrix - Matrix* result_matrix = matrix_create(matrix1->rows, matrix1->columns); - - // subtract the value of the number in matrix 2 from the value of the number in matrix 1 - for (int i = 0; i < matrix1->rows; i++) { - for (int j = 0; j < matrix1->columns; j++) { - result_matrix->numbers[i][j] = matrix1->numbers[i][j] - matrix2->numbers[i][j]; - } - } - - // return the resulting matrix - return result_matrix; -} - -Matrix* dot(Matrix* matrix1, Matrix* matrix2) { - - // check if the dimensions of the matrices are compatible to calculate the dot product - if(matrix1->columns != matrix2->rows) { - printf("ERROR: Size of matrices are not compatible! (Dot-Product)"); - exit(1); - } - - // create a new matrix with the dimensions of the dot product; - Matrix* result_matrix = matrix_create(matrix1->rows, matrix2->columns); - - // iterate through all rows of matrix 1 - for (int i = 0; i < matrix1->rows; i++) { - - // iterate though all columns of matrix 2 - for (int j = 0; j < matrix2->columns; j++) { - - // sum up the products and save them into the result matrix - result_matrix->numbers[i][j] = 0; - for (int k = 0; k < matrix2->rows; k++) { - result_matrix->numbers[i][j] += matrix1->numbers[i][k] * matrix2->numbers[k][j]; - } - } - } - - // return result - return result_matrix; -} - -Matrix* apply(double (*function)(double), Matrix* matrix) { - - // create a new matrix used to calculate the result - Matrix* result_matrix = matrix_create(matrix->rows, matrix->columns); - - // apply the function to all values in the matrix - for (int i = 0; i < matrix->rows; i++) { - for (int j = 0; j < matrix->columns; j++) { - result_matrix->numbers[i][j] = (*function)(matrix->numbers[i][j]); - int k = 0; - } - } - - // return resulting matrix - return result_matrix; -} - -Matrix* scale(Matrix* matrix, double value) { - - // create a copy of the original matrix - Matrix* result_matrix = matrix_copy(matrix); - - // iterate over all numbers in the matrix and multiply by the scalar value - for (int i = 0; i < result_matrix->rows; i++) { - for (int j = 0; j < result_matrix->columns; j++) { - result_matrix->numbers[i][j] *= value; - } - } - - // return the copy - return result_matrix; -} - -Matrix* addScalar(Matrix* matrix, double value) { - - // create a copy of the original matrix - Matrix* result_matrix = matrix_copy(matrix); - - // iterate over all numbers in the matrix and add the scalar value - for (int i = 0; i < result_matrix->rows; i++) { - for (int j = 0; j < result_matrix->columns; j++) { - result_matrix->numbers[i][j] += value; - } - } - - // return the copy - return result_matrix; -} - -Matrix* transpose(Matrix* matrix) { - - // create a new matrix of the size n-m, based on the original matrix of size m-n - Matrix* result_matrix = matrix_create(matrix->columns, matrix->rows); - - // copy the values from the original into the correct place in the copy - for (int i = 0; i < matrix->rows; i++) { - for (int j = 0; j < matrix->columns; j++) { - result_matrix->numbers[j][i] = matrix->numbers[i][j]; - } - } - - // return the result matrix - return result_matrix; - -} - void matrix_save(Matrix* matrix, char* file_string){ // open the file in append mode @@ -308,85 +136,4 @@ Matrix* load_next_matrix(FILE *save_file){ } } return matrix; -} - -Matrix* matrix_flatten(Matrix* matrix, int axis) { - // Axis = 0 -> Column Vector, Axis = 1 -> Row Vector - Matrix* result_matrix; - // Column Vector - if (axis == 0) { - result_matrix = matrix_create(matrix -> rows * matrix -> columns, 1); - } - // Row Vector - else if (axis == 1) { - result_matrix = matrix_create(1, matrix -> rows * matrix -> columns); - } else { - printf("ERROR: Argument must be 1 or 0 (matrix_flatten)"); - exit(EXIT_FAILURE); - } - for (int i = 0; i < matrix->rows; i++) { - for (int j = 0; j < matrix->columns; j++) { - if (axis == 0) result_matrix->numbers[i * matrix->columns + j][0] = matrix->numbers[i][j]; - else if (axis == 1) result_matrix->numbers[0][i * matrix->columns + j] = matrix->numbers[i][j]; - } - } - return result_matrix; -} - -int matrix_argmax(Matrix* matrix) { - // Expects a Mx1 matrix - if (matrix->columns != 1){ - printf("ERROR: Matrix is not Mx1 (matrix_argmax)"); - exit(EXIT_FAILURE); - } - - double max_value = 0; - int max_index = 0; - - for (int i = 0; i < matrix->rows; i++) { - if (matrix->numbers[i][0] > max_value) { - max_value = matrix->numbers[i][0]; - max_index = i; - } - } - return max_index; -} - -void matrix_randomize(Matrix* matrix, int n) { - - if(!RANDOMIZED){ - srand(time(NULL)); - RANDOMIZED = 1; - } - //make a min and max - double min = -1.0f / sqrt(n); - double max = 1.0f / sqrt(n); - - //calculate difference - double difference = max - min; - - //move decimal - int scaled_difference = (int)(difference * scaling_value); - - for (int i = 0; i < matrix->rows; i++) { - for (int j = 0; j < matrix->columns; j++) { - matrix->numbers[i][j] = min + (1.0 * (rand() % scaled_difference) / scaling_value); - } - } -} - -Matrix* matrix_add_bias(Matrix* matrix) { - if(matrix->columns != 1) { - printf("ERROR: The size of the matrix does not match an input matrix! (matrix_add_bias)"); - exit(1); - } - - Matrix* result = matrix_create(matrix->rows + 1, matrix->columns); - - result->numbers[0][0] = 1.0; - for (int i = 0; i < matrix->rows; ++i) { - result->numbers[i + 1][0] = matrix->numbers[i][0]; - } - - return result; } \ No newline at end of file diff --git a/matrix/matrix.h b/matrix/matrix.h index 022a8b8..ea37f59 100644 --- a/matrix/matrix.h +++ b/matrix/matrix.h @@ -1,4 +1,3 @@ -#pragma once #include typedef struct { @@ -6,8 +5,6 @@ typedef struct { double **numbers; } Matrix; -static const int scaling_value = 10000; - Matrix* matrix_create(int rows, int columns); void matrix_fill(Matrix* matrix, double value); void matrix_free(Matrix* matrix); @@ -15,18 +12,4 @@ void matrix_print(Matrix *matrix); Matrix* matrix_copy(Matrix *matrix); void matrix_save(Matrix* matrix, char* file_string); Matrix* matrix_load(char* file_string); -Matrix* load_next_matrix(FILE * save_file); - -void matrix_randomize(Matrix* matrix, int n); -int matrix_argmax(Matrix* matrix); -Matrix* matrix_flatten(Matrix* matrix, int axis); -Matrix* matrix_add_bias(Matrix* matrix); - -Matrix* multiply(Matrix* matrix1, Matrix* matrix2); -Matrix* add(Matrix* matrix1, Matrix* matrix2); -Matrix* subtract(Matrix* matrix1, Matrix* matrix2); -Matrix* dot(Matrix* matrix1, Matrix* matrix2); -Matrix* apply(double (*function)(double), Matrix* matrix); -Matrix* scale(Matrix* matrix, double value); -Matrix* addScalar(Matrix* matrix, double value); -Matrix* transpose(Matrix* matrix); \ No newline at end of file +Matrix* load_next_matrix(FILE * save_file); \ No newline at end of file diff --git a/matrix/operations.c b/matrix/operations.c index 59147e1..d969e41 100644 --- a/matrix/operations.c +++ b/matrix/operations.c @@ -1 +1,233 @@ +#include +#include +#include +#include "math.h" #include "operations.h" + +static int RANDOMIZED = 0; + +Matrix* multiply(Matrix* matrix1, Matrix* matrix2) { + + // check if the two matrices are of the same size + if(matrix1->rows != matrix2->rows || matrix1->columns != matrix2->columns) { + printf("ERROR: Size of matrices are not compatible! (Multiply)"); + exit(1); + } + + // create result matrix + Matrix* result_matrix = matrix_create(matrix1->rows, matrix1->columns); + + // multiply the values and save them into the result matrix + for (int i = 0; i < matrix1->rows; i++) { + for (int j = 0; j < matrix1->columns; j++) { + result_matrix->numbers[i][j] = matrix1->numbers[i][j] * matrix2->numbers[i][j]; + } + } + + // return resulting matrix + return result_matrix; +} + +Matrix* add(Matrix* matrix1, Matrix* matrix2) { + + // check if the two matrices are of the same size + if(matrix1->rows != matrix2->rows || matrix1->columns != matrix2->columns) { + printf("ERROR: Size of matrices are not compatible! (Add)"); + exit(1); + } + + // create result matrix + Matrix* result_matrix = matrix_create(matrix1->rows, matrix1->columns); + + // add the value of the number in matrix 1 to the value of the number in matrix 2 + for (int i = 0; i < matrix1->rows; i++) { + for (int j = 0; j < matrix1->columns; j++) { + result_matrix->numbers[i][j] = matrix1->numbers[i][j] + matrix2->numbers[i][j]; + } + } + + // return the result matrix + return result_matrix; +} + +Matrix* subtract(Matrix* matrix1, Matrix* matrix2) { + + // check if the two matrices are of the same size + if(matrix1->rows != matrix2->rows || matrix1->columns != matrix2->columns) { + printf("ERROR: Size of matrices are not compatible! (Subtract)"); + exit(1); + } + + // create result matrix + Matrix* result_matrix = matrix_create(matrix1->rows, matrix1->columns); + + // subtract the value of the number in matrix 2 from the value of the number in matrix 1 + for (int i = 0; i < matrix1->rows; i++) { + for (int j = 0; j < matrix1->columns; j++) { + result_matrix->numbers[i][j] = matrix1->numbers[i][j] - matrix2->numbers[i][j]; + } + } + + // return the resulting matrix + return result_matrix; +} + +Matrix* dot(Matrix* matrix1, Matrix* matrix2) { + + // check if the dimensions of the matrices are compatible to calculate the dot product + if(matrix1->columns != matrix2->rows) { + printf("ERROR: Size of matrices are not compatible! (Dot-Product)"); + exit(1); + } + + // create a new matrix with the dimensions of the dot product; + Matrix* result_matrix = matrix_create(matrix1->rows, matrix2->columns); + + // iterate through all rows of matrix 1 + for (int i = 0; i < matrix1->rows; i++) { + + // iterate though all columns of matrix 2 + for (int j = 0; j < matrix2->columns; j++) { + + // sum up the products and save them into the result matrix + result_matrix->numbers[i][j] = 0; + for (int k = 0; k < matrix2->rows; k++) { + result_matrix->numbers[i][j] += matrix1->numbers[i][k] * matrix2->numbers[k][j]; + } + } + } + + // return result + return result_matrix; +} + +Matrix* apply(double (*function)(double), Matrix* matrix) { + + // create a new matrix used to calculate the result + Matrix* result_matrix = matrix_create(matrix->rows, matrix->columns); + + // apply the function to all values in the matrix + for (int i = 0; i < matrix->rows; i++) { + for (int j = 0; j < matrix->columns; j++) { + result_matrix->numbers[i][j] = (*function)(matrix->numbers[i][j]); + int k = 0; + } + } + + // return resulting matrix + return result_matrix; +} + +Matrix* scale(Matrix* matrix, double value) { + + // create a copy of the original matrix + Matrix* result_matrix = matrix_copy(matrix); + + // iterate over all numbers in the matrix and multiply by the scalar value + for (int i = 0; i < result_matrix->rows; i++) { + for (int j = 0; j < result_matrix->columns; j++) { + result_matrix->numbers[i][j] *= value; + } + } + + // return the copy + return result_matrix; +} + +Matrix* transpose(Matrix* matrix) { + + // create a new matrix of the size n-m, based on the original matrix of size m-n + Matrix* result_matrix = matrix_create(matrix->columns, matrix->rows); + + // copy the values from the original into the correct place in the copy + for (int i = 0; i < matrix->rows; i++) { + for (int j = 0; j < matrix->columns; j++) { + result_matrix->numbers[j][i] = matrix->numbers[i][j]; + } + } + + // return the result matrix + return result_matrix; + +} + +Matrix* matrix_flatten(Matrix* matrix, int axis) { + // Axis = 0 -> Column Vector, Axis = 1 -> Row Vector + Matrix* result_matrix; + // Column Vector + if (axis == 0) { + result_matrix = matrix_create(matrix -> rows * matrix -> columns, 1); + } + // Row Vector + else if (axis == 1) { + result_matrix = matrix_create(1, matrix -> rows * matrix -> columns); + } else { + printf("ERROR: Argument must be 1 or 0 (matrix_flatten)"); + exit(EXIT_FAILURE); + } + for (int i = 0; i < matrix->rows; i++) { + for (int j = 0; j < matrix->columns; j++) { + if (axis == 0) result_matrix->numbers[i * matrix->columns + j][0] = matrix->numbers[i][j]; + else if (axis == 1) result_matrix->numbers[0][i * matrix->columns + j] = matrix->numbers[i][j]; + } + } + return result_matrix; +} + +int argmax(Matrix* matrix) { + // Expects a Mx1 matrix + if (matrix->columns != 1){ + printf("ERROR: Matrix is not Mx1 (argmax)"); + exit(EXIT_FAILURE); + } + + double max_value = 0; + int max_index = 0; + + for (int i = 0; i < matrix->rows; i++) { + if (matrix->numbers[i][0] > max_value) { + max_value = matrix->numbers[i][0]; + max_index = i; + } + } + return max_index; +} + +void matrix_randomize(Matrix* matrix, int n) { + + if(!RANDOMIZED){ + srand(time(NULL)); + RANDOMIZED = 1; + } + //make a min and max + double min = -1.0f / sqrt(n); + double max = 1.0f / sqrt(n); + + //calculate difference + double difference = max - min; + + //move decimal + int scaled_difference = (int)(difference * scaling_value); + + for (int i = 0; i < matrix->rows; i++) { + for (int j = 0; j < matrix->columns; j++) { + matrix->numbers[i][j] = min + (1.0 * (rand() % scaled_difference) / scaling_value); + } + } +} + +Matrix* matrix_add_bias(Matrix* matrix) { + if(matrix->columns != 1) { + printf("ERROR: The size of the matrix does not match an input matrix! (matrix_add_bias)"); + exit(1); + } + + Matrix* result = matrix_create(matrix->rows + 1, matrix->columns); + + result->numbers[0][0] = 1.0; + for (int i = 0; i < matrix->rows; ++i) { + result->numbers[i + 1][0] = matrix->numbers[i][0]; + } + + return result; +} \ No newline at end of file diff --git a/matrix/operations.h b/matrix/operations.h index 0d415b5..e4f0220 100644 --- a/matrix/operations.h +++ b/matrix/operations.h @@ -1 +1,25 @@ -#include "matrix.h" \ No newline at end of file +#include "matrix.h" + +static const int scaling_value = 10000; + +Matrix* multiply(Matrix* matrix1, Matrix* matrix2); + +Matrix* add(Matrix* matrix1, Matrix* matrix2); //only used in the batch_training method + +Matrix* subtract(Matrix* matrix1, Matrix* matrix2); + +Matrix* dot(Matrix* matrix1, Matrix* matrix2); + +Matrix* apply(double (*function)(double), Matrix* matrix); + +Matrix* scale(Matrix* matrix, double value); + +Matrix* transpose(Matrix* matrix); + +Matrix* matrix_flatten(Matrix* matrix, int axis); + +int argmax(Matrix* matrix); + +void matrix_randomize(Matrix* matrix, int n); + +Matrix* matrix_add_bias(Matrix* matrix); \ No newline at end of file diff --git a/neuronal_network.c b/neuronal_network.c index c1d5468..650633c 100644 --- a/neuronal_network.c +++ b/neuronal_network.c @@ -1,5 +1,6 @@ #include #include "neuronal_network.h" +#include "matrix\operations.h" #include #include @@ -120,7 +121,7 @@ double measure_network_accuracy(Neural_Network* network, Image** images, int amo for (int i = 0; i < amount; i++) { Matrix* prediction = predict_image(network, images[i]); - int guess = matrix_argmax(prediction); + int guess = argmax(prediction); int answer = (unsigned char) images[i]->label; if (guess == answer) {