Skip to content

Instantly share code, notes, and snippets.

@pxpc2
Created June 27, 2019 21:25
Show Gist options
  • Save pxpc2/c8a9115f9d6bccfc96119a4f746bff53 to your computer and use it in GitHub Desktop.
Save pxpc2/c8a9115f9d6bccfc96119a4f746bff53 to your computer and use it in GitHub Desktop.
oi
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include "glcm.h"
#define MAX 1025*1025
/**
* código do PROJETO 2, nada foi alterado.
* Basta incluir o header deste .c na main do PROJETO 6
* Lá chamamos o getFeaturesImg e o gerarNumerosAleatorio
*/
void exec()
{
int* nums = gerarNumerosAleatorio();
double* media_grass = (double *) calloc(536, sizeof(double));
double* media_asphalt = (double *) calloc(536, sizeof(double));
double* features_grass = (double *) calloc(536, sizeof(double));
double* features_asphalt = (double *) calloc(536, sizeof(double));
// TREINAMENTO
for (int i = 0; i < 25; i++)
{
features_grass = getFeaturesImg(nums[i], 0);
features_asphalt = getFeaturesImg(nums[i], 1);
for (int j = 0; j < 536; j++)
{
*(media_grass + j) += (*(features_grass + j) / 25.0);
*(media_asphalt + j) += (*(features_asphalt + j) / 25.0);
}
}
double taxa_acerto = 0.0, taxa_Faceitacao = 0.0, taxa_Frejeicao = 0.0;
// TESTE
for (int i = 25; i < 50; i++)
{
features_grass = getFeaturesImg(*(nums + i), 0);
features_asphalt = getFeaturesImg(*(nums + i), 1);
/* // comparar com as médias calculadas no treinamento
int dist_grass = compararImagem(media_grass, media_asphalt, features_grass);
if (dist_grass == 1) taxa_acerto++;
else if (dist_grass == 0) taxa_Frejeicao++;
int dist_asphalt = compararImagem(media_grass, media_asphalt, features_asphalt);
if (dist_asphalt == 1) taxa_Faceitacao++;
else if (dist_asphalt == 0) taxa_acerto++; */
}
free(features_grass);
free(features_asphalt);
free(media_grass);
free(media_asphalt);
free(nums);
/* double acerto = (double) (taxa_acerto / 50.0) * 100.0;
double f_aceitacao = (double) (taxa_Faceitacao / 50.0) * 100.0;
double f_rejeicao = (double) (taxa_Frejeicao / 50.0) * 100.0;
printf("TAXA DE ACERTO = %.1lf%%\n", acerto);
printf("TAXA DE FALSA ACEITAÇÃO = %.1lf%%\n", f_aceitacao);
printf("TAXA DE FALSA REJEIÇÃO = %.1lf%%\n", f_rejeicao);*/
}
/**
type 0 = grass
type 1 = asphalt
*/
int* getMatriz(int num, int type)
{
char rota[40] = {};
if (type == 1)
sprintf(rota, "%s%02d%s", "DataSet/grass/grass_", num, ".txt");
else if (type == 0)
sprintf(rota, "%s%02d%s", "DataSet/asphalt/asphalt_", num, ".txt");
FILE *arq;
arq = fopen(rota, "r"); // r = somente leitura
if (arq == NULL)
{
printf("Deu ruim\n");
return NULL;
}
char texto[1025*4];
int i = 0, j = 0;
int* matriz = (int *) calloc(2000*2000, sizeof(int));
int count = 0;
while (fgets(texto, 1025*4, arq) != NULL)
{
j = 0;
const char remover[2] = ";";
char *token;
token = strtok(texto, remover);
int pixel = atoi(token);
matriz[i * 1025 + j] = pixel;
count++;
while (token != NULL)
{
token = strtok(NULL, remover);
if (token == NULL) continue;
j++;
pixel = atoi(token);
matriz[i * 1025 + j] = pixel;
count++;
}
i++;
}
fclose(arq);
return matriz;
}
int* getVetorILBP(int* matriz)
{
const int size = 1025; // tamanho da matriz do arquivo
int* vetorILBP = (int *) calloc(512, sizeof(int));
for(int s = 0; s < size*size; s++) // a ideia é passar por todos os pixels e pegar seus vizinhos
{
int mat[3][3] = {};
int soma = 0;
int matBin[3][3]={};
double media = 0.0;
int x_pixel, y_pixel; // posicao do pixel atual na matriz
if (s < size)
{
x_pixel = 0;
y_pixel = s;
}
else
{
x_pixel = s / size;
y_pixel = s % size;
}
if (x_pixel == 0 || y_pixel == 0 || x_pixel == 1024 || y_pixel == 1024)
continue; // não queremos trabalhar com os pixels das bordas
// cálculo dos vizinhos do pixel atual, jogando em mat[x][y] 3x3
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
int dx,dy;
dx = x_pixel + i, dy = y_pixel + j;
mat[i+1][j+1] = *(matriz + dx * 1025 + dy);
soma += mat[i+1][j+1];
}
}
int palavraBin[9];
media = (double) soma / 9.0;
int d = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (mat[i][j] < media)
matBin[i][j] = 0;
else
matBin[i][j] = 1;
palavraBin[d] = matBin[i][j];
d++;
}
}
// pegar o menor valor das rotações da palavra binária, o código ILBP
int menor = 9999999, j = 9;
int aux[9];
while (j--)
{
// 9 rotações possíveis
for (int i = 0; i < 9; i++)
{
int auxx = palavraBin[i];
if (i == 0)
aux[i] = palavraBin[8];
else
aux[i] = palavraBin[i-1];
if (i == 8)
aux[0] = auxx;
else
aux[i+1] = auxx;
}
// calcular valor decimal
int decimal = 0;
for (int i = 0; i < 9; i++)
decimal += aux[i] * pow(2, 8-i);
for (int i =0; i < 9; i++)
palavraBin[i] = aux[i];
if (decimal < menor) menor = decimal;
}
*(vetorILBP + menor) += 1; // faz a contabilidade do vetor ILBP
}
return vetorILBP;
}
int repete(int* vetor, int num)
{
for (int i = 0; i < 50; i++)
if (vetor[i] == num)
return 1;
return 0;
}
/**
Gerar 25 números aleatórios e preencher o resto com o que falta, pra
compor os conjuntos TESTE e TREINAMENTO
*/
int* gerarNumerosAleatorio()
{
int* nums = (int*) calloc(50, sizeof(int));
srand(time(0));
for (int i = 0; i < 25; i++)
{
int n = rand() % 50 + 1;
if (repete(nums, n) == 1)
{
i--; // repetir essa iteração
continue;
}
*(nums + i) = n;
}
int j = 25;
for (int i = 1; i <= 50; i++)
{
if (repete(nums, i) == 1) continue;
nums[j] = i;
j++;
}
return nums;
}
/**
(dx, dy)
(0, 0) = pixel inicial
(0, 1) = acima
(0, -1) = abaixo
(1, 0) = direita
(1, 1) = diagonal direita cima
(1, -1) = diagonal direita baixo
(-1, 0) = esquerda
(-1, 1) = diagonal esquerda cima
(-1, -1) = diagonal esquerda baixo
*/
double* getMatrizGLCM(int* matriz, int dx, int dy)
{
double* glcm = (double *) calloc(256*256, sizeof(double));
int size = 1025, x1, y1, x2, y2;
for (int s = 0; s < size*size; s++) // passar por todos os pixels
{
if (s < size)
{
x1 = 0;
y1 = s;
}
else
{
x1 = s / size;
y1 = s % size;
}
x2 = x1 + dx;
y2 = y1 + dy;
if (x2 < 0 || y2 < 0 || x2 > 1024 || y2 > 1024)
continue; // pular esta iteração pois não há pixel nessa direção
int indice1 = matriz[x1 * 1025 + y1];
int indice2 = matriz[x2 * 1025 + y2];
*(glcm + (indice1 * 256) + indice2) += 1;
}
return glcm;
}
double* getMetricas(double* glcm, int* matriz, int dx, int dy)
{
double contraste = 0.0, homog = 0.0, energia = 0.0;
double* metricas = (double *) calloc(3, sizeof(double));
int size = 1025, x1, y1, x2, y2;
for (int s = 0; s < size*size; s++) // passar por todos os pixels
{
if (s < size)
{
x1 = 0;
y1 = s;
}
else
{
x1 = s / size;
y1 = s % size;
}
x2 = x1 + dx;
y2 = y1 + dy;
if (x2 < 0 || y2 < 0 || x2 > 1024 || y2 > 1024)
continue; // pular esta iteração pois não há pixel nessa direção
int indice1 = *(matriz + x1 * 1025 + y1);
int indice2 = *(matriz + x2 * 1025 + y2);
double prob_glcm = (double) glcm[indice1*256 + indice2] / (1025*1025);
//printf("PROB = %lf\n", prob_glcm);
int mod = abs(indice1-indice2);
contraste += prob_glcm * pow(mod, 2);
homog += prob_glcm / (1 + mod);
energia += pow(prob_glcm, 2);
}
*(metricas + 0) = contraste;
*(metricas + 1) = homog;
*(metricas + 2) = energia;
return metricas;
}
double* getFeaturesImg(int num, int type)
{
double* features = (double *) calloc(536, sizeof(double));
int* matriz;
int* ilbp;
double* glcm[8];
// Pegar a matriz da imagem atual
matriz = getMatriz(num, type);
// Realizar o ILBP da imagem atual
ilbp = getVetorILBP(matriz); // vetor de 512 posições
// Pegar os 8 GLCMs da imagem atual
// Cada métrica pra cada uma das 8 GLCMs
double* contraste = (double *) calloc(8, sizeof(double));
double* homog = (double *) calloc(8, sizeof(double));
double* energia = (double *) calloc(8, sizeof(double));
int cont = 0;
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
if (i == 0 && j == 0) continue; // não precisa fazer GLCM pro próprio pixel atual
// faz o GLCM da direção atual i,j
glcm[cont] = getMatrizGLCM(matriz, i, j);
double* metricas = getMetricas(glcm[cont], matriz, i, j);
*(contraste + cont) = *(metricas + 0);
*(homog + cont) = *(metricas + 1);
*(energia + cont) = *(metricas + 2);
cont++;
}
}
int i = 0;
for (i = 0; i < 512; i++)
*(features + i) = (double) *(ilbp + i);
for (i = 512; i < 520; i++)
*(features + i) = (double) *(contraste + (i-512));
for (i = 520; i < 528; i++)
*(features + i) = (double) *(homog + (i-520));
for (i = 528; i < 536; i++)
{
*(features + i) = (double) *(energia + (i - 528));
// printf("ENERGIA=%lf\n", (double) *(energia + (i - 528)));
}
normalizar(features);
return features;
}
void normalizar(double* vetor)
{
int maior = 0, menor = 9999999;
for (int i = 0; i < 536; i++)
{
double element = *(vetor + i);
if (element == 0.0) continue;
if (element < menor)
menor = element;
if (element > maior)
maior = element;
}
for (int i = 0; i < 536; i++)
{
double element = *(vetor + i);
*(vetor + i) = (double) (element - menor) / (maior - menor);
}
}
/**
* return 1 -> parece mais com grama
* return 0 -> parece mais com asfalto
*/
int compararImagem(double* media_grass, double* media_asphalt, double* vetor)
{
int result_grass = 0, result_asphalt = 0;
for (int i = 0; i < 536; i++)
{
result_grass += pow(*(vetor + i) - *(media_grass + i), 2);
result_asphalt += pow(*(vetor + i) - *(media_asphalt + i), 2);
}
result_grass = sqrt(result_grass);
result_asphalt = sqrt(result_asphalt);
return (result_grass < result_asphalt) ? 1 : 0;
}
int* getMatriz(int, int);
int* getVetorILBP(int*);
int repete(int*, int);
int* gerarNumerosAleatorio();
double* getMatrizGLCM(int*, int, int);
double* getMetricas(double*, int*, int, int);
double* getFeaturesImg(int, int);
void normalizar(double*);
/**
* código do PROJETO 2, nada foi alterado.
* Basta incluir este header e seu .c na main do PROJETO 6
* Lá chamamos o getFeaturesImg e o gerarNumerosAleatorio
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "rede.h"
#include "glcm.h"
int main(int argc, char* argv[])
{
// gera os 50 numeros das imagens, onde os 25 primeiros sao pro treinamento e os ultimos pro teste.
int* nums = gerarNumerosAleatorio();
// pega o valor definido pra qt de neuronios em runtime, se nada for definido o padrao serão 10 neuronios
int qt_oculta = (argc < 2? 10 : atoi(argv[1]));
// inicializa as camadas e seus neuronios
initRede(qt_oculta);
srand(time(NULL));
double taxa_acerto = 0.0, taxa_falsa_rejeicao = 0.0, taxa_falsa_aceitacao = 0.0;
printf("Calculando...\n");
int epoca = 0;
while (epoca < 1000)
{
printf("Iniciando epoca #%d\n", epoca+1);
epoca++;
double mse = 0.0;
for (int i = 0; i < 25; i++) // conjunto treinamento
{
int type = rand() % 2; // aleatoriamente escolhe se vai ser grass ou asphalt
if (type % 2)
type = 1;
else
type = 0;
double *feature = getFeaturesImg(nums[i], type); // 1 = grass, 0 = asphalt
double output_saida = feedForward(feature);
mse += pow(type - output_saida, 2);
backPropagate(type); // faz os ajustes dos pesos e biases
printf("...\n");
}
printf("Fim epoca\n");
mse /= 25;
if (mse < 0.2)
break;
}
printf("Iniciando o teste\n");
for (int i = 25; i < 50; i++) // TESTE
{
int type = rand() % 2; // aleatoriamente escolhe se vai ser grass ou asphalt
if (type % 2)
type = 1;
else
type = 0;
double *feature = getFeaturesImg(nums[i], type); // 1 = grass, 0 = asphalt
double output_saida = feedForward(feature);
if ((output_saida > 0.5 && type == 1) || (output_saida < 0.5 && type == 0))
taxa_acerto++;
else if (output_saida > 0.5 && type == 0)
taxa_falsa_aceitacao++;
else if (output_saida < 0.5 && type == 1)
taxa_falsa_rejeicao++;
}
freeTodos(); // libera todos os ponteiros alocados da memoria
printf("Taxa acerto = %.1lf%%\n", (taxa_acerto / 25.0) * 100.0);
printf("Taxa falsa aceitacao = %.1lf%%\n", (taxa_falsa_aceitacao / 25.0) * 100.0);
printf("Taxa falsa rejeicao = %.1lf%%\n", (taxa_falsa_rejeicao / 25.0) * 100.0);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "rede.h"
#define QT_ENTRADA 536 // quantidade de neurônios na camada entrada
#define LEARNING_RATE 0.3 // definida aleatoriamente
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;
rede->entrada->def = 0;
rede->entrada->sinal_saida = (double*) malloc(sizeof(double) * 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;
rede->oculta->def = 1;
rede->oculta->sinal_saida = (double*) malloc(sizeof(double) * qt_oculta);
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->def = 2;
rede->saida->qt_entradas = qt_oculta;
rede->saida->sinal_saida = (double*) malloc(sizeof(double) * 1);
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 a derivada da função sigmoide
* @param input entrada
* @return resultado da função sigmoide derivada pra este input
*/
double derivadaSigmoide(double input)
{
double r = funcaoLogistica(input);
return (r * (1 - r));
}
/**
* 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;
}
camada->sinal_saida = out;
return out;
}
/**
* Realiza o cálculo do custo, somatorio do resultado (esperado - saída)^2 pra cada
* neuronio de cada camada, e seta os erros pra cada neuronio
* @param expected resultado esperado
*/
void setCusto(int expected)
{
double custo = 0.0, error;
for (int i = 0; i < rede->entrada->qt_neuronios; i++)
{
error = expected - rede->entrada->neuronios[i]->s;
rede->entrada->neuronios[i]->erro = error;
custo += pow(error, 2);
}
for (int i = 0; i < rede->oculta->qt_neuronios; i++)
{
error = expected - rede->oculta->neuronios[i]->s;
rede->oculta->neuronios[i]->erro = error;
custo += pow(error, 2);
}
error = expected - rede->saida->neuronios[0]->s;
rede->saida->neuronios[0]->erro = error;
custo += pow(error, 2);
rede->custo = custo;
}
/**
* Realiza o cálculo dos gradientes de acordo com o referêncial bibliográfico
* Como o gradiente de cada neuronio da camada oculta depende dos gradientes da saída
* utilizamos recurssão
* @param c camada pra calcular os gradientes
* @return vetor de gradientes da camada c
*/
double* getGradiente(Camada* c)
{
double* gradientes = (double*) malloc(sizeof(double) * c->qt_neuronios);
if (c->def == 1 || c->def == 0)
{
for (int i = 0; i < c->qt_neuronios; i++)
{
// usamos recurssividade pra calcular os gradientes da camada oculta
for (int j = 0; j < (c->def == 1? rede->saida->qt_neuronios : rede->oculta->qt_neuronios); j++)
gradientes[i] += getGradiente((c->def == 1? rede->saida : rede->oculta))[j]*
c->def == 1? rede->saida->neuronios[j]->s : rede->oculta->neuronios[j]->w[j];
gradientes[i] *= derivadaSigmoide(c->neuronios[i]->s);
c->neuronios[i]->gradiente = gradientes[i];
}
}
else if (c->def == 2)
{
for (int i = 0; i < c->qt_neuronios; i++)
{
gradientes[i] = derivadaSigmoide(c->neuronios[i]->s) * c->neuronios[i]->erro;
rede->saida->neuronios[i]->gradiente = gradientes[i];
}
return gradientes;
}
return gradientes;
}
void setGradientes()
{
getGradiente(rede->entrada);
getGradiente(rede->oculta);
getGradiente(rede->saida);
}
/**
* Realiza o ajuste dos pesos após realizar o calculo dos gradientes
* @param camada camada dos pesos pra ajustar
*/
void ajustarPesos(Camada* camada)
{
if (camada->def == 0)
return; // não fazemos operações com a camada de entrada
for (int i = 0; i < camada->qt_neuronios; i++)
{
for (int j = 0; j < camada->neuronios[i]->p_length; j++)
{
double saida_anterior = 0.0;
if (camada->def == 1)
saida_anterior = rede->entrada->neuronios[j]->s;
else if (camada->def == 2)
saida_anterior = rede->oculta->neuronios[j]->s;
camada->neuronios[i]->w[j] = (camada->neuronios[i]->w[j]) +
(LEARNING_RATE * saida_anterior * camada->neuronios[i]->gradiente);
}
}
}
/**
* Realiza o ajuste do bias de cada neuronio
* @param camada camada pra ajustar
*/
void ajustarBias(Camada* camada)
{
if (camada->def == 0)
return; // não fazemos com a entrada
for (int i = 0; i < camada->qt_neuronios; i++)
camada->neuronios[i]->b = camada->neuronios[i]->b + (LEARNING_RATE * camada->neuronios[i]->gradiente);
}
void backPropagate(int type)
{
setCusto(type);
setGradientes();
ajustarPesos(rede->oculta);
ajustarPesos(rede->saida);
ajustarBias(rede->oculta);
ajustarBias(rede->saida);
}
/**
* Libera da memoria os neuronios da camada
* @param c camada pra liberar os seus neuronios
*/
void freeNeuronios(Camada* c)
{
for (int i = 0; i < c->qt_neuronios; i++)
{
free(c->neuronios[i]->p);
free(c->neuronios[i]->w);
free(c->neuronios[i]);
}
free(c->neuronios);
}
/**
* Libera todos os ponteiros alocados dinamicamente na memoria
*/
void freeTodos()
{
freeNeuronios(rede->entrada);
freeNeuronios(rede->oculta);
freeNeuronios(rede->saida);
free(rede->entrada->sinal_saida);
free(rede->oculta->sinal_saida);
free(rede->saida->sinal_saida);
free(rede->entrada);
free(rede->oculta);
free(rede->saida);
free(rede);
}
typedef struct neuronio
{
double* p; // conjunto de entradas deste neuronio
double* w; // conjunto de pesos deste neuronio
double b; // bias deste neuronio
double s; // saida deste neuronio
int p_length; // quantidade de entradas
double erro; // erro para propagar deste neuronio
double gradiente; // gradiente deste neuronio para o backpropagation
} Neuronio;
typedef struct camada
{
int def;
Neuronio** neuronios; // conjunto de ponteiros dos neuronios dessa camada
int qt_neuronios; // quantidade de neuronios presente na camada
int qt_entradas; // quantidade de entradas por neuronio da camada
double* sinal_saida;
} Camada;
typedef struct rede
{
Camada* entrada; // primeira camada da rede, com 536 neuronios
Camada* oculta; // camada oculta, quantidade de neuronios definida runtime
Camada* saida; // ultima camada, com somente 1 neuronio
double custo; // custo da rede com pesos e bias atuais
} Rede;
// inicializa a rede e suas camadas
void initRede(int);
// inicializa cada neuronio de uma camada (gerando os pesos e bias aleatorios)
void initNeuronios(Camada*,int);
// gera pesos aleatorios
double* gerarPesos(int);
// gera um bias aleatorio
double gerarBias();
// pega o somatorio do produto pesos por entradas, somando com o bias
double getSomatorio(Neuronio*);
// pega a saída de um neuronio usando a funcao logistica sigmoid
double funcaoLogistica(double);
// faz o processo de feedforward chamando a funcao feed
double feedForward(double*);
// realiza o processo de atribuir entradas ao neuronio e calcular sua saída
double* feed(Camada*,double*);
// faz o calculo do somatorio do custo de cada neuronio
void setCusto(int);
// joga o valor na derivada da fç sigmoide, para calculo do gradiente do neuronio
double derivadaSigmoide(double);
// chama as funcoes do backpropagation
void backPropagate(int);
// faz o processo de calcular os gradientes pra cada camada
void setGradientes();
// realiza os calculos para pegar o gradiente de cada neuronio
double* getGradiente(Camada*);
// realiza o ajuste dos pesos com os novos gradientes
void ajustarPesos(Camada*);
// realiza o ajuste de cada bias com os novos gradientes
void ajustarBias(Camada*);
// libera da memoria todos os neuronios
void freeNeuronios(Camada*);
// libera da memoria o resto dos ponteiros
void freeTodos();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment