Kom igang med maskinlæring!

William Almnes
Systek
Published in
5 min readNov 18, 2020
Photo by Markus Winkler on Unsplash

For mange så er maskinlæring et “buzzword” som blir mye brukt i den digitale verdenen for å beskrive en måte å løse små og store utfordringer. Kanskje det er litt mystisk hvordan dette fungerer, men jeg vil vise hvor enkelt det er å komme i gang med maskinlæring.

Målet i denne artikkelen er å lage et veldig primitiv nevral nettverk som vi lærer opp til å “lese” tall (0–9). Dette er en subgren av maskinlæring som kalles “computer-vision

Oppsett av miljøet

Vi skal bruke Tensorflow, et open-source bibliotek for å trene maskinlæringsmodeller, og Keras, et API som forenkler denne prosessen. Planen er at vi skal trene modellen lokalt, eksportere modellen og ta den i bruk i en webapp. For å bruke Tensorflow vil vi bruke Python. Jeg antar at dere har det allerede installert og hvis ikke så finnes det mange gode oppskrifter man kan følge ute på nettet.

Jeg vil anbefale å bruke Anaconda (og Conda) for å håndtere bruk av virtuelle miljøer og avhengighetene til applikasjonen, men man kan bruke andre alternativer også. Hvis du velger å benytte andre alternativer så kan du skippe denne delen.

Hvis du installere Anaconda Individual Edition og følger oppskriften på deres webside, så får du både Anaconda og Conda.

Da kan du opprette et miljø ved å skrive i terminalen din:

conda create --name <your-env-name> <…packages>

Så i vårt tilfellet kan vi gjøre:

conda create --name computer-vision tensorflow keras matplotlib

Dette vil opprette miljøet computer-vision og laste ned pakkene (og alle pakker de er avhengige av) Tensorflow, Keras og matplotlib (som vi trenger senere). Du blir spurt om å fortsette med nedlastningen, og da er det bare å trykke y for å fortsette.

Nå må vi aktivere miljøet ved å skrive:

conda activate computer-vision

La oss sjekke at alt er i orden. Lag en python fil som heter index.py og åpne den i din favoritt IDE. Personlig så bruker jeg Pycharm (anaconda) for Python og ML. Legg til dette i python filen din:

import tensorflow as tfprint(tf.__version__)

Hvis du kjører denne lille kodesnutten så bør du få versjon 2.2.0 eller noe lignende. Isåfall har vi satt opp miljøet riktig. Hurrah!

Bruk av MNIST

MNIST-datasettet er en samling av håndskrevne tall fra 0 til 9. Det inneholder 60 000 treningsbilder og 10 000 testebilder. Dette datasettet er veldig ofte brukt til trening og testing i ML.

Det er heldigvis veldig enkelt å benytte seg av dette datasettet fordi Keras tilbyr en enkel måte for oss til å laste det inn. La oss modifisere index.py til følgende:

import tensorflow as tfmnist = tf.keras.datasets.mnist(x_train, y_train), (x_test, y_test) = mnist.load_dataset()# Bekreft at vi har 60 000 treningsbilder og 10 000 testebilder
print(len(x_train)) # skal være 60 000
print(len(x_test)) # skal være 10 000

Hvis du fikk riktig mengde treningsbilder og testebilder så kan vi fjerne de print-kommandoene.

Noe som er veldig vanlig når man jobber med data i ML er å normalisere verdiene slik at de er mellom 0 og 1. Slik jeg forstår det så vil “activation functions” i nevral nettverket vårt fungere bedre mellom de verdiene. La oss legge til denne linjen for å normalisere verdiene:

x_train, x_test = x_train / 255.0, x_test / 255.0

Neste steg er å lage modellen vår. Modellen vår vil bestå av en “input layer”, en “hidden layer” og en “output layer”. Bildene vi får fra MNIST datasettet er 28x28 pixler. Bildene er kun i gråskala, som betyr at vi kun har en kanal for farge. Vi kan da spesifiere formen til “input layer” ved å skrive input_shape=(28, 28, 1). Vi omgjør altså inputtet vårt til en flat 1D vektor. Dette er nødvendig når “output layer” skal gjøre klassifikasjonen. Selvfølgelig, dette gjør at vi mister informasjon om hvor pixlene befinner seg i forhold til hverandre, men for dette lille eksempelet så skal vi se at vi får relativt høy presisjon allikevel.

