Theano - Trivial Training Example

Theano è molto utile nell'addestramento di reti neurali in cui dobbiamo calcolare ripetutamente costi e gradienti per ottenere un ottimo. Su set di dati di grandi dimensioni, questo diventa computazionalmente intenso. Theano lo fa in modo efficiente grazie alle sue ottimizzazioni interne del grafo computazionale che abbiamo visto in precedenza.

Dichiarazione problema

Ora impareremo come usare la libreria Theano per addestrare una rete. Prenderemo un semplice caso in cui iniziamo con un set di dati di quattro funzionalità. Calcoliamo la somma di queste caratteristiche dopo aver applicato un certo peso (importanza) a ciascuna caratteristica.

L'obiettivo della formazione è modificare i pesi assegnati a ciascuna caratteristica in modo che la somma raggiunga un valore target di 100.

sum = f1 * w1 + f2 * w2 + f3 * w3 + f4 * w4

Dove f1, f2, ... sono i valori delle caratteristiche e w1, w2, ... sono i pesi.

Consentitemi di quantizzare l'esempio per una migliore comprensione dell'enunciato del problema. Assumeremo un valore iniziale di 1.0 per ogni caratteristica e prenderemo w1 uguale0.1, w2 equivale 0.25, w3 equivale 0.15, e w4 equivale 0.3. Non esiste una logica definita nell'assegnazione dei valori di peso, è solo una nostra intuizione. Pertanto, la somma iniziale è la seguente:

sum = 1.0 * 0.1 + 1.0 * 0.25 + 1.0 * 0.15 + 1.0 * 0.3

Che si riassume in 0.8. Ora continueremo a modificare l'assegnazione del peso in modo che questa somma si avvicini a 100. Il valore risultante corrente di0.8 è lontano dal valore target desiderato di 100. In termini di Machine Learning, definiamo costcome la differenza tra il valore target meno il valore di uscita corrente, tipicamente al quadrato per far saltare l'errore. Riduciamo questo costo in ogni iterazione calcolando i gradienti e aggiornando il nostro vettore dei pesi.

Vediamo come tutta questa logica viene implementata in Theano.

Dichiarazione di variabili

Per prima cosa dichiariamo il nostro vettore di input x come segue:

x = tensor.fvector('x')

Dove x è un array monodimensionale di valori float.

Definiamo uno scalare target variabile come indicato di seguito -

target = tensor.fscalar('target')

Successivamente, creiamo un tensore dei pesi W con i valori iniziali come discusso sopra -

W = theano.shared(numpy.asarray([0.1, 0.25, 0.15, 0.3]), 'W')

Definizione dell'espressione di Theano

Calcoliamo ora l'output utilizzando la seguente espressione:

y = (x * W).sum()

Si noti che nella dichiarazione di cui sopra x e Wsono i vettori e non semplici variabili scalari. Calcoliamo ora l'errore (costo) con la seguente espressione:

cost = tensor.sqr(target - y)

Il costo è la differenza tra il valore target e l'uscita corrente, al quadrato.

Per calcolare il gradiente che ci dice quanto siamo lontani dall'obiettivo, utilizziamo il built-in grad metodo come segue -

gradients = tensor.grad(cost, [W])

Ora aggiorniamo il weights vettore prendendo un tasso di apprendimento di 0.1 come segue -

W_updated = W - (0.1 * gradients[0])

Successivamente, dobbiamo aggiornare il nostro vettore di pesi utilizzando i valori sopra. Lo facciamo nella seguente dichiarazione:

updates = [(W, W_updated)]

Definizione / richiamo della funzione Theano

Infine, definiamo un file function in Theano per calcolare la somma.

f = function([x, target], y, updates=updates)

Per richiamare la funzione di cui sopra un certo numero di volte, creiamo un file for loop come segue -

for i in range(10):
output = f([1.0, 1.0, 1.0, 1.0], 100.0)

Come detto in precedenza, l'input della funzione è un vettore contenente i valori iniziali per le quattro caratteristiche: assegniamo il valore di 1.0a ciascuna funzionalità senza alcun motivo specifico. Puoi assegnare diversi valori di tua scelta e controllare se la funzione alla fine converge. Stamperemo i valori del vettore peso e il corrispondente output in ogni iterazione. È mostrato nel codice sottostante -

print ("iteration: ", i)
print ("Modified Weights: ", W.get_value())
print ("Output: ", output)

Elenco completo del programma

L'elenco completo del programma è riprodotto qui per una rapida consultazione -

from theano import *
import numpy

x = tensor.fvector('x')
target = tensor.fscalar('target')

W = theano.shared(numpy.asarray([0.1, 0.25, 0.15, 0.3]), 'W')
print ("Weights: ", W.get_value())

y = (x * W).sum()
cost = tensor.sqr(target - y)
gradients = tensor.grad(cost, [W])
W_updated = W - (0.1 * gradients[0])
updates = [(W, W_updated)]

f = function([x, target], y, updates=updates)
for i in range(10):
   output = f([1.0, 1.0, 1.0, 1.0], 100.0)
   print ("iteration: ", i)
   print ("Modified Weights: ", W.get_value())
   print ("Output: ", output)

Quando esegui il programma vedrai il seguente output:

Weights: [0.1 0.25 0.15 0.3 ]
iteration: 0
Modified Weights: [19.94 20.09 19.99 20.14]
Output: 0.8
iteration: 1
Modified Weights: [23.908 24.058 23.958 24.108]
Output: 80.16000000000001
iteration: 2
Modified Weights: [24.7016 24.8516 24.7516 24.9016]
Output: 96.03200000000001
iteration: 3
Modified Weights: [24.86032 25.01032 24.91032 25.06032]
Output: 99.2064
iteration: 4
Modified Weights: [24.892064 25.042064 24.942064 25.092064]
Output: 99.84128
iteration: 5
Modified Weights: [24.8984128 25.0484128 24.9484128 25.0984128]
Output: 99.968256
iteration: 6
Modified Weights: [24.89968256 25.04968256 24.94968256 25.09968256]
Output: 99.9936512
iteration: 7
Modified Weights: [24.89993651 25.04993651 24.94993651 25.09993651]
Output: 99.99873024
iteration: 8
Modified Weights: [24.8999873 25.0499873 24.9499873 25.0999873]
Output: 99.99974604799999
iteration: 9
Modified Weights: [24.89999746 25.04999746 24.94999746 25.09999746]
Output: 99.99994920960002

Osserva che dopo quattro iterazioni, l'output è 99.96 e dopo cinque iterazioni, lo è 99.99, che è vicino al nostro obiettivo desiderato di 100.0.

A seconda della precisione desiderata, è possibile concludere con sicurezza che la rete viene addestrata in 4-5 iterazioni. Al termine dell'addestramento, cerca il vettore dei pesi, che dopo 5 iterazioni assume i seguenti valori:

iteration: 5
Modified Weights: [24.8984128 25.0484128 24.9484128 25.0984128]

È ora possibile utilizzare questi valori nella rete per distribuire il modello.