形態素解析


AIって結局何なのかよく分からないので、とりあえず100日間勉強してみた Day48


経緯についてはこちらをご参照ください。



■本日の進捗

  • 形態素解析を理解


■はじめに

「Pythonではじめる機械学習(オライリー・ジャパン)」は読了し、前回までで全項目履修しました。

今回はBoWを用いたセンチメント分析の応用として、完全に独自で日本語のレビューをセンチメント分析してみたいと思います。

■形態素解析

これまで英語のテキストデータに対してBoWを用いて単語(またはn-gramを用いて複数の組み合わせ)にトークン化してきましたが、日本語のテキストデータに対してはほとんどの場合これでは不十分です。それは日本語がスペースで明確に区切られてなかったり、語順が(比較的かなり)自由である性質が影響しています。有名なところで言うと「にわにはにわとりがいる」などでしょうか。

これに対応するためには形態素解析(morphological analysis)を用います。ドキュメントを意味を持つ最小の単位に分解することで、処理することができる形に変換してくれます。

■MeCab

形態素解析で有名なものにMeCabというツールがあります。もちろんPython上で利用可能です。

まずは64bit版MeCabを下記からダウンロードします。
https://github.com/ikegami-yukino/mecab/releases/tag/v0.996.2

辞書は公式のMecabから「IPA辞書」をダウンロードします。
https://taku910.github.io/mecab/

MeCabのインストールが済んだら下記コマンドを実行

基本的にはこれで使えますが、import mecabでエラーが発生する際は、
C:\Users\****\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\lib\site-packages\MeCab
にある「libmecab.dll」を下記にコピーします。
C:\Users\****\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\MeCab
Pythonの環境が違う場合は、バージョン名が違うのでご注意ください。

MeCabを使うと、繋がりを見つけることが難しい日本語をとても簡単にトークン化することができます。

import MeCab

mecab = MeCab.Tagger()
result = mecab.parse("今週はレースウィークですね。メキシコグランプリなので盛り上がりそうですね。")
print(result)

下記のように形態素解析してくれました。

「今週/は/レース/ウィーク/です/ね/。/メキシコ/グランプリ/な/の/で/盛り上がり/そう/です/ね/。」

■JRTEコーパス

さて、ここからが重要なセンチメント分析に用いることができる日本語コーパスなのですが、無料データセットはあるにはあるのですが、申請や契約、報告が必要な研究用データセットばかりで、ラベリング済みのコーパスを探すのに苦労しました。

今回探した中では唯一良さげなコーパスを見つけたので、こちらの株式会社リクルートが提供する”Japanese Realistic Textual Entailment Corpus” (https://github.com/megagonlabs/jrte-corpus)を利用したいと思います。

なお、データセット内のレビュー本文については必要の範囲内で公開可となっていますが、今回公開することは控えたいと思いますので、気になる方は各自ダウンロードの上ご確認ください。

こちらには複数のデータセットが含まれていますが、ホテル評価レビューであるdata/rhr.tsvを使わせていただきます。この中にはサンプルにもある通り、「お風呂が最高でした。」などのレビューに評価のラベルが付加されています。

早速任意の場所にデータを展開してMecabで形態素解析をしてから、いつもの手順でn-gram BoWを用いたセンチメント分析をロジスティック回帰モデルで行いたいと思います。

import pandas as pd
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression
# from sklearn.metrics import classification_report
import MeCab

mecab = MeCab.Tagger()

def tokenizer(text):
    node = mecab.parseToNode(text)
    tokens = []
    while node:
        if node.feature.split(',')[0] != 'BOS/EOS':
            tokens.append(node.surface)
        node = node.next
    return tokens

df = pd.read_csv('C:/Users/****/Documents/Python/jrte-corpus-master/jrte-corpus-master/data/rhr.tsv', sep='\t', header=None)

df.columns = ['id', 'label', 'review', 'additional_info', 'split']

X = df['review']
y = df['label']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=8)

vectorizer = CountVectorizer(tokenizer=tokenizer, ngram_range=(1, 2), max_features=5000)
X_train_vec = vectorizer.fit_transform(X_train)
X_test_vec = vectorizer.transform(X_test)

model = LogisticRegression()

param_grid = {'C': [0.01, 0.1, 1, 10, 100]}

grid_search = GridSearchCV(model, param_grid, cv=5, scoring='accuracy', n_jobs=-1)
grid_search.fit(X_train_vec, y_train)

print("Best parameters: {}".format(grid_search.best_params_))
print("best cv score: {:.2f}".format(grid_search.best_score_))



■おわりに

実は今回の形態素解析ですが、(線形モデルなどを除いて)これまでで僕が唯一使ったことのある機械学習系の技術項目になります。

その昔、新卒時代に、届いたメールを形態素解析にかけて自動返信するプログラムを作って実運用していました(今考えたら恐ろしい…若いが故の恐れのなさと過信ですね…)。当時は一般層にはAIがここまで現実的になるのは比較的遠い未来のように思えていた時期で、人工知能ならぬ「人工無脳」というのが一部界隈で流行って(?)いました。この自動返信プログラムも人工無能で、予め予測された言葉に対してのみある種定型文を返答できるチャットボットのようなものでした。

例えば、もし文中に「確認お願い」または「確認よろしく」という文字列が入っていたら「承知いたしました」と返すような感じです。お気付きの通りこのままではとても精度が悪く(機械学習モデルでもないので)精度向上が難しいのが「無脳」たる所以なのですが、そんな時代でも形態素解析は既に活躍していました。

メールの文中に含まれる「株式会社」や「と申します」、「お世話になっております」などがあれば、その前後に社名や名前が入っていると分かり、その部分を切り出して「社名 + 名前 + “様”」を付ければ第一段落は完成します。そのあとに続く文面にあるキーワードを分解していけば、届いたメールの内容をより正確に予測することができます。

そのうちプログラムの精度を上げる暇もなくなり使わなくなってしまうのですが、それまで何故か一度も怒られることなくそれっぽくメールのやり取りをしていたことは奇跡としか言い様がありません。

今では人間と見分けがつかない生成AIボットがいくつも出てきていますが、そのAPIを使ってメールを作成するプログラムを作ったとしても、とても自動送信するようなプログラムを組むことは一生ないでしょう。これが大人になるということ。つまらない大人になるということなのかもしれません。悲しいかな。

ちなみに人工無脳というワードから年齢を推定することは禁止とさせていただきます。

■参考文献

  1. Andreas C. Muller, Sarah Guido. Pythonではじめる機械学習. 中田 秀基 訳. オライリー・ジャパン. 2017. 392p.
  2. ChatGPT. 4o mini. OpenAI. 2024. https://chatgpt.com/
  3. API Reference. scikit-learn.org. https://scikit-learn.org/stable/api/index.html


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です