k47.cz  — každý den dokud se vám to nezačne líbit
výběr foto Praha povídky kultura
TECH ▞▞ kolo | twitter RSS

Statistický generátor textu

— k47 (CC by) (♪)

Jed­no­du­chý sta­tis­tický ge­ne­rá­tor textu za­lo­žený na prin­cipu Mar­ko­vova ře­tězce. Fun­guje tak, že ze vstup­ního textu, po­staví model re­pre­zen­tu­jící, jaká slova jak často ná­sle­dují po daných n-gra­mech (kon­krétně bi-gra­mech). Když je model hotový, stačí mu zadat po­čá­teční n-gram, pro­gram podle zjiš­tě­ných prav­dě­po­dob­ností ybere ná­sle­du­jící slovo. Tohle slovo se pak stane sou­částí ak­tu­ál­ního n-gramu, vybere se, co po něm bude ná­sle­do­vat a takhle to po­kra­čuje dál.


Zkusmo jsem ge­ne­rá­tor na­kr­mil všemi svými po­víd­kami a jeho sna­žení se au­to­ma­ticky pu­b­li­kuje na twit­te­ro­vém účtu @ro­bo­po­vidka.


// you need Scala 2.10 to run this

val text = ???

// we are interested in bi-grams
val n = 2

// map from ngrams to seq of following words
val map = collection.mutable.Map[Seq[String], Seq[String]]() withDefaultValue Seq()

val words = text.toLowerCase.split("(?U)\\W+").toVector

for (ngram :+ next <- words sliding n+1)
  map(ngram) = map(ngram) :+ next

// generate text
var firstNgram, lastNgram = Seq("anomalocaris", "detrimentum", "něco").take(n)

val generatedWords = for (i <- 1 to 5000) yield {
  map.get(lastNgram) match {
    case Some(nextWords) =>
      val idx = util.Random.nextInt(nextWords.size)
      val next = nextWords(idx)
      lastNgram = lastNgram.tail :+ next
      Some(next)
    case None =>
      None
  }
}

var length = 0
for (w <- firstNgram ++ generatedWords.flatten) {
  length += w.length + 1

  if (length > 140) {
    length = w.length + 1
    println()
  }
  print(w+" ")
}
println()

Po­dob­nost s La­ho­lá­to­rem je čistě ná­hodná a zcela ne­ú­myslná.

píše k47 & hosté, ascii@k47.cz