-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrbf.cpp
154 lines (124 loc) · 4.13 KB
/
rbf.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "rbf.h"
#include "util.h"
#include <fstream>
using namespace std;
RBF::RBF (int neuronas_capa_gaussiana, int neuronas_capa_salida, int n_entradas, float eta) {
capa_gaussiana.resize(neuronas_capa_gaussiana);
capa_salida.resize(
neuronas_capa_salida,
neurona(neuronas_capa_gaussiana, eta) // inicializacion de la neurona
);
ncg = neuronas_capa_gaussiana;
ncs = neuronas_capa_salida;
entradas = n_entradas;
// Inicializar los pesos de las neuronas de salida
for (int i = 0; i < neuronas_capa_salida; i++) {
capa_salida[i].inicializar();
}
}
vector<float> RBF::calcular_intermedio (vector<float> & entrada) {
vector<float> intermedio(ncg+1);
for (int i = 0; i < ncg; i++) {
intermedio[i] = capa_gaussiana[i].calcular(entrada);
}
intermedio[ncg] = 1; // entrada aumentada
return intermedio;
}
vector<float> RBF::calcular_salida_con_intermedio (vector<float> & intermedio) {
vector<float> salida(ncs);
for (int i = 0; i < ncs; i++) {
salida[i] = capa_salida[i].calcular(intermedio);
}
return salida;
}
vector<float> RBF::calcular_salida (vector<float> & entrada) {
vector<float> salida;
salida = calcular_intermedio(entrada);
salida = calcular_salida_con_intermedio(salida);
return salida;
}
void RBF::read (const char *filename) {
int n;
fstream file (filename, fstream::in);
file >> n;
input.resize(n, vector<float>(entradas));
result.resize(n, vector<float>(ncs));
for(int K=0; K<n; ++K){
for(int L=0; L<entradas; ++L){
file >> input[K][L];
file.ignore(); //csv o ssv funciona
}
for(int L=0; L<ncs; ++L){
file >> result[K][L];
file.ignore(); //csv o ssv funciona
}
}
}
void RBF::inicializar () {
int ind;
for (int i = 0; i < ncg; i++) {
ind = randomize(0, input.size() - 1);
capa_gaussiana[i].set_centroid(input[ind]);
}
}
void RBF::entrenar_capa_gaussiana () {
int ind;
bool cambio;
while (true) {
vector<vector<float> > centroides_acumulados(ncg, vector<float>(entradas, 0));
vector<int> cantidad_centroides(ncg, 0);
for (int i = 0; i < input.size(); i++) {
ind = centroide_mas_cerca(input[i]);
centroides_acumulados[ind] = sumar_vectores(centroides_acumulados[ind], input[i]);
cantidad_centroides[ind]++;
}
cambio = false;
for (int i = 0; i < ncg; i++) {
centroides_acumulados[i] = dividir_vector(centroides_acumulados[i], cantidad_centroides[i]);
// si el centroide cambia, actualizo la bandera
if (capa_gaussiana[i].set_centroid(centroides_acumulados[i])) cambio = true;
}
if (!cambio) break;
}
//TODO varianza
}
int RBF::entrenar_capa_salida (int cant_epocas, float acierto_minimo) {
vector<float> intermedio, salida_obtenida;
int epoca, aciertos;
for (epoca = 1; epoca <= cant_epocas; epoca++) {
aciertos = 0;
for (int i = 0; i < input.size(); i++) { // por cada patron de entrenamiento
intermedio = calcular_intermedio(input[i]);
salida_obtenida = calcular_salida_con_intermedio(intermedio);
if (comparar_vectores(salida_obtenida, result[i])) { // si acierta
aciertos++;
}
else { // si no son iguales, entreno las neuronas
for (int j = 0; j < ncs; j++) {
capa_salida[j].entrenar(intermedio, result[i][j] - salida_obtenida[j]);
}
}
}
// si el porcentaje de aciertos es el deseado, salgo
if ( (float(aciertos)/input.size()) >= acierto_minimo) break;
}
if (epoca <= cant_epocas) { // si convergio
return epoca;
}
else {
return -1;
}
}
int RBF::centroide_mas_cerca (vector<float> & punto) {
int i_min = 0;
float dist_min, dist;
dist_min = capa_gaussiana[0].distancia2(punto);
for (int i = 1; i < ncg; i++) {
dist = capa_gaussiana[i].distancia2(punto);
if (dist < dist_min) {
dist_min = dist;
i_min = i;
}
}
return i_min;
}