LoginSignup
11
17

More than 5 years have passed since last update.

新型の形態素解析エンジン JUMAN++をRubyから使う

Last updated at Posted at 2016-11-23

今一番熱い形態素解析エンジンといえば、やっぱりJUMAN++ですよね!

(参考1)JUMAN++ - 黒橋・河原研究室 - 京都大学

(参考2)新形態素解析器JUMAN++を触ってみたけど思ったより高精度でMeCabから乗り換えようかと思った話

少しだけ使ってみましたが、状況次第ではmecab + NEologdを凌駕する精度が出そうだと感じました。

JUMAN++にはpythonラッパーが提供されていますが、今回はrubyから利用する方法を試してみました。

[17年1月24日追記]Gemとして公開してみました。

GitHub:EastResident/jumanpp_ruby

RubyGem:jumanpp_ruby

環境

OS: Mac OS X EI Capitan
Ruby: 2.3.1

前提

前提として、当然ではありますがJUMAN++が入っている環境である必要があります。Macならhomebrewで一発なので、それが一番簡単かと思います。

brew install jumanpp

jumanppコマンドが実行できる環境なら問題ありません。

ラッパーモジュールの定義

方法は色々あるかと思いますが、今回はごくシンプルな方法で実装しました。

# coding: utf-8
require 'open3'

module Jumanpp

  def parse(sentents)
    o, = Open3.capture2("echo \"#{sentents}\" \| jumanpp --force-single-path")
    sep_words = o.split("\n").map { |r| r.delete("\\").delete("\"")}
    if block_given?
      sep_words.each do |word|
        yield word.split
      end
    else
      sep_words.map { |word| word.split.first }
    end
  end

  module_function :parse
end

使用例

Jumanpp.parseメソッドは、引数に与えた文字列を形態素に分解し、表層形のみを一次元配列の形で返します。ざっくり言うと、分かち書きして配列で返すだけです。

p Jumanpp.parse('モビルスーツの性能の違いが、戦力の決定的差でないということを教えてやる')

出力結果

["モビルスーツ", "の", "性能", "の", "違い", "が", "、", "戦力", "の", "決定", "的", "差", "で", "ない", "と", "いう", "こと", "を", "教えて", "やる", "EOS"]

さらに、Jumanpp.parseメソッドにブロックを与えることで、構文解析結果を形態素ごとにイテレートして処理することも可能です。

Jumanpp.parse('ララァ…私を導いてくれ!') do |word|
  p word
end

出力結果

["ララァ", "ララァ", "ララァ", "名詞", "6", "普通名詞", "1", "*", "0", "*", "0", "自動獲得:Wikipedia", "Wikipediaリダイレクト:ララァ・スン"]
["…", "…", "…", "特殊", "1", "記号", "5", "*", "0", "*", "0", "NIL"]
["私", "わたし", "私", "名詞", "6", "普通名詞", "1", "*", "0", "*", "0", "代表表記:私/わたし", "漢字読み:訓", "カテゴリ:人"]
["を", "を", "を", "助詞", "9", "格助詞", "1", "*", "0", "*", "0", "NIL"]
["導いて", "みちびいて", "導く", "動詞", "2", "*", "0", "子音動詞カ行", "2", "タ系連用テ形", "14", "代表表記:導く/みちびく"]
["くれ", "くれ", "くれる", "接尾辞", "14", "動詞性接尾辞", "7", "母音動詞", "1", "基本連用形", "8", "代表表記:くれる/くれる"]
["!", "!", "!", "特殊", "1", "記号", "5", "*", "0", "*", "0", "NIL"]
["EOS"]

ひらがなだけの文章でも試してみました。

# 認めたくないものだな、自分自身の若さ故の過ちというものを
Jumanpp.parse('みとめたくないものだな、じぶんじしんのわかさゆえのあやまちというものを') do |word|
  p word
end

出力結果

["みとめ", "みとめ", "みとめる", "動詞", "2", "*", "0", "母音動詞", "1", "基本連用形", "8", "代表表記:認める/みとめる", "補文ト"]
["たく", "たく", "たい", "接尾辞", "14", "形容詞性述語接尾辞", "5", "イ形容詞アウオ段", "18", "基本連用形", "7", "代表表記:たい/たい"]
["ない", "ない", "ない", "接尾辞", "14", "形容詞性述語接尾辞", "5", "イ形容詞アウオ段", "18", "基本形", "2", "代表表記:ない/ない"]
["もの", "もの", "もの", "名詞", "6", "形式名詞", "8", "*", "0", "*", "0", "NIL"]
["だ", "だ", "だ", "判定詞", "4", "*", "0", "判定詞", "25", "基本形", "2", "NIL"]
["な", "な", "な", "助詞", "9", "終助詞", "4", "*", "0", "*", "0", "NIL"]
["、", "、", "、", "特殊", "1", "読点", "2", "*", "0", "*", "0", "NIL"]
["じぶん", "じぶん", "じぶん", "名詞", "6", "時相名詞", "10", "*", "0", "*", "0", "代表表記:時分/じぶん", "カテゴリ:時間"]
["じしん", "じしん", "じしん", "名詞", "6", "普通名詞", "1", "*", "0", "*", "0", "代表表記:自身/じしん", "カテゴリ:人"]
["の", "の", "の", "助詞", "9", "接続助詞", "3", "*", "0", "*", "0", "NIL"]
["わか", "わか", "わかい", "形容詞", "3", "*", "0", "イ形容詞アウオ段", "18", "語幹", "1", "代表表記:若い/わかい"]
["さ", "さ", "さ", "接尾辞", "14", "名詞性述語接尾辞", "1", "*", "0", "*", "0", "代表表記:さ/さ", "準内容語", "カテゴリ:抽象物;数量"]
["ゆえ", "ゆえ", "ゆえ", "名詞", "6", "副詞的名詞", "9", "*", "0", "*", "0", "代表表記:故/ゆえ"]
["の", "の", "の", "助詞", "9", "接続助詞", "3", "*", "0", "*", "0", "NIL"]
["あやまち", "あやまち", "あやまち", "名詞", "6", "普通名詞", "1", "*", "0", "*", "0", "代表表記:過ち/あやまちv", "連用形名詞化:形態素解析"]
["と", "と", "と", "助詞", "9", "格助詞", "1", "*", "0", "*", "0", "NIL"]
["いう", "いう", "いう", "動詞", "2", "*", "0", "子音動詞ワ行", "12", "基本形", "2", "代表表記:言う/いう", "補文ト"]
["もの", "もの", "もの", "名詞", "6", "形式名詞", "8", "*", "0", "*", "0", "NIL"]
["を", "を", "を", "助詞", "9", "格助詞", "1", "*", "0", "*", "0", "NIL"]
["EOS"]

最後に

とりあえずRubyから処理できるようにしてみました。mecabと性能比較して、自分の目的に合うようなら本格的に使ってみたいですねー。

11
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
17