Machine Learning

Home/Machine Learning

February 2018

Singularity Report – volume I

By |February 25th, 2018|Machine Learning|

Den første skikkelige datamaskinen jeg eide, var en IBM AT. Du kunne åpne panseret, og under, så fant man en Intel 80286, som ble drevet av ei klokke på 6MHz. Skjermkortet var av typen Hercules. Det kunne produsere grafikk med en farge, men oppløsningen var overlegen alt annet som var på markedet, vanvittige 720 x 350 piksler. Dessverre, så hadde jeg ikke råd til matteprosessor i maskina (80287), så flyttallsberegninger kunne nok gått raskere. Uansett – det var en fullverdig datamaskin.

Man kunne gjøre mye, selv med relativt moderat regnekraft. Jeg husker at jeg ivrig hoppet et stykke fram i matteboka for å lære meg å regne med komplekse tall, slik at jeg kunne lage programmer i C for å tegne fraktaler.

Mye har skjedd i løpet av de 30 siste årene, og gæmliser, som meg forsøker gjerne å sette utviklingen i perspektiv ved å, til det kjedsommelige, fortelle kidsa at datamaskinen de nå går rundt med i lomma er sykt mye kraftigere enn hva som var nødvendig for å sende folk til Månen – en gang for lenge siden.

“Meh..”

I kveld forsøkte jeg å imponere kidsa igjen. Denne gangen ved å demonstrere at det var mulig å bytte ut ansiktet til Harrison Ford med mitt eget i Blade Runner-traileren ved hjelp av en autoencoder. Dette er et neuralt nett, som forsøker å gjenskape sin input på basis av en laveredimensjonal representasjon (ikke helt ulikt lossy kompresjon). I dette tilfellet, så trenes det opp to nettverk, der begge nettverkene deler encoder, men har hver sin decoder.

Jeg forsøkte å fortelle kidsa at man ikke trengte å programmere maskinene lenger, man trengte kun å vise fram ting til dem og så fortelle hva som var rett og galt. Maskinene kunne nå lære som barn. Ihvertfall nesten.

Eldstejenta var ikke imponert, selv om jeg insisterte på at hun levde i en UTROLIG SPENNENDE TID. YAY!?!

“Meh…”

Vi vandret så opp fra kjelleren og spiste taco og drakk cola.

Anyways,

Maskinlæring er tidvis mindboggling. Det som er litt mer mindboggling er hvis vi sier noe om hvor Moores lov har brakt oss i dag. FakeApp har snurret på GPUen min i et par døgn nå. Den har 2560 kjerner, som hver snurrer på 1,6 Ghz – sånn ca. To døgns prosessering på dette kortet, som fysisk er på størrelse med det gamle Hercules-kortet mitt, kanskje litt feitere i bredden, ville tatt – wait for it – 32 MILLIONER ÅR på den gamle IBM AT’en min. Hadde jeg startet beregningene på samme tid som denne 2,5 meter høye karen herjet Wyoming, så ville de vært ferdige i dag (bildet er rappet skamløst fra Wikipedia).

Denne økningen i regnekraft skyldes kun 22 doblinger siden IBM AT ble lansert. Eksponentielle ting har en tendens til å være morsommere mot slutten enn i starten. Jeg er rimelig overbevist om at vi har noen interessante år foran oss, og det er allerede ikke helt lett å henge med i svingene.

Du har sannsynligvis gjettet riktig. Jeg snakker om DeepFakes , og jepp, resten av posten er safe for work. No Worries, TimeExpander er en familievennlig bedrift.

Er du nysgjerrig på hvordan DeepFakes er skrudd sammen, men ikke føler for å få hodepine, så kan jeg anbefale motormunn Siraj Ravals introduksjon av DeepFakes på YouTube.

Jeg eksperimenterte først litt med ymse nett-topologier og trente på bilder av Harrison Ford og meg selv. Lot GPUen jobbe i et par dager. Resultatet ble sådär.

Det som er moro med neurale nett er at de lærer. Ingen programmering nødvendig!. Vis frem data og så er det stokk og gulrot som sørger for læringa. Akkurat som med unger.

Det er dog klin umulig å vite hva nettet velger å ekstrahere av kunnskap, hvilket jo gjør ting litt vanskelig for byråkrater og lovgivere, som ønsker å få kontroll på tekniken. Eksempelvis mht GDPR, som er litt i vinden for tiden.

Jeg trodde for eksempel at nettet her hadde lært seg å kjenne igjen Harrison Ford, så jeg så ikke fram til to nye døgn med læring når jeg hadde lyst til å ta plassen til Ryan Gosling istedet.

No worries. Jeg gjenbrukte forrige modell og trente i 20 minutter for å kunne ta plassen til Ryan i en av scenene.

