Kun merikotka saa henkilötietosuojaa — ja mitä oikeasta tietosuojasta voisi oppia

Differentiaalinen yksityisyys ja bayeslainen anonymisointi selitettynä

Suomen pelastuslaitos kieltäytyi kertomasta merikotkan pelastamisesta vedoten henkilötietolakiin — lakiin, joka koskee vain ihmisiä, ei eläimiä. Tapaus on hauska, mutta se paljastaa jotain vakavaa: emme osaa puhua julkisessa hallinnossa tietosuojasta täsmällisesti. Tässä postauksessa näytän, miten tietosuoja todella toimii — jakaumien, ei kieltojen kautta.

tietosuoja
bayeslaiset menetelmät
avoimen datan analytiikka
differentiaalinen yksityisyys
Author

Kristian Vepsäläinen

Published

12.6.2026

Tapaus: merikotka, automaattisalaus ja algoritmi joka ei osaa lukea lakia

Toukokuussa 2026 merikotka törmäsi tuulivoimalaan Kalajoella ja menetti osan siivestään. Pelastuslaitos kävi paikalla. Helsingin Sanomat pyysi nähtäväkseen tapauksen onnettomuusselosteen eli teki aivan normaalin viranomaistietopyynnön, sillä Suomessa viranomaisasiakirjat ovat julkisuuslain mukaan lähtökohtaisesti julkisia.

Seloste saapui. Keskeiset kohdat, kuten onnettomuuden kulku ja pelastuslaitoksen toiminta, oli mustattu. Salausta perusteltiin viittaamalla Pelastuslakiin (379/2011) 86 §:ään, Henkilötietolakiin (523/1999) 11 §:ään ja Julkisuuslakiin (621/1999) 24 §:ään.

Asianosaisena oli merikotka eli Haliaeetus albicilla. Henkilötietolaki koskee luonnollisia henkilöitä, ei lintuja.

Pohjois-Pohjanmaan pelastuslaitoksen johto myöntää virheellisen salauksen. Kehityspäällikkö Matti Virtanen selittää: taustalla on Pelastusopiston kehittämä Pronto-järjestelmä, joka on mustanut onnettomuusselosteista aina samat kohdat automaattisesti, riippumatta siitä, onko kussakin tapauksessa yhtään salattavaa. “Automaatin mukaan mennään”, Virtanen tiivistää. “Voihan siellä olla sitten tilanne, että siellä ei olekaan mitään salattavaa.”

Hallinto-oikeuden emeritusprofessori Olli Mäenpää pitää tilannetta suoraan lainvastaisena: “Ei ole mitään yleistä ehdotonta salassapitoperustetta, jonka perusteella voisi kaikki tiedot automaattisesti salata, vaan ne pitää arvioida tieto kerrallaan.”

Pronto korvataan tänä vuonna uudella Kivijalka-järjestelmällä. Vanhaa järjestelmää ei Virtasen mukaan aiottu kehittää tähän suuntaan, mutta sitä ei myöskään kehitetty pois tästä suunnasta.


Tämä tapaus on hauska. Mutta se ei ole vain koominen väärinkäsitys; se on oire algoritmisesta päätöksenteosta ilman ihmisarviointia. Järjestelmä tekee salauksia, koska se on ohjelmoitu tekemään salauksia. Kukaan ei tarkista, onko salaukselle perustetta. Tulos: merikotka saa henkilötietosuojaa.

Nyt tulee se kiinnostava kysymys: jos laki velvoittaa arvioimaan jokaisen salauksen erikseen, miten se tehtäisiin oikein? Ja mitä teknisiä menetelmiä oikeaan tietosuojaan ylipäätään on, kun asianosaisena on ihminen eikä kotka?

Tässä kirjoituksessa näytän, miten moderni tietosuoja oikeasti toimii juuri tässä kontekstissa: yksittäisessä onnettomuusselosteessa, jossa voi olla sensitiivisiä tekstikenttiä kuten osoitteita tai nimiä. Käyn läpi kaksi menetelmää ja demonstroin ne koodilla: ensin NLP-pohjaisen sensitiivisyysluokittelun, jolla kone tunnistaa, mikä teksti vaatii salauksen, ja sitten differentiaalisen yksityisyyden, jolla pelastuslaitoksen tilastot voidaan julkaista turvallisesti.

Loppuun vedän yhteen sen, mitä Pronto-järjestelmän voisi korvata. ei automaattisalauksen, vaan automaattisen arvioinnin, jossa kone tunnistaa sensitiivisyyden ja salaus kohdistuu juuri oikeaan kohtaan.


Automaattisalaus on algoritminen päätös ilman arviointia ja miksi se on ongelma

Pronto-järjestelmän logiikka on ymmärrettävä insinööriratkaisuna: salauksen automatisointi säästää aikaa. Mutta oikeudellisesti se on väärässä lähtökohdassa. Julkisuuslaki lähtee avoimuusolettamasta — salaus on poikkeus, joka vaatii perusteen. Kun järjestelmä automaattisesti mustaa samat kentät jokaisessa selosteessa, se kääntää tämän logiikan nurinpäin: salaus on oletus, avoimuus on poikkeus.

Tämä on tuttu ongelma koneoppimisessa ja algoritmisessa päätöksenteossa yleisemmin. Algoritmi optimoi sen, mitä se on opetettu optimoimaan. Jos Pronto on rakennettu niin, että salaus on turvallinen oletusasetus, se tuottaa ylisalauksia eli salaa tämän esimerkkimme kotkatapauksen.

Moderni tietosuojateoria lähtee aivan toisesta suunnasta. Keskeinen kysymys ei ole “salaako vai ei?” vaan “miten paljon lisätietoa tämä julkaisu antaa yksittäisestä henkilöstä verrattuna siihen, mitä ulkopuolinen jo tietää?”

Tähän kysymykseen voi vastata matemaattisesti ja sen perusteella tehdä perusteltu päätös tapauskohtaisesti.


Differentiaalinen yksityisyys: matemaattinen tietosuoja

Idea lyhyesti

Differentiaalinen yksityisyys (DP) on vuonna 2006 Cynthia Dworkin ym. kehittämä tietosuojamenetelmä, jolla on tiukka matemaattinen takuu. Se toimii lisäämällä dataan harkittua kohinaa niin, että yksittäistä henkilöä koskeva johtopäätös ei ole tilastollisesti mahdollinen tietyn tarkkuuden yli.

