テキストをjanomeで形態素解析をする【自然言語処理の基礎】

こんにちは、@Yoshimiです。

以前、自然言語処理のライブラリでMeCabを紹介しました。そこでも簡単に触れましたが、有名なライブラリでJanomeというのもあるので紹介します。というか勉強したのでメモ書きです。

janomeとは?

JanomeはPythonの形態素解析エンジンです。形態素解析とは、文書を言語上の最小単位である形態素(名詞、形容詞、動詞など)に分割し、それぞれの品詞や変化などを割り出すことです。

形態素解析に関しての詳しい情報はwikipediaでご確認くださいね。

Mecabとの違い

形態素解析の代表ライブラリではMeCabがあり、当ブログでも簡単に触れています。MeCabの特徴は高速・判別精度の高さが挙げられます。しかし、必要な外部パッケージのインストール、ユーザー辞書の準備がそこそこ面倒というのが玉に傷です。

Janomeの内部ではMecabのipadicを使っているようなので、辞書は同じということです。

janomeを実装してみる(基本t系な使い方)

基本的な使い方は以下の通り

  • TokenizerをインポートしてTokenizerオブジェクトのインスタンスを生成
  • tokenize()メソッドに対象の文字列を渡す
  • tokenize()メソッドはjanome.tokenizer.Tokenオブジェクトを要素とするリストを返す

至ってシンプルです。

from janome.tokenizer import Tokenizer

t = Tokenizer()
text = '吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。'

for token in t.tokenize(text):
    print(token)
吾輩  名詞,代名詞,一般,*,*,*,吾輩,ワガハイ,ワガハイ
は  助詞,係助詞,*,*,*,*,は,ハ,ワ
猫  名詞,一般,*,*,*,*,猫,ネコ,ネコ
で  助動詞,*,*,*,特殊・ダ,連用形,だ,デ,デ
ある  助動詞,*,*,*,五段・ラ行アル,基本形,ある,アル,アル
。  記号,句点,*,*,*,*,。,。,。
名前  名詞,一般,*,*,*,*,名前,ナマエ,ナマエ
は  助詞,係助詞,*,*,*,*,は,ハ,ワ
まだ  副詞,助詞類接続,*,*,*,*,まだ,マダ,マダ
無い  形容詞,自立,*,*,形容詞・アウオ段,基本形,無い,ナイ,ナイ
。  記号,句点,*,*,*,*,。,。,。
どこ  名詞,代名詞,一般,*,*,*,どこ,ドコ,ドコ
で  助詞,格助詞,一般,*,*,*,で,デ,デ
生れ  動詞,自立,*,*,一段,連用形,生れる,ウマレ,ウマレ
た  助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
か  助詞,副助詞/並立助詞/終助詞,*,*,*,*,か,カ,カ
とんと  副詞,一般,*,*,*,*,とんと,トント,トント
見当  名詞,サ変接続,*,*,*,*,見当,ケントウ,ケントー
が  助詞,格助詞,一般,*,*,*,が,ガ,ガ
つか  動詞,自立,*,*,五段・カ行イ音便,未然形,つく,ツカ,ツカ
ぬ  助動詞,*,*,*,特殊・ヌ,基本形,ぬ,ヌ,ヌ
。  記号,句点,*,*,*,*,。,。,。

単語ごとに分割し、品詞も出力してくれていますね。

Tokenオブジェクトは、次のインスタンス変数を持ちます。

  • surface (表層形)
  • part_of_speech (品詞)
  • infl_type (活用型)
  • infl_form (活用形)
  • base_form (基本形)
  • reading (読み)
  • phonetic (発音)
  • node_type

品詞分類を細かく見てみます。

for token in t.tokenize(text):
    print('-----------------')
    print('表層形:', token.surface) 
    print('品詞:', token.part_of_speech.split(',')[0])
    print('品詞細分類1:', token.part_of_speech.split(',')[1])
    print('品詞細分類2:', token.part_of_speech.split(',')[2])
    print('品詞細分類3:', token.part_of_speech.split(',')[3])
    print('活用型:', token.infl_type)
    print('活用形:', token.infl_form)
    print('読み:', token.base_form)
    print('読み:', token.reading)
    print('発音:', token.phonetic) 
    print('-----------------')
—————–
表層形: 問お
品詞: 動詞
品詞細分類1: 自立
品詞細分類2: *
品詞細分類3: *
活用型: 五段・ワ行促音便
活用形: 未然ウ接続
読み: 問う
読み: トオ
発音: トオ
—————–


実際には、もっと長い抽出結果になっています。アスタリスクは該当なしということです。

格納されたデータから試しに名詞だけ抽出します。

# -*- coding:utf-8 -*-
from janome.tokenizer import Tokenizer

t = Tokenizer()

text = '吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。'

for token in t.tokenize(text):
    if token.part_of_speech.split(',')[0] == '名詞':
        print('名詞:', token.surface)
名詞: 吾輩
名詞: 猫
名詞: 名前
名詞: どこ
名詞: 見当

