Indholdsfortegnelse[Skjule][At vise]
Hjernen kan sammenlignes med neurale netværk. Dette er den analogi, der typisk bruges til at hjælpe en nybegynder til at forstå ideerne bag maskinlæring og kunstige neurale netværk.
Fordi der foregår flere lag af matematiske og statistiske beregninger bag kulisserne, er det en mere avanceret metode at definere disse netværk som en matematisk funktion.
Dette er for de mennesker, der rent faktisk er interesserede i maskinlæring og ønsker at se, hvordan Python neurale netværkskode er skrevet.
I denne artikel vil vi demonstrere, hvordan man konstruerer et fuldt tilsluttet dybt neuralt netværk (DNN) fra bunden i Python 3.
En oversigt over filstrukturen for vores Python-neurale netværkskode
Der vil blive oprettet tre filer her. Den første er den enkle nn.py-fil, som vil blive diskuteret i "Opsætning af hjælpefunktioner" og "Opbygning af det neurale netværk fra bunden."
Vi vil også have en fil med navnet mnist loader.py til at indlæse testdataene, som beskrevet i "Indlæsning af MNIST-data."
Endelig vil vi have en fil ved navn test.py, der vil blive lanceret i terminalen for at teste vores neurale netværk.
Denne fil er beskrevet detaljeret i "Running Tests."
Installation
NumPy Python-biblioteket skal downloades for at følge denne vejledning. Du kan opnå dette ved at bruge følgende kommando på terminalen:
Import af moduler og opsætning af hjælpefunktionen
De eneste to biblioteker, vi har brug for, er random og NumPy, som vi importerer med det samme. For vores neurale netværks indledende vægte blander vi dem ved hjælp af det tilfældige bibliotek.
For at fremskynde vores beregninger bruger vi NumPy eller np (efter konvention importeres det ofte som np). Vores to hjælperfunktioner bliver lavet efter vores import. To sigmoid funktioner: en og sigmoid prime.
Logistisk regression vil klassificere data ved hjælp af sigmoid-funktionen, mens backpropagation vil beregne delta eller gradient ved hjælp af sigmoid-prime-funktionen.
Oprettelse af netværksklasse
Opbygning af et fuldt forbundet neuralt netværk er det eneste fokus i dette afsnit. Netværksklassen vil omfatte alle de funktioner, der kommer efter. Funktionen Object() { [native code] } bliver oprindeligt oprettet i vores netværksklasse.
Et argument, størrelser, er påkrævet af funktionen Object() { [native code] }. Størrelsesvariablen er en samling af numeriske værdier, der repræsenterer antallet af inputnoder, der er til stede i hvert lag af vores neurale netværk.
Vi initialiserer fire egenskaber i vores __init__ metode. Inputvariablerne, størrelser, bruges til at angive henholdsvis listen over lagstørrelser og antallet af lag, antal lag.
Det første trin er tilfældigt at tildele vores netværks indledende skævheder til hvert lag, der følger inputlaget.
Endelig har hver forbindelse mellem input- og outputlagene sine vægte genereret tilfældigt. Np.Random.Randn() giver en tilfældig stikprøve trukket fra normalfordelingen for kontekst.
Fremføringsfunktion
I et neuralt netværk sendes information videre af feedforward-funktionen. Et argument, a, der angiver den aktuelle aktiveringsvektor, vil være påkrævet af denne funktion.
Denne funktion estimerer aktiveringerne på hvert lag ved at iterere over alle skævheder og vægte i netværket. Det givne svar er forudsigelsen, som er aktiveringerne af det sidste lag.
Mini-batch Gradient Descent
Vores netværksklasses arbejdshest er Gradient Descent. I denne version bruger vi mini-batch (stokastisk) gradient descent, en modificeret variation af gradient descent.
Dette indikerer, at en lille batch af datapunkter vil blive brugt til at opdatere vores model. Fire påkrævede og et valgfrit argument sendes til denne metode. De fire nødvendige variabler er træningsdatasættet, antallet af epoker, størrelsen af mini-batches og indlæringshastigheden (eta).
Testdata er tilgængelige efter anmodning. Vi leverer testdata, når vi til sidst evaluerer dette netværk. Antallet af prøver i denne funktion er oprindeligt indstillet til længden af listen, når træningsdataene er blevet transformeret til en listetype.
Vi anvender også den samme proces til at teste data, som er givet i. Dette skyldes, at i stedet for at blive returneret til os som lister, er de i virkeligheden zips af lister. Når vi indlæser MNIST-dataeksemplerne senere, lærer vi mere om dette.
Hvis vi kan sikre, at vi leverer begge slags data som lister, så er denne type-casting ikke nødvendigvis afgørende.
Når vi har dataene, gennemgår vi træningsepokerne i en sløjfe. En træningsperiode er kun én omgang neural netværkstræning. Vi blander først dataene i hver epoke for at sikre tilfældighed, før vi laver en liste over mini-batches.
Opdateringsminibatchfunktionen, som diskuteres nedenfor, vil blive kaldt for hver minibatch. Testnøjagtigheden vil også blive returneret, hvis testdataene er tilgængelige.
Omkostningsafledt hjælpefunktion
Lad os først udvikle en hjælpefunktion kaldet cost derivative, før vi virkelig opretter backpropagation-koden. Hvis vi laver en fejl i vores outputlag, vil omkostningsafledte funktion vise det.
Det kræver to input: outputaktiveringsarrayet og y-koordinaterne for de forventede outputværdier.
Backpropagation funktion
Vores nuværende aktiveringsvektor, aktivering, såvel som alle andre aktiveringsvektorer, aktiveringer og z-vektorer, zs, skal alle huskes. Et lag kaldet inputlaget aktiveres først.
Vi gennemgår hver bias og vægt efter at have sat dem op. Hver sløjfe involverer at beregne z-vektoren som prikproduktet af vægtene og aktiveringen, tilføje den til listen over zs, genberegne aktiveringen og tilføje den opdaterede aktivering til listen over aktiveringer.
Til sidst matematik. Deltaet, som er lig med fejlen fra det foregående lag multipliceret med sigmoid-primtal for det sidste element af zs-vektorerne, beregnes, før vi starter vores tilbageløb.
Det sidste lag af nabla b er sat til at være deltaet, og det sidste lag af nabla w er sat til at være prikproduktet af deltaet og det næstsidste lag af aktiveringer (transponeret, så vi faktisk kan regne ud) .
Vi fortsætter som før, starter med det andet lag og afslutter med det sidste, og gentager processen efter at have afsluttet disse sidste lag. Nablaerne gives derefter tilbage som en tupel.
Opdaterer Mini-batch gradient nedstigning
Vores SGD (stokastisk gradient descent) metode fra før inkorporerer mini-batch opdatering. Da det bruges i SGD, men også kræver backprop, diskuterede jeg, hvor jeg skulle placere denne funktion.
Til sidst valgte jeg at poste det her. Det begynder med at generere 0 vektorer af biases og vægtes nablas, ligesom vores backprop-funktion gjorde.
Det kræver mini-batchen og eta-indlæringshastigheden som dens to input. I mini-batchen bruger vi derefter backprop-funktionen til at opnå deltaet for hver nabla-array for hver input, x, og output, y. Nabla-listerne opdateres derefter med disse deltaer.
Til sidst bruger vi indlæringshastigheden og nablas til at opdatere netværkets vægte og skævheder. Hver værdi opdateres til den seneste værdi, minus indlæringshastigheden, ganget med minibatchstørrelsen og føjes derefter til nabla-værdien.
Evaluer funktion
Evalueringsfunktionen er den sidste, vi skal skrive. Testdata er det eneste input til denne funktion. I denne funktion sammenligner vi kun netværkets output med det forventede resultat, y. Ved at føre input, x, fremad, bestemmes netværkets output.
Komplet kode
Når vi kombinerer al koden, er det sådan, det ser ud.
Test af neurale netværk
Indlæser MNIST-data
MNIST-data er i .pkl.gz-format, som vi åbner ved hjælp af GZIP og indlæser med pickle. Lad os skrive en hurtig metode til at indlæse disse data som en tuple af størrelse tre, opdelt i trænings-, validerings- og testdata.
For at gøre vores data nemmere at administrere, skriver vi en anden funktion til at kode y'et til et 10-elements array. Arrayet vil være alle 0'er undtagen en 1, der matcher billedets korrekte ciffer.
Vi bruger de grundlæggende indlæsningsdata og én hot-encode-metode til at indlæse vores data i et læsbart format. En anden funktion vil blive skrevet, som vil konvertere vores x-værdier til en liste med størrelse 784, der matcher billedets 784 pixels, og vores y-værdier til deres enkelt hot-kodede vektorform.
Derefter kombinerer vi x- og y-værdierne, så det ene indeks matcher det andet. Dette gælder for trænings-, validerings- og testdatasættene. Vi returnerer derefter de ændrede data.
Løb test
Vi laver en ny fil kaldet "mnist loader", der vil importere både det neurale netværk, vi etablerede tidligere (simpelt nn) og MNIST-datasætindlæseren, før vi begynder at teste.
I denne fil skal vi blot importere dataene, bygge et netværk med en inputlagstørrelse på 784 og en outputlagstørrelse på 10, køre netværkets SGD-funktion på træningsdataene og derefter teste det ved hjælp af testdataene.
Husk, at for vores liste over inputlag gør det ingen forskel, hvad tallene er mellem 784 og 10. Vi kan ændre de andre lag, som vi vil; kun input- og outputstørrelserne er faste.
Tre lag er ikke nødvendigt; vi bruger måske fire, fem eller endda bare to. God fornøjelse med at eksperimentere med det.
Konklusion
Her skaber vi ved hjælp af Python 3 et neuralt netværk fra bunden. Sammen med matematik på højt niveau diskuterede vi også de særlige forhold ved implementering.
Vi startede med at implementere hjælpefunktioner. For at neuronerne kan fungere, er sigmoideum og sigmoid primære funktioner afgørende. Vi sætter derefter feedforward-funktionen i praksis, som er den grundlæggende proces til at føre data ind i det neurale netværk.
Dernæst oprettede vi gradient descent-funktionen i Python, motoren, der driver vores neurale netværk. For at lokalisere "lokale minima" og optimere deres vægte og skævheder, bruger vores neurale netværk gradientnedstigning. Vi oprettede tilbagepropageringsfunktionen ved hjælp af gradient nedstigning.
Ved at levere opdateringer, når udgangene ikke matcher de korrekte etiketter, gør denne funktion det neurale netværk i stand til at "lære".
Til sidst sætter vi vores splinternye Python neurale netværk til testen ved hjælp af MNIST-datasættet. Alt fungerede glat.
Glad kodning!
Giv en kommentar