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; | ||