Skip to content

Instantly share code, notes, and snippets.

@pxpc2
Created June 27, 2019 00:46
Show Gist options
  • Select an option

  • Save pxpc2/c25b5dd31ead1f376b89b86e92f5eb2d to your computer and use it in GitHub Desktop.

Select an option

Save pxpc2/c25b5dd31ead1f376b89b86e92f5eb2d to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "rede.h"
#define QT_ENTRADA 536
Rede* rede;
/**
* Aloca memoria e inicializa as camadas e seus respectivos neuronios,
* atribuindo já os pesos e bias aleatorios pras entradas dos neuronios.
*
* @param qt_oculta quantidade de neuronios na camada oculta (definida runtime)
*/
void initRede(int qt_oculta)
{
rede = (Rede*) malloc(sizeof(Rede));
rede->entrada = (Camada*) malloc(sizeof(Camada));
rede->entrada->neuronios = (Neuronio**) malloc(sizeof(Neuronio*) * QT_ENTRADA);
rede->entrada->qt_neuronios = QT_ENTRADA;
rede->entrada->qt_entradas = QT_ENTRADA;
initNeuronios(rede->entrada, qt_oculta);
rede->oculta = (Camada*) malloc(sizeof(Camada));
rede->oculta->neuronios = (Neuronio**) malloc(sizeof(Neuronio*) * qt_oculta);
rede->oculta->qt_neuronios = qt_oculta;
rede->oculta->qt_entradas = QT_ENTRADA;
initNeuronios(rede->oculta, qt_oculta);
rede->saida = (Camada*) malloc(sizeof(Camada));
rede->saida->neuronios = (Neuronio**) malloc(sizeof(Neuronio*));
rede->saida->qt_neuronios = 1;
rede->saida->qt_entradas = qt_oculta;
initNeuronios(rede->saida, qt_oculta);
}
/**
*
* Inicializa os neuronios
*
* @param camada camada da qual inicializar os neuronios
* @param qt_oculta quantidade de neuronios na camada oculta da rede
*/
void initNeuronios(Camada* camada, int qt_oculta)
{
if (camada == NULL)
return;
for (int i = 0; i < camada->qt_neuronios; i++)
{
// trocamos a seed a cada iteração pra não repetir os mesmos pesos e bias
srand(i);
double* pesos = gerarPesos(camada->qt_entradas);
camada->neuronios[i] = (Neuronio*) malloc(sizeof(Neuronio));
// se for da camada oculta ou entrada, teremos 536 pesos e 536 entradas
// se for da camada saída, teremos "qt_oculta" pesos e entradas
int size = (camada->qt_neuronios == 1? qt_oculta : QT_ENTRADA);
camada->neuronios[i]->p = (double*) malloc(sizeof(double) * size);
camada->neuronios[i]->w = (double*) malloc(sizeof(double) * size);
camada->neuronios[i]->p_length = size;
for (int j = 0; j < camada->qt_entradas; j++)
camada->neuronios[i]->w[j] = pesos[j];
camada->neuronios[i]->b = gerarBias();
}
}
/**
* Gera um vetor de pesos aleatorios
* @param quantidade quantidade de pesos pra gerar (igual a quantidade de entradas que neuronio recebe)
* @return vetor de pesos gerados
*/
double* gerarPesos(int quantidade)
{
double* pesos = (double*) malloc(sizeof(double) * quantidade);
for (int i = 0; i < quantidade; i++)
{
pesos[i] = rand() % 15000 + 1;
}
return pesos;
}
/**
* Gera um escalar aleatorio, bias.
* @return o bias
*/
double gerarBias()
{
return rand() % 15000 + 1;
}
/**
* Calcula o somatorio do produto dos pesos pelas entradas, e adiciona o bias
* @param n neuronio pra calcular o somatorio dele
* @return o valor que vai na funcao logistica
*/
double getSomatorio(Neuronio* n)
{
double sum = 0.0;
if (n == NULL)
return -1;
for (int i = 0; i < n->p_length; i++)
sum += (n->p[i]*n->w[i]);
return (n->b + sum);
}
/**
* Aplica a funcao logistica ao somatorio
* @param somatorio somatorio do produto dos pesos pelas entradas e o bias
* @return resultado da funcao logistica (sigmoid)
*/
double funcaoLogistica(double somatorio)
{
return 1 / (1 + exp(-somatorio));
}
/**
* Aplica o processo de feedforward com os inputs especificados
* @param input entrada pro feedforward
* @return saída gerada pela rede após propagar pelas camadas
*/
double feedForward(double* input)
{
double* output_entrada = feed(rede->entrada, input);
double* output_oculta = feed(rede->oculta, output_entrada);
return feed(rede->saida, output_oculta)[0];
}
/**
* Faz o processo de feedforward pra camada utilizando as features de entrada
* @param camada ponteiro pra camada a qual fazer o processo
* @param features entrada do feedforward
* @return o vetor de saída do feedforward dado a entrada, pra esta camada
*/
double* feed(Camada* camada, double* features)
{
double* out = (double*) malloc(sizeof(double) * camada->qt_neuronios);
if (features == NULL)
return NULL;
for (int i = 0; i < camada->qt_neuronios; i++)
{
// para cada neuronio desta camada
for (int j = 0; j < camada->qt_entradas; j++)
{
// para cada entrada deste neuronio, atribuimos ela a feature
camada->neuronios[i]->p[j] = features[j];
}
double somatorio = getSomatorio(camada->neuronios[i]);
double logistic = funcaoLogistica(somatorio);
camada->neuronios[i]->s = logistic;
out[i] = logistic;
}
return out;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment