En bitteliten språkmodell
Vi skal lage en bitteliten språkmodell. I stedet for å lage setninger, skal vår modell begrense seg til å kun lage nye ord. Ordene vil bli slik at de er relativt lette å uttale sammenlignet med en helt tilfeldig samling med bokstaver. Dette kan for eksempel være kjekt hvis du har lyst på et passord som er vanskelig å gjette men lett å huske.
En språkmodell virker i hovedsak i to steg:
- først trening, og
- deretter inferens.
I treningssteget leser programmet vårt treningsdata og produserer en samling med data vi kaller for vekter. Du kan se et eksempel på slike vekter i filen weights.json.
I inferens-steget leser programmet vektene sammen med et (valgfritt) prompt, og fortsetter å skrive videre derfra. I vårt tilfelle vil promptet stort sett starte som den tomme strengen, men det er teknisk sett mulig å begynne med noe annet. I så fall vil dette diktere hvordan resultatet starter.
Vi begynner kodingen med inferens-steget.
Steg 1a: skriv et program som genererer 12 (helt) tilfeldige bokstaver
Vi skriver i inference.py. Når du kjører programmet, skal det printes 12 helt tilfeldige bokstaver.
I funksjonen get_token kan du i dette steget returnere en helt tilfeldig bokstav (random.choice(“abc…”)).
Steg 1b: la get_token få tilgang til kontekst
Legg til en parameter for «kontekst» i get_token, slik at denne funksjonen vet hvor symbolet den skal returnere skal passe inn. Når du kaller på get_token, benytt resultatet så langt som argument.
I første omgang kan vi gjøre det slik at vi ser på det siste tegnet i konteksten, og så returnerer vi neste bokstav i alfabetet. Hvis konteksten er tom, returnerer vi "a".
Når du kjører programmet, skal du nå alltid få resultatet “abcdefghijkl”.
letter = 'a'
next_letter = chr(ord(letter) + 1)
print(next_letter) # b
Steg 1c: la get_token bruke vektene
Last ned weights.json i arbeidsmappen.
- Les inn filen og bruk json.loads
- Send vektene som input til get_token
- I get_token, finn frem vektoren med vekter som tilhører slutten på konteksten.
- Velg et tilfeldig symbol fra denne vektoren. La symboler med høy vekt bli valgt med høyere sannsynlighet.
import random
letters = ['a', 'b', 'c']
relative_prob = [6, 3, 1]
random_letter = random.choices(letters, weights=relative_prob, k=1)[0]
print(random_letter) # oftest a, noen ganger b, en sjelden gang c
Vi er nå ferdige med en grunnleggende inferens-algoritme. Den kan forbedres ved å f. eks. bruke en lengre kontekst enn bare ett symbol, men da må vi også håndtere de tilfellene der vi plutselig ender opp med en kontekst som ikke eksisterer i vektene. Det er ikke så veldig vanskelig (man må bare gå ned til en kortere kontekst hvis man ikke fant noe), men vi lar det ligge her som en ekstra øvelse for dem som er interessert i å prøve seg.
Steg 2: trening
Vi skriver i training.py. Last ned treningsdata til arbeidsmappen din; vi har for eksempel en oversikt over de mest brukte ord på engelsk (words_en.txt) og norsk (words_no.txt). Du kan velge hvilken av dem du bruker. Når vi er ferdig kan vi også bytte ut treningsdata og se forskjellen.
Selve prosedyren for å trene med ett ord (extend_weights-funksjonen i illustrasjonen) går ut på følgende:
- Prøv alle steder det er mulig å klippe ordet i to. Slutten på venstre side av klippet er konteksten. Første bokstav på høyre side av klippen er en mulighet for neste token.
- Hvis konteksten ikke er sett tidligere i weights -> legg til konteksten med en tom vektor
- Finn vektoren for konteksten. Hvis muligheten for neste token ikke er sett i vektoren før, legg den til med vekt 1. Hvis ikke, øk vekten for denne muligheten for neste token.
Sånn! Da er vi ferdige! Det er mulig å forbedre treningen slik at du tar hensyn til ulike lengder på kontekster (dette er gjort i eksempelet weights.json — legg merke til at denne filen har konktekster med lengde 0, 1, og 2). Vi lar det ligge som en ekstra øvelse for dem som er interessert i å prøve seg.
