profileShare

rasmusjy / countrysense

Read-only snapshot

No repository description.

main default branch 19 files Expires Sep 13, 2026, 9:06 AM
mudel.html 21,970 bytes
1 <!DOCTYPE html>
2 <html lang="et">
3 <head>
4 <meta charset="utf-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <title>CountrySense: kuidas mudel töötab</title>
7 <style>
8 :root {
9 --ink: #1d2733;
10 --muted: #5b6b7c;
11 --line: #d9e1ea;
12 --accent: #1a6feb;
13 --accent-soft: #eaf2ff;
14 --bg: #fbfcfe;
15 --code-bg: #f2f5f9;
16 }
17 * { box-sizing: border-box; }
18 body {
19 margin: 0;
20 font-family: Georgia, "Times New Roman", serif;
21 color: var(--ink);
22 background: var(--bg);
23 line-height: 1.65;
24 }
25 header {
26 background: var(--ink);
27 color: #fff;
28 padding: 3rem 1.5rem 2.5rem;
29 text-align: center;
30 }
31 header h1 { margin: 0 0 0.4rem; font-size: 2.2rem; }
32 header p { margin: 0; color: #b9c6d4; font-size: 1.05rem; }
33 main { max-width: 860px; margin: 0 auto; padding: 1.5rem; }
34 nav.toc {
35 background: #fff;
36 border: 1px solid var(--line);
37 border-radius: 8px;
38 padding: 1rem 1.5rem;
39 margin: 1.5rem 0;
40 font-family: system-ui, sans-serif;
41 font-size: 0.92rem;
42 }
43 nav.toc ol { margin: 0.3rem 0 0; padding-left: 1.3rem; columns: 2; }
44 nav.toc a { color: var(--accent); text-decoration: none; }
45 nav.toc a:hover { text-decoration: underline; }
46 h2 {
47 margin-top: 2.6rem;
48 padding-bottom: 0.3rem;
49 border-bottom: 2px solid var(--line);
50 font-size: 1.5rem;
51 }
52 h3 { margin-top: 1.8rem; font-size: 1.15rem; }
53 code, pre {
54 font-family: Consolas, "Courier New", monospace;
55 background: var(--code-bg);
56 border-radius: 4px;
57 }
58 code { padding: 0.1em 0.35em; font-size: 0.9em; }
59 pre { padding: 0.9rem 1.1rem; overflow-x: auto; border: 1px solid var(--line); }
60 pre code { background: none; padding: 0; }
61 table {
62 border-collapse: collapse;
63 width: 100%;
64 margin: 1rem 0;
65 font-family: system-ui, sans-serif;
66 font-size: 0.9rem;
67 background: #fff;
68 }
69 th, td { border: 1px solid var(--line); padding: 0.5rem 0.7rem; text-align: left; vertical-align: top; }
70 th { background: var(--accent-soft); }
71 .note {
72 background: var(--accent-soft);
73 border-left: 4px solid var(--accent);
74 padding: 0.8rem 1.1rem;
75 border-radius: 0 6px 6px 0;
76 margin: 1.2rem 0;
77 }
78 .warn {
79 background: #fff6ec;
80 border-left: 4px solid #e08a2e;
81 padding: 0.8rem 1.1rem;
82 border-radius: 0 6px 6px 0;
83 margin: 1.2rem 0;
84 }
85 .pipeline {
86 display: flex;
87 flex-wrap: wrap;
88 align-items: center;
89 justify-content: center;
90 gap: 0.4rem;
91 margin: 1.5rem 0;
92 font-family: system-ui, sans-serif;
93 font-size: 0.82rem;
94 }
95 .pipeline .box {
96 background: #fff;
97 border: 1.5px solid var(--ink);
98 border-radius: 6px;
99 padding: 0.55rem 0.8rem;
100 text-align: center;
101 min-width: 105px;
102 }
103 .pipeline .box small { display: block; color: var(--muted); }
104 .pipeline .arrow { font-size: 1.2rem; color: var(--muted); }
105 .pipeline .box.hot { background: var(--accent-soft); border-color: var(--accent); }
106 .block-diagram {
107 background: #fff;
108 border: 1px dashed var(--muted);
109 border-radius: 8px;
110 padding: 1rem 1.3rem;
111 font-family: Consolas, monospace;
112 font-size: 0.85rem;
113 white-space: pre;
114 overflow-x: auto;
115 margin: 1.2rem 0;
116 }
117 .formula {
118 text-align: center;
119 font-size: 1.1rem;
120 margin: 1.2rem 0;
121 font-style: italic;
122 }
123 footer {
124 margin-top: 3rem;
125 padding: 1.5rem;
126 text-align: center;
127 color: var(--muted);
128 font-size: 0.85rem;
129 border-top: 1px solid var(--line);
130 font-family: system-ui, sans-serif;
131 }
132 </style>
133 </head>
134 <body>
135
136 <header>
137 <h1>CountrySense</h1>
138 <p>Kuidas nägemistransformer tänavapildi järgi riigi ära arvab: arhitektuur, andmed ja kõik valikud lahti seletatuna</p>
139 </header>
140
141 <main>
142
143 <nav class="toc">
144 <strong>Sisukord</strong>
145 <ol>
146 <li><a href="#skoop">Ülesanne ja skoop</a></li>
147 <li><a href="#andmed">Andmestik ja valikukriteeriumid</a></li>
148 <li><a href="#puhastus">Andmete puhastamine</a></li>
149 <li><a href="#mudelivalik">Mudeli valik</a></li>
150 <li><a href="#vit">ViT samm-sammult</a></li>
151 <li><a href="#dense">Dense-kihid transformeri sees</a></li>
152 <li><a href="#pea">Klassifitseerimispea ja softmax</a></li>
153 <li><a href="#kadu">Kadufunktsioon</a></li>
154 <li><a href="#treening">Treening kahes faasis</a></li>
155 <li><a href="#augment">Augmentatsioonid</a></li>
156 <li><a href="#tasakaal">Klasside tasakaal</a></li>
157 <li><a href="#moodikud">Mõõdikud</a></li>
158 <li><a href="#piirangud">Piirangud ja teekaart</a></li>
159 </ol>
160 </nav>
161
162 <h2 id="skoop">1. Ülesanne ja skoop</h2>
163 <p>
164 Sisend on üks tänavapilt, väljund on riigi nimi ja tõenäosused. Kogu toru näeb välja nii:
165 </p>
166
167 <div class="pipeline">
168 <div class="box">Pilt<small>224 × 224 × 3</small></div>
169 <div class="arrow">→</div>
170 <div class="box">Patch embedding<small>196 + 1 tokenit</small></div>
171 <div class="arrow">→</div>
172 <div class="box hot">12 × Transformeri plokk<small>attention + MLP</small></div>
173 <div class="arrow">→</div>
174 <div class="box">CLS-vektor<small>768 arvu</small></div>
175 <div class="arrow">→</div>
176 <div class="box hot">Dropout + Linear<small>768 → N riiki</small></div>
177 <div class="arrow">→</div>
178 <div class="box">Softmax<small>tõenäosused</small></div>
179 </div>
180
181 <p>
182 Miks just riigi tase? Täpne geolokatsioon (koordinaatide ennustamine) on teadusartikli mõõtu ettevõtmine: miljonid pildid, suured mudelid, nädalad GPU-aega. Riigi klassifitseerimine saja klassi vahel on tavaline juhendatud õppe ülesanne, mis mahub tasuta Colabi GPU peale. Järgmine aus samm oleks regioon riigi sees, koordinaadid ei ole plaanis.
183 </p>
184
185 <h2 id="andmed">2. Andmestik ja valikukriteeriumid</h2>
186 <p>
187 Vaikimisi andmestik on Kaggle'i <em>GeoLocation, Geoguessr Images 50K</em>: umbes 50 000 Street View pilti, iga riik oma kaustas. Valik tehti nelja kriteeriumi järgi:
188 </p>
189 <table>
190 <tr><th>Kriteerium</th><th>Miks oluline</th></tr>
191 <tr><td>Sildid kaustastruktuuris</td><td>Käsitsi märgendamine oleks nädalate töö. Kausta nimi ongi klassi silt.</td></tr>
192 <tr><td>~150 riiki, ~50k pilti</td><td>Piisavalt suur, et ülesanne oleks päris, ja piisavalt väike, et tasuta GPU jaksaks.</td></tr>
193 <tr><td>Maht mõni gigabait</td><td>Mahub Colabi kettale, allalaadimine minutites, mitte tundides.</td></tr>
194 <tr><td>Vaba juurdepääs</td><td>kagglehub laadib ilma API võtmeta, notebook töötab igaühel.</td></tr>
195 </table>
196 <p>
197 Kood ei sõltu sellest konkreetsest andmestikust: iga kaust paigutusega <code>root/&lt;riik&gt;/&lt;pilt&gt;</code> sobib. Skaleerimiseks on hea kandidaat OpenStreetView-5M alamhulk.
198 </p>
199 <div class="warn">
200 <strong>Ausalt biasest.</strong> Street View katvus on kaldu jõukamate riikide poole ja eri riikides on pildistatud eri kaamerapõlvkondadega. Mudel õpib paratamatult ka kaamera artefakte (värvitoon, teravus, resolutsioon), mitte ainult maastikku ja arhitektuuri. GeoGuessri profimängijad kasutavad täpselt sama vihjet.
201 </div>
202
203 <h2 id="puhastus">3. Andmete puhastamine</h2>
204 <p>
205 Toorandmestikus on katkiseid faile, praktiliselt musti kaadreid (tunnelid, öö), uduseid pilte ja duplikaate. <code>clean.py</code> käib kõik pildid läbi ja kirjutab iga välja jäetud pildi kohta raporti reaga põhjuse.
206 </p>
207 <table>
208 <tr><th>Samm</th><th>Reegel</th><th>Miks</th></tr>
209 <tr><td>Rikutud failid</td><td>PIL ei suuda avada</td><td>Katkine fail kukutaks treeningu keset epohhi.</td></tr>
210 <tr><td>Suurus</td><td>lühem külg &lt; 128 px</td><td>Alla selle pole piisavalt detaili, ViT sisend on 224 px.</td></tr>
211 <tr><td>Heledus</td><td>halltoonide keskmine &lt; 20 või &gt; 235</td><td>Peaaegu mustad või läbipõlenud kaadrid ei kanna infot, aga kannavad silti, st ainult müra.</td></tr>
212 <tr><td>Teravus</td><td>gradiendi energia keskmine &lt; 25</td><td>Udune kaader (liikumine, vihmapiisk objektiivil). Gradiendi energia on lihtne teravuse mõõt: udusel pildil muutuvad naaberpikslid vähe.</td></tr>
213 <tr><td>Duplikaadid</td><td>korduv phash</td><td>Perceptual hash annab visuaalselt identsetele piltidele sama koodi. Kriitiline: kui sama koht satub nii treening- kui testihulka, on testitulemus petlikult hea. See on andmeleke, kõige levinum viga sedasorti projektides.</td></tr>
214 <tr><td>Väikesed klassid</td><td>riigil &lt; 100 pilti</td><td>Paarikümne pildiga ei saa õppida ega usaldusväärselt mõõta.</td></tr>
215 <tr><td>Suured klassid</td><td>lagi 2000 pilti riigi kohta</td><td>Vähendab tasakaalustamatust juba andmete tasandil, ülejäänu teeb sampler (ptk 11).</td></tr>
216 </table>
217
218 <h2 id="mudelivalik">4. Mudeli valik</h2>
219 <p>
220 Otsustuskriteeriumid: eeltreeningu kvaliteet geograafia jaoks, parameetrite maht (peab mahtuma tasuta T4 GPU 16 GB mällu koos peenhäälestusega) ja teegi tugi.
221 </p>
222 <table>
223 <tr><th>Kandidaat</th><th>Hinnang</th></tr>
224 <tr><td><strong>CLIP ViT-B/16 (valitud)</strong></td><td>OpenAI treenis seda 400 miljoni pilt-tekst paari peal. Kuna tekstid kirjeldasid ka kohti ("a street in Lisbon"), kodeerivad tunnused juba silte, taimestikku, arhitektuuri, teekattemärgistust. Lineaarne pea CLIP-i tunnuste otsas on teadaolevalt tugev geolokatsiooni baastase. 86M parameetrit mahub T4 peale.</td></tr>
225 <tr><td>ImageNet ViT / ConvNeXt</td><td>Töötaks, aga ImageNeti 1000 klassi (koeratõud, esemed) on geograafiast kaugel, transfer on mõõdetavalt nõrgem.</td></tr>
226 <tr><td>StreetCLIP (ViT-L/14)</td><td>Juba geolokatsiooniks häälestatud CLIP, aga kolm korda suurem. Peenhäälestus T4 peal on kitsas. Hea järgmine samm parema riistvaraga.</td></tr>
227 <tr><td>CNN nullist</td><td>50k pildiga lootusetu. Eeltreening on kogu projekti võimaldaja: keegi teine on juba kulutanud tuhanded GPU-tunnid üldiste visuaalsete tunnuste õppimisele.</td></tr>
228 </table>
229
230 <h3>ViT-B/16 numbrid</h3>
231 <table>
232 <tr><th>Omadus</th><th>Väärtus</th></tr>
233 <tr><td>Parameetreid</td><td>~86 miljonit</td></tr>
234 <tr><td>Transformeri plokke</td><td>12</td></tr>
235 <tr><td>Peidetud dimensioon</td><td>768</td></tr>
236 <tr><td>Attention-päid ploki kohta</td><td>12</td></tr>
237 <tr><td>MLP vahekihi laius</td><td>3072</td></tr>
238 <tr><td>Patchi suurus</td><td>16 × 16 px</td></tr>
239 <tr><td>Tokeneid 224 px pildi kohta</td><td>196 patchi + 1 CLS = 197</td></tr>
240 </table>
241
242 <h2 id="vit">5. ViT samm-sammult</h2>
243
244 <h3>5.1 Patch embedding: pilt muutub jadaks</h3>
245 <p>
246 Transformer töötab tokenite jadaga, mitte pikslivõrega. Seepärast lõigatakse 224 × 224 pilt 16 × 16 piksliseks ruudustikuks: 14 × 14 = 196 patchi. Iga patch on 16 × 16 × 3 = 768 arvu, mis lastakse läbi <em>ühe lineaarse kihi</em> (see on esimene dense-kiht kogu mudelis) ja saadakse 768-mõõtmeline vektor. Pilt on nüüd 196 "sõnast" koosnev lause.
247 </p>
248 <h3>5.2 CLS-token ja positsioonivektorid</h3>
249 <p>
250 Jada ette lisatakse üks õpitav lisatoken, <strong>CLS</strong> (classification). Tal pole pildisisu, tema ülesanne on plokkide läbimise käigus koguda attention'i kaudu kokku terve pildi kokkuvõte. Lõpus loetakse ennustus just tema pealt.
251 </p>
252 <p>
253 Kuna attention ise on järjekorra suhtes ükskõikne, liidetakse igale tokenile <strong>positsioonivektor</strong>: õpitav vektor, mis ütleb "sina oled rea 3, veeru 7 patch". Ilma selleta ei teaks mudel, kas taevas on üleval või all.
254 </p>
255
256 <h3>5.3 Transformeri plokk</h3>
257 <p>Kõik 12 plokki on identse ehitusega:</p>
258 <div class="block-diagram">sisend (197 × 768)
259
260 ├──────────────────────────────┐
261 ▼ │
262 LayerNorm │
263 ▼ │
264 Multi-head self-attention │ (12 pead)
265 ▼ │
266 + ◄───────────────────────────┘ residuaalühendus
267
268 ├──────────────────────────────┐
269 ▼ │
270 LayerNorm │
271 ▼ │
272 MLP: Linear 768 → 3072 │ (dense-kihid)
273 GELU │
274 Linear 3072 → 768 │
275 ▼ │
276 + ◄───────────────────────────┘ residuaalühendus
277
278 väljund (197 × 768)</div>
279
280 <h3>5.4 Self-attention: info liigub patchide vahel</h3>
281 <p>
282 Igast tokenist arvutatakse kolm projektsiooni: päring <strong>Q</strong> (query), võti <strong>K</strong> (key) ja väärtus <strong>V</strong> (value). Iga token "küsib" kõigilt teistelt, kui asjakohased nad talle on, ja korjab nende väärtused kokku kaalutult:
283 </p>
284 <p class="formula">Attention(Q, K, V) = softmax(Q·K<sup>T</sup> / √d) · V</p>
285 <p>
286 Jagamine √d-ga hoiab korrutised mõistlikus vahemikus, et softmax ei küllastuks. "Multi-head" tähendab, et see arvutus tehakse 12 korda paralleelselt väiksemates alamruumides (768 / 12 = 64 mõõdet pea kohta): üks pea võib jälgida värve, teine geomeetriat, kolmas teksti silmapiiril. Just attention lubab CLS-tokenil siduda kokku liiklusmärgi paremal, taimestiku vasakul ja teekattemärgistuse all, ükskõik kui kaugel need üksteisest on. CNN-il kuluks sama kaugete seoste jaoks palju kihte.
287 </p>
288
289 <h2 id="dense">6. Dense-kihid transformeri sees</h2>
290 <p>
291 Iga ploki teine pool on MLP (multi-layer perceptron), kaks dense- ehk täisühendatud kihti:
292 </p>
293 <pre><code>Linear(768 → 3072) # laiendus 4×
294 GELU # sujuv mittelineaarsus
295 Linear(3072 → 768) # tagasi kokku</code></pre>
296 <p>
297 Tööjaotus ploki sees on selge: <strong>attention liigutab infot tokenite vahel, MLP töötleb iga tokenit eraldi</strong>. MLP-s toimub tegelik tunnuste teisendamine: laiendus 3072 mõõtmesse annab ruumi vahepealsete kombinatsioonide jaoks ("kollane + ristkülik + posti otsas"), GELU teeb teisenduse mittelineaarseks (ilma selleta oleks kogu võrk üks suur maatrikskorrutis) ja tagasiprojektsioon surub tulemuse standardsesse 768-mõõtmelisse esitusse, mida järgmine plokk ootab.
298 </p>
299 <p>
300 Mahult on MLP-d mudeli põhiosa: umbes kaks kolmandikku kõigist parameetritest elab just neis dense-kihtides.
301 </p>
302 <p>
303 Kaks tugistruktuuri teevad 12 ploki virna treenitavaks: <strong>LayerNorm</strong> normaliseerib iga tokeni vektori enne igat alamosa (stabiilsed suurusjärgud), <strong>residuaalühendused</strong> (x + f(x)) lasevad gradiendil voolata otse läbi kogu virna, nii et sügav võrk ei "unusta" sisendit ega lämmata gradienti.
304 </p>
305
306 <h2 id="pea">7. Klassifitseerimispea ja softmax</h2>
307 <p>
308 Pärast 12. plokki ja lõpu LayerNorm'i võetakse CLS-tokeni 768-mõõtmeline vektor. See on kogu pildi kokkuvõte. Pea on tahtlikult minimaalne:
309 </p>
310 <pre><code>nn.Sequential(
311 nn.Dropout(0.2), # treeningul nullitakse juhuslikult 20% tunnustest
312 nn.Linear(768, N_riiki), # üks dense-kiht: 768 sisendit → N logitit
313 )</code></pre>
314 <p>
315 <strong>Dropout</strong> takistab peal toetumast üksikutele tunnustele (näiteks ainult ühe kaamerapõlvkonna värvitoonile): kui iga tunnus võib treeningul kaduda, peab otsus toetuma laiemale mustrile.
316 </p>
317 <p>
318 <strong>Linear</strong> annab igale riigile ühe reaalarvu, logiti. Sisuliselt on igal riigil 768 kaalu, mis ütlevad, millised tunnusekombinatsioonid tema poolt räägivad. <strong>Softmax</strong> teisendab logitid tõenäosusteks: e astmes iga logit, jagatud summaga, nii et tulemused on positiivsed ja annavad kokku 1.
319 </p>
320 <div class="note">
321 <strong>Miks ainult üks kiht, mitte sügavam pea?</strong> CLIP-i tunnused on juba suures osas lineaarselt eraldatavad, seda mõõdab nn linear probe. Sügavam pea lisaks selle andmemahu (~40k treeningpilti) juures peamiselt ülesobitumise riski. Kui tunnused vajavad painutamist, on parem avada backbone'i viimased plokid, mida faasis 2 teemegi.
322 </div>
323
324 <h2 id="kadu">8. Kadufunktsioon</h2>
325 <p>
326 Cross-entropy võrdleb softmax'i tõenäosusjaotust õige vastusega ja karistab logaritmiliselt: kindel vale vastus on väga kallis. Lisaks kasutame <strong>label smoothing</strong> väärtusega 0.1: sihtmärk pole "Eesti = 1.0, kõik muu = 0.0", vaid "Eesti = 0.9, ülejäänu jagab 0.1".
327 </p>
328 <p>
329 Põhjus on geograafiline: sildid on piirialadel loomupäraselt mürarikkad. Pilt Valgast näeb välja nagu Valka, ja Street View asukohaviga võib panna pildi sõna otseses mõttes vale riigi kausta. Smoothing hoiab mudelit sellistel juhtudel ülekindlaks muutumast ja parandab kalibratsiooni.
330 </p>
331
332 <h2 id="treening">9. Treening kahes faasis</h2>
333 <table>
334 <tr><th></th><th>Faas 1: lineaarne sondeerimine</th><th>Faas 2: osaline peenhäälestus</th></tr>
335 <tr><td>Mis treenib</td><td>ainult pea (Dropout + Linear)</td><td>viimased 4 plokki + lõpu norm + pea</td></tr>
336 <tr><td>Epohhe</td><td>3</td><td>8</td></tr>
337 <tr><td>Õppemäär</td><td>1e-3</td><td>2e-5 backbone, 1e-4 pea, koosinusgraafik</td></tr>
338 </table>
339 <p>
340 <strong>Miks mitte kohe kõike treenida?</strong> Pea alustab juhuslikest kaaludest ja tema esimesed gradiendid on suured ja suvalises suunas. Kui backbone oleks lahti, lammutaksid need gradiendid eeltreenitud kaale enne, kui pea üldse midagi mõistlikku nõuab. Seepärast laseme peal esmalt külmutatud tunnuste otsas paika loksuda.
341 </p>
342 <p>
343 <strong>Miks ainult viimased 4 plokki, mitte kõik 12?</strong> Alumised plokid õpivad üldisi asju (servad, tekstuurid, värvilaigud), mis on igasuguse pildiülesande jaoks niigi head. Ülemised plokid kannavad semantikat, mida tasub geograafiale kohandada. Vähem avatud plokke tähendab kolme asja korraga: väiksem mälukulu (mahume T4 peale), väiksem ülesobitumise risk ja väiksem katastroofilise unustamise risk (et mudel ei kaotaks CLIP-i üldteadmisi).
344 </p>
345 <p>
346 Tehnilised valikud: AdamW (weight decay 0.01 hoiab kaalud väiksed), AMP ehk poolttäpsusega arvutus (ligi 2× kiirem ja poole väiksem mälukulu), gradientide kärpimine normini 1.0 (üksik halb batch ei löö treeningut rööpast), koosinusgraafik faasis 2 (õppemäär langeb sujuvalt, lõpus tehakse peeneid samme).
347 </p>
348
349 <h2 id="augment">10. Augmentatsioonid</h2>
350 <table>
351 <tr><th>Teisendus</th><th>Kasutusel?</th><th>Põhjendus</th></tr>
352 <tr><td>RandomResizedCrop (50 kuni 100% pindalast)</td><td>Jah</td><td>Kaugus ja kadreering varieeruvad päriselt: sama koht näeb eri suumiga erinev välja.</td></tr>
353 <tr><td>ColorJitter (kerge)</td><td>Jah</td><td>Valgustus, aastaaeg ja kaamera värvitoon varieeruvad päriselt.</td></tr>
354 <tr><td>Horisontaalne peegeldus</td><td><strong>Ei</strong></td><td>Vasak- või parempoolne liiklus on päris geograafiline tunnus. Peegeldatud Suurbritannia näeb välja nagu Prantsusmaa, silt jääb "Suurbritannia": õpetaksime mudelile otseselt valet.</td></tr>
355 <tr><td>Pööramine</td><td>Ei</td><td>Horisont on tänavapildil alati enam-vähem loodis, kaldus pilte päriselt ei tule. Horisondi asend on info.</td></tr>
356 </table>
357 <div class="note">
358 Hea augmentatsiooni reegel: simuleeri variatsiooni, mis päris andmetes olemas on, ja mitte kunagi sellist, mis silti muudaks.
359 </div>
360
361 <h2 id="tasakaal">11. Klasside tasakaal</h2>
362 <p>
363 Pärast puhastust on riikide vahel ikkagi suurusjärguline vahe: mõnel riigil 2000 pilti, mõnel 100. Ilma sekkumiseta õpiks mudel "kahtluse korral paku suurt riiki" ja väikesed riigid jääksid nulli.
364 </p>
365 <p>
366 Lahendus on <code>WeightedRandomSampler</code>: iga pildi valikutõenäosus on pöördvõrdeline tema riigi piltide arvuga, nii et iga batch sisaldab kõiki riike ligikaudu võrdselt. Väikeste riikide pilte näidatakse lihtsalt sagedamini (tagasipanekuga valik). Alternatiiv oleks klassikaalud kadufunktsioonis; sampler annab ühtlasemad batchid ja stabiilsema treeningu, seepärast valisime tema.
367 </p>
368
369 <h2 id="moodikud">12. Mõõdikud</h2>
370 <table>
371 <tr><th>Mõõdik</th><th>Mida mõõdab</th><th>Miks siin oluline</th></tr>
372 <tr><td>Top-1</td><td>esimene pakkumine õige</td><td>Põhinäitaja. Juhuslik pakkumine ~100 riigiga oleks 1%.</td></tr>
373 <tr><td>Top-5</td><td>õige riik viie parima seas</td><td>Geograafias aus: Eesti-Läti segiajamine on väike viga, Eesti-Brasiilia suur. Vigade seas domineerivad naabrid.</td></tr>
374 <tr><td>Makro-F1</td><td>klasside keskmine F1, kõik riigid võrdse kaaluga</td><td>Paljastab, kui mudel ohverdab väikesed riigid. Top-1 üksi seda ei näita.</td></tr>
375 <tr><td>Riigipõhine tabel</td><td>täpsus ja tugi riigi kaupa</td><td>Näitab, kus mudel on nõrk ja kuhu andmeid juurde vaja.</td></tr>
376 <tr><td>Confusion matrix</td><td>mida millega segi aetakse</td><td>Tüüpilised klastrid: Balti riigid, Skandinaavia, hispaaniakeelne Ladina-Ameerika. Kui segadused on geograafiliselt loogilised, õpib mudel õigeid tunnuseid.</td></tr>
377 </table>
378 <p>
379 Testihulk on treeningust rangelt lahus (stratifitseeritud 80/10/10 jaotus, iga riigi sees eraldi) ja duplikaadid eemaldati enne jaotust, et sama koht ei satuks mõlemale poole.
380 </p>
381
382 <h2 id="piirangud">13. Piirangud ja teekaart</h2>
383 <p>
384 Mudel õpib osalt kaamerat, mitte maastikku (Street View põlvkondade bias). Riigid, mida andmestikus pole, saavad paratamatult mõne naabri sildi. Sisepildid ja inimesed pole selle mudeli teema, ta on tänavavaadete klassifitseerija.
385 </p>
386 <p>
387 Teekaart, ausas järjekorras:
388 </p>
389 <ol>
390 <li>Regioonitase riigi sees: hierarhiline pea, mis ennustab enne riigi ja siis regiooni. Sama retsept, rohkem klasse, rohkem andmeid.</li>
391 <li>Suurem andmestik (OpenStreetView-5M alamhulk) ja suurem backbone (StreetCLIP), kui riistvara lubab.</li>
392 <li>Kalibratsioon ja keeldumine: kui top-1 tõenäosus on madal, on ausam öelda "ei tea".</li>
393 <li><strong>Mitte plaanis:</strong> täpsed koordinaadid. See on teadustöö territoorium (PIGEON, GeoCLIP) ja nõuab arvutusmahtu, mida see projekt teadlikult väldib.</li>
394 </ol>
395
396 </main>
397
398 <footer>
399 CountrySense · CLIP ViT-B/16 peenhäälestus riigi klassifitseerimiseks · vt ka README.et.md
400 </footer>
401
402 </body>
403 </html>
404