Muodollisesti: algoritmi \(\mathcal{M}\) on \(\varepsilon\)-differentially private, jos kaikille kahdelle tietokannalle \(D\) ja \(D'\), jotka eroavat yhdellä rivillä, ja kaikille tuloksille \(S\):

\[\Pr[\mathcal{M}(D) \in S] \leq e^\varepsilon \cdot \Pr[\mathcal{M}(D') \in S]\]

Parametri \(\varepsilon\) (epsilon) on yksityisyysbudjetti. Pieni \(\varepsilon\) = tiukka suoja, enemmän kohinaa. Suuri \(\varepsilon\) = löysempi suoja, tarkempi data.

Miksi tämä on tärkeää

Ilman DP:tä pelkkä “anonymisointi” eli esimerkiksi nimien poistaminen tai aggregointi, ei suojaa. On hyvin dokumentoitua, että pienistä tilastoista voi “re-identifioida” henkilöitä, kun yhdistää useita datalähteitä. DP estää tämän matemaattisesti.

Konkreetti esimerkki: Laplace-kohina

Yksinkertaisin DP-mekanismi on lisätä Laplace-jakaumasta vedettyä kohinaa. Jos haluamme julkaista kyselyn herkkyydellä \(\Delta f\) yksityisyysbudjetilla \(\varepsilon\), lisäämme kohinaa skaalalla \(b = \Delta f / \varepsilon\).

Näytä koodi
# Esimerkki: "Kuinka monta eläintehtävää tällä viikolla?"
# Todellinen vastaus: 47 tehtävää
# Count-kyselyn herkkyys = 1 (yksi rivi voi muuttaa vastausta yhdellä)
true_count <- 47
sensitivity <- 1  # count query: aina 1

# Laplace-mekanismi: lisätään kohinaa skaalalla b = sensitivity / epsilon
laplace_noise <- function(sensitivity, epsilon, n = 1) {
  b <- sensitivity / epsilon
  u <- runif(n, -0.5, 0.5)
  -b * sign(u) * log(1 - 2 * abs(u))
}

epsilons <- c(0.1, 0.5, 1.0, 5.0)
n_sims   <- 8000

dp_results <- map_dfr(epsilons, function(eps) {
  noisy_estimates <- true_count + laplace_noise(sensitivity, eps, n = n_sims)
  tibble(
    epsilon   = eps,
    estimate  = noisy_estimates,
    eps_label = paste0("ε = ", eps)
  )
})

stopifnot(nrow(dp_results) == length(epsilons) * n_sims)
stopifnot(all(c("epsilon", "estimate", "eps_label") %in% names(dp_results)))

dp_results <- dp_results |>
  mutate(eps_label = factor(eps_label,
                            levels = paste0("ε = ", sort(epsilons))))

# Lasketaan 90%-välit per epsilon näytettäväksi
dp_intervals <- dp_results |>
  group_by(eps_label, epsilon) |>
  summarise(
    lo = quantile(estimate, 0.05),
    hi = quantile(estimate, 0.95),
    .groups = "drop"
  ) |>
  mutate(label = sprintf("90%% väli: [%.0f, %.0f]", lo, hi))

# Pääkuvaaja: jakaumat
p_main <- ggplot(dp_results,
                 aes(x = estimate, fill = eps_label, color = eps_label)) +
  geom_density(alpha = 0.30, linewidth = 0.9) +
  geom_vline(xintercept = true_count, linetype = "dashed",
             color = "white", linewidth = 1.0) +
  annotate("text", x = true_count + 1, y = Inf,
           label = paste0("Todellinen arvo\n(", true_count, " tehtävää)"),
           vjust = 1.8, hjust = 0, color = "white", size = 3.3) +
  scale_fill_manual(values = c(col_red, col_orange, col_teal, col_blue),
                    name = "Yksityisyysbudjetti") +
  scale_color_manual(values = c(col_red, col_orange, col_teal, col_blue),
                     name = "Yksityisyysbudjetti") +
  coord_cartesian(xlim = c(-10, 110)) +
  labs(
    title    = "Differentiaalinen yksityisyys: julkaistu luku vs. todellinen luku",
    subtitle = "Kysely: 'Kuinka monta eläintehtävää tällä viikolla?' — todellinen vastaus: 47",
    x        = "Julkaistu lukumäärä (tehtävää)",
    y        = "Tiheys"
  ) +
  theme_kv() +
  theme(legend.position = "top")

# Alataulukko: 90%-välit selkeyttämään eroa
p_intervals <- ggplot(dp_intervals,
                      aes(x = lo, xend = hi,
                          y = reorder(eps_label, -epsilon),
                          yend = reorder(eps_label, -epsilon),
                          color = eps_label)) +
  geom_segment(linewidth = 3.5, alpha = 0.8) +
  geom_point(aes(x = true_count), color = "white",
             size = 3, shape = 21, fill = "white") +
  geom_text(aes(x = (lo + hi) / 2, label = label),
            vjust = -1.2, size = 3.0, color = "#c0c0c0") +
  scale_color_manual(values = c(col_red, col_orange, col_teal, col_blue),
                     guide = "none") +
  labs(
    title    = "90 % todennäköisyysvälit julkaistulle arvolle",
    subtitle = "Valkoinen piste = todellinen arvo (47)",
    x        = "Julkaistu lukumäärä",
    y        = NULL
  ) +
  theme_kv()

p_main / p_intervals + plot_layout(heights = c(2, 1))

Differentiaalinen yksityisyys käytännössä: sama kysely eri yksityisyysbudjeteilla

Kuviossa näkyy selkeästi yksityisyyden ja tarkkuuden välinen jännitys eli jakauma. Ei ole olemassa yhtä “oikeaa” vastausta siihen, paljonko kohinaa lisätään; on olemassa valintatilanne, jossa eri arvot johtavat eri riskiprofiileihin.

Tämä on “maailma on jakauma” -periaate tietosuojaan sovellettuna: yksityisyys ei ole kytkintä. Se on parametri, jonka arvo valitaan tietoisesti.


Menetelmä 2: NLP-pohjainen sensitiivisyysluokittelu — kohdista salaus oikeaan paikkaan

Ongelma: Pronto mustaa liikaa

Pronton automaattilogiikka mustaa kenttiä rakenteen perusteella; “tässä kentässä saattaa olla henkilötieto”. Se on sama kuin sanoa: “tässä kirjekuoressa saattaa olla salainen asiakirja, joten mustaamme sen varmuuden vuoksi.” Oikeaoppinen tietosuoja toimii toisin: ensin arvioidaan, onko sensitiivistä tietoa, sitten päätetään toimenpiteestä.

Tähän tehtävään sopii nimettyjen entiteettien tunnistus (Named Entity Recognition, NER). Se on yksi luonnollisen kielen käsittelyn perusmenetelmiä. Se tunnistaa tekstistä henkilönimet, organisaatiot, osoitteet ja muut vastaavat tunnistetiedot.

Idea simuloituna

Alla simuloin kuvitteellisia onnettomuusselosteen tekstikatkelmia ja lasken niille sensitiivisyyspisteet. Oikeassa järjestelmässä käytettäisiin esimerkiksi Spacy- tai Hugging Face -kirjastoja; tässä simuloin tuloksen R:ssä säännöllisillä lausekkeilla, jotka edustavat samaa logiikkaa.

Näytä koodi
selosteet <- tibble(
  id     = 1:12,
  kentta = c(
    rep("Kuvaus onnettomuuden kulusta", 4),
    rep("Selvitys pelastuslaitoksen toiminnasta", 4),
    rep("Muut tiedot", 4)
  ),
  teksti = c(
    "Maastossa kulkija oli havainnut merikotkan liikkuvan maassa, eikä se ollut lähtenyt lentoon.",
    "Asukas Matti Virtanen, s. 12.3.1975, soitti hätänumeroon klo 14:23 kertoakseen löytäneensä haavoittuneen linnun.",
    "Kohteessa Metsätie 4, 85100 Kalajoki havaittu lintuvahinkopaikka tuulivoimalan juurella.",
    "Yksikkö P231 saapui kohteeseen 8 minuutin kuluttua hälytyksestä. Kotka oli loukkaantunut siipeen.",
    "Lintua yritetty saada kiinni, mutta se ei onnistu. Jätettiin metsään, JoKe ilmoittaa eteenpäin.",
    "Pelastusryhmä koostui kahdesta henkilöstä. Varustuksena eläintensiirtolaatikko ja suojakäsineet.",
    "Potilaan nimi: Hanna Korhonen, hetu 150489-XXXX. Erillinen tehtävä samana päivänä.",
    "Toiminta-aika kohteessa 23 minuuttia. Kotka evakuoitiin Keski-Pohjanmaan luontokeskukseen.",
    "Sää: puolipilvinen, tuuli 6 m/s lounaasta. Näkyvyys hyvä.",
    "Yhteystiedot: pelastuspäällikkö Juha Mäkinen, p. 040-123 4567.",
    "Tapaukseen ei liity henkilövahinkoja. Merikotka on rauhoitettu laji (lsl 42 §).",
    "Tehtävä kirjattu numerolla 2026-05-1847. Ei jatkotoimenpiteitä."
  )
)

# Sensitiivisyyspisteytys: simuloi NER-mallin tunnistusta
laske_sensitiivisyys <- function(teksti) {
  pisteet <- 0L
  # Henkilötunnus tai syntymäaika
  if (grepl("\\d{6}[-+A]\\d{3}[A-Z0-9]|s\\.\\s*\\d{1,2}\\.\\d{1,2}\\.\\d{4}", teksti))
    pisteet <- pisteet + 40L
  # Puhelinnumero
  if (grepl("\\d{3}[-\\s]\\d{3,4}\\s\\d{4}|04\\d[-\\s]\\d{3}", teksti))
    pisteet <- pisteet + 25L
  # Osoite
  if (grepl("\\b\\d{5}\\b|[A-ZÄÖÅ][a-zäöå]+(tie|katu|väylä)\\s+\\d", teksti))
    pisteet <- pisteet + 20L
  # Henkilönimi (kaksi isolla alkavaa sanaa — ei organisaatioita)
  if (grepl("\\b[A-ZÄÖÅ][a-zäöå]+\\s+[A-ZÄÖÅ][a-zäöå]+\\b", teksti) &&
      !grepl("^(Pelastus|Pohjois|Keski|Länsi|Itä|Etelä|Merikotka)", teksti))
    pisteet <- pisteet + 15L
  min(as.integer(pisteet), 100L)
}

selosteet <- selosteet |>
  mutate(
    sensitiivisyys      = map_int(teksti, laske_sensitiivisyys),
    suositellaan_salaus = sensitiivisyys >= 20L,
    sensitiivisyys_lk   = case_when(
      sensitiivisyys == 0L ~ "Ei sensitiivinen",
      sensitiivisyys < 20L ~ "Matala",
      sensitiivisyys < 50L ~ "Kohtalainen",
      TRUE                 ~ "Korkea"
    ) |> factor(levels = c("Ei sensitiivinen", "Matala", "Kohtalainen", "Korkea"))
  )

stopifnot(nrow(selosteet) == 12L)
stopifnot(all(selosteet$sensitiivisyys >= 0L & selosteet$sensitiivisyys <= 100L))

n_salattavia <- sum(selosteet$suositellaan_salaus)

ggplot(selosteet,
       aes(x = sensitiivisyys,
           y = reorder(paste0("Rivi ", id, ": ", str_trunc(teksti, 48)),
                       sensitiivisyys),
           fill = sensitiivisyys_lk)) +
  geom_col(width = 0.7) +
  geom_vline(xintercept = 20, linetype = "dashed",
             color = col_orange, linewidth = 0.9) +
  annotate("text", x = 22, y = 0.7,
           label = "Salausraja", hjust = 0,
           color = col_orange, size = 3.2) +
  scale_fill_manual(
    values = c("Ei sensitiivinen" = col_teal,
               "Matala"           = col_blue,
               "Kohtalainen"      = col_orange,
               "Korkea"           = col_red),
    name = "Sensitiivisyysluokka"
  ) +
  labs(
    title    = "NLP-sensitiivisyysluokittelu: mitkä rivit tarvitsevat salauksen?",
    subtitle = paste0(n_salattavia, "/", nrow(selosteet),
                      " rivistä ylittää salausrajan — loput julkaistaan sellaisenaan"),
    x        = "Sensitiivisyyspisteet (0–100)",
    y        = NULL
  ) +
  theme_kv() +
  theme(axis.text.y = element_text(size = 8))

NLP-sensitiivisyysluokittelu: mitkä tekstikentät tarvitsevat salauksen?

Tässä on avainero Pronton logiikkaan: järjestelmä ei mustaa kenttää rakenteen takia, vaan sisällön takia. Merikotkan pelastustehtävässä kuvauskenttä “Maastossa kulkija havaitsi merikotkan liikkuvan maassa” saa pisteet 0. Toisin sanoen ei henkilötietoja, ei salaustarvetta. Mutta rivi, jossa mainitaan henkilötunnus tai puhelinnumero saa pisteet 40–65 ja ohjataan automaattisesti salaukseen tai ihmisarvioon.

Pronto mustasi kaiken. NER mustaa vain sen mikä ansaitsee mustauksen.


Menetelmä 3: Differentiaalinen yksityisyys pelastuslaitoksen tilastoihin

DP ei sovi yksittäisen onnettomuusselosteen salaamiseen. Se on tarkoitettu tilanteeseen, jossa julkaistaan aggregoituja tilastoja isolle joukolle tapauksia. Pelastuslaitos julkaisee vuosiraportteja, tehtävätilastoja, vasteaikoja. Juuri näissä DP loistaa.

Edellisessä osiossa demonstroin Laplace-mekanismin yksinkertaisella count-kyselyllä. Laajennetaan nyt esimerkki useampaan samanaikaiseen kyselyyn — mikä on realistisempi tilanne: pelastuslaitos haluaa julkaista tehtävätyypeittäin eritellyn viikkotaulukon.

Näytä koodi
tosi_arvot <- c(
  "Tulipalo"             = 12,
  "Liikenneonnettomuus"  = 31,
  "Eläintehtävä"         = 8,
  "Ensiapuavustus"       = 47,
  "Tarkistuskäynti"      = 19,
  "Muu tehtävä"          = 23
)

epsilon_total <- 1.0  # rinnakkaisella koostumuksella sama budjetti riittää kaikille

set.seed(42)
n_sims <- 3000

sim_results <- map_dfr(names(tosi_arvot), function(tyyppi) {
  tosi  <- tosi_arvot[tyyppi]
  noisy <- tosi + laplace_noise(sensitivity = 1, epsilon = epsilon_total, n = n_sims)
  tibble(tyyppi = tyyppi, tosi_arvo = tosi, julkaistu = noisy)
})

stopifnot(nrow(sim_results) == length(tosi_arvot) * n_sims)

dp_summary <- sim_results |>
  group_by(tyyppi, tosi_arvo) |>
  summarise(
    med  = median(julkaistu),
    lo80 = quantile(julkaistu, 0.10),
    hi80 = quantile(julkaistu, 0.90),
    lo95 = quantile(julkaistu, 0.025),
    hi95 = quantile(julkaistu, 0.975),
    .groups = "drop"
  )

stopifnot(all(dp_summary$lo80 < dp_summary$hi80))

ggplot(dp_summary, aes(y = reorder(tyyppi, tosi_arvo))) +
  geom_errorbar(aes(xmin = lo95, xmax = hi95),
                orientation = "y",
                width = 0.3, color = col_blue, linewidth = 1.0, alpha = 0.6) +
  geom_errorbar(aes(xmin = lo80, xmax = hi80),
                orientation = "y",
                width = 0, color = col_teal, linewidth = 3.0, alpha = 0.8) +
  geom_point(aes(x = med),       color = col_orange, size = 3.5) +
  geom_point(aes(x = tosi_arvo), color = "white",    size = 2.5,
             shape = 4, stroke = 1.5) +
  labs(
    title    = "DP-tilastotaulukko: tehtävämäärät tehtävätyypeittäin (ε = 1.0)",
    subtitle = "Oranssi piste = julkaistu mediaani | Valkoinen × = todellinen arvo\nPaksu viiva = 80% väli, ohut viiva = 95% väli",
    x        = "Tehtävämäärä (kpl viikossa)",
    y        = NULL
  ) +
  theme_kv()

DP useammalle kyselylle samanaikaisesti: epävarmuus kasvaa pienillä tehtävätyypeillä

Huomaa tärkeä havainto: eläintehtäviä on 8 — julkaistu arvo heiluu eniten. Ensiapuavustuksia on 47 — jakauma on suhteellisesti kapeampi. Tämä on matemaattisesti oikein: pienistä luvuista yksittäinen havainto on suhteellisesti merkittävämpi, joten DP:n antama suoja on samalla enemmän “tarpeen” ja samalla enemmän “näkyvissä” epävarmuutena.


Yhteenveto menetelmistä

Menetelmien vertailu pelastuslaitoksen kontekstissa
Menetelmä Sopii yksittäiseen selosteeseen Sopii tilastojulkaisuun Matemaattinen tae Kohdistuu sisältöön Suositus
Pronto: automaattisalaus rakenteen perusteella Kyllä (mutta ylisalaa) Ei Ei ole Ei Ei
NLP / NER -sensitiivisyysluokittelu Kyllä Ei tarpeen Ei ole Kyllä Kyllä selosteisiin
Differentiaalinen yksityisyys (tilastot) Ei Kyllä Vahva (ε-DP) Kyllä Kyllä tilastoihin
Ihmisarvio (korkean riskin tapaukset) Kyllä Liian hidas Ei mitattavissa Kyllä Kyllä epäselviin tapauksiin

Takaisin merikotkaan ja Pronton seuraajaan

Merikotkan tapauksessa kumpikaan menetelmistä ei ollut tarpeen: lintu ei ole luonnollinen henkilö, selosteessa ei ole suojattavaa tietoa, ja julkisuuslaki edellyttäisi avointa julkaisua. Järjestelmä silti mustasi.

Mutta nyt on oikea hetki kysyä: rakennetaanko uusi järjestelmä samalla logiikalla, automaattisalaus oletuksena, vai voisiko lähestymistapa olla erilainen?

Datatieteellinen vaihtoehto olisi kääntää logiikka: automaattinen avoimuus oletuksena, salaus poikkeuksena, joka vaatii lasketun perusteen.

Käytännössä tämä voisi toimia näin:

Vaihe 1: Luokittelualgoritmi arvioi sensitiivisyyden. Tekstinlouhinta tai kielimalli tunnistaa, sisältääkö seloste tunnistetietoja (nimet, osoitteet, sosiaaliturvatunnukset, terveystiedot). Eläintapauksessa malli palauttaisi: “ei henkilötietoja havaittu.”

Vaihe 2: Differentiaalinen yksityisyys suojaa aggregaatit. Jos tapaukseen liittyy henkilötietoja, niitä sisältävät kentät suojataan DP:llä ennen julkaisua; ei mustauksella, joka estää kaiken hyödyntämisen, vaan kohinalla, joka mahdollistaa tilastollisen käytön.

Vaihe 3: Bayeslainen arviointimalli tuottaa julkaisusuosituksen. Jokainen seloste saa posterioritodennäköisyyden: kuinka todennäköisesti tämä sisältää lain edellyttämää salattavaa? Matalan todennäköisyyden tapaukset julkaistaan automaattisesti; korkean todennäköisyyden tapaukset menee ihmisarvioon.

Tämä ei ole utopia, sillä vastaavia järjestelmiä käytetään esimerkiksi Yhdysvaltain Census Bureaun datajulkaisuissa ja EU:n tilastovirasto Eurostatin mikroaineistoissa.

Hallinto-oikeuden emeritusprofessori Mäenpää sanoo, että “turvallisuus ja avoimuus kulkevat pikemminkin käsi kädessä kuin ovat toistensa vastakohtia.” Datatiede on samaa mieltä. Mutta se vaatii, että salauksen logiikka käännetään — ja että päätöksentekijät ymmärtävät, mitä automaattinen salausjärjestelmä oikeastaan tekee.


Lopuksi: tietosuoja on jakauma, ei kytkin. Se ei ole algoritmi, joka ei osaa lukea lakia

Pronto-järjestelmä on ollut käytössä yli kymmenen vuotta ja se on mustanut onnettomuusselosteita “ehkä koko olemassaolonsa ajan”, kuten kehityspäällikkö Virtanen arvioi. Kukaan ei näytä kyseenalaistaneen tätä käytäntöä. Se on klassinen esimerkki siitä, miten automatisoitu prosessi muuttuu näkymättömäksi — kunnes merikotka törmää tuulivoimalaan ja paljastaa, että keisarilla ei ole vaatteita.

Automaattisalaus on huono ratkaisu paitsi oikeudellisesti myös tilastollisesti: se hävittää tietoa, jota yhteiskunta tarvitsee. Onnettomuusselosteet ovat arvokasta dataa turvallisuustutkimukselle, resurssisuunnittelulle ja viranomaisvalvonnalle. Kun ne salaataan automaattisesti, menetetään paitsi yksittäinen tapaus myös kumulatiivinen oppiminen.

Moderni tilastotiede, ja erityisesti bayeslainen ajattelu, tarjoaa paljon hienovaraisemman työkalupakin. Epävarmuus on tietoa. Julkaisemalla jakauma pisteen sijaan paljastetaan, mitä tiedetään ja mitä ei. Ja kun tiedetään, mitä ei tiedetä, voidaan päättää viisaammin siitä, mikä todella tarvitsee suojaa.

Maailma on jakauma. Myös tietosuojakin.


Kristian Vepsäläinen on itsenäinen data-analytiikan konsultti ja Fractional Head of Data. Hän auttaa pk-yrityksiä tekemään parempia päätöksiä datan avulla — ilman täysiaikaisen datajohtajan palkkausta. Varaa maksuton kartoituskeskustelu.