Compare commits
3
Commits
WIP
..
d3ebd81b54
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3ebd81b54 | ||
|
|
ca603a658b | ||
|
|
bc17c78440 |
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"tinymist.fontPaths": ["${workspaceFolder}"]
|
||||||
|
}
|
||||||
Vendored
+1
-1
@@ -7,7 +7,7 @@
|
|||||||
"label": "run",
|
"label": "run",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "typst",
|
"command": "typst",
|
||||||
"args": ["c", "diploma_nikola_petrov.typ"],
|
"args": ["c", "--font-path", ".", "diploma_nikola_petrov.typ"],
|
||||||
"options": {"cwd": "${workspaceFolder}"},
|
"options": {"cwd": "${workspaceFolder}"},
|
||||||
"group": {
|
"group": {
|
||||||
"kind": "build",
|
"kind": "build",
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -634,7 +634,42 @@ Ostale funkcije so podobne; najprej pretvorimo v `uint_8*` in nato:
|
|||||||
- `clone` naključno kopiramo iz starša in vstavljamo naključne vrednosti,
|
- `clone` naključno kopiramo iz starša in vstavljamo naključne vrednosti,
|
||||||
- `mutate` pa sprecificirano število vrednosti spremenimo v naključne vrednosti.
|
- `mutate` pa sprecificirano število vrednosti spremenimo v naključne vrednosti.
|
||||||
|
|
||||||
|
#pagebreak()
|
||||||
|
|
||||||
|
== GENETSKI ALGORITEM <genetski_algoritem>
|
||||||
|
Ob koncu vsake generacije funkcija `newGen` iz uporabnikovih ocen zgradi novo populacijo. Ker prav ta korak določa, kako hitro se populacija zoži k uporabnikovemu okusu in koliko naključnosti v njej ostane, ga v nadaljevanju opišemo po posameznih delih.
|
||||||
|
|
||||||
|
=== Selekcija in elitizem
|
||||||
|
Vsi všečni osebki se v naslednjo generacijo prenesejo nespremenjeni, otroci pa prepišejo samo mesta nevšečnih osebkov. Velikost populacije zato ostane enaka, delež na novo ustvarjenih osebkov pa je enak deležu nevšečnih ocen v prejšnji generaciji. Če uporabnik označi kot všečnih deset od šestnajstih osebkov, se na novo ustvari le preostalih šest.
|
||||||
|
|
||||||
|
=== Križanje
|
||||||
|
Za vsako mesto nevšečnega osebka enakomerno naključno izberemo dva različna starša iz množice všečnih. Križanje je uniformno na ravni bajtov: za vsak bajt genoma z verjetnostjo 0,5 prepišemo vrednost prvega ali drugega starša, tako da otrok v povprečju podeduje polovico genoma od vsakega starša.
|
||||||
|
|
||||||
|
=== Robna primera
|
||||||
|
- *En všečni osebek.* Križanje ni mogoče, zato uporabimo funkcijo `clone`, ki vsak bajt otroka z verjetnostjo 0,5 prepiše od starša, sicer pa ga nadomesti z naključno vrednostjo. Polovica genoma otroka je torej naključna, kar je najmočnejši vir naključnosti v celotnem postopku.
|
||||||
|
- *Noben všečni osebek.* Celotno populacijo nadomestimo z novo naključno populacijo.
|
||||||
|
|
||||||
|
=== Mutacija
|
||||||
|
Po križanju mutiramo *vse* osebke, tudi všečne. Mutacija na naključno izbranih mestih zamenja tri bajte z naključnimi vrednostmi. Genom obsega 180 bajtov, kar pomeni približno 1,7 % genoma na osebek na generacijo.
|
||||||
|
|
||||||
|
Ker mutacija deluje tudi na všečne osebke, se populacija ne more nikoli povsem poenotiti. To je tudi razlog, da podobnost znotraj generacije doseže strop pri približno 82 % in ne pri 100 % (@interpretacija_konvergence), kar so kot motečo lastnost opazili tudi uporabniki.
|
||||||
|
|
||||||
|
#figure(caption: [Postopek tvorjenja nove generacije])[
|
||||||
|
```
|
||||||
|
newGen(populacija, všečni, nevšečni):
|
||||||
|
če je množica všečni prazna:
|
||||||
|
za vsak osebek v populaciji: newDna(osebek)
|
||||||
|
končaj
|
||||||
|
če ima množica všečni natanko en element:
|
||||||
|
za vsako mesto i iz množice nevšečni:
|
||||||
|
clone(všečni[0], populacija[i])
|
||||||
|
sicer:
|
||||||
|
za vsako mesto i iz množice nevšečni:
|
||||||
|
p1, p2 = dva različna naključna starša iz množice všečni
|
||||||
|
makeChild(p1, p2, populacija[i])
|
||||||
|
za vsak osebek v populaciji: mutate(osebek, 3)
|
||||||
|
```
|
||||||
|
]<psevdokoda_newgen>
|
||||||
|
|
||||||
#pagebreak()
|
#pagebreak()
|
||||||
|
|
||||||
@@ -1280,8 +1315,6 @@ Krivulje na @graf_podobnost se med seboj razlikujejo po zalogi vrednosti, njihov
|
|||||||
|
|
||||||
*Strop pri približno 82 %.* Po generaciji 9 podobnost spet naraste in se pri generacijah 11 in 12 ustali okoli 82 % (Hammingova mera). Popolnega ujemanja postopek ne more doseči, ker se mutacija izvede tudi na všečnih osebkih: vsak osebek v vsaki generaciji dobi tri naključne bajte, zato v populaciji vedno ostane nekaj razlik.
|
*Strop pri približno 82 %.* Po generaciji 9 podobnost spet naraste in se pri generacijah 11 in 12 ustali okoli 82 % (Hammingova mera). Popolnega ujemanja postopek ne more doseči, ker se mutacija izvede tudi na všečnih osebkih: vsak osebek v vsaki generaciji dobi tri naključne bajte, zato v populaciji vedno ostane nekaj razlik.
|
||||||
|
|
||||||
Iz tega je razvidno, da je mera razdalje uporabna tudi kot diagnostika postopka in ne le kot številka na zaslonu; iz njenega poteka je mogoče razbrati, katera veja postopka se je izvedla in kako močno je vplivala na populacijo. Naravno nadaljevanje tega opazovanja je merjenje hitrosti konvergence pri različnih stopnjah mutacije in različnih velikostih generacije, kar navajamo med predlogi za nadaljnje delo (@zakljucek).
|
|
||||||
|
|
||||||
== Odločitev <odlocitev_mera>
|
== Odločitev <odlocitev_mera>
|
||||||
Izbrali smo Hammingovo razdaljo. Ustreza vsem štirim kriterijem iz uvoda tega poglavja: računa se neposredno nad bajti genoma, njena zaloga vrednosti je celoten razpon od 0 % do 100 %, med konvergenco narašča, izračun 120 parov pa traja približno 100 μs. Odločilna je bila zaloga vrednosti: pri naključni začetni populaciji se začne pri približno 0 % in se z zoževanjem izbire pomika proti 100 %, zato je uporabniku razumljiva brez dodatne razlage. Kosinusna podobnost je za prikaz manj primerna, ker se že pri naključni populaciji začne pri 75 %, evklidska pri 59 %, skalarni produkt pa se giblje le med 25 % in 32 %. Časov računanja pri odločitvi nismo upoštevali, saj so vse mere razen Levenshteinove pod 0,5 ms, kar je za enkraten izračun ob prehodu med generacijama zanemarljivo; Levenshteinova razdalja je s približno 100 ms na generacijo za prikaz v realnem času neuporabna.
|
Izbrali smo Hammingovo razdaljo. Ustreza vsem štirim kriterijem iz uvoda tega poglavja: računa se neposredno nad bajti genoma, njena zaloga vrednosti je celoten razpon od 0 % do 100 %, med konvergenco narašča, izračun 120 parov pa traja približno 100 μs. Odločilna je bila zaloga vrednosti: pri naključni začetni populaciji se začne pri približno 0 % in se z zoževanjem izbire pomika proti 100 %, zato je uporabniku razumljiva brez dodatne razlage. Kosinusna podobnost je za prikaz manj primerna, ker se že pri naključni populaciji začne pri 75 %, evklidska pri 59 %, skalarni produkt pa se giblje le med 25 % in 32 %. Časov računanja pri odločitvi nismo upoštevali, saj so vse mere razen Levenshteinove pod 0,5 ms, kar je za enkraten izračun ob prehodu med generacijama zanemarljivo; Levenshteinova razdalja je s približno 100 ms na generacijo za prikaz v realnem času neuporabna.
|
||||||
|
|
||||||
@@ -1400,7 +1433,9 @@ Po tem, ko smo objavili aplikacijo na Play Store, smo prosili prijatelje in sode
|
|||||||
Uporabnikom ni bilo jasno, kako uporabiti aplikacijo, ni jim bilo, jasno da lahko povlečejo sliko levo ali desno, da označijo, ali jim je všeč ali ne. Da rešimo to, lahko ob prvem zagonu aplikacije prikažemo animacijo, kako lahko premikajo sliko po zaslonu.
|
Uporabnikom ni bilo jasno, kako uporabiti aplikacijo, ni jim bilo, jasno da lahko povlečejo sliko levo ali desno, da označijo, ali jim je všeč ali ne. Da rešimo to, lahko ob prvem zagonu aplikacije prikažemo animacijo, kako lahko premikajo sliko po zaslonu.
|
||||||
|
|
||||||
== Nepričakovani rezultati
|
== Nepričakovani rezultati
|
||||||
Po razlagi, kako uporabljati aplikacijo, jim ni bilo jasno, zakaj niso videli nobenih sprememb na drevesih in v rezultatu podobnosti. Tukaj je glavni problem majhno število vzorcev na generacijo (trenutno 16); s tem težko izločimo, kaj je uporabniku všeč. Med testiranjem nam večje število vzorcev ni bilo všeč, ker predolgo traja, da pridemo skozi generacijo in vidimo spremembe.Ker smo vedeli kako deluje algoritem, med izdelavo aplikacije te nismo uporabljali kot uporabnik. Namesto da bi izbirali videz celotne slike, smo izbirali specifične lastnosti na slikah. Nekaterim uporabnikom je to vspelo ugotoviti in so s tem ustvarili precej lepe slike.
|
Po razlagi, kako uporabljati aplikacijo, jim ni bilo jasno, zakaj na drevesih in v prikazanem odstotku niso videli sprememb. Glavni razlog je majhno število osebkov na generacijo (16), saj iz 16 binarnih ocen težko izluščimo, katera lastnost slike je uporabniku všeč. Večje generacije med razvojem nismo uporabili, ker traja predolgo, da uporabnik pride skozi generacijo in vidi učinek svojih ocen.
|
||||||
|
|
||||||
|
Pokazala se je še ena razlika. Ker smo poznali delovanje postopka, aplikacije med razvojem nismo uporabljali kot uporabnik: namesto celotnega videza slike smo ocenjevali posamezne lastnosti, na primer barvo ali gostoto vej. Nekateri uporabniki so to sami ugotovili in s takim načinom ocenjevanja prišli do vidno lepših dreves, drugi pa ne, kar kaže, da bi aplikacija ta način dela morala nakazati sama.
|
||||||
|
|
||||||
== Moteč rezultat podobnosti
|
== Moteč rezultat podobnosti
|
||||||
Nekaj uporabnikov nam je sporočilo da jih je motilo, da jim ni uspelo doseči 100 % podobnosti. Da lahko to rešimo, bi mogoče lahko uporabili kak drugačen algoritem ali pa bi lahko preslikali rezultat, da se vsaka vrednost nad 85 % prikaže kot 100 %.
|
Nekaj uporabnikov nam je sporočilo da jih je motilo, da jim ni uspelo doseči 100 % podobnosti. Da lahko to rešimo, bi mogoče lahko uporabili kak drugačen algoritem ali pa bi lahko preslikali rezultat, da se vsaka vrednost nad 85 % prikaže kot 100 %.
|
||||||
|
|||||||
Reference in New Issue
Block a user