読者です 読者をやめる 読者になる 読者になる

golang で形態素解析を並列実行させて Word Count する

はじめに

kagome は goroutine セーフに作ってあるんですが,あんまり並列実行的なサンプルとか書いてないなと思って並列実行でテキストに出てくる名詞を引っこ抜いて数えるサンプルを作りました.

あと,昨日 suzuken =san が 形態素解析をした後の品詞が取り出しにくいよという Issue を上げてくださって,Token に Pos() という品詞を取り出すメソッド追加しました.今までは,

if t := tok.Features(); len(t) > 0 && t[0] == "名詞" {
     // 名詞の時の処理
}

と書いていたのを

if tok.Pos() == "名詞" {
     // 名詞の時の処理
}

と書けるようになりました.suzuken = san ありがとうございます.

( '-`).oO( 品詞以外も便利関数欲しいところですが,辞書によって辞書内容がかなり自由に作れるので,とりあえずは品詞だけの対応になるかなとおもいます.

Word Count

テキストを文区切りして,区切った文ごとに goroutine 呼び出して形態素解析します. 形態素解析結果から名詞だけ取り出して,チャンネルに送り返します.

チャンネルに送り返された語を数えていけば,Word Count のできあがりです.

エラー処理とかが適当なのはご了承ください(^^ゞ

package main

import (
    "bufio"
    "fmt"
    "io"
    "strings"
    "sync"

    "github.com/ikawaha/kagome/splitter"
    "github.com/ikawaha/kagome/tokenizer"
)

const sampleText = `人魚は、南の方の海にばかり棲んでいるのではあ
                    りません。北の海にも棲んでいたのであります。
                    北方の海うみの色は、青うございました。ある
                    とき、岩の上に、女の人魚があがって、あたりの景
                    色をながめながら休んでいました。

                     小川未明作 赤い蝋燭と人魚より`

func nounFilter(ch chan<- string, r io.Reader) {
    var wg sync.WaitGroup
    t := tokenizer.New()
    scanner := bufio.NewScanner(r)
    scanner.Split(splitter.ScanSentences)
    for scanner.Scan() {
        wg.Add(1)
        go func(s string) {
            defer wg.Done()
            tokens := t.Tokenize(s)
            for _, tok := range tokens {
                if tok.Pos() == "名詞" {
                    ch <- tok.Surface
                }
            }
        }(scanner.Text())
    }
    if err := scanner.Err(); err != nil {
        close(ch)
    }
    wg.Wait()
    close(ch)
}

func main() {
    ch := make(chan string, 1024)

    r := strings.NewReader(sampleText)
    go nounFilter(ch, r)

    m := map[string]int{}
    for {
        s, ok := <-ch
        if !ok {
            break
        }
        m[s]++
    }
    for k, v := range m {
        fmt.Printf("%v\t%v\n", k, v)
    }
}

結果はこんな感じになります.

小川   1
作 1
北 1
女 1
方 1
未明  1
海 3
上 1
人魚  3
の 2
景色  1
南 1
北方  1
蝋燭  1
とき  1
岩 1
あたり   1
色 1