Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions nn/include/backprop.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ void backpropagate(NeuralNetwork* nn, const Matrix* y_true,
LossFunction loss_func, LossFunctionGrad loss_func_grad);

/** @brief Calculate weight gradient for a specific layer. */
Matrix* calculate_weight_gradient(const Cache* cache, int layer_index,
int total_layers);
Matrix* calculate_weight_gradient(const Cache* cache, size_t layer_index,
size_t total_layers);

/** @brief Calculate bias gradient for a specific layer. */
Matrix* calculate_bias_gradient(const Cache* cache, int layer_index,
int total_layers);
Matrix* calculate_bias_gradient(const Cache* cache, size_t layer_index,
size_t total_layers);
2 changes: 1 addition & 1 deletion nn/include/feedforward.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
//==============================

/** @brief Allocate and initialize a network with `num_layers` slots. */
NeuralNetwork* create_network(int num_layers);
NeuralNetwork* create_network(size_t num_layers);

/** @brief Free a network and its associated resources. */
void free_network(NeuralNetwork* nn);
Expand Down
10 changes: 6 additions & 4 deletions nn/include/linalg.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <stddef.h>

/**
* @file linalg.h
* @brief Matrix data structure and linear algebra primitives.
Expand All @@ -20,8 +22,8 @@
// 1D array used, this is way more performant than a 2D array is
typedef struct _Matrix {
double* matrix_data;
int rows;
int cols;
size_t rows;
size_t cols;
} Matrix;

//==============================
Expand All @@ -35,7 +37,7 @@ typedef struct _Matrix {
/** @brief Read a matrix from a text file. */
Matrix* read_matrix(const char* filename);
/** @brief Create an uninitialized matrix with given shape. */
Matrix* create_matrix(int rows, int cols);
Matrix* create_matrix(size_t rows, size_t cols);
/** @brief Deep copy a matrix. */
Matrix* copy_matrix(const Matrix* m);
/** @brief Flatten a matrix along an axis (implementation-specific). */
Expand All @@ -57,7 +59,7 @@ int matrix_argmax(Matrix* m);
// Matrix Operations
//============================
/** @brief Create an identity matrix of size n×n. */
Matrix* identity_matrix(int n);
Matrix* identity_matrix(size_t n);
/** @brief Elementwise addition: result = a + b. */
Matrix* add_matrix(Matrix* a, Matrix* b);
/** @brief Elementwise subtraction: result = a - b. */
Expand Down
4 changes: 2 additions & 2 deletions nn/include/neural_network.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ typedef struct {
* @brief Neural network composed of sequential fully connected layers.
*/
typedef struct {
Layer** layers; /**< Array of layer pointers (length = num_layers). */
int num_layers; /**< Number of layers. */
Layer** layers; /**< Array of layer pointers (length = num_layers). */
size_t num_layers; /**< Number of layers. */

/** Caches intermediate forward/backward values. */
Cache* cache;
Expand Down
97 changes: 50 additions & 47 deletions nn/src/activation/activation.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,25 @@

Matrix* sigmoid(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying sigmoid activation to a %dx%d matrix.", m->rows, m->cols);
LOG_INFO("Applying sigmoid activation to a %zux%zu matrix.", m->rows,
m->cols);

Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
result->matrix_data[i] = 1.0 / (1.0 + exp(-m->matrix_data[i]));
}
return result;
}

Matrix* sigmoid_prime(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying sigmoid_prime activation to a %dx%d matrix.", m->rows,
LOG_INFO("Applying sigmoid_prime activation to a %zux%zu matrix.", m->rows,
m->cols);

Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
double sigmoid_val = 1.0 / (1.0 + exp(-m->matrix_data[i]));
result->matrix_data[i] = sigmoid_val * (1.0 - sigmoid_val);
}
Expand All @@ -52,11 +53,11 @@ Matrix* sigmoid_prime(Matrix* m) {

Matrix* relu(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying ReLU activation to a %dx%d matrix.", m->rows, m->cols);
LOG_INFO("Applying ReLU activation to a %zux%zu matrix.", m->rows, m->cols);

Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
if (m->matrix_data[i] > 0) {
result->matrix_data[i] = m->matrix_data[i];
} else {
Expand All @@ -68,12 +69,12 @@ Matrix* relu(Matrix* m) {

Matrix* relu_prime(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying ReLU_prime activation to a %dx%d matrix.", m->rows,
LOG_INFO("Applying ReLU_prime activation to a %zux%zu matrix.", m->rows,
m->cols);

Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
if (m->matrix_data[i] > 0) {
result->matrix_data[i] = 1;
} else {
Expand All @@ -89,24 +90,24 @@ Matrix* relu_prime(Matrix* m) {

Matrix* tanh_activation(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying Tanh activation to a %dx%d matrix.", m->rows, m->cols);
LOG_INFO("Applying Tanh activation to a %zux%zu matrix.", m->rows, m->cols);

Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
result->matrix_data[i] = tanh(m->matrix_data[i]);
}
return result;
}

Matrix* tanh_prime(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying Tanh_prime activation to a %dx%d matrix.", m->rows,
LOG_INFO("Applying Tanh_prime activation to a %zux%zu matrix.", m->rows,
m->cols);

Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
double tanh_val = tanh(m->matrix_data[i]);
result->matrix_data[i] = 1.0 - pow(tanh_val, 2);
}
Expand All @@ -121,12 +122,12 @@ Matrix* tanh_prime(Matrix* m) {
// This will assume the alpha
Matrix* leaky_relu(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying Leaky ReLU activation to a %dx%d matrix.", m->rows,
LOG_INFO("Applying Leaky ReLU activation to a %zux%zu matrix.", m->rows,
m->cols);

Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
if (m->matrix_data[i] > 0) {
result->matrix_data[i] = m->matrix_data[i];
} else {
Expand All @@ -138,12 +139,12 @@ Matrix* leaky_relu(Matrix* m) {

Matrix* leaky_relu_prime(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying Leaky ReLU_prime activation to a %dx%d matrix.", m->rows,
LOG_INFO("Applying Leaky ReLU_prime activation to a %zux%zu matrix.", m->rows,
m->cols);

Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
if (m->matrix_data[i] > 0) {
result->matrix_data[i] = 1;
} else {
Expand All @@ -162,13 +163,13 @@ Matrix* leaky_relu_with_alpha(Matrix* m, double leak_parameter) {

LOG_INFO(
"Applying Leaky ReLU with leak_parameter=%.2f activation function to a "
"%dx%d "
"%zux%zu "
"matrix.",
leak_parameter, m->rows, m->cols);

Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
if (m->matrix_data[i] > 0) {
result->matrix_data[i] = m->matrix_data[i];
} else {
Expand All @@ -182,12 +183,13 @@ Matrix* leaky_relu_with_alpha(Matrix* m, double leak_parameter) {
Matrix* leaky_relu_prime_with_alpha(Matrix* m, double leak_parameter) {
ASSERT(m != NULL, "Input matrix for leaky_relu_prime is NULL.");
ASSERT(leak_parameter >= 0.0, "Alpha value must be non-negative.");
LOG_INFO("Applying Leaky ReLU with alpha=%.2f derivative to a %dx%d matrix.",
leak_parameter, m->rows, m->cols);
LOG_INFO(
"Applying Leaky ReLU with alpha=%.2f derivative to a %zux%zu matrix.",
leak_parameter, m->rows, m->cols);
Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
size_t total_elements = m->rows * m->cols;

for (int i = 0; i < total_elements; i++) {
for (size_t i = 0; i < total_elements; i++) {
if (m->matrix_data[i] > 0) {
result->matrix_data[i] = 1.0;
} else {
Expand All @@ -204,11 +206,11 @@ Matrix* leaky_relu_prime_with_alpha(Matrix* m, double leak_parameter) {

Matrix* sign_activation(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying Sign activation to a %dx%d matrix.", m->rows, m->cols);
LOG_INFO("Applying Sign activation to a %zux%zu matrix.", m->rows, m->cols);

Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
if (m->matrix_data[i] > 0) {
result->matrix_data[i] = 1.0;
} else if (m->matrix_data[i] < 0) {
Expand All @@ -222,14 +224,14 @@ Matrix* sign_activation(Matrix* m) {

Matrix* sign_prime(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying Sign_prime activation to a %dx%d matrix.", m->rows,
LOG_INFO("Applying Sign_prime activation to a %zux%zu matrix.", m->rows,
m->cols);
// The derivative of the sign function is 0 everywhere except at 0, where it
// is undefined. For backpropagation, the derivative is commonly approximated
// as 0.
Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
result->matrix_data[i] = 0.0;
}
return result;
Expand All @@ -241,18 +243,19 @@ Matrix* sign_prime(Matrix* m) {

Matrix* identity_activation(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying Identity activation to a %dx%d matrix.", m->rows, m->cols);
LOG_INFO("Applying Identity activation to a %zux%zu matrix.", m->rows,
m->cols);
return copy_matrix(m);
}

Matrix* identity_prime(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying Identity_prime activation to a %dx%d matrix.", m->rows,
LOG_INFO("Applying Identity_prime activation to a %zux%zu matrix.", m->rows,
m->cols);

Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
result->matrix_data[i] = 1.0;
}
return result;
Expand All @@ -264,12 +267,12 @@ Matrix* identity_prime(Matrix* m) {

Matrix* hard_tanh(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying Hard Tanh activation to a %dx%d matrix.", m->rows,
LOG_INFO("Applying Hard Tanh activation to a %zux%zu matrix.", m->rows,
m->cols);

Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
if (m->matrix_data[i] > 1.0) {
result->matrix_data[i] = 1.0;
} else if (m->matrix_data[i] < -1.0) {
Expand All @@ -283,12 +286,12 @@ Matrix* hard_tanh(Matrix* m) {

Matrix* hard_tanh_prime(Matrix* m) {
ASSERT(m != NULL, "Input matrix is NULL.");
LOG_INFO("Applying Hard Tanh_prime activation to a %dx%d matrix.", m->rows,
LOG_INFO("Applying Hard Tanh_prime activation to a %zux%zu matrix.", m->rows,
m->cols);

Matrix* result = create_matrix(m->rows, m->cols);
int total_elements = m->rows * m->cols;
for (int i = 0; i < total_elements; i++) {
size_t total_elements = m->rows * m->cols;
for (size_t i = 0; i < total_elements; i++) {
if (m->matrix_data[i] > -1.0 && m->matrix_data[i] < 1.0) {
result->matrix_data[i] = 1.0;
} else {
Expand Down
6 changes: 3 additions & 3 deletions nn/src/cache/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ static unsigned int hash(const char* key) {
// not the most secure, but I'll look into a better hash function
// later.
unsigned long long hash = 0;
int i = 0;
size_t i = 0;
while (key[i] != '\0') {
hash = hash * 31 + key[i];
i++;
Expand All @@ -48,7 +48,7 @@ Cache* init_cache() {
return NULL;
}

for (int i = 0; i < HASH_MAP_SIZE; i++) {
for (size_t i = 0; i < HASH_MAP_SIZE; i++) {
cache->entries[i] = NULL;
}
return cache;
Expand Down Expand Up @@ -101,7 +101,7 @@ void clear_cache(Cache* cache) {
if (cache == NULL) {
return;
}
for (int i = 0; i < HASH_MAP_SIZE; i++) {
for (size_t i = 0; i < HASH_MAP_SIZE; i++) {
CacheEntry* current = cache->entries[i];
while (current != NULL) {
CacheEntry* to_free = current;
Expand Down
Loading