% APRENDIZAJE AUTOMÁTICO (Gonzalo Pajares y Jesús M. de la Cruz, Eds.)
% Editorial: RA-MA
% Capítulo 4: Redes Neuronales Artificiales
% Autores: José Antonio López Orozco



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%  SELECCIÓN DEL EJEMPLO %%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Ejemplo: 
% 0 : Con XOR de dos entradas
% 2 : Fourier: Con el archivo de prueba puntos.txt
% 3 : Ejemplo clasificación puntos (archivo entrena3)

Ejemplo=0

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%  PREPARACIÓN DE LOS DATOS DE ENTRADA Y PARÁMETROS DE LA RED %%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


if Ejemplo==0,  % ----- XOR de dos entradas -----
   patrones=[0 0;0 1;1 0;1 1]';
   salida=[0 1 1 0];
   validacion=[];
   
   alpha = 0.3 
   beta = 0.7;
   errorCuadraticoMedioMaximo = 0.01;
   iterMax=1000;
   Pesos0=[];

   NeuOcultas=2;
   funsActivacion = 		['sigmoide';'sigmoide'];
   dersFunsActivacion=	['derSigmoide';'derSigmoide'];
end;

% ----------------------------------------------------
if Ejemplo==2,  % ----- Fourier: Con el archivo de prueba puntos.txt -----
datos=load('Ej1_puntos.txt');
patrones=datos(:,1)';
salida=datos(:,2)';
validacion=load('Ej1_puntosVal.txt');

[numEntradas, numPatrones] = size(patrones);
[numSalidas, numPatrones] = size(salida);
NeuOcultas=25;%20; %15;%5;%10;
topologia = [numEntradas NeuOcultas numSalidas];
funsActivacion= 			['sin      ';'identidad'];
dersFunsActivacion=	['cos2       ';'derIdent2  '];
%funsActivacion= 			['sigmoide ';'identidad'];
%dersFunsActivacion=	['derSigmoide';'derIdent2  '];

alpha =0.0001; %0.0006; %0.006 %0.0001; %0.0001; %0.0006;%0.08; 
beta = 0.009;   %0.09;   %0.08; %0.009;  %0.03;   %0.003; %0.025;
errorCuadraticoMedioMaximo =0.05; %3;%0.05
iterMax= 3200; %90; %10000; %20000;%2000;%5000;%30000
Pesos0=1;%1233;%44;%1;%0.564; %2;

%Pruebas Funcion 1:
% alpha=0.007;beta=0.2;PEsos0=1 => sig, 10000: SIG1 (25 neuron)
% alpha=0.007;beta=0.2;PEsos0=1 => sig, 10000: SIG2 (30 neuron)
% alpha=0.007;beta=0.2;PEsos0=1 => sig, 90: SIG3 (30 neuron)
% alpha=0.007;beta=0.2;PEsos0=1 => sig, 90: SIG4 (25 neuron)
% alpha=0.0001;beta=0.009;PEsos0=1 => seno, 3000: SENO (25 neuron)
% alpha=0.0001;beta=0.009;PEsos0=1 => seno, 10000: SENO (25 neuron), sobreajuste


% Pruebas Funcion 2 (15 neuronas):
% alpha=0.05;beta=0.07;PEsos0=1
% alpha=0.0006;beta=0.08;PEsos0=1 => Seno, 10000 
% alpha=0.0006;beta=0.09;PEsos0=1 => Seno, 30000 
% alpha=0.006;beta=0.09;PEsos0=1 => sig, 30000: SIG1 
% alpha=0.003;beta=0.2;PEsos0=1 => sig, 30000: SIG2 
% alpha=0.003;beta=0.2;PEsos0=1 => sig, 10500: SIG2 

if (0),
Pesos0=zeros(15,16,2);
Pesos0(:,1:2,1)=[    0.0260   -0.0973         
   -0.0286   -0.1353         
   -0.1597    0.0580         
   -0.4097   -0.0990         
   -0.0697   -0.1305         
    0.2234   -0.0862         
   -0.3944   -0.3812         
   -0.1360   -0.1536         
    6.3056   -1.9802         
   -0.4499   -0.0951         
   -1.0825    0.9767         
    0.0227   -0.1654         
    0.3532   -0.2311         
    0.1826    0.2860         
    0.2277   -0.3658 ];
Pesos0(1,:,2)=[ 0.3556   -0.1398   -0.4267    0.1666    0.5331   -0.3525  0.0260   -0.4817    0.6595    3.6637    0.5147   -1.0247  -0.1203    1.1412    0.4370    0.1969];
end;

end;

% ----------------------------------------------------
if Ejemplo==3,  % ----- Ejemplo clasificación puntos (archivo entrena3) -----
   % Ejemplo con entrena3
   datos=load('entrena3');
   patrones=datos(:,1:2)';
   salida=datos(:,3)'-1;
   validacion=[];
   
   [numEntradas, numPatrones] = size(patrones);
   [numSalidas, numPatrones] = size(salida);
   NeuOcultas=2; %2; %3;
   
   funsActivacion = 	['sigmoide';'sigmoide'];
   dersFunsActivacion=	['derSigmoide';'derSigmoide'];

   alpha = 0.07; %0.6; %0.4;%0.2; 
   beta = 0.5; %0.4;%0.2;%0.1
   
   errorCuadraticoMedioMaximo = 0.5;
   iterMax= 4000 %5000;
   
   %Pesos0(:,:,1) =[   5.3413   -.53600  -1.49754
   %					  1.80		-.2180  -.345525];
   					  
   %Pesos0(:,:,2) =[    0.08078  -1.91694  1.32325 
   %                     0         0         0    ];                   
  
   % Ejemplo A:
   %Pesos0(:,:,1) =[   53.4137   -5.3600  -14.9754 
   %					  180		-21.8007  -34.5525];
  
   %Pesos0(:,:,2) =[    0.8078  -19.1694  13.2325 
   %                     0         0         0    ];
   
   % Ejemplo B
   Pesos0=1;  %1; %100; %5; %semilla
    
