Inhoudsopgave[Zich verstoppen][Laten zien]
De hersenen zijn vergelijkbaar met neurale netwerken. Dit is de analogie die doorgaans wordt gebruikt om iemand die nieuw is in het onderwerp te helpen de ideeën achter machine learning en kunstmatige neurale netwerken te begrijpen.
Omdat er achter de schermen verschillende lagen van wiskundige en statistische berekeningen plaatsvinden, is het een meer geavanceerde methode om deze netwerken als een wiskundige functie te definiëren.
Dit is voor de mensen die echt geïnteresseerd zijn in machine learning en willen zien hoe de neurale netwerkcode van Python wordt geschreven.
In dit artikel laten we zien hoe je vanaf het begin een volledig verbonden diep neuraal netwerk (DNN) kunt bouwen Python 3.
Een overzicht van de bestandsstructuur voor onze Python neurale netwerkcode
Er worden hier drie bestanden gemaakt. De eerste is het eenvoudige nn.py-bestand, dat wordt besproken in "Helperfuncties instellen" en "Het neurale netwerk vanaf het begin opbouwen".
We hebben ook een bestand met de naam mnist loader.py om de testgegevens te laden, zoals beschreven in "MNIST-gegevens laden".
Ten slotte hebben we een bestand met de naam test.py dat in de terminal wordt gestart om ons neurale netwerk te testen.
Dit bestand wordt in detail beschreven in "Tests uitvoeren".
Installatie
De NumPy Python-bibliotheek moet worden gedownload om deze tutorial te kunnen volgen. U kunt dit bereiken door de volgende opdracht op de terminal te gebruiken:
Modules importeren en de Helper-functie instellen
De enige twee bibliotheken die we nodig hebben, zijn willekeurig en NumPy, die we meteen zullen importeren. Voor de initiële gewichten van ons neurale netwerk zullen we ze door elkaar schudden met behulp van de willekeurige bibliotheek.
Om onze berekeningen te versnellen, gebruiken we NumPy of np (volgens conventie wordt het vaak geïmporteerd als np). Onze twee hulpfuncties worden gemaakt na onze invoer. Twee sigmoïde functies: één en sigmoïde prime.
Logistische regressie classificeert gegevens met behulp van de sigmoid-functie, terwijl backpropagation de delta of gradiënt berekent met behulp van de sigmoid prime-functie.
Netwerkklasse maken
Het bouwen van een volledig gekoppeld neuraal netwerk is de enige focus van deze sectie. De netwerkklasse omvat alle functies die daarna komen. De functie Object() { [native code] } wordt in eerste instantie gemaakt in onze netwerkklasse.
Eén argument, maten, is vereist door de functie Object() { [native code] }. De variabele maten is een verzameling numerieke waarden die het aantal invoerknooppunten vertegenwoordigt dat aanwezig is in elke laag van ons neurale netwerk.
We initialiseren vier eigenschappen in onze __init__ methode. De invoervariabelen, maten, worden gebruikt om respectievelijk de lijst met laagformaten en het aantal lagen, het aantal lagen, in te stellen.
De eerste stap is om de initiële vooroordelen van ons netwerk willekeurig toe te wijzen aan elke laag die volgt op de invoerlaag.
Ten slotte heeft elke koppeling tussen de invoer- en uitvoerlagen willekeurig gegenereerde gewichten. Np.Random.Randn() geeft een willekeurige steekproef getrokken uit de normale verdeling voor context.
Feed Forward-functie
In een neuraal netwerk wordt informatie doorgestuurd door de feedforward-functie. Eén argument, a, dat de huidige activeringsvector aangeeft, is vereist voor deze functie.
Deze functie schat de activeringen op elke laag door alle vooroordelen en gewichten in het netwerk te herhalen. Het gegeven antwoord is de voorspelling, de activeringen van de laatste laag.
Mini-batch gradiëntafdaling
Het werkpaard van onze netwerkklas is Gradient Descent. In deze versie gebruiken we mini-batch (stochastische) gradiëntafdaling, een aangepaste variant van gradiëntafdaling.
Dit geeft aan dat een kleine reeks gegevenspunten zal worden gebruikt om ons model bij te werken. Aan deze methode worden vier vereiste en één optioneel argument doorgegeven. De vier vereiste variabelen zijn de trainingsgegevensset, het aantal tijdperken, de grootte van de minibatches en de leersnelheid (eta).
Testgegevens zijn op aanvraag beschikbaar. We zullen testgegevens leveren wanneer we dit netwerk uiteindelijk evalueren. Het aantal monsters in deze functie wordt aanvankelijk ingesteld op de lengte van de lijst zodra de trainingsgegevens zijn omgezet in een lijsttype.
We passen hetzelfde proces ook toe op het testen van de gegevens die worden opgegeven. Dit komt omdat ze niet als lijsten naar ons worden teruggestuurd, maar in feite uitlopers van lijsten. Wanneer we de MNIST-gegevensvoorbeelden later laden, zullen we hier meer over leren.
Als we ervoor kunnen zorgen dat we beide soorten gegevens als lijsten aanleveren, is deze typecasting niet per se essentieel.
Zodra we de gegevens hebben, overlopen we de trainingsperioden in een lus. Een trainingsperiode is slechts één ronde van neurale netwerktraining. We schudden eerst de gegevens in elk tijdperk om willekeur te garanderen voordat we een lijst met mini-batches maken.
De functie mini-batch bijwerken, die hieronder wordt besproken, wordt voor elke mini-batch aangeroepen. De testnauwkeurigheid wordt ook geretourneerd als de testgegevens beschikbaar zijn.
Kostenafgeleide helperfunctie
Laten we eerst een helperfunctie ontwikkelen met de naam kostenderivaat voordat we echt de backpropagation-code maken. Als we een fout maken in onze uitvoerlaag, zal de kostenderivaatfunctie dit laten zien.
Het vereist twee inputs: de output activaties array en de y-coördinaten van de verwachte output waarden.
Backpropagation-functie
Onze huidige activeringsvector, activering, evenals alle andere activeringsvectoren, activeringen en z-vectoren, zs, moeten allemaal in gedachten worden gehouden. Een laag genaamd de invoerlaag wordt eerst geactiveerd.
We zullen elke bias en gewicht doornemen nadat we ze hebben opgehangen. Elke lus omvat het berekenen van de z-vector als het puntproduct van de gewichten en de activering, het toevoegen aan de lijst met zs, het herberekenen van de activering en het toevoegen van de bijgewerkte activering aan de lijst met activeringen.
Tot slot de wiskunde. De delta, die gelijk is aan de fout van de vorige laag vermenigvuldigd met het sigmoïde priemgetal van het laatste element van de zs-vectoren, wordt berekend voordat we aan onze achterwaartse pas beginnen.
De laatste laag van nabla b is ingesteld als de delta, en de laatste laag van nabla w is ingesteld als het puntproduct van de delta en de voorlaatste laag van activeringen (getransponeerd zodat we de wiskunde daadwerkelijk kunnen doen) .
We gaan verder zoals voorheen, beginnend met de tweede laag en eindigend met de laatste, en herhalen het proces na het voltooien van deze laatste lagen. De nablas worden dan teruggegeven als een tupel.
Mini-batch gradiëntafdaling bijwerken
Onze SGD-methode (stochastische gradiëntafdaling) van vroeger bevat mini-batch-updates. Omdat het wordt gebruikt in SGD maar ook backprop vereist, heb ik gedebatteerd waar ik deze functie moest plaatsen.
Uiteindelijk heb ik de keuze gemaakt om het hier te plaatsen. Het begint met het genereren van 0 vectoren van de nablas van de biases en weights, net zoals onze backprop-functie deed.
Het vereist de mini-batch en de eta-leersnelheid als zijn twee ingangen. In de mini-batch gebruiken we vervolgens de backprop-functie om de delta van elke nabla-array te verkrijgen voor elke invoer, x en uitvoer, y. De nabla-lijsten worden vervolgens bijgewerkt met deze delta's.
Ten slotte gebruiken we de leersnelheid en de nablas om de gewichten en vooroordelen van het netwerk bij te werken. Elke waarde wordt bijgewerkt naar de meest recente waarde, verminderd met de leersnelheid, vermenigvuldigd met de minibatchgrootte en vervolgens opgeteld bij de nabla-waarde.
Functie evalueren
De evaluatiefunctie is de laatste die we moeten schrijven. De testgegevens zijn de enige invoer voor deze functie. In deze functie vergelijken we alleen de uitgangen van het netwerk met het verwachte resultaat, y. Door de input, x, vooruit te voeren, worden de outputs van het netwerk bepaald.
Volledige code
Als we alle code combineren, ziet het er zo uit.
Neurale netwerk testen
MNIST-gegevens laden
De MNIST-gegevens is in .pkl.gz-indeling, die we openen met GZIP en laden met augurk. Laten we een snelle methode schrijven om deze gegevens te laden als een tupel van grootte drie, verdeeld in trainings-, validatie- en testgegevens.
Om onze gegevens gemakkelijker te beheren te maken, schrijven we een andere functie om de y te coderen in een array van 10 items. De array zal allemaal nullen zijn, behalve een 0 die overeenkomt met het juiste cijfer van de afbeelding.
We gebruiken de basislaadgegevens en één hot-coderingsmethode om onze gegevens in een leesbaar formaat te laden. Er zal een andere functie worden geschreven die onze x-waarden zal converteren naar een lijst met een grootte van 784, overeenkomend met de 784 pixels van de afbeelding, en onze y-waarden naar hun enkele hot-gecodeerde vectorvorm.
Vervolgens combineren we de x- en y-waarden zodat de ene index overeenkomt met de andere. Dit geldt voor de trainings-, validatie- en testdatasets. Wij retourneren dan de gewijzigde gegevens.
Tests uitvoeren
We zullen een nieuw bestand maken met de naam "mnist loader" dat zowel het neurale netwerk dat we eerder hebben opgezet (eenvoudige nn) als de MNIST dataset loader zal importeren voordat we beginnen met testen.
In dit bestand hoeven we alleen maar de gegevens te importeren, een netwerk te bouwen met een invoerlaaggrootte van 784 en een uitvoerlaaggrootte van 10, de SGD-functie van het netwerk op de trainingsgegevens uit te voeren en deze vervolgens te testen met behulp van de testgegevens.
Houd er rekening mee dat het voor onze lijst met invoerlagen geen verschil maakt wat een van de getallen tussen 784 en 10 is. We kunnen de andere lagen veranderen zoals we willen; alleen de invoer- en uitvoergroottes zijn vast.
Drie lagen zijn niet nodig; we kunnen er vier, vijf of zelfs maar twee gebruiken. Experimenteer er met plezier mee.
Conclusie
Hier, met behulp van Python 3, creëren we een neuraal netwerk vanuit het niets. Naast wiskunde op hoog niveau hebben we ook de details van de implementatie besproken.
We zijn begonnen met het implementeren van helperfuncties. Om de neuronen te laten werken, zijn de sigmoïde en sigmoïde prime-functies cruciaal. Vervolgens hebben we de feedforward-functie in de praktijk gebracht, het fundamentele proces voor het invoeren van gegevens in het neurale netwerk.
Vervolgens hebben we de gradiënt-afdalingsfunctie gemaakt in Python, de engine die ons neurale netwerk aandrijft. Om "lokale minima" te lokaliseren en hun gewichten en vooroordelen te optimaliseren, gebruikt ons neurale netwerk gradiëntafdaling. We hebben de backpropagation-functie gemaakt met behulp van gradiënt afdaling.
Door updates te leveren wanneer de outputs niet overeenkomen met de juiste labels, stelt deze functie het neurale netwerk in staat om te 'leren'.
Tot slot zetten we onze gloednieuwe Python neuraal netwerk aan de test met behulp van de MNIST-gegevensset. Alles functioneerde soepel.
Gelukkig codering!
Laat een reactie achter