Požari SDŽ

Doprinos 1 · detaljni vodič s kodom

Geolokacija iz teksta: regex naspram LLM-a

Cijela prva faza objašnjena korak-po-korak — što radimo, zašto, i kako kod radi. Nije potrebno otvarati Python datoteke; sve se može pročitati ovdje.

1. Što želimo postići

Požarni tekstovi (vatrogasna izvješća i Facebook objave) napisani su običnim jezikom i ne sadrže koordinate — samo opise poput „požar na području Zablača" ili „gorí iznad Omiša". Cilj je iz takvog teksta automatski izvući:

  • 📍 Mjesto → naziv naselja i njegove koordinate
  • 🕐 Vrijeme → datum i sat događaja

Isti zadatak rješavamo na dva načina i uspoređujemo ih — to je sam istraživački doprinos:

Pristup A — Regex

Pravila koja prepoznaju obrasce u tekstu. Brzo i besplatno, ali „krhko" — lako pogriješi kad je tekst neobičan.

Pristup B — LLM

Veliki jezični model (Claude) koji razumije kontekst rečenice i prepoznaje mjesto/vrijeme čak i kad je nejasno napisano.

2. Zašto je to teško

Dva izvora izgledaju vrlo različito:

HVZ izvješća — uredna i strukturirana

Dana 02. veljače u 16:51 sati ŽVOC Šibenik zaprimio je dojavu o požaru
otvorenog prostora na području Zablača. Radilo se o požaru trave na
površini 4 ha. Na intervenciji je sudjelovalo 28 vatrogasaca...

