システム開発<基本編>Pythonで形態素解析:janome

Python

前回の記事では、形態素解析器(MeCab)解析処理を深堀りした記事を紹介しました。

今回は、形態素解析器(janome)について、深堀りをする記事を紹介しようと思います。

先ずは、以前のWordCloudの記事でも紹介しました形態素解析について、振り返ります。

 

形態素解析(分かち書き)

WordCloudの実装する際に、前提処理を行うのが、形態素解析になります。

形態素解析は、自然言語のテキストデータをいくつかの単位に分け、各単語の品詞や活用などを

解析・判別して取り出す処理です。

形態素は、言語で意味を持つ最小単位にする事です。

テキストを形態素に分割する処理は、分かち書き(tokenization)とも呼ばれており、

こちらの方が、聞き覚えの有る方もいると思います。

 

形態素解析器(ソフト/エンジン)

形態素解析は、実際に形態素解析器(ソフト/エンジン)を利用して、各単語の品詞や

活用などを解析・判別して取り出します。

日本語の形態素解析器(ソフト/エンジン)として、有名なのは下記になります。

  • ChaSen(茶筌):2012年に奈良先端科学技術大学院大学松本研究室で開発
  • JUMAN:2014年に京都大学黒橋・褚・村脇研究室で開発
  • KAKASI(かかし):Namazu等の全文検索エンジンと組み合わせで用いられる
  • KyTea(キューティー):京都テキスト解析ツールキット
  • MeCab(和布蕪):Google 日本語入力開発者の一人である工藤拓氏によって開発
  • Janome(蛇の目):Python用の形態素解析エンジン
  • Kagome(籠目):Go用の形態素解析エンジン

 

辞書 (dictionary)

品詞や活用形の特定は、辞書 (dictionary) を活用して行うのが一般的です。

日本語の形態素解析用辞書として、有名なのは下記になります。

  • ipadic:ChaSen用の辞書 → IPA 品詞体系をもとに設計
  • UniDic:MeCab用の辞書
  • NAIST-jdic:ChaSen、MeCab用の辞書
  • JUMAN用の辞書 → 益岡・田窪文法をもとに設計

形態素解析の詳細については、下記を参照して下さい。

 

WordCloud処理

形態素解析器と、WordCloudの処理の順番と役割を簡単に紹介します。

  1. 形態素解析器:各単語の品詞や活用などを解析・判別して抽出
  2. WordCloud:単語ごとに出現頻度をカウントします
  3. WordCloud:出現頻度に応じて、サイズを変更して単語を描画します

 

では、形態素解析について、もう少し深堀りしてみます。

内包辞書

janome は、内包辞書として mecab-ipadic-2.7.0-20070801 を使っています。

v0.3.8+ では、新元号「令和」がシステム辞書に追加されています。

下記は、janome のソースコードリポジトリです。

 

品詞一覧

デフォルトユーザー定義辞書のフォーマットは、上記でも記載したように MeCab 辞書と同じ

なので、品詞一覧出力フォーマットは、そのまま流用します。

その他,間投,*,* 0
フィラー,*,*,* 1
感動詞,*,*,* 2
記号,アルファベット,*,* 3
記号,一般,*,* 4
記号,括弧開,*,* 5
記号,括弧閉,*,* 6
記号,句点,*,* 7
記号,空白,*,* 8
記号,読点,*,* 9
形容詞,自立,*,* 10
形容詞,接尾,*,* 11
形容詞,非自立,*,* 12
助詞,格助詞,一般,* 13
助詞,格助詞,引用,* 14
助詞,格助詞,連語,* 15
助詞,係助詞,*,* 16
助詞,終助詞,*,* 17
助詞,接続助詞,*,* 18
助詞,特殊,*,* 19
助詞,副詞化,*,* 20
助詞,副助詞,*,* 21
助詞,副助詞/並立助詞/終助詞,*,* 22
助詞,並立助詞,*,* 23
助詞,連体化,*,* 24
助動詞,*,*,* 25
接続詞,*,*,* 26
接頭詞,形容詞接続,*,* 27
接頭詞,数接続,*,* 28
接頭詞,動詞接続,*,* 29
接頭詞,名詞接続,*,* 30
動詞,自立,*,* 31
動詞,接尾,*,* 32
動詞,非自立,*,* 33
副詞,一般,*,* 34
副詞,助詞類接続,*,* 35
名詞,サ変接続,*,* 36
名詞,ナイ形容詞語幹,*,* 37
名詞,一般,*,* 38
名詞,引用文字列,*,* 39
名詞,形容動詞語幹,*,* 40
名詞,固有名詞,一般,* 41
名詞,固有名詞,人名,一般 42
名詞,固有名詞,人名,姓 43
名詞,固有名詞,人名,名 44
名詞,固有名詞,組織,* 45
名詞,固有名詞,地域,一般 46
名詞,固有名詞,地域,国 47
名詞,数,*,* 48
名詞,接続詞的,*,* 49
名詞,接尾,サ変接続,* 50
名詞,接尾,一般,* 51
名詞,接尾,形容動詞語幹,* 52
名詞,接尾,助数詞,* 53
名詞,接尾,助動詞語幹,* 54
名詞,接尾,人名,* 55
名詞,接尾,地域,* 56
名詞,接尾,特殊,* 57
名詞,接尾,副詞可能,* 58
名詞,代名詞,一般,* 59
名詞,代名詞,縮約,* 60
名詞,動詞非自立的,*,* 61
名詞,特殊,助動詞語幹,* 62
名詞,非自立,一般,* 63
名詞,非自立,形容動詞語幹,* 64
名詞,非自立,助動詞語幹,* 65
名詞,非自立,副詞可能,* 66
名詞,副詞可能,*,* 67
連体詞,*,*,* 68

 