Janomeで分かち書き(単語ごとに分割)

分かち書きができれば品詞の数を取得することも可能です。ちなみに、分かち書きとは文章の単語を空白で区切ることです。
引数wakati
tokenize()メソッドの引数wakatiをTrueとするとTokenオブジェクトのリストではなく表層形の文字列strのリストを返す。

例文は今まで通り同じです。

from janome.tokenizer import Tokenizer
import collections

t = Tokenizer()

text = '吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。'

for token in t.tokenize(text):
    print(token)
吾輩 名詞,代名詞,一般,*,*,*,吾輩,ワガハイ,ワガハイ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
猫 名詞,一般,*,*,*,*,猫,ネコ,ネコ
で 助動詞,*,*,*,特殊・ダ,連用形,だ,デ,デ
ある 助動詞,*,*,*,五段・ラ行アル,基本形,ある,アル,アル
。 記号,句点,*,*,*,*,。,。,。
名前 名詞,一般,*,*,*,*,名前,ナマエ,ナマエ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
まだ 副詞,助詞類接続,*,*,*,*,まだ,マダ,マダ
無い 形容詞,自立,*,*,形容詞・アウオ段,基本形,無い,ナイ,ナイ
。 記号,句点,*,*,*,*,。,。,。
どこ 名詞,代名詞,一般,*,*,*,どこ,ドコ,ドコ
で 助詞,格助詞,一般,*,*,*,で,デ,デ
生れ 動詞,自立,*,*,一段,連用形,生れる,ウマレ,ウマレ
た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
か 助詞,副助詞/並立助詞/終助詞,*,*,*,*,か,カ,カ
とんと 副詞,一般,*,*,*,*,とんと,トント,トント
見当 名詞,サ変接続,*,*,*,*,見当,ケントウ,ケントー
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
つか 動詞,自立,*,*,五段・カ行イ音便,未然形,つく,ツカ,ツカ
ぬ 助動詞,*,*,*,特殊・ヌ,基本形,ぬ,ヌ,ヌ
。 記号,句点,*,*,*,*,。,。,。

分かち書きをします。

wakati_list = t.tokenize(text, wakati=True)
wakati_list
[‘吾輩’,’は’,’猫’,’で’,’ある’,’。’,’名前’,’は’,’まだ’,’無い’,’。’,’どこ’,’で’,’生れ’,’た’,’か’,’とんと’,’見当’,’が’,’つか’,’ぬ’,’。’]

分かち書きができましたが、このままでは使い物になりません。
単語のリストをコンストラクタCounter()に渡すとCounterオブジェクトが得られますので、それを利用します。

c = collections.Counter(t.tokenize(text, wakati=True))
print(type(c))
print(c)
<class ‘collections.Counter’>
Counter({‘。’: 3, ‘は’: 2, ‘で’: 2, ‘吾輩’: 1, ‘猫’: 1, ‘ある’: 1, ‘名前’: 1, ‘まだ’: 1, ‘無い’: 1, ‘どこ’: 1, ‘生れ’: 1, ‘た’: 1, ‘か’: 1, ‘とんと’: 1, ‘見当’: 1, ‘が’: 1, ‘つか’: 1, ‘ぬ’: 1})

Counterオブジェクトのmost_common()メソッドは、(単語, 出現回数)のタプルが出現回数の多いほうから順に並んだリストを返す。

mc = c.most_common()
print(mc)
[(‘。’, 3), (‘は’, 2), (‘で’, 2), (‘吾輩’, 1), (‘猫’, 1), (‘ある’, 1), (‘名前’, 1), (‘まだ’, 1), (‘無い’, 1), (‘どこ’, 1), (‘生れ’, 1), (‘た’, 1), (‘か’, 1), (‘とんと’, 1), (‘見当’, 1), (‘が’, 1), (‘つか’, 1), (‘ぬ’, 1)]

最後に

janomeはpipでパッケージをインストールできる点はMecabより導入敷居が低くて良いです。ただ処理速度がMecab比べ遅いので大量のデータを処理するには処理完了時間に差が出てきます。janomeが悪いというわけではないので用途により使い分けましょうということですね。

janomeには形態素解析の前処理・後処理が可能なAnalyzerフレームワークがあります。このフレームワークでは、単語の出力回数のカウントも可能になります。Analyzerフレームも勉強し次回紹介します。


なりたい自分になれる
スキルアップならUdemy

私も利用し、高収入エンジニアになったのよ。未経験から機械学習、データサイエンティスト、アプリ開発エンジニアを目指せるコンテンツが多数あります。優秀な講師が多数!割引を利用すれば1,200円〜から動画購入可能です。!

ABOUTこの記事をかいた人

大学卒業して、キラキラしていたのでIT業界にはいりましたが、中身はブラックでした!!だから、投資技術を磨いて早くリタイヤしたいです。株価、Python、機械学習をもうもう勉強中です。経済的自由を手に入れて農家やりたい!