Created
June 27, 2019 00:46
-
-
Save pxpc2/c25b5dd31ead1f376b89b86e92f5eb2d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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