Magical Thinking - Part 2: Cargo Cult AI

Forfatter: Richard Rostad, Promis Qualify

Vi har tidligere snakket om Cargo Cult Automation, og de siste par årene har det dukket opp en ny cargo cult:  Cargo Cult Kunstig Intelligens (AI) og maskinlæring (ML). Ofte virker det som om logikken går som følger:

  • Google og Facebook tjener store penger på kunstig intelligens og maskinlæring
  • Derfor trenger vi også kunstig intelligens og maskinlæring
  • Uansett hva slags datagrunnlag og forretningsmodell vi har i dag.

Dette blir fort som håndverkeren som ser at kollegaen jobber raskere med spikerpistol og så kjøper den kraftigste modellen for å utelukkende skru opp gipsplater.  - Ikke alltid like vellykket.

Trenden mot maskinlæring presses også frem av teknologer og konsulenter i en feedback loop;  ML er ‘hot’ og spennende og gunstig å ha på CV-en.  Derfor leter man etter prosjekter der man kan benytte ML, noe som gjør ML enda hottere og mer attraktivt, som gjør at man får større press for å sette ML på CV-en osv.

Spesielt fra et test- og QA perspektiv er denne trenden litt bekymringsverdig fordi kunstig intelligens og maskinlæring har en del innebygde kvalitetsrisikoer som blir mangelfullt ivaretatt i de fleste AI prosjekter i dag og resulterer i store mengder teknisk gjeld som er vanskelig å håndtere.

På den annen side vil det antakelig bli et godt marked for QA konsulenter med spesialitet i å rydde opp i ML modeller de nærmeste årene, så alt er ikke mørkt :)

La oss se litt nærmere på hvorfor utstrakt bruk av maskinlæring byr på nye og spennende problemstillinger for QA:

For at ML skal være regningssvarende å benytte som verktøy er det tre ting som må være på plass:

  • Det må finnes et mønster som ML modellen kan finne
  • Det må finnes et stort datasett som modellen kan trene på (og et annet, uavhengig sett som den kan testes mot, det siste blir ofte oversett)
  • Det må være meget vanskelig eller umulig å lage samme funksjonalitet med konvensjonelle algoritmer.

Uten at alle disse forutsetningene er på plass er ikke ML et egnet verktøy for prosjektet.  Med dagens press i retning ML syndes det mye mot alle tre, noen ganger i samme prosjekt, men spesielt det siste er undervurdert fordi ML tilsynelatende er en rask og billig metode for generering av ‘gode’ algoritmer.  Videre har ML i stor grad hittil blitt benyttet i forskningssammenheng der langsiktig teknisk gjeld ikke er et relevant problem etter at artikkelen er publisert.  I den virkelige verden der prosjekter og produkter har levetid målt i decennier, ikke dager er det en ganske annen problemstilling.

ML og teknisk gjeld

Begrepet teknisk gjeld ble innført av Ward Cunningham i 1992 som en metode for å kvantifisere langtidskostnaden ved å prioritere kortsiktig produksjon av ny funksjonalitet over langsiktig robusthet i løsningen.  

Tradisjonelle metoder for nedbetaling av slik gjeld er å legge arbeid i refaktorering, økt enhetstestdekning, sletting av død kode, bedre dokumentasjon, funksjonell testing, spissing av API-er etc.  Ingen av disse aktivitetene tilfører ny funksjonalitet, men gjør det lettere å vedlikeholde, utvide og forbedre løsningen i fremtiden.

En vesensforskjell mellom ML og tradisjonelle metoder er at ML beholder alle de kjente elementene av kompleksitet og i tillegg innfører systemnivå kompleksitet som kan gjøre at den tekniske gjelden vokser raskere enn man kan håndtere med tradisjonelle metoder.

Noen (få) eksempler:

Tett kobling av datasett og logikk:

Fra litt høynivå er ML en metode for å la datastrukturer generere algoritmer.  Det fører til at forretningslogikken er ekstremt tett knyttet til datagrunnlaget slik at enhver endring i data og informasjon fører til at hele modellen endrer karakter;  Enhver endring endrer alt.  For å bøte på dette problemet kan man dele opp ML modellene sine til å håndtere isolerte deldatasett, men det fører lett til et annet problem:

