kenkovlog

けんこふたんっオフィシャユブヨグッ
アンッ!アンッ!アンッ!アンッ!

lucene-sen をインストールしてScala で使う

昨日 MeCab のJava バインディングをインストール したのですが、5 万文くらいの文章 を解析している時に

create sentence tables
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fbf2d6a2680, pid=2968, tid=140459060225792
#
# JRE version: 7.0_17-b02
# Java VM: OpenJDK 64-Bit Server VM (23.7-b01 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# V  [libjvm.so+0x83c680]  JVM_handle_linux_signal+0x1389f0
#
# Core dump written. Default location: /home/kenkov/Projects/smtscala/core or core.2968
#
# An error report file with more information is saved as:
# /home/kenkov/Projects/smtscala/hs_err_pid2968.log
#
# If you would like to submit a bug report, please include
# instructions on how to reproduce the bug and visit:
#   http://icedtea.classpath.org/bugzilla
#
java.lang.RuntimeException: Nonzero exit code returned from runner: 134
        at scala.sys.package$.error(package.scala:27)

というような感じでセグフォしてしまいました。(上の結果はArch Linux で実行したものです。Mac でも同様なことが起きました。) ですので、Java で作られている形態素解析ライブラリ lucene-gosen を試してみました。

そもそもJava で実装された形態素解析器は…

  • Sen
  • GoSen
  • mecab-java
  • Kuromoji

などなどっ

インスヨール

jar ファイルを 公式サイト からDL してきて、PATH を通すだけ。(sbt なら lib/ ディレクトリに入れる) DL してくる時には、辞書付き(ipadic かnaist-chasen) のものをDL してくれば辞書をインストールしなくてもそのまま使える。

サンプルコード

import net.java.sen.{SenFactory}
import java.util.Locale
import scala.collection.JavaConverters._


class Keitaiso(val hyousoukei: String,
               val genkei: String,
               val pos: String,
               val conjugationalForm: String,
               val conjugationalType: String,
               val pronunciations: List[String],
               val readings: List[String],
               val length: Int,
               val start: Int,
               val cost: Double) {

  override def toString: String = {
    "Keitaiso(" + List(hyousoukei, genkei, pos, conjugationalForm, conjugationalType,
                       pronunciations, readings, length, start, cost).mkString(", ") + ")"
  }

  override def equals(that: Any): Boolean = that match {
    case other: Keitaiso =>
      other.hyousoukei == hyousoukei &&
      other.genkei == genkei &&
      other.pos == pos &&
      other.pronunciations == pronunciations &&
      other.readings == readings &&
      other.length == length
    case _ => false
  }
}

object Keitaiso {
  type Words = List[String]

  def stringToKeitaisos(input: String): List[Keitaiso] = {
    val tagger = SenFactory.getStringTagger(null)
    val token = tagger.analyze(input).asScala.toList
    // for (t <- token) yield
    token map { t =>
      val mor = t.getMorpheme()
      new Keitaiso(
        t.getSurface(),
        mor.getBasicForm(),
        mor.getPartOfSpeech(),
        mor.getConjugationalForm(),
        mor.getConjugationalType(),
        mor.getPronunciations().asScala.toList,
        mor.getReadings().asScala.toList,
        t.getLength(),
        t.getStart(),
        t.getCost())
    }
  }

  def stringToWords(input: String): Words = {
    val tagger = SenFactory.getStringTagger(null)
    val token = tagger.analyze(input).asScala.toList
    for (t <- token) yield t.toString
  }
}

object SenTest {
  def main(args: Array[String]) {
    val words = List("今日は初めてなの。",
                     "やさしくしてねっ")
    words foreach { x => println(Keitaiso.stringToKeitaisos(x)) }
    words foreach { x => println(Keitaiso.stringToWords(x)) }
  }
}
けんこふたん