Fiktive norske navn
- 1. July 2023
- #datascience
Etter å ha sett Neural Networks: Zero to Hero på YouTube av Andrej Karpathy, ble jeg inspirert til å teste makemore på norske navn. Makemore er en språkmodell som lager flere (make more) ord, gitt en liste med eksempler som modellen trener på. Andrej bruker engelske navn, men det virker gøy å prøve med norske navn.
Om du vil se resultatet, bla til seksjonen Steg 3: Velg favoritter.
Steg 1: Hent norske navn
Først må vi hente en liste med treningsdata.
Vi trenger en tekstfil jentenavn_snl.txt
, som inneholder en linje per navn.
Om vi kjører følgende kode to ganger, én gang for guttenavn og én gang for jentenavn, får vi to filer med navn fra Store norske leksikon.
from requests import get
from bs4 import BeautifulSoup
# Hent HTML. 4025 er jentenavn, 4024 er guttenavn
html = get("https://snl.no/.taxonomy/4025").text
# Konverter til suppe :)
soup = BeautifulSoup(html)
# Hent delen av dokumentet som inneholder navn
soup_names = soup.find("div", attrs={"class": "l-taxonomy__contents"})
# Teksten i alle <a> tags (linker)
names = [a.text for a in soup_names.find_all("a")]
# Fjern bokstavene fra starten
names = [n for n in names if '\n' not in n]
# Konverter elementer som 'Abel – kvinnenamn' til 'abel'
names = [n.split("–")[0].strip().lower() for n in names]
# Lagre navnene til en fil
with open("jentenavn_snl.txt", "w") as file:
for name in set(names):
file.write(name + "\n")
Deretter bruker vi Linux-terminalen til å slå sammen filene til én fil:
$ cat guttenavn_snl.txt jentenavn_snl.txt | sort | uniq | sort -R > navn_snl.txt
Vi bruker sort
og piper til uniq
for å fjerne navn som både er gutte- og jentenavn.
Deretter bruker vi sort -R
for å få en tilfeldig rekkefølge, og skriver til filen navn_snl.txt
.
Vi står igjen med 5703 unike navn:
$ wc navn_snl.txt --lines
5703 navn_snl.txt
Steg 2: Kjør makemore
Vi kopierer koden til makemore fra GitHub:
$ git clone https://github.com/karpathy/makemore
$ mv navn_snl.txt makemore
$ cd makemore
Deretter trener vi språkmodellen. Legg merke til hvor dårlige de første navnene er, og at de kontinuerlig blir bedre etter hvert som modellen trenes.
$ python makemore.py -i navn_snl.txt --device cpu --type transformer \
-o navn --batch-size 128 --seed 42
{'input_file': 'navn_snl.txt', 'work_dir': 'navn', 'resume': False,
'sample_only': False, 'num_workers': 4, 'max_steps': -1, 'device': 'cpu',
'seed': 42, 'top_k': -1, 'type': 'transformer', 'n_layer': 4,
'n_head': 4, 'n_embd': 64, 'n_embd2': 64, 'batch_size': 128,
'learning_rate': 0.0005, 'weight_decay': 0.01}
number of examples in the dataset: 5703
max word length: 12
number of unique characters in the vocabulary: 32
vocabulary:
abcdefghijklmnopqrstuvwxyzäåæçéø
split up the dataset into 5133 training examples and 570 test examples
dataset determined that: vocab_size=33, block_size=13
number of parameters: 0.20M
model #params: 205120
step 0 | loss 3.7378 | step time 58.69ms
...
step 200 | loss 2.1815 | step time 34.64ms
--------------------------------------------------------------------------------
2 samples that are in train:
sima
berna
0 samples that are in test:
8 samples that are new:
tyavand
ralfen
ramola
harsjør
manfriæ
eikrof
palolia
gannaç
--------------------------------------------------------------------------------
step 210 | loss 2.1291 | step time 34.23ms
...
step 400 | loss 1.9094 | step time 33.92ms
--------------------------------------------------------------------------------
0 samples that are in train:
0 samples that are in test:
10 samples that are new:
odsjann
winjoneseg
loyman
jarzta
alien
fristoh
lidi
joand
parle
haçricke
--------------------------------------------------------------------------------
step 410 | loss 2.0024 | step time 33.36ms
...
step 500 | loss 1.8918 | step time 33.54ms
step 500 train loss: 1.9086905717849731 test loss: 2.018773317337036
test loss 2.018773317337036 is the best so far, saving model to navn/model.pt
step 510 | loss 1.8711 | step time 40.03ms
...
step 600 | loss 1.8519 | step time 34.55ms
--------------------------------------------------------------------------------
1 samples that are in train:
eina
0 samples that are in test:
9 samples that are new:
wissy
estie
frieck
annickelie
tinstire
vilminne
eunik
osaa
amaan
--------------------------------------------------------------------------------
step 610 | loss 1.9095 | step time 34.70ms
...
step 800 | loss 1.8492 | step time 34.20ms
--------------------------------------------------------------------------------
3 samples that are in train:
sigurd
torgeir
gunni
0 samples that are in test:
7 samples that are new:
cath
jespe
sonjalf
rayma
jandies
berto
siandra
--------------------------------------------------------------------------------
step 810 | loss 1.7994 | step time 35.49ms
...
step 1000 | loss 1.6185 | step time 34.21ms
step 1000 train loss: 1.730794072151184 test loss: 1.9632741212844849
test loss 1.9632741212844849 is the best so far, saving model to navn/model.pt
--------------------------------------------------------------------------------
3 samples that are in train:
owen
ester
annelise
0 samples that are in test:
7 samples that are new:
alecella
tio
thormey
gudlmeig
nuz
gullvard
torke
--------------------------------------------------------------------------------
Om vi vil kan vi kjøre litt mer med lavere learning rate:
$ python makemore.py -i navn_snl.txt --device cpu --type transformer \
-o navn --batch-size 128 --seed 42 --resume --learning-rate 0.00001
Vi kan nå generere navn ved hjelp av --sample-only
argumentet:
$ python makemore.py -i navn_snl.txt --sample-only -o navn --seed 42
{'input_file': 'navn_snl.txt', 'work_dir': 'navn', 'resume': False,
'sample_only': True, 'num_workers': 4, 'max_steps': -1, 'device': 'cpu',
'seed': 42, 'top_k': -1, 'type': 'transformer', 'n_layer': 4, 'n_head': 4,
'n_embd': 64, 'n_embd2': 64, 'batch_size': 32, 'learning_rate': 0.0005,
'weight_decay': 0.01}
number of examples in the dataset: 5703
max word length: 12
number of unique characters in the vocabulary: 32
vocabulary:
abcdefghijklmnopqrstuvwxyzäåæçéø
split up the dataset into 5133 training examples and 570 test examples
dataset determined that: vocab_size=33, block_size=13
number of parameters: 0.20M
model #params: 205120
resuming from existing model in the workdir
--------------------------------------------------------------------------------
11 samples that are in train:
hanna
armando
ingemann
emmi
dagfrid
annika
malika
karleif
klaudi
randa
ana
1 samples that are in test:
herman
38 samples that are new:
annethy
mirios
rosalina
anuk
lydvik
milbjørg
rithaam
oaron
harloæb
lenette
lodvald
haar
chrastian
zawa
rudon
valgor
idu
gunnlauge
thovil
halborg
ryver
hettor
emlin
jore
usaun
edgund
oddla
arnjo
khadis
héelda
haimon
elan
eiselli
petrvy
hedni
berndickt
danicken
nori
--------------------------------------------------------------------------------
Steg 3: Velg favoritter
Her er noen av mine favoritter. De er ikke perfekte, men fremstår stort sett som om de kunne vært norske navn:
alexa
allida
amisa
andrien
arlon
axan
betta
bilbjørn
borgard
brya
dagvy
digfrid
dormine
elbert
ellebjøn
emmund
erlina
geirun
gerdyne
gertbjørn
gladborg
gottleif
guddfrid
gudni
haldebjørg
harbjørg
helger
helmund
imma
ingbard
janak
jannitta
jørid
jorlaug
josny
katiline
katina
katine
laury
lingjerd
linny
luma
lynveig
nagve
olauf
olfine
øyverle
raja
stefine
tasma
torelia
torja
torjei
trestina
ulina
vilda
yrva
That’s all folks!
- For å lære med om web scraping i Python, se Beautiful Soup Documentation.
- For å lære mer om Linux-terminalen, les The Linux Command Line.
- For å lære mer om språkmodeller, lær først om nevrale nettverk generelt i Hands-On Machine Learning, deretter se Neural Networks: Zero to Hero og les gjerne The Illustrated Transformer.
Bonus: Stedsnavn
Jeg lastet også ned 1,2 millioner stedsnavn fra https://github.com/paulskeie/stadnamn og trente en modell. Her er noen av favorittene mine på fiktive stedsnavn:
Bakfjordgata
Bontjørn
Botteveien
Duganeset
Dyrsøyodden
Fjøllsoksjøen
Fremmer kirke
Geitskardbakkane
Grøthaugane
Haraldsjøbekken
Heggefjell
Henningen
Høgvelta
Hudnes
Kløvtjønna
Krossenget
Langøya
Laugeneset
Lille Dalsberget
Lonerød
Mælumsundet
Mjåvassbærlia
Mykjølen
Nedre Lomtjørna
Nordbøheia
Pergadalen
Plomstad
Rognesvika
Sagborg
Sjøvegen
Skineset
Skjeftleheia
Slognesosen
Store Brattstølen
Store Grenneholten
Sundbunuten
Tjørnmyrane
Tjukkgrabbane
Tranlemyrfjellet
Urddalsbakkan