Skip to content

Commit

Permalink
Add nn_neuron_set_weights and nn_neuron_set_bias
Browse files Browse the repository at this point in the history
  • Loading branch information
devfacet committed Apr 7, 2024
1 parent b06d8c2 commit 6c7dd92
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 54 deletions.
4 changes: 2 additions & 2 deletions examples/arch/arm/cmsis-dsp/neuron/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ int main(int argc, char *argv[]) {

// Init vars
NNNeuron neuron;
int n_inputs = 3;
float inputs[NEURON_MAX_WEIGHTS] = {1, 2, 3};
float weights[NEURON_MAX_WEIGHTS] = {0.2f, 0.8f, -0.5f};
int n_weights = 3;
float bias = 2.0f;

// Compute the output
nn_neuron_init(&neuron, weights, n_inputs, bias, nn_activation_func_identity, nn_dot_product_cmsis);
nn_neuron_init(&neuron, weights, n_weights, bias, nn_activation_func_identity, nn_dot_product_cmsis);
printf("output (CMSIS): %f\n", nn_neuron_compute(&neuron, inputs));

return 0;
Expand Down
4 changes: 2 additions & 2 deletions examples/arch/arm/neon/neuron/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ int main(int argc, char *argv[]) {

// Init vars
NNNeuron neuron;
int n_inputs = 3;
float inputs[NEURON_MAX_WEIGHTS] = {1, 2, 3};
float weights[NEURON_MAX_WEIGHTS] = {0.2f, 0.8f, -0.5f};
int n_weights = 3;
float bias = 2.0f;

// Compute the output
nn_neuron_init(&neuron, weights, n_inputs, bias, nn_activation_func_identity, nn_dot_product_neon);
nn_neuron_init(&neuron, weights, n_weights, bias, nn_activation_func_identity, nn_dot_product_neon);
printf("output (NEON): %f\n", nn_neuron_compute(&neuron, inputs));

return 0;
Expand Down
4 changes: 2 additions & 2 deletions examples/arch/generic/neuron/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ int main(int argc, char *argv[]) {

// Init vars
NNNeuron neuron;
int n_inputs = 3;
float inputs[NEURON_MAX_WEIGHTS] = {1, 2, 3};
float weights[NEURON_MAX_WEIGHTS] = {0.2f, 0.8f, -0.5f};
int n_weights = 3;
float bias = 2.0f;

// Compute the output
nn_neuron_init(&neuron, weights, n_inputs, bias, nn_activation_func_identity, nn_dot_product);
nn_neuron_init(&neuron, weights, n_weights, bias, nn_activation_func_identity, nn_dot_product);
printf("output (generic): %f\n", nn_neuron_compute(&neuron, inputs));

return 0;
Expand Down
10 changes: 8 additions & 2 deletions include/nn_neuron.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,20 @@
// real-world applications since it's not optimized for performance.
typedef struct {
float weights[NEURON_MAX_WEIGHTS];
size_t n_weights;
float bias;
size_t n_inputs;
NNActivationFunction act_func;
NNDotProductFunction dot_product_func;
} NNNeuron;

// nn_neuron_init initializes a neuron with the given arguments.
void nn_neuron_init(NNNeuron *neuron, const float *weights, size_t n_inputs, float bias, NNActivationFunction act_func, NNDotProductFunction dot_product_func);
void nn_neuron_init(NNNeuron *neuron, const float *weights, size_t n_weights, float bias, NNActivationFunction act_func, NNDotProductFunction dot_product_func);

// nn_neuron_set_weights sets the weights of the given neuron.
void nn_neuron_set_weights(NNNeuron *neuron, const float *weights);

// nn_neuron_set_bias sets the bias of the given neuron.
void nn_neuron_set_bias(NNNeuron *neuron, float bias);

// nn_neuron_compute computes the given neuron and returns the output.
float nn_neuron_compute(const NNNeuron *neuron, const float *inputs);
Expand Down
23 changes: 19 additions & 4 deletions src/nn_neuron.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
#include <stdio.h>

// nn_neuron_init initializes a neuron with the given arguments.
void nn_neuron_init(NNNeuron *neuron, const float *weights, size_t n_inputs, float bias, NNActivationFunction act_func, NNDotProductFunction dot_product_func) {
void nn_neuron_init(NNNeuron *neuron, const float *weights, size_t n_weights, float bias, NNActivationFunction act_func, NNDotProductFunction dot_product_func) {
if (weights == NULL) {
return;
}
neuron->n_inputs = n_inputs;
for (size_t i = 0; i < neuron->n_inputs; ++i) {
neuron->n_weights = n_weights;
for (size_t i = 0; i < neuron->n_weights; ++i) {
neuron->weights[i] = weights[i];
}
neuron->bias = bias;
Expand All @@ -23,6 +23,21 @@ void nn_neuron_init(NNNeuron *neuron, const float *weights, size_t n_inputs, flo
}
}

// nn_neuron_set_weights sets the weights of the given neuron.
void nn_neuron_set_weights(NNNeuron *neuron, const float *weights) {
if (weights == NULL) {
return;
}
for (size_t i = 0; i < neuron->n_weights; ++i) {
neuron->weights[i] = weights[i];
}
}

// nn_neuron_set_bias sets the bias of the given neuron.
void nn_neuron_set_bias(NNNeuron *neuron, float bias) {
neuron->bias = bias;
}

// nn_neuron_compute computes the given neuron and returns the output.
float nn_neuron_compute(const NNNeuron *neuron, const float *inputs) {
// Compute the output of the neuron:
Expand All @@ -32,7 +47,7 @@ float nn_neuron_compute(const NNNeuron *neuron, const float *inputs) {
float result = 0.0f;
if (neuron->dot_product_func != NULL) {
// Sum the weighted inputs
result = neuron->dot_product_func(neuron->weights, inputs, neuron->n_inputs);
result = neuron->dot_product_func(neuron->weights, inputs, neuron->n_weights);
}
// Add the bias
result += neuron->bias;
Expand Down
24 changes: 12 additions & 12 deletions tests/arch/arm/cmsis-dsp/neuron/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
typedef struct {
float inputs[NEURON_MAX_WEIGHTS];
float weights[NEURON_MAX_WEIGHTS];
int n_inputs;
int n_weights;
float bias;
NNDotProductFunction dot_product_func;
float output_tolerance;
Expand All @@ -28,7 +28,7 @@ void run_test_cases(TestCase *test_cases, int n_cases, char *info, NNDotProductF
TestCase tc = test_cases[i];
NNNeuron neuron;

nn_neuron_init(&neuron, tc.weights, tc.n_inputs, tc.bias, nn_activation_func_identity, dot_product_func);
nn_neuron_init(&neuron, tc.weights, tc.n_weights, tc.bias, nn_activation_func_identity, dot_product_func);
const float output = nn_neuron_compute(&neuron, tc.inputs);
assert(isnan(output) == false);
assert(fabs(output - tc.expected_output) < tc.output_tolerance);
Expand All @@ -41,7 +41,7 @@ int main() {
{
.inputs = {0.5f, 1.2f, -0.8f},
.weights = {0.2f, 0.3f, -0.1f},
.n_inputs = 3,
.n_weights = 3,
.bias = 0.5f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 1.04f,
Expand All @@ -50,7 +50,7 @@ int main() {
{
.inputs = {-0.6f, -1.1f, 0.9f},
.weights = {-0.2f, 0.5f, 0.3f},
.n_inputs = 3,
.n_weights = 3,
.bias = -0.5f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = -0.66f,
Expand All @@ -59,7 +59,7 @@ int main() {
{
.inputs = {1.5f, 2.0f, -1.0f},
.weights = {0.4f, 0.4f, -0.2f},
.n_inputs = 3,
.n_weights = 3,
.bias = 2.0f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 3.6f,
Expand All @@ -68,7 +68,7 @@ int main() {
{
.inputs = {0.1f, -0.2f, 0.3f},
.weights = {0.3f, -0.2f, 0.1f},
.n_inputs = 3,
.n_weights = 3,
.bias = 0.05f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 0.15f,
Expand All @@ -77,7 +77,7 @@ int main() {
{
.inputs = {-2.5f, 3.0f, -1.5f},
.weights = {0.5f, -0.5f, 0.75f},
.n_inputs = 3,
.n_weights = 3,
.bias = 1.0f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = -2.875f,
Expand All @@ -86,7 +86,7 @@ int main() {
{
.inputs = {0.0f, 0.0f, 0.0f},
.weights = {0.25f, -0.75f, 0.5f},
.n_inputs = 3,
.n_weights = 3,
.bias = 0.5f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 0.5f,
Expand All @@ -95,7 +95,7 @@ int main() {
{
.inputs = {1.2f, -1.2f, 0.8f},
.weights = {0.0f, 0.0f, 0.0f},
.n_inputs = 3,
.n_weights = 3,
.bias = 0.25f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 0.25f,
Expand All @@ -104,7 +104,7 @@ int main() {
{
.inputs = {1.0f, -1.0f, 1.0f},
.weights = {-1.0f, 1.0f, -1.0f},
.n_inputs = 3,
.n_weights = 3,
.bias = -0.5f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = -3.5f,
Expand All @@ -113,7 +113,7 @@ int main() {
{
.inputs = {0.123f, 0.456f, -0.789f},
.weights = {0.321f, -0.654f, 0.987f},
.n_inputs = 3,
.n_weights = 3,
.bias = 0.1f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = -0.937484,
Expand All @@ -122,7 +122,7 @@ int main() {
{
.inputs = {0.001f, -0.002f, 0.003f},
.weights = {0.004f, 0.005f, -0.006f},
.n_inputs = 3,
.n_weights = 3,
.bias = 0.0f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 0.000012f,
Expand Down
24 changes: 12 additions & 12 deletions tests/arch/arm/neon/neuron/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
typedef struct {
float inputs[NEURON_MAX_WEIGHTS];
float weights[NEURON_MAX_WEIGHTS];
int n_inputs;
int n_weights;
float bias;
NNDotProductFunction dot_product_func;
float output_tolerance;
Expand All @@ -28,7 +28,7 @@ void run_test_cases(TestCase *test_cases, int n_cases, char *info, NNDotProductF
TestCase tc = test_cases[i];
NNNeuron neuron;

nn_neuron_init(&neuron, tc.weights, tc.n_inputs, tc.bias, nn_activation_func_identity, dot_product_func);
nn_neuron_init(&neuron, tc.weights, tc.n_weights, tc.bias, nn_activation_func_identity, dot_product_func);
const float output = nn_neuron_compute(&neuron, tc.inputs);
assert(isnan(output) == false);
assert(fabs(output - tc.expected_output) < tc.output_tolerance);
Expand All @@ -41,7 +41,7 @@ int main() {
{
.inputs = {0.5f, 1.2f, -0.8f},
.weights = {0.2f, 0.3f, -0.1f},
.n_inputs = 3,
.n_weights = 3,
.bias = 0.5f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 1.04f,
Expand All @@ -50,7 +50,7 @@ int main() {
{
.inputs = {-0.6f, -1.1f, 0.9f},
.weights = {-0.2f, 0.5f, 0.3f},
.n_inputs = 3,
.n_weights = 3,
.bias = -0.5f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = -0.66f,
Expand All @@ -59,7 +59,7 @@ int main() {
{
.inputs = {1.5f, 2.0f, -1.0f},
.weights = {0.4f, 0.4f, -0.2f},
.n_inputs = 3,
.n_weights = 3,
.bias = 2.0f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 3.6f,
Expand All @@ -68,7 +68,7 @@ int main() {
{
.inputs = {0.1f, -0.2f, 0.3f},
.weights = {0.3f, -0.2f, 0.1f},
.n_inputs = 3,
.n_weights = 3,
.bias = 0.05f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 0.15f,
Expand All @@ -77,7 +77,7 @@ int main() {
{
.inputs = {-2.5f, 3.0f, -1.5f},
.weights = {0.5f, -0.5f, 0.75f},
.n_inputs = 3,
.n_weights = 3,
.bias = 1.0f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = -2.875f,
Expand All @@ -86,7 +86,7 @@ int main() {
{
.inputs = {0.0f, 0.0f, 0.0f},
.weights = {0.25f, -0.75f, 0.5f},
.n_inputs = 3,
.n_weights = 3,
.bias = 0.5f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 0.5f,
Expand All @@ -95,7 +95,7 @@ int main() {
{
.inputs = {1.2f, -1.2f, 0.8f},
.weights = {0.0f, 0.0f, 0.0f},
.n_inputs = 3,
.n_weights = 3,
.bias = 0.25f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 0.25f,
Expand All @@ -104,7 +104,7 @@ int main() {
{
.inputs = {1.0f, -1.0f, 1.0f},
.weights = {-1.0f, 1.0f, -1.0f},
.n_inputs = 3,
.n_weights = 3,
.bias = -0.5f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = -3.5f,
Expand All @@ -113,7 +113,7 @@ int main() {
{
.inputs = {0.123f, 0.456f, -0.789f},
.weights = {0.321f, -0.654f, 0.987f},
.n_inputs = 3,
.n_weights = 3,
.bias = 0.1f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = -0.937484,
Expand All @@ -122,7 +122,7 @@ int main() {
{
.inputs = {0.001f, -0.002f, 0.003f},
.weights = {0.004f, 0.005f, -0.006f},
.n_inputs = 3,
.n_weights = 3,
.bias = 0.0f,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 0.000012f,
Expand Down
12 changes: 6 additions & 6 deletions tests/arch/generic/dot_product/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
typedef struct {
float a[4];
float b[4];
int n_inputs;
int n_weights;
float bias;
NNDotProductFunction dot_product_func;
float output_tolerance;
Expand All @@ -26,7 +26,7 @@ void run_test_cases(TestCase *test_cases, int n_cases, char *info, NNDotProductF
for (int i = 0; i < n_cases; ++i) {
TestCase tc = test_cases[i];

const float output = dot_product_func(tc.a, tc.b, tc.n_inputs);
const float output = dot_product_func(tc.a, tc.b, tc.n_weights);
assert(isnan(output) == false);
assert(fabs(output - tc.expected_output) < tc.output_tolerance);
printf("passed: %s case=%d info=%s\n", __func__, i + 1, info);
Expand All @@ -38,31 +38,31 @@ int main() {
{
.a = {0.5f},
.b = {0.2f},
.n_inputs = 1,
.n_weights = 1,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 0.1f,
},

{
.a = {-0.6f, -1.1f},
.b = {-0.2f, 0.5f},
.n_inputs = 2,
.n_weights = 2,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = -0.43f,
},

{
.a = {1.5f, 2.0f, -1.0f},
.b = {0.4f, 0.4f, -0.2f},
.n_inputs = 3,
.n_weights = 3,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 1.6f,
},

{
.a = {0.36f, 0.17f, 0.96f, 0.12f},
.b = {0.77f, 0.09f, 0.12f, 0.81f},
.n_inputs = 4,
.n_weights = 4,
.output_tolerance = DEFAULT_OUTPUT_TOLERANCE,
.expected_output = 0.5048,
},
Expand Down
Loading

0 comments on commit 6c7dd92

Please sign in to comment.