Remove old extension
This commit is contained in:
parent
15c8482dd3
commit
fd1fcbf7f7
@ -1,18 +0,0 @@
|
|||||||
CC = gcc
|
|
||||||
CFLAGS = -std=c17 -g\
|
|
||||||
-D_POSIX_SOURCE -D_DEFAULT_SOURCE\
|
|
||||||
-Wall -Werror -pedantic\
|
|
||||||
|
|
||||||
LDLIBS = -lm
|
|
||||||
|
|
||||||
.SUFFIXES: .c .o
|
|
||||||
|
|
||||||
.PHONY: all clean
|
|
||||||
|
|
||||||
all: test/test_math test/test_ann
|
|
||||||
|
|
||||||
test/test_math: test/test_math.o mymath.o
|
|
||||||
test/test_ann: test/test_ann.o ann.o mymath.o
|
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o test/*.o
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include "ann.h"
|
|
||||||
|
|
||||||
// Helper function that simulate 'bias' term by setting a neuron that always outputs 1.0
|
|
||||||
static void network_fillbias(Network network, unsigned int layerIndex) {
|
|
||||||
|
|
||||||
for (int j = 0; j < network->trainingWidth; j++) {
|
|
||||||
*(network->outputs[layerIndex]->data + network->layers[layerIndex].neuronCount * network->trainingWidth + j) = 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defines a sequence of random numbers sampled from a standard normal distribution
|
|
||||||
double normalseq(unsigned int i) {
|
|
||||||
return stdnormal();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a new network instance given an array of layers and the size of the array
|
|
||||||
Network network_create(Layer *layers, unsigned int noLayers, unsigned int trainingWidth) {
|
|
||||||
|
|
||||||
// Initialize network struct and its fields
|
|
||||||
Network network = malloc(sizeof(struct Network));
|
|
||||||
if (network == NULL) {
|
|
||||||
fprintf(stderr, "ERROR: Couldn't allocate sufficient memory for Network struct!\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
network->layers = layers;
|
|
||||||
network->noLayers = noLayers;
|
|
||||||
network->trainingWidth = trainingWidth;
|
|
||||||
|
|
||||||
network->outputs = malloc(sizeof(struct Matrix) * noLayers);
|
|
||||||
if (network->outputs == NULL) {
|
|
||||||
fprintf(stderr, "ERROR: Couldn't allocate sufficient memory for Network output matrix array!\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
network->weights = malloc(sizeof(struct Matrix) * (noLayers - 1));
|
|
||||||
if (network->weights == NULL) {
|
|
||||||
fprintf(stderr, "ERROR: Couldn't allocate sufficient memory for Network weight matrix array!\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize output and weight matrix array data
|
|
||||||
for (unsigned int i = 0; i < noLayers; i++) {
|
|
||||||
network->outputs[i] = matrix_create(layers[i].neuronCount + 1, trainingWidth);
|
|
||||||
|
|
||||||
network_fillbias(network, i);
|
|
||||||
|
|
||||||
if (i < noLayers - 1) {
|
|
||||||
network->weights[i] = matrix_seqcreate(layers[i + 1].neuronCount + 1, layers[i].neuronCount + 1, &normalseq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return network;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Returns the output of the ANN given the specified input
|
|
||||||
Matrix network_pass(Network network, Matrix features) {
|
|
||||||
|
|
||||||
Matrix currentOut = features;
|
|
||||||
for (int i = 0; i < network->noLayers; i++) {
|
|
||||||
|
|
||||||
// Update current layer's outputs
|
|
||||||
matrix_free(network->outputs[i]);
|
|
||||||
network->outputs[i] = currentOut;
|
|
||||||
network_fillbias(network, i);
|
|
||||||
|
|
||||||
// Calculate outputs of next layer if not in last layer
|
|
||||||
if (i < network->noLayers - 1) {
|
|
||||||
currentOut = matrix_apply(matrix_multiply(network->weights[i], currentOut), network->layers[i].activation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Matrix log_loss(Matrix result, Matrix expected) {
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
/* @file ann.h
|
|
||||||
@brief Data structures and functions for feedforward neural networks.
|
|
||||||
|
|
||||||
@author Themis Demetriades */
|
|
||||||
|
|
||||||
#ifndef __ANN__
|
|
||||||
#define __ANN__
|
|
||||||
|
|
||||||
#include "mymath.h"
|
|
||||||
|
|
||||||
// Defines function pointer type for activation functions
|
|
||||||
typedef double (*activationFunc)(double);
|
|
||||||
|
|
||||||
// Specifies structure of a given layer within a network
|
|
||||||
typedef struct {
|
|
||||||
unsigned int neuronCount;
|
|
||||||
activationFunc activation;
|
|
||||||
} Layer;
|
|
||||||
|
|
||||||
// Defines a specific instance of an active network
|
|
||||||
struct Network {
|
|
||||||
Layer *layers; // Array of layers specifying network structure
|
|
||||||
unsigned int noLayers;
|
|
||||||
Matrix *weights; // Array of matrices specifying weights of *outputs* to each layer
|
|
||||||
Matrix *outputs;
|
|
||||||
|
|
||||||
unsigned int trainingWidth; // Number of training examples to train per gradient descent step
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct Network *Network;
|
|
||||||
|
|
||||||
// Creates a new network instance given an array of layers and the size of the array
|
|
||||||
Network network_create(Layer *layers, unsigned int noLayers, unsigned int trainingWidth);
|
|
||||||
|
|
||||||
// Returns the output of the ANN given the specified input
|
|
||||||
Matrix network_pass(Network network, Matrix features);
|
|
||||||
|
|
||||||
// Calculates the log loss of a result wrt to the expected result
|
|
||||||
Matrix log_loss(Matrix result, Matrix expected);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,166 +0,0 @@
|
|||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include "mymath.h"
|
|
||||||
|
|
||||||
#define LRELU_SFACTOR 0.001
|
|
||||||
|
|
||||||
// Maximum number of characters that would ever be required to represent a valid matrix entry
|
|
||||||
#define MAX_ENTRY_LENGTH 100
|
|
||||||
|
|
||||||
// Defines the format used to print matrix entries
|
|
||||||
#define VALUE_PRINT_FORMAT "%.2lf"
|
|
||||||
|
|
||||||
// Pretty print matrix data to the given output stream
|
|
||||||
void matrix_print(Matrix m, FILE *stream) {
|
|
||||||
|
|
||||||
double (*data)[m->cols] = (double (*)[m->cols]) m->data;
|
|
||||||
char valstr[MAX_ENTRY_LENGTH];
|
|
||||||
unsigned int maxlen = 1;
|
|
||||||
|
|
||||||
// Get maximum length of a matrix entry
|
|
||||||
for (int i = 0; i < m->rows; i++) {
|
|
||||||
for (int j = 0; j < m->cols; j++) {
|
|
||||||
sprintf(valstr, VALUE_PRINT_FORMAT, data[i][j]);
|
|
||||||
unsigned int curlen = strlen(valstr);
|
|
||||||
if (curlen > maxlen) maxlen = curlen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print matrix entries
|
|
||||||
for (int i = 0; i < m->rows; i++) {
|
|
||||||
fputc('[', stream);
|
|
||||||
for (int j = 0; j < m->cols; j++) {
|
|
||||||
sprintf(valstr, VALUE_PRINT_FORMAT, data[i][j]);
|
|
||||||
fprintf(stream, "%s", valstr);
|
|
||||||
for (int k = 0; k < maxlen - strlen(valstr); k++) fputc(' ', stream);
|
|
||||||
if (j < m->cols - 1) fputc(' ', stream);
|
|
||||||
}
|
|
||||||
fprintf(stream, "]\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return matrix with specified dimensions and random values as its entries
|
|
||||||
Matrix matrix_create(unsigned int rows, unsigned int cols) {
|
|
||||||
|
|
||||||
// Allocate memory for matrix struct, aborting if couldn't allocate memory
|
|
||||||
Matrix m = malloc(sizeof(struct Matrix));
|
|
||||||
if (m == NULL) {
|
|
||||||
fprintf(stderr, "ERROR: Couldn't allocate sufficient memory for matrix struct!\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate memory for matrix data (values), aborting if couldn't allocate memory
|
|
||||||
m->data = malloc(rows * cols * sizeof(double));
|
|
||||||
if (m->data == NULL) {
|
|
||||||
fprintf(stderr, "ERROR: Couldn't allocate sufficient memory for matrix data!\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize matrix struct data
|
|
||||||
m->rows = rows;
|
|
||||||
m->cols = cols;
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free data associated with the specified matrix
|
|
||||||
void matrix_free(Matrix m) {
|
|
||||||
|
|
||||||
free(m->data);
|
|
||||||
free(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return matrix with specified dimensions and entries whose values are the first values of the specified matrix sequence
|
|
||||||
Matrix matrix_seqcreate(unsigned int rows, unsigned int cols, matrix_sequence seq) {
|
|
||||||
|
|
||||||
// Create matrix with specified dimensions containing entries with random values
|
|
||||||
Matrix m = matrix_create(rows, cols);
|
|
||||||
|
|
||||||
double (*data)[cols] = (double (*)[cols]) m->data;
|
|
||||||
// Fill matrix with correct entries
|
|
||||||
for (int i = 0; i < rows; i++) {
|
|
||||||
for (int j = 0; j < cols; j++) {
|
|
||||||
data[i][j] = seq(i * cols + j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multiply left matrix (l) with right matrix (r), returning a new instance representing the result
|
|
||||||
Matrix matrix_multiply(Matrix l, Matrix r) {
|
|
||||||
|
|
||||||
// Ensure that dimensions of matrices are compatible for multiplication
|
|
||||||
if (l->cols != r->rows) {
|
|
||||||
fprintf(stderr, "ERROR: Attempting to multiply matrices with incompatible dimensions!\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create matrix instance to store result of product
|
|
||||||
Matrix prod = matrix_create(l->rows, r->cols);
|
|
||||||
|
|
||||||
double (*prod_data)[prod->cols] = (double (*)[prod->cols]) prod->data;
|
|
||||||
double (*l_data)[l->cols] = (double (*)[l->cols]) l->data;
|
|
||||||
double (*r_data)[r->cols] = (double (*)[r->cols]) r->data;
|
|
||||||
// Perform matrix multiplication, storing result in prod
|
|
||||||
for (int i = 0; i < l->rows; i++) {
|
|
||||||
for (int j = 0; j < r->cols; j++) {
|
|
||||||
|
|
||||||
prod_data[i][j] = 0.0;
|
|
||||||
for (int k = 0; k < l->cols; k++) {
|
|
||||||
prod_data[i][j] += l_data[i][k] * r_data[k][j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return result
|
|
||||||
return prod;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return result of applying given function to each entry in the matrix independently
|
|
||||||
Matrix matrix_apply(Matrix m, matrix_entrytrans f) {
|
|
||||||
|
|
||||||
Matrix result = matrix_create(m->rows, m->cols);
|
|
||||||
double (*result_data)[result->cols] = (double (*)[result->cols])result->data;
|
|
||||||
double (*m_data)[m->cols] = (double (*)[m->cols])m->data;
|
|
||||||
|
|
||||||
for (int i = 0; i < m->rows; i++) {
|
|
||||||
for (int j = 0; j < m->cols; j++) {
|
|
||||||
result_data[i][j] = f(m_data[i][j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draws a value from the standard normal distribution
|
|
||||||
double stdnormal() {
|
|
||||||
|
|
||||||
// Generate 2 random numbers in the interval [0, 1)
|
|
||||||
double s1 = ((double)rand() / RAND_MAX);
|
|
||||||
double s2 = ((double)rand() / RAND_MAX);
|
|
||||||
|
|
||||||
// Peform box-muller transform
|
|
||||||
return sqrt(-2 * log(s1)) * cos(2 * PI * s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defines the leaky rectified linear unit activation function
|
|
||||||
double lrelu(double x) {
|
|
||||||
if (x > 0) {
|
|
||||||
return x;
|
|
||||||
} else {
|
|
||||||
return LRELU_SFACTOR * x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defines the identity activation function f(x) = x
|
|
||||||
double identity(double x) {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defines a simple counting sequence
|
|
||||||
double countseq(unsigned int i) {
|
|
||||||
return i + 1;
|
|
||||||
}
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
/* @file math.h
|
|
||||||
@brief Math functions and types for feedforward ANNs.
|
|
||||||
|
|
||||||
@author Themis Demetriades */
|
|
||||||
|
|
||||||
#ifndef __MATH__
|
|
||||||
#define __MATH__
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#define PI 3.1415926535
|
|
||||||
|
|
||||||
// Definition of matrix types
|
|
||||||
struct Matrix {
|
|
||||||
unsigned int rows;
|
|
||||||
unsigned int cols;
|
|
||||||
double *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct Matrix *Matrix;
|
|
||||||
|
|
||||||
// Pretty print matrix data to the given output stream
|
|
||||||
void matrix_print(Matrix m, FILE *stream);
|
|
||||||
|
|
||||||
// Defines a sequence that maps matrix entry indices to floating point values
|
|
||||||
typedef double (*matrix_sequence)(unsigned int);
|
|
||||||
|
|
||||||
// Defines a function that transforms matrix entries
|
|
||||||
typedef double (*matrix_entrytrans)(double);
|
|
||||||
|
|
||||||
// Return matrix with specified dimensions and random values as its entries
|
|
||||||
Matrix matrix_create(unsigned int rows, unsigned int cols);
|
|
||||||
|
|
||||||
// Free data associated with the specified matrix
|
|
||||||
void matrix_free(Matrix m);
|
|
||||||
|
|
||||||
// Return matrix with specified dimensions and entries whose values are the first values of the specified matrix sequence
|
|
||||||
Matrix matrix_seqcreate(unsigned int rows, unsigned int cols, matrix_sequence seq);
|
|
||||||
|
|
||||||
// Multiply left matrix (l) with right matrix (r), returning a new instance representing the result
|
|
||||||
Matrix matrix_multiply(Matrix l, Matrix r);
|
|
||||||
|
|
||||||
// Return result of applying given function to each entry in the matrix independently
|
|
||||||
Matrix matrix_apply(Matrix m, matrix_entrytrans f);
|
|
||||||
|
|
||||||
// Draws a value from the standard normal distribution
|
|
||||||
double stdnormal();
|
|
||||||
|
|
||||||
// Defines the identity activation function f(x) = x
|
|
||||||
double identity(double x);
|
|
||||||
|
|
||||||
// Defines the rectified linear unit activation function
|
|
||||||
double lrelu(double x);
|
|
||||||
|
|
||||||
// Defines a simple counting sequence
|
|
||||||
double countseq(unsigned int i);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Binary file not shown.
@ -1,28 +0,0 @@
|
|||||||
#include "../ann.h"
|
|
||||||
|
|
||||||
#define TEST1_LAYERS 4
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
|
|
||||||
Layer layers[] = {{1, &lrelu}, {3, &lrelu}, {3, &lrelu}, {2, &identity}};
|
|
||||||
Network network = network_create(layers, TEST1_LAYERS, 1);
|
|
||||||
|
|
||||||
for (int i = 0; i < TEST1_LAYERS; i++) {
|
|
||||||
matrix_print(network->outputs[i], stdout);
|
|
||||||
printf("\n");
|
|
||||||
if (i < TEST1_LAYERS - 1) {
|
|
||||||
matrix_print(network->weights[i], stdout);
|
|
||||||
printf("\n ------------- \n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("===========================\n");
|
|
||||||
|
|
||||||
Matrix features = matrix_create(2, 1);
|
|
||||||
*(features->data + 0) = 1;
|
|
||||||
|
|
||||||
Matrix out = network_pass(network, features);
|
|
||||||
|
|
||||||
matrix_print(out, stdout);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,20 +0,0 @@
|
|||||||
#include "../mymath.h"
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
|
|
||||||
Matrix l = matrix_seqcreate(4, 3, &countseq);
|
|
||||||
Matrix r = matrix_seqcreate(3, 2, &countseq);
|
|
||||||
|
|
||||||
matrix_print(l, stdout);
|
|
||||||
printf("\n");
|
|
||||||
matrix_print(r, stdout);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
Matrix p = matrix_multiply(l, r);
|
|
||||||
matrix_print(p, stdout);
|
|
||||||
|
|
||||||
matrix_free(l);
|
|
||||||
matrix_free(r);
|
|
||||||
matrix_free(p);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user