Vælg land og sprog
Sprog
Byg en hjerne på 10 minutter med Nvidia
I dag bygger vi en meget enkel hjerne. Ikke en science fiction-robothjerne, men et grundlæggende neuralt netværk, der kan lære at genkende billeder af tøj med datasættet Fashion MNIST. Målet er at få en maskine til at se et utydeligt gråtonebillede og sige: ”Det er en sneaker.”
Vi arbejder i TensorFlow og Keras, to populære biblioteker til deep learning i Python. Gennemgangen er inspireret af NVIDIAs Deep Learning Institute.
Perceptronen, udviklet af Frank Rosenblatt i 1958, er en af de tidligste milepæle i neurale netværks historie. Det var en enkel neural model med ét lag, som skulle efterligne hjernens læring gennem forsøg og fejl. Selvom evnerne var begrænsede – den kunne eksempelvis ikke løse XOR – lagde forskningen grundlaget for nutidens deep learning-systemer. Dokumentaren minder os om, hvordan tidlige AI-ambitioner banede vej for de stærke modeller, vi bygger i dag.
Først: Er computeren udstyret til deep learning? Vi beder TensorFlow vise de fysiske GPU-enheder. De er som turboladere til træning af neurale netværk. En CPU kan også klare det, men det er som et kapløb mellem en hest og et lille barn.
import tensorflow as tf tf.config.list_physical_devices('GPU')
Hvis svaret viser en GPU, er vi heldige. Træningen går hurtigere.
Nu tager vi fat på en udfordring, der ville have virket næsten umulig for få årtier siden: at træne en computer i billedgenkendelse med computer vision. Vores konkrete opgave er at identificere forskellige typer tøj i Fashion MNIST -datasættet.
Inspireret af menneskers læring gennem forsøg og fejl simulerer vi processen med digitale huskekort. Den kunstige hjerne, vores neurale netværk, gætter på de viste beklædningsgenstande, og vi retter den ved at oplyse de rigtige etiketter. Over tid lærer den både af fejl og succeser.
Ligesom elever før en prøve holder vi data tilbage for at vurdere generalisering til eksempler, der ikke blev brugt til at tilpasse vægtene. Gode valideringsresultater hjælper med at opdage overtilpasning, men beviser ikke menneskelig forståelse eller ræsonnement. Bevar et separat testsæt til den endelige vurdering, når valideringsresultater bruges til at justere modellen.
De data, vi bruger til at lære modellen, kaldes training dataset, mens de reserverede testdata kaldes validation dataset. Fashion MNIST er et velkendt datasæt, så TensorFlow inkluderer det som standard. Lad os indlæse det og se, hvordan det ser ud.
fashion_mnist = tf.keras.datasets.fashion_mnist (train_images, train_labels), (valid_images, valid_labels) = fashion_mnist.load_data()
Før vi beder et neuralt netværk skelne mellem en sneaker og en skjorte, er det nyttigt at kontrollere, at vi selv kan fortolke dataene.
Datasættet giver os train_images og train_labels. Tænk på train_images som de spørgsmål, vi stiller modellen – det, den ser – og train_labels som de tilhørende svar. Inden for datavidenskab kaldes disse svar normalt labels.
For bedre at forstå inputtet kan vi vise et eksempelbillede med Matplotlib, et populært plottingbibliotek i Python.
import matplotlib.pyplot as plt data_idx = 69 plt.figure() plt.imshow(train_images[data_idx], cmap='gray') plt.colorbar() plt.grid(False) plt.show()
Her ser vi ét eksempelbillede, i dette tilfælde nummer #69. Når du ser på det, siger du måske: ”Det ligner en fallisk genstand.”
Det har du nok ret i, men det er faktisk et par bukser:
train_labels[data_idx] # Output: 1
Etiket 1 svarer til bukser. Godt klaret, menneske. Her er en fin tabel, som hjælper os med at se de forskellige kategorier.
Neuroner er de grundlæggende enheder i et neuralt netværk. Biologiske neuroner sender elektriske signaler, når de modtager den rette påvirkning, hvilket eksempelvis hjælper dig med at skelne mellem rødt og gult. Kunstige neuroner gør noget lignende, men arbejder med tal: Når du indtaster bestemte værdier, producerer de et numerisk resultat.
Du kan tænke på oprettelsen af en neuron i tre hovedtrin:
Først definerer vi strukturen, altså arkitekturen.
Derefter træner vi den med data.
Til sidst vurderer vi, hvor godt den klarer sig.
Biologiske neuroner bruger et system, der minder om morsekode, til at sende information. De modtager signaler gennem dendritterne, og hvis inputtet opfylder de rette betingelser, sender de en impuls gennem axonet til neuronens ender.
Man mener, at både pulsernes timing og rækkefølge bidrager til informationen. De fleste kunstige neurale netværk efterligner ikke denne komplekse timing, men modellerer i stedet adfærden med matematiske ligninger.
Computere håndterer information som sekvenser af 0 og 1, mens mennesker og dyr arbejder med mere kontinuerlige input. Tidlige kunstige neuroner forsøgte at efterligne biologiske neuroner med en lineær regressionsfunktion: y = mx + b. Her er x inputtet, ligesom signalerne ind i dendritterne, og y er outputtet, ligesom impulsen ud af enderne. Efterhånden som systemet ser flere data og forudsigelser, justerer det værdierne af m og b for at forbedre nøjagtigheden.
Neuroner skal ofte behandle mange input samtidig. I vores eksempel er hver pixel i billedet, med en værdi fra 0 for sort til 255 for hvid, et selvstændigt input. Hvert input får sin egen vægt, svarende til vores m, og disse vægte betegnes med w. Pixel ét har altså w0, pixel to har w1og så videre. Dermed bliver ligningen noget i retning af: y = w0x0 + w1x1 + w2x2 + ... + b.
Hvert billede er 28 pixels bredt og 28 pixels højt, så hver outputneuron har 784 inputvægte. Hver pixel bidrager via sin tilhørende vægt. Med ti outputneuroner har hele modellen 7.840 vægte plus ti biasværdier.
Vi har brugt en enkel ligning, y = mx + b, der giver ét tal som output. Men vi prøver at genkende tøjtyper og ikke blot udskrive et tal. Hvordan omsætter vi et tal til en beslutning som ”Det er en T-shirt” eller ”Det er en sneaker”?
En enkel løsning er én outputneuron for hver tøjtype. Fashion MNIST har ti kategorier, så vi bruger ti neuroner. Hver producerer en rå klassescore, en logit. Den største logit bestemmer den forudsagte klasse; en logit er ikke i sig selv en sandsynlighed.
Vi kan nemt bygge denne opsætning med Keras, et højniveau-API, som nu er del af TensorFlow. Vi bruger dets Sequential API, der organiserer modellen som stablede lag. Tænk på lagene som behandlingstrin, der omsætter inputdata til forudsigelser.
Modellen, vi bygger, har to lag:
Et Flatten-lag, der omformer vores 28×28-billede til én liste med 784 værdier.
Et Dense-lagmed 10 neuroner. Hver neuron har sin egen vægt for hver inputpixel og én biasværdi. Hver neuron beregner en rå klassescore, en logit, frem for en sandsynlighed.
Vi angiver også en input_shape på (28, 28), som matcher hvert billedes pixelmål.
number_of_classes = 10 model = tf.keras.Sequential([ tf.keras.layers.Flatten(input_shape=(28, 28)), tf.keras.layers.Dense(number_of_classes) ])
Kontrollér modellen
For at sikre, at modellen har den forventede struktur, kan vi kalde dens summary -metode. Outputtet ser sådan ud:
Lad os se, hvor tallet 7.850 kommer fra. Hvert 28×28-billede har 784 pixels. For hver af de 10 outputneuroner, som repræsenterer de 10 klasser, skal vi have en unik vægt for hvert af de 784 input. Det er 784 * 10 = 7,840 vægte. De ekstra 10 parametre er biasværdier, én for hver outputneuron, så det samlede antal bliver 7,840 + 10 = 7,850. Disse biasværdier fungerer som b i ligningen y = mx + bog lader hver neuron justere sit aktiveringsgrundniveau uafhængigt.
I videnskabelig litteratur vises modelarkitekturer nogle gange som diagrammer med knuder og forbindelser. De fungerer til små netværk, men bliver uoverskuelige med moderne modeller. Diagrammet her viser kun et lille udsnit af modellen: 28 inputknuder øverst, svarende til én billedrække, og 10 outputneuroner nederst. I virkeligheden ville vi have 784 input, ét for hver pixel.
Hver prik er et input eller en neuron, og hver forbindelseslinje er en vægt, altså en af de 7.840 parametre, der kan læres.
Til sidst er der endnu en måde at kontrollere modellen visuelt: Du kan tegne den. Men når netværk bliver komplekse, ligner diagrammerne mere abstrakt kunst end nyttige værktøjer.
Model: "sequential"
| Lag (type) | Outputform | Antal parametre |
| flatten (Flatten) | (None, 784) | 0 |
| dense (Dense) | (None, 10) | 7,850 |
Total params: 7,850 (30.66 KB)
Trainable params: 7,850 (30.66 KB)
Non-trainable params: 0 (0.00 B)
Før træningen kompilerer vi modellen med en tabsfunktion og en optimizer.
Vi har bygget modellen, men hvordan hjælper vi den til at blive bedre? Tænk på det som at give en elev en prøve og et bedømmelsesskema. Vi skal kunne vurdere, hvor langt modellens svar er fra de korrekte. Det er det, loss -funktionen gør: Den beregner forskellen mellem forudsigelsen og den rigtige etiket, så modellen kan justere sine indstillinger.
Til klassifikation som vores bruger vi en bestemt tabsfunktion kaldet SparseCategoricalCrossentropy. Her er, hvad navnets dele betyder:
Sparse – I stedet for one-hot-kodede etiketter, hvor hver klasse repræsenteres af en vektor med én ener og resten nuller, bruger funktionen heltalsetiketter, eksempelvis 0 til 9. Kategorierne er altså numerisk indekserede.
Categorical – Den er beregnet til klassifikation, hvor vi forudsiger en kategori frem for en kontinuerlig værdi.
Cross-entropy – Denne del straffer forudsigelser, der giver den korrekte klasse meget lav sandsynlighed. Tabet er ikke-negativt og vokser mod plus uendelig, når sandsynligheden nærmer sig nul. Et lavere tab er bedre.
Tabsfunktionen passer godt til modellen, fordi den vurderer alle ti outputneuroner samtidig. Hvis flere neuroner kraftigt angiver deres egen klasse som rigtig, siger funktionen: ”Beklager, kun én af jer kan have ret.”
Ud over tabet kan vi inkludere andre metrics, såsom accuracy, for at få et bedre billede af ydeevnen. Nogle gange er tabet lavt, hvilket antyder gode gennemsnitlige forudsigelser, mens klassifikationsnøjagtigheden halter. Målepunkter hjælper med at synliggøre forskellen.
model.compile( optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy'] )
adam: En populær optimizer, der tilpasser læringshastighederne dynamisk.
SparseCategoricalCrossentropy: Bruges, når etiketterne er heltal fra 0 til 9 og ikke one-hot-vektorer.
from_logits=True – Det fortæller funktionen, at modellens output er rå scorer, logits, som endnu ikke er omdannet til sandsynligheder. Tabsfunktionen håndterer denne omdannelse internt.
Nu kommer det spændende, hvor modellen træner og tester sig selv. TensorFlows fit-metode gør det muligt at lære fra træningsdata og også teste på valideringsdata.
I maskinlæring betyder en epoch én fuld gennemgang af hele træningsdatasættet. Det er som en elev, der går alle sine huskekort igennem én gang. Ligesom mennesker ofte må gentage stoffet flere gange, har modellen gavn af at se træningseksemplerne flere gange.
Ved slutningen af hver epoke holder modellen pause fra studierne og tager en kort prøve med valideringsdatasættet. Det hjælper os med at måle læring i forhold til ren memorering. Nu skal den arbejde og blive klogere!
history = model.fit(
train_images, train_labels,
epochs=5,
validation_data=(valid_images, valid_labels)
)
Hvordan klarede modellen sig så? Måske et solidt B-minus? Lad os give den en chance: Den arbejdede kun med 10 neuroner, mens menneskehjernen har milliarder i gang samtidig.
Vi kan forvente en nøjagtighed omkring 80%, men tallet er ikke fast. Resultatet kan variere med rækkefølgen af træningsbillederne og den tilfældige initialisering af vægtene ved træningsstart. Lidt tilfældighed indgår i hver kørsel, så to træninger er aldrig helt identiske.
Nu hvor træningen er færdig, kan vi undersøge forudsigelserne. Eksemplerne nedenfor bruger træningsbilleder og er derfor en demonstration, ikke en uafhængig evaluering. Vi bruger predict -metoden til at se dens forudsigelser for et hvilket som helst billede, både fra træningsdatasættet og helt nye billeder.
Husk, at Keras altid forventer input i batches, også selvom der kun er ét billede. For at forudsige ét billede skal vi derfor stadig sende det som en batch med ét element.
Vi ser på forudsigelser for de første 10 træningsbilleder. De rå output er logits: relative klassescores, ikke kalibrerede sandsynligheder. Softmax omdanner logit-vektoren til sandsynligheder, der summerer til én, men garanterer ikke kalibrering.
Vi viser inputbilledet og et søjlediagram over logits. Sammenlign scorerne indbyrdes: Den højeste score giver den forudsagte klasse. En negativ logit betyder ikke i sig selv, at klassen er usandsynlig eller forkert; lægges den samme konstant til alle logits, ændres softmax-sandsynlighederne ikke.
Du kan ændre data_idx -værdien for at se forudsigelser for andre eksempler. Hvor nøjagtig synes du, modellen er? Er dens fejl forståelige?
plt.imshow(train_images[data_idx], cmap='gray') plt.show() predictions = model.predict(train_images[data_idx:data_idx+1]) plt.bar(range(10), predictions.flatten()) plt.xticks(range(10)) plt.show() print("correct answer:", train_labels[data_idx])
Diagrammet sammenligner scorer for de 10 kategorier. Ideelt matcher den højeste søjle den rigtige klasse. I dette eksempel var det en sneaker.
Ideelt er søjlen for klasse 7 højest. Det betyder, at modellen vælger sneaker som sin forudsagte klasse; selve søjlehøjden er ikke en sandsynlighed.
Bum. Det var en sneaker.
Og sådan, kære lytter, bygger du en hjerne på 10 minutter. Den er ikke bevidst og drømmer ikke, men den kan genkende sko.
Vi brugte:
TensorFlow og Keras til at bygge modellen
Fashion MNIST til data
Matplotlib til visualisering
Endnu vigtigere så vi hele forløbet: indlæs data, visualisér, byg en model, træn den og kontrollér dens forudsigelser.
I praksis er dette kun begyndelsen. Bedre modeller ville bruge dybere lag, dropout til regularisering og normalisering af data. Men hvis du forstod dette, forstår du kernen i maskinlæring.
Maskinen ændrede ikke verden endnu, men måske blev din lidt klogere.
Sprog