(TF)² #12 - Ekvationen för intelligens
Vad är AI? Tja, vad är intelligens? Det finns flera definitioner på det, men den som är användbar inom AI är rationalitet. Dessa termer är så sammanflätade att det som kallas intelligenta agenter på svenska heter rational agents på engelska. Ekonomisk rationalitet definierar vi som förmåga att uppnå ett mål, givet den kunskap och de förutsättningar man har.
Ska man vara ännu mer exakt så handlar det inte om den binära frågan om man lyckas uppnå ett mål eller inte, utan om att maximera nytta enligt användarens definition på nytta. Mål kan uppnås i olika hög grad, med olika nytta.
För att uppnå ett mål behöver man agera. Att agera är att manipulera ett systems (världen eller någon delmängd av den) tillstånd, där målfunktionen är en funktion från systemets tillstånd till nytta. Givet mina tillgängliga handlingar, vilken ska jag utföra för att öka sannolikheten att världen blir som jag vill? Det vanliga sättet att lösa den frågan är att dela upp resonemanget i tre delar:
Först behöver jag skapa en modell för hur olika handlingar påverkar världen och sedan vill jag
planera genom att simulera olika serier av handlingar genom min handlingsmodell för att se var jag hamnar och slutligen
mäta nyttan på dessa utfall.
Följande kommer bli den mest tekniska Tenfifty Teknikfredag som jag skrivit hittills, så spänn på mattebyxorna så kör vi!
Modellera
Vi vill alltså skapa en modell som förutsäger (en distribution över) utfall av handlingar, givet all information den fått se hittills (data som den blivit tränad på, i ML-termer). Hur ser den ideala modellen ut? En AI kör på en dator, vilket betyder att modellerna är datorprogram. Om vi tänker oss den uppräkneligt oändliga rymden av alla möjliga datorprogram som ger en modell av världen som utfall, så kan vi tänka oss att vikta varje datorprogram efter sannolikheten att just detta är den sanna formeln. Om vi sedan summerar alla modellers utfall viktat med hur sannolik modellen är, så få vi en distribution över olika världar.
Men hur vet vi hur sannolikt varje program är? Bayes sats berättar hur vi ska uppdatera en modellsannolikhet givet en observation, så om vi helt enkelt kör vår oändliga rymd av möjliga program/modeller och låter dessa förutsäga allt som vår agent någonsin upplevt, alltså informationen den fått se, och multiplicerar ihop sannolikheterna som varje modell gett för varje observerat utfall så får vi den mest troliga sannolikhetfördelningen över alla våra modeller:
Sannolikheten för en specifik nästa datapunkt F (som i "framtid"), givet observerad data D är snittet av alla sannolikhetsförutsägelser av F från alla modeller M, givet tidigare data D, viktat med modellens sannolikhet. Modellens sannolikhet fås sedan i andra steget av Bayes sats.
Detta kallas Solomonoffinduktion och om du verkligen vill gräva ned dig i hur och varför det fungerar, så föreslår jag den långa men pedagogiska artikeln An intuitive explanation of Solomonoff Induction. Solomonoff visade att denna metod är komplett, vilket i detta sammanhang betyder att den är optimal - felet blir inte större än Kolmogorovkomplexiteten på den datagenererande processen.
Alla modeller har en initial bias eller en prior. Vad tror du innan du har fått se några datapunkter? Vad tror du när du fått se en? Solomonoffinduktion har också en sådan bias i den initiala sannolikheten för varje program, samt vilka instruktioner som finns tillgängliga. Man kan visa att med tillräckligt mycket data så spelar denna bias ingen roll, så länge instruktionsmängden är turingkomplett. Om du inte har "tillräckligt mycket data", så krävs det i all modellering att du explicit eller implicit ger viss startinformation om hur sannolika olika modeller eller parameterinställningar är. Problemet är att om du ger för lite förkunskap så behöver du mycket data, men om du ger för säker förkunskap så kommer modellen inte lyssna på data. Inom AI kallar vi det bias/variance-avvägningen.
En intressant aspekt är att det härifrån går att härleda en form av Ockhams rakkniv - att man bör välja den enklaste/kortaste förklaringen. Eftersom vi summerar över oändligt många program, men vill ha en sannolikhet mellan 0 och 1 i slutändan så måste sannolikheten för långa program gå mot noll. För att den ska göra det måste vår startsannolikhet - vår prior - för långa program gå mot noll.
Approximera
Det låter ju fantastiskt att ha en formel som ger optimala modeller, men tyvärr är Solomonoffinduktion inte beräkningsbart av flera skäl (i själva verket är det lätt att visa att ingen metod kan vara både optimal och beräkningsbar). Ett av dem är att stopproblemet säger att du inte generellt för program kan bevisa om de någonsin kommer stanna eller inte, så några av dina modeller kommer aldrig att ge något svar. Även om vi approximerar bort detta och säger att programmen t.ex har en maxtid på sig, så har vi det större problemet med att rymden av alla program är oändlig. Vi har även det mer praktiska problemet att rymden av rimliga modeller också är för stor för att man ska kunna beräkna alla.
För att faktiskt göra en modell i praktiken gör vi en mängd antaganden och approximationer vilket leder till olika modellval.
Till exempel är det vanligt att man i stället för att beräkna den oändliga ensemblen av viktade modeller ovan bara försöker hitta den mest sannolika.
Man brukar också anta att verklighetens distribution över möjliga utfall följer någon känd fördelning och att din modell bara ska ge medelvärdet för den fördelningen.
Ofta antar man normalfördelning, vilket i sin tur leder till att man kan mäta en modells godhet med kvadraterna på felen.
Man brukar också anta att varje datapunkt i D är oberoende (eller mer strikt i.i.d), snarare än i en serie, vilket gör att modellerna inte behöver ha något minne eller hålla något tillstånd.
Dessa antaganden är så vanliga att man ibland glömmer att man gör dem, vilket kan leda till många olyckligheter.
Det låter ju fantastiskt att ha en formel som ger optimala modeller, men tyvärr är Solomonoffinduktion inte beräkningsbart av flera skäl (i själva verket är det lätt att visa att ingen metod kan vara både optimal och beräkningsbar). Ett av dem är att stopproblemet säger att du inte generellt för program kan bevisa om de någonsin kommer stanna eller inte, så några av dina modeller kommer aldrig att ge något svar. Även om vi approximerar bort detta och säger att programmen t.ex har en maxtid på sig, så har vi det större problemet med att rymden av alla program är oändlig. Vi har även det mer praktiska problemet att rymden av rimliga modeller också är för stor för att man ska kunna beräkna alla.
För att faktiskt göra en modell i praktiken gör vi en mängd antaganden och approximationer vilket leder till olika modellval.
Till exempel är det vanligt att man i stället för att beräkna den oändliga ensemblen av viktade modeller ovan bara försöker hitta den mest sannolika.
Man brukar också anta att verklighetens distribution över möjliga utfall följer någon känd fördelning och att din modell bara ska ge medelvärdet för den fördelningen.
Ofta antar man normalfördelning, vilket i sin tur leder till att man kan mäta en modells godhet med kvadraterna på felen.
Man brukar också anta att varje datapunkt i D är oberoende (eller mer strikt i.i.d), snarare än i en serie, vilket gör att modellerna inte behöver ha något minne eller hålla något tillstånd.
Dessa antaganden är så vanliga att man ibland glömmer att man gör dem, vilket kan leda till många olyckligheter.
Givet vanliga antaganden om att man vill ha en punktskattning (ofta medelvärde) och en massa andra antaganden ovanför, så närmar vi oss något som man faktiskt kan åstadkomma i praktiken. Det vanligaste sättet inom maskininlärning att modellera givet ovanstående antaganden är med så kallade universella funktioner. Funktioner som är så generella att de kan approximera vilken annan funktion som helst, givet tillräckligt med parametrar och tillräckligt med data för att ansätta dem. Neuronnät är ett exempel på en familj universella funktioner. Den andra vanliga varianten är boosting - att man skapar en ensemble av "svaga" modeller som var för sig inte kan approximera universellt, men genom att göra nästa modell bra där de tidigare har varit dåliga kan man gradvis få en grupp av modeller som tillsammans är en universell funktion. Det mest kända paketet för detta är XGBoost. Med ytterligare något antagande så är även kernelbaserade modeller, som gaussiska processer och SVM, universella approximatorer.
Det är inte alls ovanligt att man fortsätter att approximera och säger att världen beror ungefär linjärt på saker om vi inte flyttar oss så långt. Det ger i sin tur en lång rad förenklingar som gör att man kan köra sådana modeller snabbt på mycket data. Eller robust på lite data.
Planera
Vår modell ovan är prediktiv. För att agera behöver vi använda våra modeller för att se vilka handlingar som har den största förväntade nyttan. Detta ger oss en preskriptiv modell.
När man diskuterar hur man ska ändra sitt agerande så blir det plötsligt viktigt att skilja på korrelation och kausation. Har denna handling tidigare bara korrelerat med ett bra utfall, eller orsakade den det faktiskt? I praktiken är det inte alltid så lätt att veta och man behöver ofta göra experiment för att se vad som leder till bäst utfall. Men teoretiskt så fungerar dessa modeller på exakt samma sätt. Vi behöver bara tillåta en speciell sorts symboler i vår datamängd D, som anger våra egna handlingar.
För att värdera nytta så behöver någon definiera vad nytta är. David Hume kom fram till att man inte kan härleda ett bör från ett är. Våra modeller modellerar hur saker är, men från detta kan vi inte säga hur saker bör vara. För att planera behöver vi därför en målfunktion, m, som värderar varje symbol/upplevelse. Givet detta kan vi beskriva en situation med den totala historik som givit upphov till situationen, samma D som ovan, och vi kan beskriva en funktion v som värderar situationens framtida potential:
Där P(F|D) beräknas med Solomonoff-formeln ovan. ⌢ betyder konkatenering - att vi lägger till ett element i slutet på en sekvens. Med denna värderingsfunktion kan vi sedan med vår tredje och sista ekvation trivialt beskriva optimalt handlande som den handling, h, i mängden av alla möjliga handlingar H givet situationen D, som ger det mest värdefulla tillståndet.
I det generella fallet där framtiden aldrig tar slut (även om agentens handlingar gör det förr eller senare), leder detta till en insikt liknande den vi gjorde för Solomonoffinduktion. För att den rekursiva summan i v inte ska divergera så behöver tid vara en komponent i F och formeln för målfunktionen m måste vikta ned nyttovärdet långt in i framtiden, så att summan blir ändlig. Inom ekonomi kallas det att vi diskonterar framtiden. Sannolikheten för långa modeller måste gå mot noll. Nyttan av framtiden måste gå mot noll.
Handlingsformeln är ännu mindre beräkningsbar än Solomonoffinduktion, eftersom det inbegriper att utföra Solomonoffinduktion för varje unik möjlig värld över distributionen av alla möjliga världar, givet alla möjliga handlingar och sedan rekursivt vidare ned i ett exponentiellt växande träd. Det inbegriper också att vi som en del i vår modell simulerar vårt eget framtida handlande, vilket varje gång ger upphov till ett nytt exponentiellt träd av beräkningar.
Om vi har approximerat prediktiv modellering enligt någon metod, så behöver vi ändå approximera summan i v. Det finns en mängd metoder för att göra det från många olika fält, men det mest generella sättet att approximera summor och integraler är med Monte Carlo-metoden. Man samplar rekursivt handlingar och utfall från sina distributioner och mäter målfunktionen långt in i framtiden. Efter en tid summerar man alla körningar för alla handlingar och får ett medelutfall per handling, som man sedan kan ta. Detta är ungefär samma sak som Thompsonsampling.
Om man vill vara lite mer praktisk, så kan man titta på bayesisk optimering, där vi genom en surrogatfunktion balanserar den handling som ger bäst utfall på kort sikt, med den som vi lär oss mest på. På det sättet separerar vi världen i modell och omvärld och väljer den handling som hjälper båda mest. En vanlig algoritm för att välja handling är att approximera ännu hårdare och vara girig. Då väljer man helt enkelt den handling som har den bästa förväntade nyttan på kort sikt.
En stor grej inom AI och planering nuförtiden är att låta ett neuronnät approximera v, som t.ex MuZero gör.
Metanivåer
En vanlig approximation är att "glömma" att det tänkande systemet är en del av världen. När vi modellerar vad som händer givet olika handlingar så måste vi också modellera den kunskap och de förändrade modeller som olika utfall leder till. Ännu lurigare är att själva beräkningen av en approximativ lösning också är en handling. Om den handlingen tar för lång tid så kommer världen ha ändrats och dina möjligheter försvunnit. Det betyder att egentligen behöver vi en egen modell som beräknar på vilket sätt och hur länge vi ska fundera på nästa handling och rekursivt behöver vi en modell som beräknar hur länge metamodellen ska beräkna. Och så vidare.. Sköldpaddor hela vägen ned.
Dessa metanivåer är så jobbiga att fundera kring att vi tenderar att justera optimal tankelängd för AI-system manuellt, men det finns de som funderar kring detta också. Probabilistic Numerics är ett matematiskt område som handlar om att balansera tiden det tar att beräkna en approximation med hur användbart det är att få ett mer exakt resultat. De behandlar inte alla sköldpaddor, men i alla fall en.
Slutsats
Formeln för optimal intelligens och optimalt agerande givet ett mål är egentligen inte så komplicerad. Här är allt sammanfattat om du känner för en ny mailsignatur, T-shirt eller tatuering:
Enkelt.. så länge man glömmer att det inte går att beräkna. Intelligens ligger egentligen i alla de sätt vi approximerar formeln, t.ex genom att anta att världen består av saker som är konstanta, eller oberoende av varandra eller på sin höjd linjärt beroende. De mest intressanta AI-framstegen är de som approximerar något som vi egentligen redan känner till, på ett nytt och användbart sätt, eller som uttrycker förkunskap om en problemfamilj till en modell på ett nytt och naturligt sätt.
Magin ligger i att göra de förenklande antaganden som behövs för att åstadkomma något i praktiken, utan att förvrida originalmålet för mycket. Det är också här de vanligaste misstagen en data scientist gör ligger. Vissa approximationer är så vanliga och "vackra" att man glömmer hur det påverkar projektets verkliga mål.
Välj en AI-leverantör som vet hur komplicerat det är att modellera, men inte glömmer affärsvärde och originalmål när vi förenklar!