Tror ikke resultatet lurer noen, men det var en moro øvelse likevel. I.o.m at jeg har gått til innkjøp av fænci GPU, og nå også har hylla full av deep learning-litteratur, så tror jeg kanskje det ligger an til noen enkle maskinlæringsprosjekter i tiden fremover. Har allerede tafset litt på TensorFlow og har også lyst til å lære meg Keras.  Vi får se hvor det bærer :)

June 2016

Making a brain – for recreational purposes. Step 3 (XP+1)

By |June 20th, 2016|Machine Learning, Programming|

Etter å ha brynet meg på egen implementasjon av neurale nett, effektiv backprop, softmax, gradienter, cross-entropy og fandens oldemor i C++ i noen uker, så bestemte jeg meg for å igjen slippe Tensorflow ut av Ubuntu-buret sitt. Semantikken er relativt tight, så jeg håpet å få litt mer ut av det, nå som maskinlæringsvokabularet mitt har modnet litt – etter uker med “selvplaging”. Jeg prøvekjørte det litt mer avanserte MNIST-eksempelet i Tensorflow, der det benyttes convolutional nettverk. Dette kjørte i kanskje 10 minutter, før det resulterte i 99.26% treffsikkerhet ved klassifikasjon av siffer i testsettet (kun CPU).

Jeg sitter nå igjen med en mulighetsfølelse, som jeg kun har opplevd ved…

  • første eksponering for programmering i 1983,
  • første eksponering for internett i 1992
  • første eksponering for 3D-printere i 2011.

Jeg er faktisk litt satt ut. Ikke nødvendigvis av teorien, selv om backpropagation og gradient descent er konseptuelt vakkert. Ikke av alfabetsuppa, selv om den har gitt meg hodepine, samt resultert i ganske kraftig språkbruk her i kjelleren.

Man aner konturene av noe som er ekstremt kraftig. Ekstremt elegant. Og som i tillegg skalerer.

Min generasjon hadde Meccano og Lego. En generasjon senere, så er det innenfor mulighetsrommet til et gjennomsnittlig ressurssterkt barn å nå kunne komponere kognitive funksjoner til sin egen autonome 3D-printede dronesverm. Hvor kult er ikke det ?

Making a brain – for recreational purposes. Step 2 (Level up!)

By |June 10th, 2016|Machine Learning, Programming|

Makan til alfabetsuppe skal man lete lenge etter. Matematikere burde sporenstreks ta seg et kurs i hvordan man kommuniserer enkle konsepter til andre mennesker. Deler av maskinlæringslitteraturen er imho direkte menneskefiendtlig.

Jeg er nå nesten helt sikker på at jeg har implementert Stochastic Gradient Descent med Nesterov momentum og L2-regularization – riktig. Jeg er nesten også helt sikker på at jeg normaliserer input, bruker tanh-aktiveringsfunksjon og softmax på output – riktig. Beviset ligger likevel, som kjent, i puddingen. Evne til overfitting og korrekt klassifisering av et treningssett er en indikasjon på en viss grad av virk. Og for å kunne sjekke om man har en rimelig grad av virk, så trenger man da det som på fagspråket heter “data” :)

Et glitrende datasett, som det er moro å bryne seg på er MNIST.

MNIST er en database over håndskrevne siffer. Den består av et treningssett med 60000 siffer og et testsett på 10000 siffer. Hvert siffer er et bitmap på 28×28 pixels. Gitt at man ikke har featuredetektorer i forkant, så vil et enkelt nett for å lære seg å klassifisere disse, ha 784 inputnoder, et eller flere skjulte lag med noder og 10 noder i outputlaget. Ved å benytte softmax-algoritmen, så tvinger man output inn i en sannsynlighetsfordeling, hvilket er glitrende når man skal bygge et et neuralt nett, som skal klassifisere noe.

Utfordringen er å ikke trene nettet slik at det kun husker treningssettet , men på en slik måte at det er i stand til å lære å ekstrahere features fra treningsettet.

Det sparker rimelig greit unna, selv om koden sannsynligvis ikke er helt optimal mht hastighet (Jeg fokuserte i første omgang på egenopplæring + korrekt oppførsel + kode som ikke resulterte i hjerneblødning ved forsøk på å lese den dagen etter). På en relativt gammel i7, så klarer et {I:784, H:128, O:10}-nett typisk å lære seg å klassifisere 2000 siffer på 10-12 sekunder. Anser det som “innafor”, selv om det nepper er i TensorFlow-divisjonen mht ytelse.

Backpropagation er i essens et sett av matrise-/vektoroperasjoner og treningen er et høyst dataparallelliserbart problem. Hvorfor nøye seg med kun en kjerne ? Neste trinn blir derfor å gå litt mer i dybden på C++AMP for å kunne trene større nett på GPU.

Det klør også litt mht å skrape i overflata på andre typer av nettverk, som eksempelvis RNN for tidsserieprediksjon, convolutional nettverk mtp bildegjenkjenning, deep belief-nettverk, samt visualisering av hva som skjer under trening.

PS. Jeg vet det finnes glitrende rammeverk der ute, men man lærer mye mer av å implementere ting fra first principles.

December 2015

Making a brain – for recreational purposes. Step 1

By |December 23rd, 2015|Machine Learning, Programming|

Neurale nett har blitt poppis igjen. Sist jeg lekte med slike, så forsøkte jeg å trene opp nett, implementert i Turbo C (2 disketter…)  på en 12 MHz IBM AT. Det var ikke spesielt moro. Sånn i etterpåklokskapens lys, så er det vel heller ikke helt utelukket at jeg kan ha blingsa litt på på et par av formlene.

Jeg nøyde meg derfor med å lese om maskinlæring og AI istedet. Jeg leste Neuromancer, Burning Chrome og Mona Lisa Overdrive med det ene øyet og alt for vanskelige bøker og papers med det andre. Jeg skal ærlig innrømme at jeg kanskje fikk mest ut av William Gibson sine romaner på den tiden, men det var likevel moro å skrape litt i overflata på algoritmene, slik at man kunne bli ufordragelig i baren i Bodegaen, når folk begynte å bli filosofiske, etter et par øl for mye.

Det var på starten av 90-tallet et ganske markant gap mellom science fiction-AI og AI i den virkelige verden. Selv om neurale nett var den nærmeste analogen man hadde til neuroner og synapser i biologiske systemer, så endte det gjerne opp i rene teoretiske øvelser. Vi manglet nok “oomph” under panseret på datamaskinene våre, til at vi kunne trene opp litt større nett, som gjorde særlig spennende saker . (Trening av nett er tungt, men kjøring av et ferdig trent nett, koker ned til et lite antall matriseoperasjoner, som man kan kjøre på en liten mikrokontroller med flyttallsstøtte, uten videre problem).

I dag, så er det litt anderledes. Har du handlet deg en datamaskin for å kunne “surfe på nett”, “bruke nettbank” eller “levere lottokupong”, så har du etter all sannsynlighet nok prosesseringskraft tilgjengelig for å kunne leke deg med enkel AI uten at maskina blir svett. Gapet er i ferd med å lukkes og jeg har en liten følelse av at det nå, gitt ressursene til eksempelvis Google, nå begynner å bli “sping tinglingly”smalt. Litt usikker på om våre venner, politikerne, er helt forberedt på scenariene vi nå vil få se, der den selvkjørende bilen din, eksempelvis velger å drepe deg, ved å kjøre i grøfta, fremfor å kjøre ned fotgjengeren i gangfeltet, eller når den første kunstige intelligensen blir installert i droner for å ta kill-beslutninger, slik at ikke soldatene skal få PTSD etter litt for mange timer foran skjermen.

Det eneste en AI forsøker å gjøre er å minimalisere kostfunksjonen sin – en funksjon spesifisert av mennesker – forhåpentligvis korrekt, og forhåpentligvis en funksjon, som ikke har utilsiktede sideeffekter.

Genetiske algoritmer, fuzzy logic og neurale nett var all the rage tidlig på 90-tallet, men så forsvant de under radaren min. Inntil i år. Fire ting skjedde (omtrent i denne rekkefølgen) :

  1. En kompis (Hei, Ståle !) sendte meg en link til “The Unreasonable Effectiveness of Recurrent Neural Networks”.
  2. “Deep Dream”-videoer og bilder begynte å poppe opp her og der i newsfeeden min.
  3. Jeg traff en freelance-koder i Roma, som jobbet med AI. Jeg beynttet anledningen til å spørre litt om det jeg trodde jeg hadde lært om NN på 90-tallet fremdeles var good shit.
  4. Google opensourcet TensorFlow.

Inspired, I became…

Det var på tide med et lite litteraturstudie igjen. Dette er vel strengt tatt pensum for kidsa på Gløshaugen, men siden jeg er mer i “halvstudert røver” / “old fart”-kategorien, så må jeg stadig vekk gjøre slike øvelser for å henge med.

Valget sto mellom å bruke tid på tensorflow, eller forsøke å plugge kunnskapshullene som oppsto når jeg prioriterte William Gibson sine romaner fremfor å forsøke forstå matematikken bak minimalisering av kost-funksjonen i et neuralt nett via backpropagation og deltaregelen.

Siden jeg er selværklært maker (begynner så smått å bli et litt utslitt begrep, men), så ønsket jeg også en implementasjon, som var såpass lettbeint at den kunne trenes på en PC (eks med styrings-/sensortelemetri-data fra en liten robot) og så lett kunne kjøre det trente nettet på svært billig embedded hardware.

