Innehållsförteckning[Dölj][Visa]
Hjärnan är jämförbar med neurala nätverk. Detta är analogin som vanligtvis används för att hjälpa någon ny i ämnet att förstå idéerna bakom maskininlärning och artificiella neurala nätverk.
Eftersom det finns flera lager av matematiska och statistiska beräkningar bakom kulisserna, är det en mer avancerad metod att definiera dessa nätverk som en matematisk funktion.
Detta är för personer som faktiskt är intresserade av maskininlärning och vill se hur Pythons neurala nätverkskod skrivs.
I den här artikeln visar vi hur man konstruerar ett helt uppkopplat djupt neuralt nätverk (DNN) från början Python 3.
En översikt över filstrukturen för vår Python-neurala nätverkskod
Det kommer att skapas tre filer här. Den första är den enkla nn.py-filen, som kommer att diskuteras i "Ställa in hjälparfunktioner" och "Bygga det neurala nätverket från grunden."
Vi kommer också att ha en fil som heter mnist loader.py för att ladda testdata, enligt beskrivningen i "Ladda in MNIST-data."
Slutligen kommer vi att ha en fil med namnet test.py som kommer att lanseras i terminalen för att testa vårt neurala nätverk.
Den här filen beskrivs i detalj i "Köra tester."
Installation
NumPy Python-biblioteket måste laddas ner för att kunna följa denna handledning. Du kan åstadkomma detta genom att använda följande kommando på terminalen:
Importera moduler och ställa in hjälpfunktionen
De enda två bibliotek vi behöver är random och NumPy, som vi kommer att importera direkt. För vårt neurala nätverks initiala vikter blandar vi dem med hjälp av det slumpmässiga biblioteket.
För att påskynda våra beräkningar kommer vi att använda NumPy eller np (av konvention importeras det ofta som np). Våra två hjälpfunktioner kommer att göras efter våra importer. Två sigmoidfunktioner: en och sigmoid prime.
Logistisk regression kommer att klassificera data med hjälp av sigmoidfunktionen, medan backpropagation kommer att beräkna delta eller gradient med hjälp av sigmoid prime-funktionen.
Skapa nätverksklass
Att bygga ett helt länkat neuralt nätverk är det enda fokus i detta avsnitt. Nätverksklassen kommer att omfatta alla funktioner som kommer efter. Funktionen Object() { [native code] } skapas initialt i vår nätverksklass.
Ett argument, storlekar, krävs av funktionen Object() { [native code] }. Storleksvariabeln är en samling numeriska värden som representerar antalet ingångsnoder som finns i varje lager i vårt neurala nätverk.
Vi initierar fyra egenskaper i vår __init__-metod. Indatavariablerna, storlekar, används för att ställa in listan över lagerstorlekar respektive antalet lager, antal lager.
Det första steget är att slumpmässigt tilldela vårt nätverks initiala fördomar till varje lager som följer indatalagret.
Slutligen har varje länk mellan ingångs- och utgångsskikten sina vikter genererade slumpmässigt. Np.Random.Randn() ger ett slumpmässigt urval från normalfördelningen för sammanhang.
Frammatningsfunktion
I ett neuralt nätverk skickas information vidare av feedforward-funktionen. Ett argument, a, som indikerar den aktuella aktiveringsvektorn, kommer att krävas av denna funktion.
Denna funktion uppskattar aktiveringarna vid varje lager genom att iterera över alla förspänningar och vikter i nätverket. Svaret som ges är förutsägelsen, vilket är aktiveringarna av det sista lagret.
Mini-batch Gradient Descent
Vår nätverksklasss arbetshäst är Gradient Descent. I den här versionen använder vi mini-batch (stokastisk) gradientnedstigning, en modifierad variant av gradientnedstigning.
Detta indikerar att en liten grupp datapunkter kommer att användas för att uppdatera vår modell. Fyra obligatoriska och ett valfritt argument skickas till denna metod. De fyra nödvändiga variablerna är träningsdatauppsättningen, antalet epoker, storleken på minibatcherna och inlärningshastigheten (eta).
Testdata finns tillgängliga på begäran. Vi kommer att tillhandahålla testdata när vi så småningom utvärderar detta nätverk. Antalet prover i denna funktion är initialt inställt på längden på listan när träningsdata har omvandlats till en listtyp.
Vi tillämpar också samma process för testdata som ges i. Detta beror på att istället för att returneras till oss som listor, är de verkligen zippar av listor. När vi laddar MNIST-dataproverna senare kommer vi att lära oss mer om detta.
Om vi kan se till att vi tillhandahåller båda typerna av data som listor, är denna typgjutning inte nödvändigtvis nödvändig.
När vi väl har data går vi igenom träningsepokerne i en slinga. En träningsperiod är bara en omgång av neurala nätverksträning. Vi blandar först data i varje epok för att säkerställa slumpmässighet innan vi gör en lista över minibatcher.
Uppdateringsminibatchfunktionen, som diskuteras nedan, kommer att anropas för varje minibatch. Testnoggrannheten kommer också att returneras om testdata finns tillgänglig.
Kostnadsderivatande hjälpfunktion
Låt oss först utveckla en hjälpfunktion som kallas kostnadsderivat innan vi verkligen skapar backpropagation-koden. Om vi gör ett misstag i vårt utdatalager kommer kostnadsderivatfunktionen att visa det.
Den kräver två ingångar: utgångsaktiveringsmatrisen och y-koordinaterna för de förväntade utgångsvärdena.
Backpropagation funktion
Vår nuvarande aktiveringsvektor, aktivering, liksom alla andra aktiveringsvektorer, aktiveringar och z-vektorer, zs, måste alla ha i åtanke. Ett lager som kallas ingångslagret aktiveras först.
Vi går igenom varje bias och vikt efter att ha satt upp dem. Varje slinga involverar att beräkna z-vektorn som punktprodukten av vikterna och aktiveringen, lägga till den i listan över zs, räkna om aktiveringen och lägga till den uppdaterade aktiveringen till listan med aktiveringar.
Äntligen matematiken. Deltat, som är lika med felet från det föregående lagret multiplicerat med sigmoid primtal för det sista elementet i zs-vektorerna, beräknas innan vi börjar vår bakåtpassning.
Det sista lagret av nabla b är inställt på deltat, och det sista lagret av nabla w är inställt på att vara prickprodukten av deltat och det näst sista lagret av aktivering (transponerat så att vi faktiskt kan räkna ut) .
Vi fortsätter som tidigare, börjar med det andra lagret och avslutar med det sista, och upprepar processen efter att ha slutfört dessa sista lager. Nablas ges sedan tillbaka som en tupel.
Uppdaterar Mini-batch-gradientnedstigning
Vår SGD-metod (stochastic gradient descent) från tidigare inkluderar mini-batch-uppdatering. Eftersom det används i SGD men också kräver backprop, diskuterade jag var jag skulle placera den här funktionen.
Äntligen valde jag att lägga upp den här. Det börjar med att generera 0 vektorer av fördomarnas och vikternas nablas, precis som vår backprop-funktion gjorde.
Den kräver minibatchen och eta-inlärningshastigheten som två ingångar. I minibatchen använder vi sedan backprop-funktionen för att erhålla deltat för varje nabla-array för varje ingång, x, och utgång, y. Nabla-listorna uppdateras sedan med dessa delta.
Slutligen använder vi inlärningshastigheten och nablas för att uppdatera nätverkets vikter och fördomar. Varje värde uppdateras till det senaste värdet, minus inlärningshastigheten, multiplicerat med minibatchstorleken och läggs sedan till nablavärdet.
Utvärdera funktion
Utvärdera funktionen är den sista vi behöver skriva. Testdata är den enda ingången för denna funktion. I den här funktionen jämför vi bara utdata från nätverket med det förväntade resultatet, y. Genom att mata ingången, x, framåt, bestäms utgångarna från nätverket.
Komplett kod
När vi kombinerar all kod ser det ut så här.
Testar neurala nätverk
Laddar MNIST-data
Smakämnen MNIST-data är i .pkl.gz-format, som vi öppnar med GZIP och laddar med pickle. Låt oss skriva en snabb metod för att ladda dessa data som en tuppel av storlek tre, uppdelad i tränings-, validerings- och testdata.
För att göra vår data enklare att hantera, kommer vi att skriva en annan funktion för att koda y till en array med 10 artiklar. Arrayen kommer att vara alla nollor förutom en 0 som matchar bildens rätta siffra.
Vi kommer att använda grundläggande laddningsdata och en hetkodningsmetod för att ladda vår data till ett läsbart format. En annan funktion kommer att skrivas som kommer att konvertera våra x-värden till en lista med storlek 784, matchande med bildens 784 pixlar, och våra y-värden till sin enda varmkodade vektorform.
Sedan kommer vi att kombinera x- och y-värdena så att det ena indexet matchar det andra. Detta gäller utbildnings-, validerings- och testdatauppsättningarna. Vi returnerar sedan de ändrade uppgifterna.
Löpande tester
Vi kommer att skapa en ny fil som heter "mnist loader" som kommer att importera både det neurala nätverk som vi etablerade tidigare (enkelt nn) och MNIST-datauppsättningsladdaren innan vi börjar testa.
I den här filen behöver vi bara importera data, bygga ett nätverk med en indatalagerstorlek på 784 och en utdatalagerstorlek på 10, köra nätverkets SGD-funktion på träningsdata och sedan testa den med hjälp av testdata.
Tänk på att för vår lista med indatalager spelar det ingen roll vilka siffror som helst mellan 784 och 10. Vi kan ändra de andra lagren som vi vill; bara ingångs- och utmatningsstorlekarna är fasta.
Tre lager är inte nödvändigt; vi kan använda fyra, fem eller till och med bara två. Ha kul att experimentera med det.
Slutsats
Här skapar vi med Python 3 ett neuralt nätverk från grunden. Tillsammans med matematik på hög nivå diskuterade vi också detaljerna kring implementering.
Vi började med att implementera hjälpfunktioner. För att neuronerna ska fungera är sigmoid- och sigmoid-primfunktionerna avgörande. Vi tillämpar sedan feedforward-funktionen, som är den grundläggande processen för att mata in data till det neurala nätverket.
Därefter skapade vi gradient descent-funktionen i Python, motorn som driver vårt neurala nätverk. För att lokalisera "lokala minima" och optimera deras vikter och fördomar, använder vårt neurala nätverk gradientnedstigning. Vi skapade backpropagation-funktionen med hjälp av lutning nedstigning.
Genom att leverera uppdateringar när utgångarna inte matchar de rätta etiketterna, gör den här funktionen det möjligt för det neurala nätverket att "lära sig".
Slutligen lägger vi vår helt nya Python neurala nätverk till testet med hjälp av MNIST-datauppsättningen. Allt fungerade smidigt.
Lycklig kodning!
Kommentera uppropet