Perceptron Bolado - perceptron simples escrito em C

Publicado por Samuel Leonardo (última atualização em 18/01/2023)

[ Hits: 2.972 ]

Homepage: https://nerdki.blogspot.com/

Download perceptronBolado.c




Segue um perceptron simples (a primeira IA criada) escrito em C.
Baseado no código da @alexabolada via fórum do VOL.

Como testar esse programa?

O perceptron é um tipo de rede neural (uma IA). Com ele é possível usar para aprender padrões simples. O perceptron não é tão complexo e sua simplicidade tem o preço com o problema XOR. O perceptron não consegue aproximar uma simples porta lógica XOR. Mas consegue aproximar outras, como NOT, AND e OR. Cada neurônio aqui, é identificado pelas variáveis inputs e outputs.

Para compilar use:
gcc -o perceptronBolado perceptronBolado.c

Execute pelo terminal
./perceptronBolado

  



Esconder código-fonte

/**
 * @file perceptron.c
 * @author Samuel Leonardo e @alexabolada
 * @brief Perceptron simples de entender por qualquer programador
 * @version 0.1
 * @date 2023-01-04
 * 
 * @copyleft Copyleft (!c) 2023
 * Ideia original em
 * https://www.vivaolinux.com.br/topico/Off-Code-Cafe/Alex-Bolada/?pagina=5
 * 
 * ....
 * ....
 * ....._.._.
 * ..__|.||.|_.
 * ./._..||.|_.
 * |.(_|.||.|_.
 * .\\__,_\\|_|..
 */

/**
 * Como testar esse programa?
 * O perceptron é um tipo de rede neural (uma IA).
 * Com ele é possível usar para aprender padrões simples.
 * O perceptron não é tão complexo e sua simpliciddade tem o preço 
 * com o problema XOR.
 * O perceptron não consegue aproximar uma simples porta lógica XOR.
 * Mas consegue aproximar outras, como NOT, AND e OR.
 * Cada neurônio aqui, é identificado pelas variáveis inputs e outputs.
 * Para compilar use:
 * gcc -o perceptronBolado perceptronBolado.c
 * Execute pelo terminal
*/

#include <stdio.h>
#include <stdlib.h>

//quantidade de padrões para aprender
#define PATTERNS 4
//esses são os padrões de entrada
#define NUM_INPUTS 2
//padrões de saida
#define NUM_OUTPUTS 1
//taxa de aprendizado
#define LEARN 1.0

//abaixo, a porta lógica AND
float and[PATTERNS][NUM_INPUTS] = {
  {0,0},
  {0,1},
  {1,0},
  {1,1},
};
// Define os valores de saída esperados
float outputs[PATTERNS] = {0,0,0,1};

// Define os pesos das entradas, bias fica na última posição
float inputsWeight[NUM_INPUTS + 1] = {0,0,0};


// Define a função de ativação
//função usada para ativar a lógica do neurônio
float activationFunc(float x) {
  return x > 0 ? 1 : 0;
}
float calcSum(float inputs[], int numInputs) {
  float sum = 0;
  for (int i = 0; i < numInputs; i++) {
    sum += inputs[i] * inputsWeight[i];
  }
  //soma o bias
  sum += 1 * inputsWeight[numInputs];
  return sum;
}

// Calcula a saída para a rede multicamada
float calcOutput(float *inputs, int numInputs) {
  float sum = calcSum(inputs, numInputs);
  return activationFunc(sum);
}

//calculed é a saida calculada para o apdrão p
float calcError (float output, float calculed) {
  return output - calculed;
}

void trainFunc () {
  int epochs = 1;
  while (epochs < 100) {
    float error = 0, ok = 0;
    float calculed = 0;

    //corrige os pesos
    for (int i = 0; i < PATTERNS; i++) {
      float sum = calcSum(and[i], NUM_INPUTS);
      calculed = activationFunc(sum);
      error = calcError(outputs[i], calculed);
      //se errour, tem que ajustar os pesos
      if (calculed != outputs[i]) {
        for (int j = 0; j < NUM_INPUTS; j++) {
          //and[i][j] é o sinal de entrada
          //calcula o ajuste dos pesos
          inputsWeight[j] += outputs[i] + (LEARN * error * and[i][j]);
        }
        //calcula o ajuste do bias
        inputsWeight[NUM_INPUTS] += outputs[i] + (LEARN * error * 1);
      }
      else {
        //contador de padrões corretos
        ok += 1;
      }
    }

    //acertos global
    ok /= (float)PATTERNS;
    if (ok >= LEARN)
      break;

    epochs++;
  }
}

int main(int argc, char **argv) {
  float inputs[NUM_INPUTS] = {};
  
  //executa o treinamento
  trainFunc();

  //imprime as saidas desejadas
  printf("Saidas desejadas = ");
  for (int i = 0; i < PATTERNS; i++) {
    printf("%d ", (int)outputs[i]);
  }
  printf("\n");

  for (int i = 0; i < PATTERNS; i++) {
    //coloca as entradas nos neuronios
    for (int j = 0; j < NUM_INPUTS; j++)
      inputs[j] = and[i][j];
    
    //calcula o valor de saida
    float output = calcOutput(inputs, NUM_INPUTS);
    // Imprime a saída
    printf("Saída: %d and %d  = %f\n", (int)(inputs[0]), (int)(inputs[1]), (output));
  }

  return 0;
}

Scripts recomendados

Labirinto de Teseu

Árvore binária de busca, algoritmos de inserção, caminhamento e busca explicados

Diária Hotel

Par ou ímpar

Jogo da Forca em C


  

Comentários
[1] Comentário enviado por maurixnovatrento em 28/01/2023 - 21:43h


Muito bom.

___________________________________________________________
Conhecimento não se Leva para o Túmulo.
https://github.com/mxnt10


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts