Sommario[Nascondere][Spettacolo]
Il cervello è paragonabile alle reti neurali. Questa è l'analogia che viene in genere utilizzata per aiutare qualcuno che non conosce l'argomento a comprendere le idee alla base dell'apprendimento automatico e delle reti neurali artificiali.
Poiché ci sono diversi livelli di calcoli matematici e statistici in corso dietro le quinte, definire queste reti come una funzione matematica è un metodo più avanzato.
Questo è per le persone che sono effettivamente interessate all'apprendimento automatico e vogliono vedere come viene scritto il codice della rete neurale Python.
In questo articolo, dimostreremo come costruire da zero una rete neurale profonda (DNN) completamente connessa Python 3.
Una panoramica della struttura dei file per il nostro codice di rete neurale Python
Ci saranno tre file creati qui. Il primo è il semplice file nn.py, che verrà discusso in "Impostazione di funzioni di supporto" e "Costruzione della rete neurale da zero".
Avremo anche un file chiamato mnist loader.py per caricare i dati del test, come descritto in "Caricamento dei dati MNIST".
Infine, avremo un file chiamato test.py che verrà lanciato nel terminale per testare la nostra rete neurale.
Questo file è descritto in dettaglio in "Esecuzione dei test".
Installazione
La libreria NumPy Python deve essere scaricata per seguire questo tutorial. Puoi farlo usando il seguente comando sul terminale:
Importazione di moduli e configurazione della funzione Helper
Le uniche due librerie di cui abbiamo bisogno sono random e NumPy, che importeremo subito. Per i pesi iniziali della nostra rete neurale, li mescoleremo usando la libreria casuale.
Per velocizzare i nostri calcoli, useremo NumPy o np (per convenzione, è spesso importato come np). Le nostre due funzioni di supporto verranno eseguite dopo le nostre importazioni. Due funzioni sigmoidee: una e sigmoidea primo.
La regressione logistica classificherà i dati utilizzando la funzione sigmoide, mentre la backpropagation calcolerà il delta o il gradiente utilizzando la funzione primo sigmoide.
Creazione di classe di rete
Costruire una rete neurale completamente collegata è l'unico obiettivo di questa sezione. La classe di rete comprenderà tutte le funzioni successive. La funzione Object() { [codice nativo] } verrà creata inizialmente nella nostra classe di rete.
Un argomento, dimensioni, è richiesto dalla funzione Object() { [codice nativo] }. La variabile size è una raccolta di valori numerici che rappresenta il numero di nodi di input presenti in ogni livello della nostra rete neurale.
Inizializziamo quattro proprietà nel nostro metodo __init__. Le variabili di input, dimensioni, vengono utilizzate per impostare rispettivamente l'elenco delle dimensioni dei livelli e il numero di livelli, num livelli.
Il primo passo consiste nell'assegnare casualmente i bias iniziali della nostra rete a ogni livello che segue il livello di input.
Infine, ogni collegamento tra i livelli di input e output ha i suoi pesi generati casualmente. Np.Random.Randn() fornisce un campione casuale tratto dalla distribuzione normale per il contesto.
Funzione feed forward
In una rete neurale, le informazioni vengono inviate dalla funzione feedforward. Un argomento, a, che indica il vettore di attivazione corrente, sarà richiesto da questa funzione.
Questa funzione stima le attivazioni a ciascun livello iterando su tutti i bias e i pesi nella rete. La risposta data è la previsione, che è l'attivazione dell'ultimo livello.
Discesa graduale in mini batch
Il cavallo di battaglia della nostra classe Network è Gradient Descent. In questa versione, utilizziamo la discesa del gradiente mini-batch (stocastica), una variazione modificata della discesa del gradiente.
Ciò indica che un piccolo lotto di punti dati verrà utilizzato per aggiornare il nostro modello. Quattro argomenti obbligatori e uno facoltativo vengono passati a questo metodo. Le quattro variabili richieste sono il set di dati di addestramento, il numero di epoche, la dimensione dei mini-batch e il tasso di apprendimento (eta).
I dati del test sono disponibili su richiesta. Forniremo i dati di test quando alla fine valuteremo questa rete. Il numero di campioni in questa funzione viene inizialmente impostato sulla lunghezza dell'elenco una volta che i dati di addestramento sono stati trasformati in un tipo di elenco.
Applichiamo lo stesso processo anche per testare i dati che vengono forniti. Questo perché invece di essere restituiti a noi come elenchi, sono in realtà zip di elenchi. Quando caricheremo i campioni di dati MNIST in seguito, ne sapremo di più.
Se possiamo assicurarci di fornire entrambi i tipi di dati come elenchi, questo cast di tipi non è necessariamente essenziale.
Una volta che abbiamo i dati, esaminiamo le epoche di addestramento in un ciclo. Un periodo di addestramento è solo un ciclo di addestramento della rete neurale. Per prima cosa mescoliamo i dati in ogni epoca per garantire la casualità prima di creare un elenco di mini-batch.
La funzione di aggiornamento mini batch, discussa di seguito, verrà chiamata per ogni mini batch. L'accuratezza del test verrà restituita anche se i dati del test sono disponibili.
Funzione di supporto derivata dal costo
Sviluppiamo una funzione di supporto chiamata derivata di costo prima di creare davvero il codice di backpropagation. Se commettiamo un errore nel nostro livello di output, la funzione di derivata di costo lo mostrerà.
Richiede due input: l'array di attivazioni dell'uscita e le coordinate y dei valori di uscita previsti.
Funzione di retropropagazione
Il nostro attuale vettore di attivazione, attivazione, così come qualsiasi altro vettore di attivazione, attivazione e z-vettori, zs, devono essere tutti tenuti a mente. Viene attivato per primo un livello chiamato livello di input.
Analizzeremo ogni pregiudizio e peso dopo averli inseriti. Ogni ciclo prevede il calcolo del vettore z come prodotto scalare dei pesi e dell'attivazione, l'aggiunta all'elenco di zs, il ricalcolo dell'attivazione e l'aggiunta dell'attivazione aggiornata all'elenco delle attivazioni.
Infine, la matematica. Il delta, che è uguale all'errore del livello precedente moltiplicato per il primo sigmoideo dell'ultimo elemento dei vettori zs, viene calcolato prima di iniziare il nostro passaggio all'indietro.
L'ultimo strato di nabla b è impostato per essere il delta e lo strato finale di nabla w è impostato per essere il prodotto scalare del delta e il penultimo strato di attivazioni (trasposto in modo che possiamo effettivamente fare i calcoli) .
Procediamo come prima, iniziando con il secondo strato e concludendo con l'ultimo, e ripetiamo il processo dopo aver completato questi ultimi strati. Le nabla vengono poi restituite come tuple.
Aggiornamento discesa gradiente Mini-batch
Il nostro metodo SGD (discesa del gradiente stocastico) di prima incorpora l'aggiornamento in mini-batch. Poiché è utilizzato in SGD ma richiede anche il backprop, ho discusso su dove mettere questa funzione.
Alla fine ho deciso di postarlo qui. Inizia generando 0 vettori dei nablas di bias e weights, proprio come ha fatto la nostra funzione backprop.
Richiede il mini-batch e il tasso di apprendimento eta come suoi due input. Nel mini-batch, utilizziamo quindi la funzione backprop per ottenere il delta di ogni array nabla per ogni input, x, e output, y. Le liste nabla vengono quindi aggiornate con questi delta.
Infine, utilizziamo il tasso di apprendimento e i nablas per aggiornare i pesi e le distorsioni della rete. Ogni valore viene aggiornato al valore più recente, meno il tasso di apprendimento, moltiplicato per la dimensione del minibatch e quindi aggiunto al valore nabla.
Valuta la funzione
La funzione di valutazione è l'ultima che dobbiamo scrivere. I dati del test sono l'unico input per questa funzione. In questa funzione, confrontiamo solo le uscite della rete con il risultato previsto, y. Alimentando l'ingresso, x, in avanti, si determinano le uscite della rete.
Codice completo
Quando combiniamo tutto il codice, ecco come appare.
Test della rete neurale
Caricamento dei dati MNIST
I dati MNIST è in formato .pkl.gz, che apriremo usando GZIP e caricheremo con pickle. Scriviamo un metodo rapido per caricare questi dati come una tupla di dimensione tre, suddivisa in dati di addestramento, convalida e test.
Per semplificare la gestione dei nostri dati, scriveremo un'altra funzione per codificare y in un array di 10 elementi. L'array sarà tutti 0 tranne un 1 che corrisponde alla cifra corretta dell'immagine.
Useremo i dati di caricamento di base e un metodo di codifica a caldo per caricare i nostri dati in un formato leggibile. Verrà scritta un'altra funzione che convertirà i nostri valori x in un elenco di dimensione 784, corrispondente ai 784 pixel dell'immagine, e i nostri valori y nella loro singola forma vettoriale codificata a caldo.
Quindi combineremo i valori xey in modo tale che un indice corrisponda all'altro. Questo vale per i set di dati di addestramento, convalida e test. Quindi restituiamo i dati modificati.
Test in corso
Creeremo un nuovo file chiamato "mnist loader" che importerà sia la rete neurale che abbiamo stabilito in precedenza (semplice nn) sia il data set loader MNIST prima di iniziare il test.
In questo file, tutto ciò che dobbiamo fare è importare i dati, costruire una rete con una dimensione del livello di input di 784 e una dimensione del livello di output di 10, eseguire la funzione SGD della rete sui dati di addestramento, quindi testarla utilizzando i dati di test.
Tieni presente che per il nostro elenco di livelli di input, non fa differenza quali siano i numeri compresi tra 784 e 10. Possiamo cambiare gli altri livelli come vogliamo; solo le dimensioni di input e output sono fisse.
Non sono necessari tre strati; potremmo usarne quattro, cinque o anche solo due. Divertiti a sperimentarlo.
Conclusione
Qui, usando Python 3, creiamo una rete neurale da zero. Insieme alla matematica di alto livello, abbiamo anche discusso le specifiche dell'implementazione.
Abbiamo iniziato implementando funzioni di supporto. Affinché i neuroni funzionino, le funzioni sigmoide e sigmoide prime sono cruciali. Mettiamo quindi in pratica la funzione feedforward, che è il processo fondamentale per alimentare i dati nella rete neurale.
Successivamente, abbiamo creato la funzione di discesa del gradiente in Python, il motore che guida la nostra rete neurale. Per individuare i "minimi locali" e ottimizzare i loro pesi e pregiudizi, la nostra rete neurale utilizza la discesa del gradiente. Abbiamo creato la funzione di backpropagation usando discesa gradiente.
Fornendo aggiornamenti quando gli output non corrispondono alle etichette corrette, questa funzione consente alla rete neurale di "apprendere".
Infine, abbiamo messo il nostro nuovissimo Python rete neurale al test utilizzando il set di dati MNIST. Tutto ha funzionato senza intoppi.
Buona programmazione!
Lascia un Commento