729G78 Artificiell intelligens
Laboration 7: Artificiella neurala nät
Sammanfattning
I den här laborationen ska ni testa neurala nät som kan känna igen handskrivna siffror.
Syfte
Syftet med denna laboration är att ge ett konkret exempel på hur neurala nät fungerar och hur man kan tillämpa dem på mönsterigenkänning. Laborationen ger även möjlighet att använda och fördjupa den teori som förmedlas i föreläsningarna och i kursboken.
Om laborationen
För att laborationen ska gå så smidigt som möjligt, förbered er väl.
- Repetera materialet om neurala nät.
- Läs igenom de relevanta delarna av kursboken.
- Läs noggrant igenom labbinstruktionerna.
Materialet till denna laboration består av följande:
- en implementation av en enkel nätarkitektur i Python
- en datamängd för att träna och testa på
- ett färdigtränat exempelnät som ni kan testa på denna datamängd
Den centrala filen är network.py
som innehåller en implementation av en enkel nätverksarkitektur. Den definierar en klass Network
som representerar feedforward-nät med sigmoid-neuroner.
Den för laborationen viktigaste metoden i klassen är feedforward(x)
som beräknar nätets utvärde (en vektor med utsignaler) för ett givet invärde (en vektor med insignaler) x
. Vektorer är speciella datatyper; ni behöver bara veta att de i stort sett fungerar som listor. Till exempel är det så att x[5]
ger den 5:e komponenten i en vector x
.
Den enda kodfil som ni behöver ändra i för att utföra denna laboration är Lab7-LiU-ID-1_LiU-ID-2.py
. Denna fil innehåller skelettkod och ett antal funktioner som ni kan använda för att testa hur långt ni har kommit med att lösa uppgifterna (se nedan).
Datamängd
Den datamängd som används i laborationen kommer från MNIST-databasen av handskrivna siffror. Den är uppdelad i en träningsmängd (60 000 exempel) och en testmängd (10 000 exempel). Varje datum består av en bild på en handskriven siffra och ett facit (siffran som bilden föreställer). Här är några exempel på hur bilderna kan se ut:
Varje bild består av 28 x 28 = 784 pixlar som representerar nyanser av grått. För att kunna användas som indata till ett neuralt nät så transformeras varje bild till en vektor med 784 komponenter där varje komponent anger motsvarande pixelns gråvärde som ett flyttal mellan 0 och 1.
Träningsdatamängden kan läsas med hjälp av funktionen read_training_data()
; ett konkret anrop visas i filen Lab7-LiU-ID-1_LiU-ID-2.py
. Funktionen returnerar en lista med par (x, y)
där x
är en bildvektor och y
är en vektor som representerar facit för bilden (siffran som bilden föreställer). Facitvektorn för en siffra i är en vektor med 10 komponenter; den har värdet 1.0 i komponent i och värdet 0.0 i alla andra komponenter.
Här är exempel på träningsdata. Istället för bildvektorn visas själva bilden. Till höger om bilden visualiseras facitvektorn genom att rita ett svart sträck vars position i rutan motsvarar komponentens index. Sträcket ligger högst upp för siffran 0 och längst ner för siffran 9.
Testdatamängden kan läsas med hjälp av funktionen read_test_data()
; även här visas ett konkret anrop i filen Lab7-LiU-ID-1_LiU-ID-2.py
. Funktionen returnerar en lista med par (x, y)
där x
är en bildvektor och y
är facit för bilden, den här gången representerat som ett heltal mellan 0 och 9. Notera alltså att träningsdata och testdata representeras lite olika.
Exempelnätet
Exempelnätet har tre lager: ett indatalager, ett utdatalager och ett dolt lager. Indatalagret består av 784 neuroner (en för varje pixel i en bild), utdatalagret består av 10 neuroner (en för varje möjlig siffra).
Nedanstående rutor visualiserar exempel på nätets utdata när det matas med bildvektorer. Rutorna visar (från vänster till höger) bildvektorn, facitvektorn och vektorn med nätets utsignaler. I visualiseringen av utvektorn används gråvärden för att representera olika aktiveringsgrader i olika neuroner.
För att översätta en utvektor till en siffra tittar man på vilken komponent av vektorn som har det högsta gråvärdet. Om det är komponent 0 så tolkas vektorn som en representation av siffran 0, om det är komponent 1 så tolkas vektorn som en representation av siffran1, och så vidare. Om det finns flera komponenter med samma (högsta) gråvärde så ska den första användas för tolkningen.
Enligt denna tolkning så representerar alla ovanstående rutor fall där nätet har korrekt identifierat siffran. I nästan alla fall är faktiskt neuronen för guldstandardsiffran den enda neuronen som är aktiv. I exemplet med siffran 5 ser vi att två neuroner (5 och 6) konkurrerar med varandra; neuron 5 vinner. (Den har den största aktiveringen, dvs. kodar det största gråvärdet.)
Följande bilder visar fall där nätet inte lyckats att korrekt identifiera siffran: Den starkast aktiverade neuronen är inte den neuron som motsvarar guldstandardsiffran. Notera att nätets aktivitet är i många fall utspridd över flera neuroner på utlagret.
Utförande
-
Testa att koden fungerar genom att köra filen
Lab7-LiU-ID-1_LiU-ID-2.py
(se Föreberedelser nedan). Detta kör ett test som försöker att ladda testdatamängden. Om allt går som det ska rapporterar kommandot "Test succeeded". -
Implementera en funktion
evaluate()
som räknar ut felkvoten (error rate) för ett givet neuralt nät. Funktionen ska ta två argument: ett objekt som representerar ett neuralt nät (dvs. en instans av klassenNetwork
) och en testdatamängd. Felkvoten är andelen inkorrekt klassificerade exempel. (Detta är alltså ett flyttal mellan 0 och 1.) Skelettkod finns iLab7-LiU-ID-1_LiU-ID-2.py
. Testet för detta steg laddar exempelnätet och testdatamängden och anropar sedanevaluate
på dessa. Den korrekta felkvoten för exempelnätet är 4.37%. - Gör Exercise 1 och 2.
-
Filen
Lab7-LiU-ID-1_LiU-ID-2.py
innehåller en funktiontest_train
som tränar ett nät med följande inställningar:- antal noder i det dolda lagret: 20
- inlärningsparametern eta: 0.5
- variera antalet noder i det dolda lagret
- variera inlärningsparametern
- variera både antalet dolda noder och inlärningsparametern
- Gör Exercise 3, 4 och 5.
- Endast för VG: Gör Exercise 6 och 7.
Föreberedelser
- Skapa en katalog för labben och navigera in i den från terminalen.
- Kopiera filerna från kurskatalogen:
$ cp -r /courses/729G78/Lab7/* .
- Byt namn på
Lab7-LiU-ID-1_LiU-ID-2.py
för att matcha er grupps LiU-IDs. - Byt namn på och öppna exercises-dokumentet
Lab7Exercises_LiU-ID-1_LiU-ID-2.odt
för att matcha er grupps LiU-IDs. - Aktivera labbmiljön. OBS: Miljön måste aktiveras varje gång terminalen stängs.
$ source /courses/729G78/labs/environment/bin/activate
Arbeta på egen dator
- Unix
- Skapa labbmiljön
$ python3 -m venv /path/to/my/lab/environment
- Aktivera miljön
$ source /path/to/my/lab/environment/bin/activate
- Kontrollera att miljön är aktiv (bör peka på miljön du skapade ovan)
$ which python
- Installera nödvändiga bibliotek med pip
$ pip install numpy
- Skapa labbmiljön
- Windows Power Shell
- Skapa labbmiljön
$ python -m venv /path/to/my/lab/environment
- Aktivera miljön
$ /path/to/my/lab/environment/Scripts/Activate.ps1
På Windows kan det vara nödvändigt att fixa ett rättighetsproblem under inställningar:
$ Set-ExecutionPolicy Unrestricted -Scope Process
- Kontrollera att miljön är aktiv (bör peka på miljön du skapade ovan)
$ pip -V
- Installera nödvändiga bibliotek med pip
$ pip install numpy
- Skapa labbmiljön
- Ladda ned och packa upp filerna: Lab7.zip
- OBS: Miljön måste aktiveras varje gång terminalen stängs.
Inlämning
- Den uppdaterade kodfilen.
- Exercises-dokumentet som PDF.
- Ladda upp era filer i Lisam.
Krav för godkänt
För godkänt krävs att ni bearbetat alla uppgifter, visat upp en korrekt implementation av funktionen evaluate
och kunnat svara på relevanta frågor gällande era testresultat med kopplingar till terorin.
Krav för väl godkänt
För väl godkänt krävs att ni utvöver kraven ovan även bearbetat VG-uppgifterna. Dessutom krävs att svaren ni ger är utförliga, håller god kvalitet och har mycket tydliga kopplingar till teorin.
Sidansvarig: Robin Keskisärkkä