Jeg fyrte så opp C++-kompilatoren og skred til verket. Første forsøk bar galt av sted i.o.m. at jeg lot OO-nissen i meg få slippe til med helt feil abstraksjoner (Jeg er et barn av OO-generasjonen, men kjenner litt på en dragning mot funksjonell programmering). Jeg modellerte min forståelse av et NN, Dvs “nettverk”, “lag”, “inputlag”, “skjult lag”, “outputlag” etc. Koden eksploderte og ting ble ikke spesielt pent.

Det gikk 2-3 kvelder før jeg innså at de eneste abstraksjonene jeg trengte var “nettverk”, “treningssett”, “matrise” og “vektor”.  Dette ga en 1:1 mapping med begrepsverdenen i litteraturen og algoritmene. Koden ble da tight. Vi snakker 3-400 linjer (inludert tracing / graphvizoutput) for implementasjon av klasser som lar deg spesifisere nettverk med vilkårlig antall lag og vilkårlig antall noder i hvert lag. Eksempelvis så vil følgende deklarasjon resultere i et nettverk med 3 lag, der man har 5 inputnoder, 5 skjulte noder og ett outputnode:

   Network n({5, 5, 1});

Ønsker man en visuell representasjon av nettverket, så kan man generere en graf-representasjon for GraphViz:

   n.ExportAsDigraph("d:\\MyNetwork.gv");

Formatet for treningssettene er en liste med kommaseparerte inputverdier -> liste med kommaseparerte output. Eksempelvis, så vil treningssettet for sannhetstabellen for XOR, se slik ut:

   # XOR
   1,1 -> 0
   1,0 -> 1
   0,1 -> 1
   0,0 -> 0

Kode for trening av nettverket vil kunne se noenlunde slik ut:

   TrainingSet set("MySet.training");
   int iter = n.Train(set, learningrate, maxError, maxIterations);

Jeg brukte enkle nettverk for å debugge funksjonene for backpropagation-algoritmen. Treningssettene under debuggingsesjoner var typisk sannhetstabeller for AND, OR og XOR.

Men,…

En ting er enkle mappinger mellom input og output. Det som ga meg TOTAL BAKOVERSVEIS var når jeg forsøkte meg på et treningssett, som i praksis krevde at nettet var translasjonsinvariant. Jeg bestemte meg for å sjekke om koden ville klare å identifisere bitpar i et ringbuffer. Eksempelvis klassifisere 11000, 01100, 00110, 00011 og 10001, som samme greie, men forkaste alle andre bitmønster. Jeg bestemte meg for å teste med et 5:5:1 nett:

network2

Og dette er trace-output fra nettet…

1 1 0 0 0 -> 0.98942
0 1 1 0 0 -> 0.955088
0 0 1 1 0 -> 0.994225
0 0 0 1 1 -> 0.956921
1 0 0 0 1 -> 0.946448
0 0 0 0 0 -> 8.01082e-007
1 1 1 0 0 -> 0.000139072
0 1 1 1 0 -> 0.000123884
0 0 1 1 1 -> 0.00241042
1 0 0 1 1 -> 0.000115517
1 1 0 0 1 -> 0.00316957
0 0 0 0 0 -> 8.01082e-007
1 0 0 0 0 -> 0.0152408
0 1 0 0 0 -> 0.000225992
0 0 1 0 0 -> 0.000161386
0 0 0 1 0 -> 0.0165893
0 0 0 0 1 -> 0.0240119
1 1 1 1 1 -> 0.00393661
1 1 1 1 0 -> 0.000946888
0 1 1 1 1 -> 4.03198e-005
1 0 1 1 1 -> 0.00302191
1 1 0 1 1 -> 0.00172643
1 1 1 0 1 -> 5.37666e-005
1 1 1 1 0 -> 0.000946888
Training result : PASSED in 227 iterations.
Layering structure : 5 5 1

matrix[i, j]
-7.381501e-001 4.910103e-001 2.348347e+000 5.589301e-001 1.393025e-001
6.232929e+000 -3.010492e+000 -3.575540e+000 6.308999e+000 -2.263603e+000
7.602698e+000 -4.410647e+000 -4.660858e+000 7.579302e+000 -3.254401e+000
2.161218e-001 5.300884e+000 -3.041684e-001 -8.590031e+000 2.228310e+000
-8.501116e+000 2.924318e-002 4.881199e+000 5.905061e-002 2.334400e+000

matrix[k, l]
3.230551e+000 8.396336e+000 1.152779e+001 1.566610e+001 1.500300e+001

Tankene går til åpningsstrofene i “For What it’s worth” (Buffalo Springfield). “There’s something happening here. What it is ain’t exactly clear…”

Next up: “Andre greier jeg ikke lærte på skolen . D.v.s RNN, Markovmodeller & annen crazy shit vi trenger å implementere Skynet”