Domino-modeller:

Når man lager mange begrensede ML modeller som sammen løser et problem er den enkleste og raskeste metoden å basere en modell på resultatet fra en annen modell. Det betyr imidlertid at en liten isolert endring i en spesifikk submodell potensielt fører til en kaskade av potensielt store og uforutsette endringer i alle etterfølgende modeller (slike endringer er det vi i tradisjonelle systemer kaller “feil”). Denne kaskaden av følgefeil er iboende i den grunnleggende arkitekturen i ML/AI løsninger.

Skjulte feedback loops:

Mange ML algoritmer er koblet mer eller mindre direkte til virkeligheten, eksempelvis de algoritmene som gir deg ‘relevante’ reklamer fra facebook. Et problem med dette er imidlertid at brukeroppførsel endrer seg langsommere enn det som er mulig å reprodusere i en test. Når man så sender produksjonsdata inn som et nytt treningsdatasett fører dette til en langsom drift i modellalgoritmen utenfor utviklernes kontroll. I de tilfelle der konsekvensene av slik drift er større enn at man får litt mindre relevante reklamer på skjermen er det nyttig å være klar over slike kvalitetsrisikoer.

Ustabile og skjulte dataavhengigheter:

I tradisjonell programvareutvikling er man opptatt av å redusere interne avhengigheter i kode. Alle de tre eksemplene over representerer en tilsvarende avhengighet av data. Dataavhengigheter er vanskeligere å isolere enn kodeavhengigheter og feilsøking og kvalitetssikring av ML modeller er derfor betydelig mer kostbare enn avhengigheter i kode.  

Døde eller lite brukte modellelementer:

Det fenomenet blir ikke bedre av at en trent modell ofte vil ha deler med veldig liten vekting som med treningsdataene egentlig er å betrakte som død kode.  Gitt andre data kan imidlertid disse ‘døde’ segmentene av modellen plutselig vekkes til live og få signifikant effekt på resultatene. Denne feilsituasjonen forverres av at det ikke dukker opp noen målbare feil; modellen vil bare plutselig gi helt annerledes resultater enn tidligere.  

Løsningen på det problemet er å gå manuelt inn og fjerne modellelementer med liten og/eller uønsket signifikans som et preventivt tiltak. I dag virker det som om et meget lite fåtall av data scientists og/eller programmerere har tilstrekkelig dybdekunnskap om den interne strukturen i ML modeller til å kunne utføre slike analyser og oppgaver.

Små muligheter for statisk analyse av dataavhengigheter:

Moderne programmering er støttet av gode og velprøvde verktøy for statisk analyse; kompilatorer, avhengighetssjekkere, ‘lint’, kompleksitetssjekker etc. Ingen slike verktøy finnes per i dag for statiske analyser av data og følgelig har vi liten mulighet for automatisert statisk analyse av ML algoritmer og derav større risiko for at det skal oppstå feilsituasjoner.

Konfigurasjonsgjeld:

Ofte er datapreparering og konfigurasjon den største delen av et maskinlæringsløp. I noen tilfelle er over 90% av koden slik ‘forberedende’ kode. Siden denne kodebasen er sett på som konfigurasjon og forberedelser til den ‘egentlige’ utviklingen (modelltreningen) er den sjelden gjenstand for kvalitetskontroll og testing på samme måte som produksjonskode. Dette øker igjen risikoen for feil i modellene, særlig over tid der stabilitet og vedlikeholdbarhet av konfigurasjonskoden blir viktigere.

Konklusjon

ML og AI kan ved første blikk se ut som en besnærende enkel måte for utvikling av kompliserte systemer uten behov for dybdeforståelse av hverken ML algoritmene eller forretningsdomenet. I virkeligheten er potensialet for feil ofte betydelig større ved bruk av ML enn ved tradisjonelle metoder og man bør tenke seg godt om før man kaster seg ukritisk på ML bølgen, særlig dersom man ser at ML løsningen vokser utover små isolerte modeller med klart definerte datasett.