Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- // the perceptron
- typedef struct {
- size_t inputs_count;
- double learning_rate;
- double bias;
- double *weight;
- double (*activation)(double aggregation);
- } perceptron;
- // a basic activation function
- double step_function(double value) {
- return value < 0.5? 0 : 1;
- }
- // initialization of a perceptron
- void perceptron_init(perceptron *p, size_t inputs_count, double learning_rate, double (*activation_function)(double)) {
- srand(time(NULL));
- p->bias = (double)rand() / (double)RAND_MAX; // between 0 and 1
- p->weight = malloc(sizeof(double) * inputs_count);
- p->inputs_count = inputs_count;
- p->learning_rate = learning_rate;
- p->activation = activation_function;
- // basic error handling
- if(p->weight == NULL) {
- p->inputs_count = 0;
- return;
- }
- for(size_t i = 0; i < inputs_count; ++i) {
- p->weight[i] = (double)rand() / (double)RAND_MAX;
- }
- }
- // activation_function(bias + input[0] * weight[0] + input[1] * weight[1] + ...)
- double perceptron_predict(perceptron *p, double inputs[]) {
- double aggregation = p->bias;
- for(size_t i = 0; i < p->inputs_count; ++i) {
- aggregation += inputs[i] * p->weight[i];
- }
- double output = p->activation(aggregation);
- return output;
- }
- // trains a perceptron with a dataset of inputs and the expected outpus for them
- void perceptron_train(perceptron *p, double **inputs, double *expected_outputs, size_t data_count) {
- double y;
- double error;
- size_t row = 0;
- while(row < data_count) {
- y = perceptron_predict(p, inputs[row]);
- error = expected_outputs[row] - y;
- if(error == 0) {
- // if there is no error take the next group of inputs
- ++row;
- } else {
- // if the error is set then recalculate the weights and go to da capo
- p->bias += p->learning_rate * error;
- for(int i = 0; i < p->inputs_count; ++i) {
- p->weight[i] += p->learning_rate * error * inputs[row][i];
- }
- row = 0;
- }
- }
- }
- // print the internal state of a perceptron
- void perceptron_print(perceptron *p) {
- printf("perceptron %p\n", p);
- printf(" + learning rate: %lf\n", p->learning_rate);
- printf(" + bias: %lf\n", p->bias);
- for(size_t i = 0; i < p->inputs_count; ++i) {
- printf(" + wheight[%u]: %lf\n", i, p->weight[i]);
- }
- }
- // frees the 'weight' dynamic array
- void perceptron_dispose(perceptron *n) {
- free(n->weight);
- }
- int main() {
- // dataset for an 'and' gate
- double *inputs[] = {
- (double[]){ 0, 0 },
- (double[]){ 0, 1 },
- (double[]){ 1, 0 },
- (double[]){ 1, 1 }
- };
- double outputs[] = { 0, 0, 0, 1 };
- // creating the perceptron
- perceptron p;
- perceptron_init(&p, 2, 0.1, step_function);
- if(p.inputs_count == 0)
- return EXIT_FAILURE;
- // training the perceptron
- perceptron_train(&p, inputs, outputs, 4);
- perceptron_print(&p);
- // demostration
- for(int k=0; k<4; ++k) {
- double x[] = {(k>>1) & 1, k & 1};
- double s = perceptron_predict(&p, x);
- printf("%1.0lf y %1.0lf = %1.0lf\n", x[0], x[1], s);
- }
- // liberation of resources
- perceptron_dispose(&p);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement