Reti neurali con Matlab

Rete Feed-forward con backpropagation

Prima di tutto è necessario definire come è fatta la rete:

  • numero di inputs (fissati dal problema),
  • numero di strati di neuroni,
  • numero di neuroni per ogni strato,
  • funzioni di trasferimento di ogni strato al successivo (o all'output),
  • selezionare l’algoritmo di apprendimento (ce n'è un certo numero),
  • vedere i valori minimi e massimi dei pattern di addestramento.

L’oggetto rete è la prima cosa da creare. Facciamo l'esempio dello XOR e cerchiamo di risolverlo con una rete di due strati, il primo strato con 2 neuroni (ciascuno con due input) ed il secondo (output) con un solo neurone, e prendiamo come funzione di trasferimento la funzione logistica (logsig).

L'oggetto rete si crea con il comando newff che contiene 4 elementi:

net = newff([0 1; 0 1], [2, 1], {'logsig', 'logsig'}, 'traingd');
  • [0 1; 0 1] sono i valori minimi e massimi dei pattern di addestramento.
  • [2, 1] sono rispettivamente il numero di neuroni nel primo strato e nel secondo strato.
  • {'logsig', 'logsig'} sono le funzioni di trasferimento del primo strato e del secondo strato.
  • 'traingd' è l'algoritmo di apprendimento scelto che è il "gradient descent".

Addestramento incrementale: la struttura dei dati è quella definita da p1 e t1. Se non è in quella forma, ma in forma batch, si può convertire alla forma incrementale con il comando:

p1 = num2cell(p, 1); 
t1 = num2cell(t, 1);

Ci sono molti parametri che possono essere definiti a valori diversi da quelli di default, in particolare il learning rate ed il numero di passi di addestramento:

net.adaptParam.lr = 0.02; 
net.adaptParam.passes = 200;

Il comando di addestramento è:

[net, a, e] = adapt(net, p1, t1);

Per la simulazione:

y = sim(net,p1);

Per inizializzare nuovamente la rete dopo un addestramento fallito basta il comando:

net = init(net);

Esempio più complicato

Vediamo ora un pattern recognition più complicato. Si consideri una distribuzione 'random' di punti interni ad un rettangolo di vertici (-1,-1) , (-1,1), (1,1), (1,-1). Si costruisca una rete feed-forward che riconosca i punti interni ad una circonferenza di centro (0,0) e raggio 0.5.

Generiamo prima i dati per l'addestramento ed la verifica. I seguenti comandi generano i pattern di addestramento:

x = rand(1, 5000)*2 - 1; y = rand(1, 5000)*2 - 1; 
kk = find(sqrt(x.^2 + y.^2) < 0.5); 
t = zeros(1, 5000); t(kk) = 1; 
plot(x ,y, '.', x(kk), y(kk), '.')

Il comando x = rand(1, 5000)*2 - 1; genera una distribuzione 'random' uniforme di numeri fra -1 e +1. Identicamente per la y. Il vettore t ha valore uno se il punto corrispondente è interno al cerchio, ed ha uno zero in corrispondenza degli altri punti. La corrispondenza da generare è quindi molto semplice, anche se una risposta binaria è difficile da generare con una rete FF.

I pattern di addestramento sono in P ed il target sarà T:

P = [x; y]; T = t;

Definiamo la rete Feed-Forward:

net = newff([0 1; 0 1], [4, 1], {'logsig', 'logsig'}, 'traingd');

Questo comando genera una rete con due input, 4 neuroni nel primo strato ed un neurone nel secondo strato (output).
Iniziamo l’addestramento con l’algoritmo di apprendimento "gradient descent" (traingd), devono essere inizializzati i valori del learning rate e del valore minimo dell’errore.

net.trainParam.lr = 0.2; 
net.trainParam.goal = 0.001; 
net.trainParam.epochs = 300; 

net = train(net, P, T);

MATLAB genera la risposta ed apre una finestra grafica che riporta l'andamento dell’errore.

TRAINGD, Epoch 0/300, MSE 0.295668/0.001, Gradient 0.052528/1e-010 
TRAINGD, Epoch 25/300, MSE 0.281624/0.001, Gradient 0.0534453/1e-010 
TRAINGD, Epoch 50/300, MSE 0.267218/0.001, Gradient 0.0537358/1e-010 
TRAINGD, Epoch 75/300, MSE 0.25302/0.001, Gradient 0.0524865/1e-010 
TRAINGD, Epoch 100/300, MSE 0.239988/0.001, Gradient 0.0492168/1e-010 
TRAINGD, Epoch 125/300, MSE 0.228942/0.001, Gradient 0.0444966/1e-010 
TRAINGD, Epoch 150/300, MSE 0.220134/0.001, Gradient 0.0392682/1e-010 
TRAINGD, Epoch 175/300, MSE 0.213375/0.001, Gradient 0.0341517/1e-010 
TRAINGD, Epoch 200/300, MSE 0.208305/0.001, Gradient 0.029475/1e-010 
TRAINGD, Epoch 225/300, MSE 0.204538/0.001, Gradient 0.0253984/1e-010 
TRAINGD, Epoch 250/300, MSE 0.201734/0.001, Gradient 0.0219594/1e-010
TRAINGD, Epoch 275/300, MSE 0.199625/0.001, Gradient 0.0191147/1e-010 
TRAINGD, Epoch 300/300, MSE 0.198015/0.001, Gradient 0.0167843/1e-010 
TRAINGD, Maximum epoch reached, performance goal was not met.

La precedente ci dice che, con l'algoritmo scelto, 300 epoche non sono sufficienti per l'addestramento. Si può continuare l'addestramento ripartendo da dove era arrivato dopo 300 epoche ripetendo il comando

net = train(net, P, T);

oppure si può cambiare algoritmo di apprendimento con il comando:

net.trainFcn = 'traincgf';

Questo algoritmo è quello dei gradienti coniugati con l’approssimazione di Polak-Ribiere. Alcune variabili sono automaticamente riinizializzate, alcune non servono. Sicuramente deve essere riinizializzato l’errore minimo (goal) ed il numero di epoche (il default è 100).

net.trainParam.goal = 0.001; 
net.trainParam.epochs = 100;

Il comando seguente inizia l’addestramento da dove era rimasto con il nuovo algoritmo.

net = train(net, P, T);

la rete risponde con:

TRAINCGF-srchcha, Epoch 0/100, MSE 0.191217/0.001, Gradient 0.00746413/1e-006 
TRAINCGF-srchcha, Epoch 25/100, MSE 0.102958/0.001, Gradient 0.00856038/1e-006 
TRAINCGF-srchcha, Epoch 50/100, MSE 0.0497994/0.001, Gradient 0.00209067/1e-006 
TRAINCGF-srchcha, Epoch 75/100, MSE 0.0451331/0.001, Gradient 0.00235278/1e-006 
TRAINCGF-srchcha, Epoch 100/100, MSE 0.0384347/0.001, Gradient 0.00430209/1e-006 
TRAINCGF, Maximum epoch reached, performance goal was not met.

Si vede che questo algoritmo migliora l'errore più rapidamente del precedente, anche se probabilmente non arriverà rapidamente all’errore minimo fissato.

Possiamo cambiare ancora algoritmo con quello Levenberg-Marquardt.

net.trainFcn = 'trainlm'; 
net.trainParam.goal = 0.001; 
net = train(net, P, T);

la rete risponde con:

TRAINLM, Epoch 0/100, MSE 0.0384347/0.001, Gradient 10.7552/1e-010 
TRAINLM, Epoch 23/100, MSE 0.000810088/0.001, Gradient 17.1158/1e-010 
TRAINLM, Performance goal met.

e raggiunge il minimo errore richiesto.

Possiamo ora verificare come funziona la rete sul set di verifica (da costruire).

xt = rand(1:5000)*2-1; yt=rand(1,5000)*2-1; hh=find(sqrt(xt.^2+yt.^2)<0.5); 
tt = zeros(1,5000); tt(hh)=1;

Questo genera il set di test.

ytest = sim(net,[xt;yt]); 
jj = find(ytest>0.5); ytest = zeros(1,5000); ytest(jj) = 1; 
ss = find(abs(ytest-tt)>0.1); 
plot(x(ss), y(ss), '.')

Il primo comando genera gli output della rete, che non saranno "digitali" cioe’ (0,1). Per convenzione si digitalizzano gli output della funzione logsig prendendo = 1 gli output > 0.5 e zero gli altri.
Gli indici ss sono quelli dei dati riprodotti errati dalla rete. Essi vengono visualizzati dal comando plot.

Vedi anche

Salvo diversa indicazione, il contenuto di questa pagina è sotto licenza Creative Commons Attribution-ShareAlike 3.0 License