出力フォーマット

MeCab出力フォーマットの日本語表現については、下記となっています。

表層形\t品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音

 

janomeの解析処理

MeCab と同じ品詞一覧出力フォーマットを利用して、形態素解析器(janome)

処理をして、解析結果可視化してみます。

 

統合開発環境(IDLE)の起動

いつものように、Python開発向けに、統合開発環境(IDLE)を起動しましょう。

IDLE Shell より、新規画面を起動します。

 

janome 解析のソース例

それでは、janome を利用した解析ソースを紹介します。


# ライブラリのインポート
from janome.tokenizer import Tokenizer
from datetime import datetime as dt
import time

outfile = 'C:/work/python/data/Input_Janome_Analysis.txt'

def Janome_Analysis(msg):
    
    # 開始時間
    start_time = time.time()
    
    tdatetime = dt.now()

    string_start_time = "処理開始日時:"+tdatetime.strftime('%Y/%m/%d %H:%M:%S')

    print(string_start_time)

    with open(outfile, mode='a', encoding='utf-8') as f:   # w:write  a:add
        f.write(string_start_time +'\n')
        f.write("Enter a message = "+msg +'\n')

    # テキストの読み込み
    text = msg

    # 単語の分割
    tokenizer = Tokenizer()

    # 形態素解析
    tokens = tokenizer.tokenize(text)

    for token in tokens:

        string_asterisk = '****************************'

        string_token_surface = '[表層形]:' + token.surface

        string_token_part_of_speech_0 = '[品詞] 0:' + token.part_of_speech.split(',')[0]

        string_token_part_of_speech_1 = '[品詞細分類1] 1:' + token.part_of_speech.split(',')[1]

        string_token_part_of_speech_2 = '[品詞細分類2] 2:' + token.part_of_speech.split(',')[2]

        string_token_part_of_speech_3 = '[品詞細分類3] 3:' + token.part_of_speech.split(',')[3]

        string_token_infl_type = '[活用型] 4:' + token.infl_type

        string_token_infl_form = '[活用形] 5:' + token.infl_form

        string_token_base_form = '[原形] 6:' + token.base_form

        string_token_reading = '[読み] 7:' + token.reading

        string_token_phonetic = '[発音] 8:' + token.phonetic

        # ファイル書き込み
        with open(outfile, mode='a', encoding='utf-8') as f:   # w:write  a:add
            f.write(string_asterisk +'\n')
            f.write(string_token_surface +'\n')
            f.write(string_token_part_of_speech_0 +'\n')
            f.write(string_token_part_of_speech_1 +'\n')
            f.write(string_token_part_of_speech_2 +'\n')
            f.write(string_token_part_of_speech_3 +'\n')
            f.write(string_token_infl_type +'\n')
            f.write(string_token_infl_form +'\n')
            f.write(string_token_base_form +'\n')
            f.write(string_token_reading +'\n')
            f.write(string_token_phonetic +'\n')

        # コンソール出力
        print(string_asterisk)
        print(string_token_surface)
        print(string_token_part_of_speech_0)
        print(string_token_part_of_speech_1)
        print(string_token_part_of_speech_2)
        print(string_token_part_of_speech_3)
        print(string_token_infl_type)
        print(string_token_infl_form)
        print(string_token_base_form)
        print(string_token_reading)
        print(string_token_phonetic)

    # 終了時間
    end_time = time.time()

    # 差分
    dif_time = end_time - start_time

    # 終了時間
    tdatetime = dt.now()

    string_line = "----------------------------------"

    string_end_time = "処理終了日時:"+ tdatetime.strftime('%Y/%m/%d %H:%M:%S')

    string_dif_time = "処理時間:"+ str(dif_time) +"秒"

    string_success = "Input Data Janome Analysis Successfully"

    with open(outfile, mode='a', encoding='utf-8') as f:   # w:write  a:add
        f.write(string_line +'\n')
        f.write(string_end_time +'\n')
        f.write(string_line +'\n')
        f.write(string_dif_time +'\n')
        f.write(string_line +'\n')
        f.write(string_success +'\n')
        f.write(string_line +'\n')

    # コンソール出力
    print(string_line)
    print(string_end_time)
    print(string_line)
    print(string_dif_time)
    print(string_line)
    print(string_success)
    print(string_line)

