Goで形態素解析する - mecab-golang
golang NLP
Lastmod: 2020-10-19

MeCab とは

MeCab: Yet Another Part-of-Speech and Morphological Analyzer

自然言語処理界隈では ChaSen と並び有名な形態素解析エンジン。
形態素解析とは、テキストデータを文法や単語の品詞情報(辞書)を元に言語の最小単位(形態素)へと分割し、各形態素の品詞などを判別すること。

ex. 裾野は長し赤城山

裾野 名詞,一般,*,*,*,*,裾野,スソノ,スソノ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
長し 形容詞,自立,*,*,形容詞・アウオ段,文語基本形,長い,ナガシ,ナガシ
赤城山 名詞,固有名詞,地域,一般,*,*,赤城山,アカギヤマ,アカギヤマ

mecab-golang

Go から mecab を使用するライブラリ。mecab の go wrapper。 なので使用する場合は mecab-golang とは別に、MeCab や辞書をインストールする必要がある。

Install

Mecab のインストール

mecab をインストール。
mecab を扱うには、MeCab が形態素解析に使用する辞書が別途必要になる。
mecab-ipadic はその MeCab 用の辞書の一つであり、日本語の単語情報(読み方や品詞など)を掲載している。1

$ brew install mecab
$ brew install mecab-ipadic

mecab-ipadic-NEologd のインストール

mecab-ipadic-NEologd

Web 上から逐一新語を登録してくれる辞書 mecab-ipanic では判断できない新語を(全てではないが)サポートする。 ↓ こんなかんじに、例えば名詞をより細かい品詞に分割して解釈してくれる。

default system dictionary	  |	mecab-ipadic-NEologd
ピット 星 人 			  |	ピット 星人
この 世界 の 片隅 に 		  |	この世界の片隅に
辛 坊 				  |	辛坊
東海大 市原 望 洋 		  |	東海大市原望洋
方言 ラジオ 体操 			  |	方言 ラジオ体操
コイ キング 			  |	コイキング
はだし の ゲン 			  |	はだしのゲン
あさ パラ 			  |	あさパラ
雪 組 				  |	雪組

-n で最新 ver 辞書をインストール

$ git clone git@github.com:neologd/mecab-ipadic-neologd.git
$ cd mecab-ipadic-neologd
$ ./bin/install-mecab-ipadic-neologd -n

mecab-golang のインストール

$ export CGO_LDFLAGS="-L/{libフォルダへのパス}/lib -lmecab -lstdc++"
$ export CGO_CFLAGS="-I/{includeフォルダへのパス}/include"
$ go get github.com/bluele/mecab-golang

Usage

bluele/mecab-golang)サンプルコードを参考にした。

package main

import (
	"fmt"
	"strings"

	"github.com/bluele/mecab-golang"
)

const BOSEOS = "BOS/EOS"

func parseToNode(m *mecab.MeCab, text string) error {

	tg, err := m.NewTagger()
	if err != nil {
		return err
	}
	defer tg.Destroy()

	lt, err := m.NewLattice(text)
	if err != nil {
		return err
	}
	defer lt.Destroy()

	node := tg.ParseToNode(lt)
	for {
		features := strings.Split(node.Feature(), ",")
		if features[0] != BOSEOS {
			fmt.Printf("%s %s\n",node.Surface(), node.Feature())
		}
		if node.Next() != nil {
			break
		}
	}
	return nil
}

func main() {
	m, err := mecab.New("-Owakati")
	if err != nil {
		panic(err)
	}
	defer m.Destroy()

	err = parseToNode(m, "すもももももももものうち")
	if err != nil {
		panic(err)
	}
}

解説

func main()

mecab.New() で MeCab モデルオブジェクトを生成する。
引数には元々の MeCab 実行バイナリの引数に指定できるものを渡すことができる。ここでは形態素解析の結果(後述の Tagger::Parse で取得)を分かち書きで出力させるオプション -Owakati を指定している。
他のオプションはここを参照。

parseToNode() は第 2 引数にとる文字列を形態素解析・その結果を標準出力へ書き込む。

func parseToNode()

引数に取る MeCab モデルオブジェクトと文字列から、形態素解析の結果を出力する。

以下で説明する関数やメソッドは MeCab c++ ライブラリ準拠のもののため、MeCab 本家の C/C++ライブラリを読めば問題なさそう。2

MeCab::NewTagger()

辞書オブジェクト Tagger を生成する。

MeCab::NewLattice()

解析に必要なローカル変数を含むオブジェクト Lattice を生成する。
生成時に解析対象となる文字列を渡す。

Tagger::ParseToNode()

Lattice を引数に取ることで、 Lattice が保持する文字列を解析し、木構造のオブジェクト Node として解析結果を返す。

ちなみに parseToNode() 内では BOS/EOS( BOS は beginning of sentence で文頭、EOS は end of sentence で文末) 品詞タグのついた形態素情報以外を出力するようにしている。

Node::Feature()

Node の解析結果を出力する。
例えば分かち書き指定の場合こんな感じ。

名詞,一般,*,*,*,*,すもも,スモモ,スモモ
Node::Surface()

単語の品詞を出力する。

実行結果

すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ

独自フォーマットで形態素解析の結果を取得する

Tagger::ParseToNode で取得する Node からは特定のフォーマットで結果が出力できるが、 mecab.New() でフォーマットを指定することで、 Tagger::Parse の文字列結果を変更することができる。

分かち書き

m, err := mecab.New("-Owakati" )
すもも も もも も もも の うち

フォーマット

-F オプションを使用すると、下記の出力フォーマットを使用して自由に出力を切り替えられる。 出力フォーマット

ex.
m, err := mecab.New("-F%m(素性ID:%h)\\n")

3

すもも(素性ID:38)
も(素性ID:16)
もも(素性ID:38)
も(素性ID:16)
もも(素性ID:38)
の(素性ID:24)
うち(素性ID:66)
EOS

参考文献

MeCab: Yet Another Part-of-Speech and Morphological Analyzer

mecab-ipadic-neologd/README.ja.md at master · neologd/mecab-ipadic-neologd

MeCab: Yet Another Japanese Dependency Structure Analyzer

bluele/mecab-golang: A golang wrapper for mecab.

IPADIC(IPA 辞書)とはなにものか? - ぱらめでぃうす


  1. 元々は別の形態素解析エンジンである ChaSen に使用された辞書を、MeCab 用に更に変更を加えたもの。ipa とついているのは、その品詞フォーマットが情報処理振興事業協会(IPA)で設定された IPA 品詞体系(THiMCO97)に基づいているため。参考:http://parame.mwj.jp/blog/0209 [return]
  2. この C/C++ライブラリドキュメントでは Tagger によるシングルスレッド環境向けサンプルと Tagger/Model(NewMecab 返戻値型に対応)/Lattice によるマルチスレッド環境向けサンプルがある。mecab-golang では Go を使用する以上、goroutine によるマルチスレッド環境の可能性を前提にライブラリが組まれていると思われ、そのため Tagger::Parse/ParseToNode は Lattice を引数に取っている。 [return]
  3. 素性 ID - 品詞/活用/読みに割り振られた MeCab 内部 ID [return]