Vår “hidden layer” består av 128 nevroner og bruker en “rectified linear activation function (ReLU/relu). Laurence Moroney (“lead AI advocacy” i Google), gir en enkel forklaring av dette (oversatt til norsk av meg): Det er enklere å tenke på nevroner som parametere til en funksjon. Målet med nevral nettverket er å finne en regel som passer for alle parameterene som omgjør de 784 verdiene vi får fra “input layer” til en av kategoriene (tallene 0–9).

“Output layer” har like mange nevroner som vi har kategorier. I vårt tilfelle blir det 10 kategorier for tallene 0 til 9.

model = tf.keras.Sequential([
// input layer
tf.keras.layers.Flatten(input_shape=(28, 28, 1)),
// hidden layer
tf.keras.layers.Dense(128, activation=’relu’),
// output layer
tf.keras.layers.Dense(10, activation=’softmax’)
])
# For å inspisere modellen vår:
model.summary()

Under ser du resultatet av model.summary(). Her ser vi at vi får 784 verdier fra “input layer” (fra 28*28 pixels).

Layer (type) Output Shape Param # 
=================================================================
flatten_1 (Flatten) (None, 784) 0
_________________________________________________________________
dense_2 (Dense) (None, 128) 100480
_________________________________________________________________
dense_3 (Dense) (None, 10) 1290
=================================================================

Neste steg er å kompilere modellen vår. Da må vi spesifisere en “optimizer function”, en “loss function” og metrikker. Jeg vil bare kort beskrive disse funksjonene fordi ellers vil denne artikkelen bli altfor lang, i tillegg til at jeg har begrenset kunnskap i detaljene rundt disse funksjonene.

Nevral nettverket vet ikke noe om forholdet mellom bildene og kategoriene. Når nevral nettverket gjør et forsøk på å lage en funksjon som beskriver forholdet, så vil “loss function” målet hvor bra dette forsøket var. Deretter vil “optimizer function” finne ut hvordan neste forsøk bør være basert på dataen fra “loss function”.

model.compile(
optimizer=’adam’,
loss=’sparse_categorical_crossentropy’,
metrics=[‘accuracy’])

Etter at vi har kompilert modellen vår så kan starte å trene den. Dette gjøres med model.fit-metoden. Vi kommer til å bruke treningsdataen vi fikk fra MNIST-datasettet og trener det for 20 epoker. Grunnen til at jeg valgte 20 er fordi jeg inspiserte resultatet og ser at jeg ikke får noe særlig økning i presisjon etter det. Legg merke til at vi sender testdataen inn i validation_data for at modellen kan sjekke hvor godt den gjør det per epoke.

model.fit(x_train, y_train, epochs=20, validation_data=(x_test, y_test))

Nå som vi har trent modellen må vi undersøke hvor godt den presterer. Da bruker vi model.evaluate metoden og sender inn testdataen.

model.evaluate(x_test, y_test, verbose=2)

Jeg får en presisjon på 97.85%, men dette kan variere fra maskin til maskin og hver gang man eksekverer koden.

Resultatet og et webeksempel

Nå har vi laget et veldig enkelt nevral nettverk som gjenkjenner tallene 0–9. Det var ikke så ille! Når man har trent en modell så kan man ønske å bruke det mot ekte data (i motsetning til testdataen) for å se hvordan den fungerer i “den virkelig verden”.

Jeg lagde en enkel webapp som tar input fra bruker og sender det til modellen vår som da gjetter hvilke tall brukeren tegnet inn. Det kan testes her. Her vil man oppleve at presisjonen ikke er like god pga modellen er veldig primitiv.

Et screenshot av en bruker som tester “computer vision”-webappen
Et screenshot av en bruker som tester “computer vision”-webappen

Som du nå har sett så trenger det ikke å være så vanskelig å begynne med maskinlæring. Begynn med noe enkelt og prøv deg litt frem, så vil du se at det åpner seg en verden av muligheter. Lykke til!

--

--