diff options
| author | jeanne <jeanne@localhost.localdomain> | 2022-05-11 09:54:38 -0700 |
|---|---|---|
| committer | jeanne <jeanne@localhost.localdomain> | 2022-05-11 09:54:38 -0700 |
| commit | 411f66a2540fa17c736116d865e0ceb0cfe5623b (patch) | |
| tree | fa92c69ec627642c8452f928798ff6eccd24ddd6 /src/lib/include | |
| parent | 7705b07456dfd4b89c272613e98eda36cc787254 (diff) | |
Initial commit.
Diffstat (limited to 'src/lib/include')
| -rw-r--r-- | src/lib/include/neuralnet/matrix.h | 111 | ||||
| -rw-r--r-- | src/lib/include/neuralnet/neuralnet.h | 64 | ||||
| -rw-r--r-- | src/lib/include/neuralnet/train.h | 42 | ||||
| -rw-r--r-- | src/lib/include/neuralnet/types.h | 3 |
4 files changed, 220 insertions, 0 deletions
diff --git a/src/lib/include/neuralnet/matrix.h b/src/lib/include/neuralnet/matrix.h new file mode 100644 index 0000000..9816b81 --- /dev/null +++ b/src/lib/include/neuralnet/matrix.h | |||
| @@ -0,0 +1,111 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <neuralnet/types.h> | ||
| 4 | |||
| 5 | #include <assert.h> | ||
| 6 | |||
| 7 | /// NxM matrix. | ||
| 8 | typedef struct nnMatrix { | ||
| 9 | int rows; | ||
| 10 | int cols; | ||
| 11 | R* values; | ||
| 12 | } nnMatrix; | ||
| 13 | |||
| 14 | /// Construct a matrix. | ||
| 15 | nnMatrix nnMatrixMake(int rows, int cols); | ||
| 16 | |||
| 17 | /// Delete a matrix and free its internal memory. | ||
| 18 | void nnMatrixDel(nnMatrix*); | ||
| 19 | |||
| 20 | /// Move a matrix. | ||
| 21 | /// | ||
| 22 | /// |in| is an empty matrix after the move. | ||
| 23 | /// |out| is a matrix like |in| before the move. | ||
| 24 | void nnMatrixMove(nnMatrix* in, nnMatrix* out); | ||
| 25 | |||
| 26 | /// Deep-copy a matrix. | ||
| 27 | void nnMatrixCopy(const nnMatrix* in, nnMatrix* out); | ||
| 28 | |||
| 29 | /// Write the matrix values into an array in a row-major fashion. | ||
| 30 | void nnMatrixToArray(const nnMatrix* in, R* out); | ||
| 31 | |||
| 32 | /// Write the given row of a matrix into an array. | ||
| 33 | void nnMatrixRowToArray(const nnMatrix* in, int row, R* out); | ||
| 34 | |||
| 35 | /// Copy a column from a source to a target matrix. | ||
| 36 | void nnMatrixCopyCol(const nnMatrix* in, nnMatrix* out, int col_in, int col_out); | ||
| 37 | |||
| 38 | /// Mutable borrow of a matrix. | ||
| 39 | nnMatrix nnMatrixBorrow(nnMatrix* in); | ||
| 40 | |||
| 41 | /// Mutable borrow of a subrange of rows of a matrix. | ||
| 42 | nnMatrix nnMatrixBorrowRows(nnMatrix* in, int row_start, int num_rows); | ||
| 43 | |||
| 44 | /// Initialize the matrix from an array of values. | ||
| 45 | /// | ||
| 46 | /// The array must hold values in a row-major fashion. | ||
| 47 | void nnMatrixInit(nnMatrix*, const R* values); | ||
| 48 | |||
| 49 | /// Initialize all matrix values to a given constant. | ||
| 50 | void nnMatrixInitConstant(nnMatrix*, R value); | ||
| 51 | |||
| 52 | /// Multiply two matrices. | ||
| 53 | void nnMatrixMul(const nnMatrix* left, const nnMatrix* right, nnMatrix* out); | ||
| 54 | |||
| 55 | /// Matrix multiply-add. | ||
| 56 | /// | ||
| 57 | /// out = left + (right * scale) | ||
| 58 | void nnMatrixMulAdd(const nnMatrix* left, const nnMatrix* right, R scale, nnMatrix* out); | ||
| 59 | |||
| 60 | /// Matrix multiply-subtract. | ||
| 61 | /// | ||
| 62 | /// out = left - (right * scale) | ||
| 63 | void nnMatrixMulSub(const nnMatrix* left, const nnMatrix* right, R scale, nnMatrix* out); | ||
| 64 | |||
| 65 | /// Hadamard product of two matrices. | ||
| 66 | void nnMatrixMulPairs(const nnMatrix* left, const nnMatrix* right, nnMatrix* out); | ||
| 67 | |||
| 68 | /// Add two matrices. | ||
| 69 | void nnMatrixAdd(const nnMatrix* left, const nnMatrix* right, nnMatrix* out); | ||
| 70 | |||
| 71 | /// Subtract two matrices. | ||
| 72 | void nnMatrixSub(const nnMatrix* left, const nnMatrix* right, nnMatrix* out); | ||
| 73 | |||
| 74 | /// Adds a row vector to all rows of the matrix. | ||
| 75 | void nnMatrixAddRow(const nnMatrix* matrix, const nnMatrix* row, nnMatrix* out); | ||
| 76 | |||
| 77 | /// Scale a matrix. | ||
| 78 | void nnMatrixScale(nnMatrix*, R scale); | ||
| 79 | |||
| 80 | /// Transpose a matrix. | ||
| 81 | /// |in| must be different than |out|. | ||
| 82 | void nnMatrixTranspose(const nnMatrix* in, nnMatrix* out); | ||
| 83 | |||
| 84 | /// Threshold the values of a matrix using a greater-than operator. | ||
| 85 | /// | ||
| 86 | /// out[x,y] = 1 if in[x,y] > threshold else 0 | ||
| 87 | void nnMatrixGt(const nnMatrix* in, R threshold, nnMatrix* out); | ||
| 88 | |||
| 89 | /// Return the matrix value at the given row and column. | ||
| 90 | static inline R nnMatrixAt(const nnMatrix* matrix, int row, int col) { | ||
| 91 | assert(matrix); | ||
| 92 | return matrix->values[row * matrix->cols + col]; | ||
| 93 | } | ||
| 94 | |||
| 95 | /// Set the matrix value at the given row and column. | ||
| 96 | static inline void nnMatrixSet(nnMatrix* matrix, int row, int col, R value) { | ||
| 97 | assert(matrix); | ||
| 98 | matrix->values[row * matrix->cols + col] = value; | ||
| 99 | } | ||
| 100 | |||
| 101 | /// Return a pointer to the given row in the matrix. | ||
| 102 | static inline const R* nnMatrixRow(const nnMatrix* matrix, int row) { | ||
| 103 | assert(matrix); | ||
| 104 | return &matrix->values[row * matrix->cols]; | ||
| 105 | } | ||
| 106 | |||
| 107 | /// Return a mutable pointer to the given row in the matrix. | ||
| 108 | static inline R* nnMatrixRow_mut(nnMatrix* matrix, int row) { | ||
| 109 | assert(matrix); | ||
| 110 | return &matrix->values[row * matrix->cols]; | ||
| 111 | } | ||
diff --git a/src/lib/include/neuralnet/neuralnet.h b/src/lib/include/neuralnet/neuralnet.h new file mode 100644 index 0000000..1cf1c53 --- /dev/null +++ b/src/lib/include/neuralnet/neuralnet.h | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <neuralnet/types.h> | ||
| 4 | |||
| 5 | typedef struct nnMatrix nnMatrix; | ||
| 6 | |||
| 7 | typedef struct nnNeuralNetwork nnNeuralNetwork; | ||
| 8 | typedef struct nnQueryObject nnQueryObject; | ||
| 9 | |||
| 10 | /// Neuron activation. | ||
| 11 | typedef enum nnActivation { | ||
| 12 | nnIdentity, | ||
| 13 | nnSigmoid, | ||
| 14 | nnRelu, | ||
| 15 | } nnActivation; | ||
| 16 | |||
| 17 | /// Create a network. | ||
| 18 | nnNeuralNetwork* nnMakeNet(int num_layers, const int* layer_sizes, const nnActivation* activations); | ||
| 19 | |||
| 20 | /// Delete the network and free its internal memory. | ||
| 21 | void nnDeleteNet(nnNeuralNetwork**); | ||
| 22 | |||
| 23 | /// Set the network's weights. | ||
| 24 | void nnSetWeights(nnNeuralNetwork*, const R* weights); | ||
| 25 | |||
| 26 | /// Set the network's biases. | ||
| 27 | void nnSetBiases(nnNeuralNetwork*, const R* biases); | ||
| 28 | |||
| 29 | /// Query the network. | ||
| 30 | /// | ||
| 31 | /// |input| is a matrix of inputs, one row per input and as many columns as the | ||
| 32 | /// input's dimension. | ||
| 33 | /// | ||
| 34 | /// The query object's output matrix (see nnQueryOutputs()) is a matrix of | ||
| 35 | /// outputs, one row per output and as many columns as the output's dimension. | ||
| 36 | void nnQuery(const nnNeuralNetwork*, nnQueryObject*, const nnMatrix* input); | ||
| 37 | |||
| 38 | /// Query the network, array version. | ||
| 39 | void nnQueryArray(const nnNeuralNetwork*, nnQueryObject*, const R* input, R* output); | ||
| 40 | |||
| 41 | /// Create a query object. | ||
| 42 | /// | ||
| 43 | /// The query object holds all the internal memory required to query a network. | ||
| 44 | /// Query objects allocate all memory up front so that network queries can run | ||
| 45 | /// without additional memory allocation. | ||
| 46 | nnQueryObject* nnMakeQueryObject(const nnNeuralNetwork*, int num_inputs); | ||
| 47 | |||
| 48 | /// Delete the query object and free its internal memory. | ||
| 49 | void nnDeleteQueryObject(nnQueryObject**); | ||
| 50 | |||
| 51 | /// Return the outputs of the query. | ||
| 52 | const nnMatrix* nnNetOutputs(const nnQueryObject*); | ||
| 53 | |||
| 54 | /// Return the network's input size. | ||
| 55 | int nnNetInputSize(const nnNeuralNetwork*); | ||
| 56 | |||
| 57 | /// Return the network's output size. | ||
| 58 | int nnNetOutputSize(const nnNeuralNetwork*); | ||
| 59 | |||
| 60 | /// Return the layer's input size. | ||
| 61 | int nnLayerInputSize(const nnMatrix* weights); | ||
| 62 | |||
| 63 | /// Return the layer's output size. | ||
| 64 | int nnLayerOutputSize(const nnMatrix* weights); | ||
diff --git a/src/lib/include/neuralnet/train.h b/src/lib/include/neuralnet/train.h new file mode 100644 index 0000000..79f8e7b --- /dev/null +++ b/src/lib/include/neuralnet/train.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <neuralnet/neuralnet.h> | ||
| 4 | |||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | |||
| 8 | typedef struct nnMatrix nnMatrix; | ||
| 9 | |||
| 10 | /// Weight initialization strategy. | ||
| 11 | /// | ||
| 12 | /// Note that regardless of strategy, a layer's weights are scaled by the | ||
| 13 | /// layer's size. This is to avoid saturation when, e.g., using a sigmoid | ||
| 14 | /// activation with many inputs. Thus, a (0,1) initialization is really | ||
| 15 | /// (0,scale), for example. | ||
| 16 | typedef enum nnWeightInitStrategy { | ||
| 17 | nnWeightInit01, // (0,1) range. | ||
| 18 | nnWeightInit11, // (-1,+1) range. | ||
| 19 | nnWeightInitNormal, // Normal distribution. | ||
| 20 | } nnWeightInitStrategy; | ||
| 21 | |||
| 22 | /// Network training parameters. | ||
| 23 | typedef struct nnTrainingParams { | ||
| 24 | R learning_rate; | ||
| 25 | int max_iterations; | ||
| 26 | uint64_t seed; | ||
| 27 | nnWeightInitStrategy weight_init; | ||
| 28 | bool debug; | ||
| 29 | } nnTrainingParams; | ||
| 30 | |||
| 31 | /// Train the network. | ||
| 32 | /// | ||
| 33 | /// |inputs| is a matrix of inputs, one row per input and as many columns as | ||
| 34 | /// the input's dimension. | ||
| 35 | /// | ||
| 36 | /// |targets| is a matrix of targets, one row per target and as many columns as | ||
| 37 | /// the target's dimension. | ||
| 38 | void nnTrain( | ||
| 39 | nnNeuralNetwork*, | ||
| 40 | const nnMatrix* inputs, | ||
| 41 | const nnMatrix* targets, | ||
| 42 | const nnTrainingParams*); | ||
diff --git a/src/lib/include/neuralnet/types.h b/src/lib/include/neuralnet/types.h new file mode 100644 index 0000000..e8d3942 --- /dev/null +++ b/src/lib/include/neuralnet/types.h | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | typedef double R; | ||