if __name__ == "__main__":
    try:
        while True:    
            msg = input("Enter a message = ")
            msg_leng = len(msg)
            
            print('msg_leng : ', msg_leng)
            print('---------------------------')

            Janome_Analysis(msg)
            
    except Exception as e:
        print("Exception : ", e)

    finally:
        print("Janome Analysis End...")

 

ソースの解析


from janome.tokenizer import Tokenizer
from datetime import datetime as dt
import time

outfile = 'C:/work/python/data/Input_Janome_Analysis.txt'

こちらはの先頭文では、janome と日時処理を行うライブラリ環境をインポートしています。

また、outfiile として、解析した結果をテキストファイルで保存する場所とファイル名を

指定しています。

保存場所とファイル名については、お手持ちのパソコン環境に合わせて、修正して下さい。


    start_time = time.time()
    
    tdatetime = dt.now()

    string_start_time = "処理開始日時:"+tdatetime.strftime('%Y/%m/%d %H:%M:%S')

    print(string_start_time)

    with open(outfile, mode='a', encoding='utf-8') as f:   # w:write  a:add
        f.write(string_start_time +'\n')
        f.write("Enter a message = "+msg +'\n')

MeCab解析処理と同様、処理開始日時を、IDLE Shellテキストファイル に出力しています。

テキストファイル には、見やすくする為、改行コード(’\n’)を入れています。

テキストファイル の書き込み方法は、‘a’addモード(追記)を利用しています。

纏まったテキスト文を一度に書き込む場合は、‘w’writeモード(上書き)を利用する事も

有ると思いますが、MeCab解析処理と同様、複数の単語ごとに解析結果を表示するので、

‘a’addモード(追記)を利用しています。


    # テキストの読み込み
    text = msg

    # 単語の分割
    tokenizer = Tokenizer()

    # 形態素解析
    tokens = tokenizer.tokenize(text)

こちらでは、janome の tokenizeメソッドを利用して、形態素解析をしています。


    for token in tokens:
        string_asterisk = '****************************'
        string_token_surface = '[表層形]:' + token.surface
        string_token_part_of_speech_0 = '[品詞] 0:' + token.part_of_speech.split(',')[0]
        string_token_part_of_speech_1 = '[品詞細分類1] 1:' + token.part_of_speech.split(',')[1]
        string_token_part_of_speech_2 = '[品詞細分類2] 2:' + token.part_of_speech.split(',')[2]
        string_token_part_of_speech_3 = '[品詞細分類3] 3:' + token.part_of_speech.split(',')[3]
        string_token_infl_type = '[活用型] 4:' + token.infl_type
        string_token_infl_form = '[活用形] 5:' + token.infl_form
        string_token_base_form = '[原形] 6:' + token.base_form
        string_token_reading = '[読み] 7:' + token.reading
        string_token_phonetic = '[発音] 8:' + token.phonetic

こちらは、入力されたテキスト文を、janome で解析した結果、一旦、出力フォーマット毎に

ワークデータへ代入しています。


        with open(outfile, mode='a', encoding='utf-8') as f:   # w:write  a:add
            f.write(string_asterisk +'\n')
            f.write(string_token_surface +'\n')
            f.write(string_token_part_of_speech_0 +'\n')
            f.write(string_token_part_of_speech_1 +'\n')
            f.write(string_token_part_of_speech_2 +'\n')
            f.write(string_token_part_of_speech_3 +'\n')
            f.write(string_token_infl_type +'\n')
            f.write(string_token_infl_form +'\n')
            f.write(string_token_base_form +'\n')
            f.write(string_token_reading +'\n')
            f.write(string_token_phonetic +'\n')
            
        # コンソール出力
        print(string_asterisk)
        print(string_token_surface)
        print(string_token_part_of_speech_0)
        print(string_token_part_of_speech_1)
        print(string_token_part_of_speech_2)
        print(string_token_part_of_speech_3)
        print(string_token_infl_type)
        print(string_token_infl_form)
        print(string_token_base_form)
        print(string_token_reading)
        print(string_token_phonetic)