end;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%  ENTRENAMIENTO DE LA RED HACIA DELANTE  %%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   
[evolPesos,Ep,evolSalida] = bp_train(patrones,salida,validacion,NeuOcultas,funsActivacion,dersFunsActivacion,alpha,beta,errorCuadraticoMedioMaximo,iterMax,Pesos0);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%  REPRESENTACIÓN DE LOS RESULTADOS %%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

figure,plot(Ep);title('Evolución del e.c.m.');

switch Ejemplo,
   case 0,
       % ---------------------------------------------------------
[numEntradas, numPatrones] = size(patrones);
[numSalidas, numPatrones] = size(salida);
topologia = [numEntradas NeuOcultas numSalidas];
numCapas = length(topologia);

MaxPesos1=max([numEntradas, 1+numSalidas]);
MaxPesos2=max([numEntradas+1, NeuOcultas+1]);
PesosFIN=reshape(evolPesos(end,:),MaxPesos1,MaxPesos2,numCapas-1);

x=0:0.1:1;
% y = -w1o1/w2o1*x+ w0o1/w2o1;
k=1; Pw0=PesosFIN(k,1,1); Px=PesosFIN(k,2,1); Py=PesosFIN(k,3,1);
y1=-Px/Py.*x-Pw0/Py;
k=2; Pw0=PesosFIN(k,1,1); Px=PesosFIN(k,2,1); Py=PesosFIN(k,3,1);
y2=-Px/Py.*x-Pw0/Py;
ind0=find(salida==0);ind1=find(salida==1);
ptoX=patrones(1,:);ptoY=patrones(2,:);
%plot(patrones,salida,'bx',x,y1,x,y2)
figure;
plot(ptoX(ind0),ptoY(ind0),'bx',ptoX(ind1),ptoY(ind1),'ro',x,y1,x,y2)

salidaRed=Simredmcapa(topologia,PesosFIN,funsActivacion,patrones);
disp('Resultado (salida deseada /salida red):');
disp([salida;salidaRed]);
      
case 2,
       % ---------------------------------------------------------   
[numEntradas, numPatrones] = size(patrones);
[numSalidas, numPatrones] = size(salida);
topologia = [numEntradas NeuOcultas numSalidas];
numCapas = length(topologia);

MaxPesos1=max([numEntradas+1, NeuOcultas, numSalidas]);
MaxPesos2=max([numEntradas+1, NeuOcultas+1, numSalidas+1]);
PesosFIN=reshape(evolPesos(end,:),MaxPesos1,MaxPesos2,numCapas-1);

salidaRed=Simredmcapa(topologia,PesosFIN,funsActivacion,patrones);

entradas = [min(patrones)-2:0.1:max(patrones)+2];
salidas=Simredmcapa(topologia,PesosFIN,funsActivacion,entradas);

figure
plot(patrones,salida,'rx',patrones,salidaRed,'bo',entradas,salidas,'b')

title('Puntos obtenidos y función: real (x) - calculada (o)');

case 3,
       % ---------------------------------------------------------       
[numEntradas, numPatrones] = size(patrones);
[numSalidas, numPatrones] = size(salida);
topologia = [numEntradas NeuOcultas numSalidas];
numCapas = length(topologia);

MaxPesos1=max([numEntradas, NeuOcultas, numSalidas+1]);
MaxPesos2=max([numEntradas+1, NeuOcultas+1, numSalidas+1]);
PesosFIN=reshape(evolPesos(end,:),MaxPesos1,MaxPesos2,numCapas-1);

x=1:0.1:5;
for k=1:NeuOcultas,
    Pw0=PesosFIN(k,1,1); Px=PesosFIN(k,2,1); Py=PesosFIN(k,3,1);
    y(:,k)=-Px/Py.*x-Pw0/Py;
end;

ind1=find(salida==1);
ind0=find(salida==0);

datos=load('test31');
salida2=datos(:,3)'-1;
salidaRed1=Simredmcapa(topologia,PesosFIN,funsActivacion,patrones);
salidaRed2=Simredmcapa(topologia,PesosFIN,funsActivacion,datos(:,1:2)');

figure
subplot(1,2,1);
plot(patrones(1,ind0),patrones(2,ind0),'bo',patrones(1,ind1),patrones(2,ind1),'rx',x,y)
title('Elementos de entrenamiento y rectas');

ind1=find(salida2==1);
ind0=find(salida2==0);
subplot(1,2,2);
plot(datos(ind0,1),datos(ind0,2),'bo',datos(ind1,1),datos(ind1,2),'rx',x,y)
title('Elementos de test y rectas');

aciertos1=(abs(salida-salidaRed1)<0.3)';
aciertos2=(abs(salida2-salidaRed2)<0.3)';
disp('Resultado:');
disp('          (x,y) ------- Entrena --- Red  -- Aciertos --- Test -- Red -- Aciertos');
disp([datos(:,1),datos(:,2),salida' salidaRed1' aciertos1 salida2' salidaRed2' aciertos2]);
s=sprintf('Acierto: %5.2f %%     %5.2f %%',sum(aciertos1)/length(aciertos1)*100,sum(aciertos2)/length(aciertos2)*100);
disp(s);

end; %case  