Ovdje regex radi dobro jer je oblik uvijek sličan („Dana … u … sati … na području …").

Facebook — neformalno i puno šuma

"Tooooooo. VATRENIIII ❤️"            → nogomet, NIJE požar
"Vatrogasci - 193 mijenja profilnu"  → objava stranice, NIJE događaj
"Požar kod Dubrave, Bilica"          → pravi požar s lokacijom ✅

Obična pretraga ključnih riječi („vatra", „vatrogasci") lovi i nogometne objave. Tu razumijevanje konteksta (LLM) ima najviše smisla.

3. Regex pristup — objašnjen s kodom

Sav kod je u datoteci doprinos1_geolokacija/geolokator_regex.py 📄 Otvori kod. Radi u tri koraka za mjesto i posebno izvlači vrijeme. Prolazimo redom.

Korak A — pronađi „kandidate" za mjesto

Nazivi mjesta gotovo uvijek počinju velikim slovom. Zato prvo iz teksta izvučemo sve takve riječi:

def velike_rijeci(tekst):
    # makni brojke i interpunkciju (zamijeni razmakom)
    for s in "!\"#$%&()*+-./:;<=>?...1234567890":
        tekst = tekst.replace(s, " ")

    kandidati = []
    for r in tekst.split(" "):
        if len(r) > 1 and r[0].isupper():   # počinje velikim slovom?
            kandidati.append(r)
    return kandidati

Objašnjenje: za tekst „…na području Zablača" ova funkcija vrati npr. ["Dana", "ŽVOC", "Šibenik", "Zablača"]. Neke od njih (ŽVOC) nisu mjesta — to rješava sljedeći korak.

Korak B — pronađi najsličnije naselje na karti

Imamo kartu s 6758 naselja Hrvatske. Za svaki kandidat tražimo naselje s najsličnijim imenom, koristeći udaljenost uređivanja (koliko slova treba promijeniti da jedna riječ postane druga):

def nadji_toponim(kandidat, naselja):
    najbolji  = None
    najmanja  = len(kandidat)
    for z in naselja_na_isto_slovo(kandidat):     # samo naselja na isto početno slovo (brzina)
        d = edit_distance(kandidat.lower(), z["ime"].lower())
        if d < najmanja:
            najmanja = d
            najbolji = z
    # prihvati samo ako je razlika mala (manje od trećine duljine riječi)
    if najbolji and najmanja < len(kandidat) / 3:
        return najbolji
    return None

Ovdje se vidi krhkost regex pristupa! Za „Zablača" najbliže naselje po slovima je „Zamlača" (razlika 1 slovo) — ali to je selo kod Siska, a ne „Zablaće" kod Šibenika (razlika 2 slova). Bez konteksta, računalo bira krivo. Baš ovakve greške mjerimo protiv LLM-a.

Korak C — ako ima više mjesta, uzmi najmanje

Ako tekst spomene više naselja, biramo najmanje po površini — jer se požar obično opisuje najužim, najkonkretnijim mjestom (selo, a ne cijeli grad):

def odaberi_najmanje(pogodci):
    return min(pogodci, key=lambda z: z["povrsina_km2"])

Vrijeme — regex na hrvatski datum

Za vrijeme koristimo obrasce koji hvataju „Dana DD. mjesec" i „u HH:MM sati", uz popis hrvatskih mjeseci:

MJESECI = {"siječnja":1, "veljače":2, "ožujka":3, "travnja":4, ...}

DATUM = re.compile(r"Dana\s*(\d{1,2})\.?\s*([A-Za-zČĆĐŠŽčćđšž]+)")
SAT   = re.compile(r"u\s*(\d{1,2}):(\d{2})\s*sati")

Rezultat: vrijeme se iz HVZ izvješća izvlači vrlo pouzdano (npr. {dan: 2, mjesec: 2, sat: "16:51"}). Problem je uglavnom kod mjesta.

4. Kako pokrenuti (uživo isprobati)

Kad je okruženje uključeno (vidi Kako pokrenuti), u terminalu:

cd doprinos1_geolokacija
python geolokator_regex.py

Ispisat će nekoliko primjera. Za jedno HVZ izvješće izlaz izgleda ovako:

-> mjesto: Zamlača | općina: DVOR | koord: (45.09, 16.38)
-> vrijeme: {dan: 2, mjesec: 2, sat: "16:51"} | kandidati: ["Zamlača"]

(Mjesto je namjerno prikazano „kako regex vidi" — pogrešno Zamlača umjesto Zablaće — da se vidi problem koji rješavamo.)

5. Gold set — „ispravni odgovori" za mjerenje

Da bismo izmjerili koliko točno rade regex i LLM, treba nam skup tekstova s ručno provjerenim točnim odgovorom. To zovemo „gold set" (zlatni standard).

Pripremili smo Excel tablicu s 150 primjera (90 HVZ + 60 Facebook), gdje je računalo već upisalo svoj prijedlog, a čovjek samo potvrdi ili ispravi:

Boja poljaZnačenjeŠto raditi
sivoregex_* — prijedlog računalaNE dirati
zelenotocno_mjesto, tocan_datum, tocno_vrijeme, ima_lokaciju, napomenapotvrdi ili ispravi

→ Vodič: Kako označiti gold set
korak-po-korak, s primjerima prije/poslije

Datoteka: doprinos1_geolokacija/rezultati/gold_set_za_oznacavanje.xlsx (u njoj je i list „Upute"). Kako je nastala:

python napravi_gold_set.py

Zašto ovako: ispravljanje gotovog prijedloga puno je brže od upisivanja od nule, a odgovor ostaje ljudski provjeren — što je za istraživanje ključno.

6. LLM pristup

Isti zadatak damo modelu Claude: pošaljemo mu tekst i pitamo ga da vrati mjesto i vrijeme u urednom obliku. Model razumije kontekst, pa bi trebao izbjeći greške tipa „Zablača → Zamlača" i prepoznati da je „VATRENIII" nogomet, a ne požar.

Kod je napisan i spreman (doprinos1_geolokacija/geolokator_llm.py). Objašnjen je korak-po-korak, s isječcima, na zasebnoj stranici:

→ Detaljni vodič: LLM pristup s kodom
shema odgovora, uputa modelu, poziv, geokodiranje, trošak

Za pokretanje treba Anthropic API ključ. Napravi datoteku .env u glavnoj mapi sa sadržajem ANTHROPIC_API_KEY=sk-ant-... (kopiraj .env.primjer). Ključ nikad ne ide u git (već je zaštićen). Dobiva se na console.anthropic.com.

7. Kako ćemo usporediti (jednostavno objašnjeno)

Kad imamo točne odgovore (gold set) i odgovore oba pristupa, mjerimo tri broja:

MjeraPitanje na koje odgovara
PreciznostKad pristup kaže mjesto — koliko često je u pravu?
OdzivOd svih mjesta koja postoje — koliko ih pronađe?
F1Zajednička ocjena (spoj preciznosti i odziva) — glavni broj za usporedbu.

Uz brojke radimo i analizu grešaka: gdje i zašto jedan pristup pobjeđuje drugoga. To je najvredniji dio doprinosa.

Kod je napisan (doprinos1_geolokacija/usporedba.py) — objašnjen korak-po-korak, s načinom pokretanja u fazama:

→ Detaljni vodič: Usporedba (mjerenje) s kodom
TP/FP/FN, preciznost/odziv/F1, predmemorija, grafovi

Trenutni status svih koraka prati se na stranici Napredak. Sav kod je u folderu doprinos1_geolokacija/ (svaka datoteka je i komentirana iznutra).