こちらは、janome で解析した結果が代入されたワークデータを、テキストファイル(保存)

IDLE Shell 上に出力しています。

テキストファイル には、見やすくする為、改行コード(’\n’)を入れています。


    end_time = time.time()
    dif_time = end_time - start_time
    tdatetime = dt.now()

    string_line = "----------------------------------"
    string_end_time = "処理終了日時:"+ tdatetime.strftime('%Y/%m/%d %H:%M:%S')
    string_dif_time = "処理時間:"+ str(dif_time) +"秒"
    string_success = "Input Data Janome Analysis Successfully"

    with open(outfile, mode='a', encoding='utf-8') as f:   # w:write  a:add
        f.write(string_line +'\n')
        f.write(string_end_time +'\n')
        f.write(string_line +'\n')
        f.write(string_dif_time +'\n')
        f.write(string_line +'\n')
        f.write(string_success +'\n')
        f.write(string_line +'\n')

    print(string_line)
    print(string_end_time)
    print(string_line)
    print(string_dif_time)
    print(string_line)
    print(string_success)
    print(string_line)

MeCab解析処理と同様、処理終了日時と処理時間を、IDLE Shellテキストファイル 

出力しています。

テキストファイル には、見やすくする為、改行コード(’\n’)を入れています。


if __name__ == "__main__":
    try:
        while True:    
            msg = input("Enter a message = ")
            msg_leng = len(msg)
            
            print('msg_leng : ', msg_leng)
            print('---------------------------')

            Janome_Analysis(msg)

    except Exception as e:
        print("Exception : ", e)

    finally:
        print("Janome Analysis End...")

こちらは、IDLE Shell で、テキスト文が入力されたら、テキスト文の長さを表示した後、

形態素解析器(janome)解析を行う関数:Janome_Analysis()を呼び出しています。

また、エラーハンドリング最終処理を記載しています。

 

janome解析ソースの実行例

実際に、ソースを起動して解析してみましょう。

保存したソース画面の上部のタブメニューより、Run → Run Module を選択して、

ソースを起動します。

ツールを動かして、エラーが無ければ、IDLE Shell には、テキスト文の入力を促すメッセージが

表示されますので、形態素解析器(janome)解析したいテキスト文を入力します。

今回は、下記の記事を例として、

劇場版「鬼滅の刃」破格のヒットから広がる社会的影響 エンタメ以外の分野へ

を入力してみます。

劇場 版 「 鬼 滅 ・・・と、入力されたテキスト文から、それぞれ単語

分けられて、下記の出力フォーマット解析されている事が分かりますね。

表層形\t品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音

IDLE Shell を、最終行まで下にスクロールしてみます。

入力されたテキスト文解析が終了し、処理終了日時と処理時間が表示されているのを

確認する事が出来ました。

では、保存したテキストファイルの内容も確認してみます。

上記の Input_Janome_Analysis.txt を、開いてみます。

劇場 版 「 鬼 滅 ・・・と、入力されたテキスト文から、それぞれ単語に分けられて、

下記の出力フォーマット解析されている事が分かりますね。

表層形\t品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音

テキストファイル を、最終行まで下にスクロールしてみます。

IDLE Shell と同様に、入力されたテキスト文解析が終了し、処理終了日時と処理時間が

表示されているのを確認する事が出来ました。

 

まとめ

今回は、前々回のWordCloudの生成ツールでも登場した形態素解析(janome)について、

ソース例と実行例を紹介して、もう少し深堀りをしてみました。

janome は、内包辞書として mecab-ipadic-2.7.0-20070801 を使用しているので、

前回紹介した 形態素解析器(MeCab)解析処理と共通点が多かったと思います。

もし、デフォルトでは無く、独自の辞書を利用する場合は、下記を参照して下さい。

 

WordCloud処理

形態素解析器と、WordCloudの処理の順番と役割を振り返ります。

  1. 形態素解析器:各単語の品詞や活用などを解析・判別して抽出
  2. WordCloud:単語ごとに出現頻度をカウントします
  3. WordCloud:出現頻度に応じて、サイズを変更して単語を描画します

今回、紹介したように形態素解析器で、テキスト文から、それぞれ単語に分けられて、

出力フォーマット解析されている事について、理解が出来たと思います。

WordCloudの処理では、解析された単語(指定した品詞)ごとに出現頻度をカウントし、

出現頻度に応じて、サイズを変更して描画している事は、前回の記事で紹介しました。

次回は、今回の記事でも少し触れましたが、Pythonファイルの読み込みと書き込み

について、記事を紹介しようと思います。

 

コメント

タイトルとURLをコピーしました