scalaのn-gramに基づいて解離プレスアルゴリズムをコーディングしようとしています。大きなファイルの n-gram を生成する方法: たとえば、「蜂は蜂の蜂」を含むファイルの場合。
- まず、ランダムな n-gram を選択する必要があります。たとえば、蜂。
- 次に、(n-1) 個の単語で始まる n-gram を探す必要があります。たとえば、蜂の巣。
- この n-gram の最後の単語を出力します。その後、繰り返します。
やり方のヒントを教えてください。ご不便おかけしてすみません。
あなたの質問はもう少し具体的かもしれませんが、ここに私の試みがあります。
val words = "the bee is the bee of the bees"
words.split(' ').sliding(2).foreach( p => println(p.mkString))
n のパラメータでこれを試すことができます
val words = "the bee is the bee of the bees"
val w = words.split(" ")
val n = 4
val ngrams = (for( i <- 1 to n) yield w.sliding(i).map(p => p.toList)).flatMap(x => x)
ngrams foreach println
List(the)
List(bee)
List(is)
List(the)
List(bee)
List(of)
List(the)
List(bees)
List(the, bee)
List(bee, is)
List(is, the)
List(the, bee)
List(bee, of)
List(of, the)
List(the, bees)
List(the, bee, is)
List(bee, is, the)
List(is, the, bee)
List(the, bee, of)
List(bee, of, the)
List(of, the, bees)
List(the, bee, is, the)
List(bee, is, the, bee)
List(is, the, bee, of)
List(the, bee, of, the)
List(bee, of, the, bees)
これがストリームベースのアプローチです。これにより、n-gram の計算中に大量のメモリが必要になりません。
object ngramstream extends App {
def process(st: Stream[Array[String]])(f: Array[String] => Unit): Stream[Array[String]] = st match {
case x #:: xs => {
f(x)
process(xs)(f)
}
case _ => Stream[Array[String]]()
}
def ngrams(n: Int, words: Array[String]) = {
// exclude 1-grams
(2 to n).map { i => words.sliding(i).toStream }
.foldLeft(Stream[Array[String]]()) {
(a, b) => a #::: b
}
}
val words = "the bee is the bee of the bees"
val n = 4
val ngrams2 = ngrams(n, words.split(" "))
process(ngrams2) { x =>
println(x.toList)
}
}
出力:
List(the, bee)
List(bee, is)
List(is, the)
List(the, bee)
List(bee, of)
List(of, the)
List(the, bees)
List(the, bee, is)
List(bee, is, the)
List(is, the, bee)
List(the, bee, of)
List(bee, of, the)
List(of, the, bees)
List(the, bee, is, the)
List(bee, is, the, bee)
List(is, the, bee, of)
List(the, bee, of, the)
List(bee, of, the, bees)