Redes profundas

Anuncio
Práctica de redes profundas
Vamos a probar una red profunda para nuestro problema de las casas. Vamos a elegir la
siguiente arquitectura: 13 entradas, 10 procesadores en la primera capa oculta, 8 en la segunda,
5 en la tercera, 3 en la cuarta y el de salida.
Matlab
Analizaremos los siguientes casos:
1. Ninguna precaución
2. Ajuste detenido por conjunto de validación
3. Penalización de valor de pesos (hipótesis de pesos nulos con varianza general)
4. Regresión bayesiana (varianza adaptada)
5. Penalizar el exceso de activación en los procesadores ocultos
6. Desactivar aleatoriamente los procesadores ocultos durante el ajuste
7. Utilizar autocodicadores para la inicialización
Para los casos 1 a 4 utilizaremos la toolbox propia de Matlab. Para los casos 5 a 7 usaremos
la toolbox de DeepLearning. Aquí vamos dando las indicaciones propias de cada caso, pero ten
presente que el criterio de comparación no puede ser el error residual de ajuste, ni siquiera el
de prueba, sino que debes reinicializar el proceso varias veces y mirar la estadística de error en
el conjunto de prueba.
1. No podemos usar las herramientas grácas, porque van automáticamente el caso 2
red1=fitnet([10 8 5 3]);
red1.divideParam.valRatio=0;
[red1,tr]=train(red1,p,t);
Vigila el valor de Performance y cuando lleve un rato que no progresa detén el ajuste, o
si no se acaba de parar, déjalo llegar a las 1000 iteraciones. Mira el resultado del gráco
de regresión y anota el R² del conjunto de prueba. Para hacer la siguiente prueba:
red1=init(red1);
[red1,tr]=train(red1,p,t);
Repite varias veces hasta tener una cierta estadística del resultado en el conjunto de
prueba.
2. Para el caso inicial usaremos el gradiente conjugado. En este caso, déjalo que pare por sí
mismo.
red2=fitnet([10 8 5 3],'trainscg');
[red2,tr]=train(red2,p,t);
La reinicialización es igual.
3. Tenemos que cambiar la función de medida y no podemos usar Levemberg-Marquardt,
porque no lo admite; aquí se propone el método de cuasi-Newton. El valor de la regularización puedes jugar con él. En todo caso, con el valor que te quedes haz varias pruebas
y páralo cuando el error no progrese o déjalo llegar a las 1000 iteraciones.
red3=fitnet([10 8 5 3],'trainbfg');
red3.divideParam.valRatio=0;
red3.performFcn = 'msereg';
red3.performParam.ratio = 0.5;
[red3,tr]=train(red3,p,t);
4. Es una variante del caso 1, pero usando la función de ajuste especialmente diseñada al
efecto. Además, no separa conjunto de prueba automáticamente, por lo que tenemos que
hacerlo aparte.
red4=fitnet([10 8 5 3],'trainbr');
[ajind,valind,pruind]=dividerand(506,0.7,0,0.15);
paj=p(:,ajind);
taj=t(ajind);
ppru=p(:,pruind);
tpru=t(pruind);
[red4,tr]=train(red4,paj,taj);
redpru=red4(ppru);
plotregression(tpru,redpru);
En cada reinicialización hay que repetir la partición de la muestra, es decir:
[ajind,valind,pruind]=dividerand(506,0.7,0,0.15);
paj=p(:,ajind);
taj=t(ajind);
ppru=p(:,pruind);
tpru=t(pruind);
red4=init(red4);
[red4,tr]=train(red4,paj,taj);
redpru=sim(red4,ppru);
plotregression(tpru,redpru);
5. Nuevamente tenemos que hacer a mano la división de la muestra y además tenemos que
hacer el escalado a 0-1. Lo siguiente supone que tenemos los directorios de la toolbox de
DeepLearning en nuestra ruta. Suele dar mejor resultado empezar el descenso gradiente
estocástico con paso individual. Puedes jugar con los parámetros, pero con la jugada que
te quedes, mídela varias veces.
maxp=max(p');
maxt=max(t);
pesc=p./repmat(maxp',1,506);
tesc=0.1+0.8*t/maxt;
[ajind,valind,pruind]=dividerand(506,0.85,0,0.15);
paj=pesc(:,ajind);
taj=tesc(ajind);
ppru=pesc(:,pruind);
tpru=t(pruind);
red5 = nnsetup([13 10 8 5 3 1]);
red5.nonSparsityPenalty=0.1;
red5.sparsityTarget = 0.25;
opc.numepochs = 10;
opc.batchsize = 1;
red5 = nntrain(red5, paj', taj', opc);
opc.numepochs = 200;
opc.batchsize = 10;
red5 = nntrain(red5, paj', taj', opc);
red5=nnff(red5,ppru',tpru');
redpru=red5.a{end};
redpru=(redpru-0.1)*maxt/0.8;
plotregression(tpru,redpru);
Para cada siguiente prueba repetimos los comandos desde dividerand
6. Parecido al anterior, cambiando los parámetros. Este método y el anterior van bien con
capas aún mayores (del orden del centenar de procesadores), pero podemos plantear una
fracción pequeña.
maxp=max(p');
maxt=max(t);
pesc=p./repmat(maxp',1,506);
tesc=0.1+0.8*t/maxt;
[ajind,valind,pruind]=dividerand(506,0.85,0,0.15);
paj=pesc(:,ajind);
taj=tesc(ajind);
ppru=pesc(:,pruind);
tpru=t(pruind);
red6 = nnsetup([13 10 8 5 3 1]);
red6.learningRate = 1;
red6.dropoutFraction = 0.05;
opc.numepochs = 20;
opc.batchsize = 1;
red6 = nntrain(red6, paj', taj', opc);
opc.numepochs = 100;
opc.batchsize = 10;
red6 = nntrain(red6, paj', taj', opc);
red6.dropoutFraction = 0;
red6=nnff(red6,ppru',tpru');
redpru=red6.a{end};
redpru=(redpru-0.1)*maxt/0.8;
plotregression(tpru,redpru);
7. Ahora se trata de crear los autocodicadores primero y luego construir con ellos el perceptrón, con una pasada de ajuste nal, que afecte sólo a una parte de los pesos. En esta
propuesta, se le deja tocar las dos últimas capas. También es fácil de hacer y da buenos
resultados, dejar ajustar sólo los pesos independientes de todas las capas y jar el resto
de pesos de todas las capas menos la de salida. En cualquier caso, pararemos el ajuste
cuando veamos que el error se estabiliza
maxp=max(p');
maxt=max(t);
pesc=p./repmat(maxp',1,506);
opc.batchsize=10;
opc.numepochs=20;
[ajind,valind,pruind]=dividerand(506,0.85,0,0.15);
paj=pesc(:,ajind);
taj=t(ajind);
ppru=pesc(:,pruind);
tpru=t(pruind);
autocod=saesetup([13 10 8 5 3]);
autocod.ae{1}.learningRate=1;
autocod.ae{2}.learningRate=1;
autocod.ae{3}.learningRate=1;
autocod.ae{4}.learningRate=1;
autocod=saetrain(autocod,paj',opc);
red7=fitnet([10 8 5 3]);
red7.layers{1}.transferFcn='logsig';
red7.layers{2}.transferFcn='logsig';
red7.layers{3}.transferFcn='logsig';
red7.layers{4}.transferFcn='logsig';
red7=configure(red7,paj,taj);
red7=init(red7);
red7.divideFcn='dividetrain';
red7.IW{1}=autocod.ae{1}.W{1};
red7.inputWeights{1}.learn=false;
red7.LW{2,1}=autocod.ae{2}.W{1};
red7.layerWeights{2,1}.learn=false;
red7.LW{3,2}=autocod.ae{3}.W{1};
red7.layerWeights{3,2}.learn=false;
red7.LW{4,3}=autocod.ae{4}.W{1};
red7.b{1}=autocod.ae{1}.b{1};
red7.biases{1}.learn=false;
red7.b{2}=autocod.ae{2}.b{1};
red7.biases{2}.learn=false;
red7.b{3}=autocod.ae{3}.b{1};
red7.biases{3}.learn=false;
red7.b{4}=autocod.ae{4}.b{1};
[red7,tr]=train(red7,paj,taj);
redpru=red7(ppru);
plotregression(tpru,redpru);
Como anteriormente, cada repetición la hacemos desde dividerand
Octave
Analizaremos los siguientes casos:
1. Ninguna precaución
2. Penalización de valor de pesos (hipótesis de pesos nulos con varianza general)
3. Penalizar el exceso de activación en los procesadores ocultos
4. Desactivar aleatoriamente los procesadores ocultos durante el ajuste
5. Utilizar autocodicadores para la inicialización
No utilizaremos netlab porque sólo está preparada para una capa oculta. Usaremos la toolbox
de DeepLearning, así que tendremos sus directorios en nuestra ruta 1 . Aquí vamos dando las
indicaciones propias de cada caso, pero ten presente que el criterio de comparación no puede
ser el error residual de ajuste, ni siquiera el de prueba, sino que debes reinicializar el proceso
varias veces y mirar la estadística de error en el conjunto de prueba.
1. red1 = nnsetup([13 10 8 5 3 1]);
% Constante del método de gradiente
%Se puede jugar. Puede ser más alto
red1.learningRate = 1;
% Número de pasadas
%Lo puedes aumentar según tu paciencia
opts.numepochs = 100;
%
Cada cuantos casos aplica optimización.
1 addpath(genpath('...DeepLearnToolbox'))
%Tiene que ser divisor de los que haya en la muestra de ajuste
opts.batchsize = 57;
%Para regular la salida
opts.silent = 1;
red1 = nntrain(red1, p, t, opts);
red1=nnff(red1,pprueba,tprueba);
salidas1=red1.a{red1.n};
Mira el resultado grácamente y anota el R² del conjunto de prueba. Repite varias veces
hasta tener una cierta estadística del resultado.
2. Es como el anterior, pero añadiendo red2.weightPenaltyL2 = 0.001;. El valor de la
regularización puedes jugar con él. En todo caso, con el valor que te quedes haz varias
pruebas.
3. Vamos a ver una estrategia que suele dar buen resultado: empezar el descenso gradiente
estocástico con paso individual. En la toolbox de DeepLearning no disponemos más que de
este algoritmo. Puedes jugar con los parámetros, pero con la jugada que te quedes, mídela
varias veces. Como la red que tenemos no tiene tantos procesadores, vamos a aumentarla
y a penalizarla si usa para un mismo caso toda la capa. Por ejemplo: cuadruplicamos el
tamaño y le ponemos como objetivo que sólo use la cuarta parte cada vez (pero no va a
ser el mismo cuarto en cada caso).
red3 = nnsetup([13 40 32 20 12 1]);
red3.nonSparsityPenalty=0.2;
red3.sparsityTarget = 0.25;
opc.numepochs = 10;
opc.batchsize = 1;
red3 = nntrain(red3, p, t, opc);
opc.numepochs = 200;
opc.batchsize = 8;
red3 = nntrain(red3, p, t, opc);
red3=nnff(red3,pprueba,tprueba);
4. Parecido al anterior, cambiando los parámetros. Este método y el anterior van bien con
capas aún mayores (del orden del centenar de procesadores), pero lo planteamos para que
lo veas.
red4 = nnsetup([13 20 16 10 6 1]);
red4.learningRate = 1;
red4.dropoutFraction = 0.5;
opc.numepochs = 20;
opc.batchsize = 1;
red4 = nntrain(red4, p, t, opc);
opc.numepochs = 100;
opc.batchsize = 8;
red4 = nntrain(red4, p, t, opc);
red4.dropoutFraction = 0; %El dropout era para constreñir el ajuste. En predicción
posterior no se usa
red4=nnff(red4,pprueba,tprueba);
5. Ahora se trata de crear los autocodicadores primero y luego construir con ellos el perceptrón, con una pasada de ajuste nal.
autocod=saesetup([13 10 8 5 3]);
autocod.ae{1}.learningRate=1;
autocod.ae{2}.learningRate=1;
autocod.ae{3}.learningRate=1;
autocod.ae{4}.learningRate=1;
autocod=saetrain(autocod,p,opc);
red5 = nnsetup([13 10 8 5 3 1]);
red5.W{1}=autocod.ae{1}.W{1};
red5.W{2}=autocod.ae{2}.W{1};
red5.W{3}=autocod.ae{3}.W{1};
red5.W{4}=autocod.ae{4}.W{1};
red5.b{1}=autocod.ae{1}.b{1};
red5.b{2}=autocod.ae{2}.b{1};
red5.b{3}=autocod.ae{3}.b{1};
red5.b{4}=autocod.ae{4}.b{1};
red5.learningRate = 0.1; % o lo que pruebes
opts.numepochs = 200;
opts.batchsize = 57; %divisor del cardinal de muestra de ajuste
opts.silent = 1;
red5 = nntrain(red5, p, t, opts);
red5=nnff(red5,pprueba,tprueba);
salidas5=red5.a{red5.n};
Descargar