Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add nn_neuron_set_weights and nn_neuron_set_bias #7

Merged
merged 1 commit into from
Apr 7, 2024
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
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
Loading