【自然言語処理】形態素解析で文章を単語に分ける | python

今回は自然言語処理の入門編ということで、形態素解析を行なってみます。

pythonの環境がある方向けに、MeCabのインストール方法も併せてご紹介します。

形態素解析

具体的な作業に入る前に、形態素解析をざっくり解説します。

形態素解析とは、「文章を単語に分割する技術」のことです。

「人間の言葉をプログラムが理解するために行う処理」である自然言語処理(Natural Language Processing)には、必須の技術です。

また、形態素解析以外にも自然言語処理の基礎技術となるタスクはあります。

例えば、構文解析や意味解析、文脈解析などが挙げられます。

形態素解析には、MeCabやJanomeというライブラリを用いることで簡単に行うことができます。

ちなみに、Mecabの開発者はメカブが好きで、この名前にしたそうです。

今回は、オープンソースライブラリ「MeCab」を使って形態素解析を行います。

形態素解析

MeCabのインストール

ターミナルに以下のコマンドを順に入れると、MeCabをインストールできます。

Homebrewからインストールします。

#手順1

brew install mecab
#手順2

brew install mecab-ipadic

このipadicというのは、MeCabで使う最もメジャーな辞書です。

辞書は、形態素解析で単語を区切る上で必須のものです。プログラムは辞書がないと、文章を単語に分けられません。

優れた辞書ほど、正確な解析ができます。

#手順3

pip install mecab-python3

最後はこちらのコードです。pythonからMeCabをインストールをするためのコードです。

では、準備ができたので実際のコードで形態素解析をやってみましょう。

Code

今回は、以下のような文章を使います。

ダッシュボードを作るデータサイエンティストが何をやっているのかというと、上司の「アクティブなユーザの割合を知りたい」という曖昧なオーダーを「課金ユーザのうち、30日以内に1回以上ログインしているユーザー」みたいに考えを引き出して具体的な条件へ落とし込んだりするのが仕事です。
import MeCab
tagger = MeCab.Tagger()
text = "ダッシュボードを作るデータサイエンティストが何をやっているのかというと、上司の「アクティブなユーザの割合を知りたい」という曖昧なオーダーを「課金ユーザのうち、30日以内に1回以上ログインしているユーザー」みたいに考えを引き出して具体的な条件へ落とし込んだりするのが仕事です。"
words = tagger.parse(text)
words

このような出力結果になりました。

1行目でMeCabライブラリをインポートしてきます。2行目では、初期化を行なっています。

3行目で今回解析する文章を代入します。

tagger.parseで形態素解析を行います。

ぐちゃぐちゃで何がなんだかわかりにくいですが、\nで単語で区切っています。また、\t以降では区切った単語の品詞などの情報が載っています。

では、分類した単語のみをリストに入れてみましょう。

#分割した単語をリストに入れてみましょう。
words = tagger.parse(text).splitlines()
words_arr = []
for i in words:
    if i == "EOS":continue
    word_tmp = i.split()[0]
    words_arr.append(word_tmp)
words_arr

載せきれないので、出力結果の一部を載せています。先ほどの文章を単語に分けたものが、リスト構造で入っていますね。

では、名詞だけ取り出してリストに入れましょう。

#名詞のみを抽出してみます。

text="ダッシュボードを作るデータサイエンティストが何をやっているのかというと、上司の「アクティブなユーザの割合を知りたい」という曖昧なオーダーを「課金ユーザのうち、30日以内に1回以上ログインしているユーザー」みたいに考えを引き出して具体的な条件へ落とし込んだりするのが仕事です。"
words = tagger.parse(text).splitlines()
words_arr = []
parts = ["名詞"]
words = tagger.parse(text).splitlines()
words_arr = []
for i in words:
    if i == "EOS" or i=="":continue
    word_tmp = i.split()[0]
    part = i.split()[1].split(",")[0]
    if not (part in parts):continue
    words_arr.append(word_tmp)
words_arr

調べた単語が、名詞ではない場合にcontinueすることで、配列words_arrに追加されないという仕組みになっています。

だいぶ数が減りましたね。ただ、「の」など不要な単語が少し残っていますね。

「の」を消してみましょう。

#名詞のみを抽出してみます。
text="ダッシュボードを作るデータサイエンティストが何をやっているのかというと、上司の「アクティブなユーザの割合を知りたい」という曖昧なオーダーを「課金ユーザのうち、30日以内に1回以上ログインしているユーザー」みたいに考えを引き出して具体的な条件へ落とし込んだりするのが仕事です。"
words = tagger.parse(text).splitlines()
words_arr = []
parts = ["名詞"]
stop_words = ["の"]
words = tagger.parse(text).splitlines()
words_arr = []
for i in words:
    if i == "EOS" or i=="":continue
    word_tmp = i.split()[0]
    part = i.split()[1].split(",")[0]
    if not (part in parts):continue

    #stop_wordsだった場合に、words_arrに加えないようにする。
    if word_tmp in stop_words:continue

    words_arr.append(word_tmp)
words_arr

「の」が消えました。

追加したのは、繰り返し処理の前のstop_words = [“の”]と、繰り返し処理の中の if word_tmp in stop_words:continueです。

単語がstop_wordsである場合、continueされ、words_arrには追加されない仕組みになります。

parts = [“名詞”]とし、part = i.split()[0]でその単語の情報を入れます。

part in partsによって、分割した単語の情報に”名詞”が含まれているものだけをwords_arrに入れます。

[]の中の数字が何が良いかについては、word_tmpを出力して、リストの何番目に品詞名がくるのかを確認してください。

分析に応じて、他の単語も消したりしてみましょう。このように、自然言語処理は泥臭い処理が大半です。

例えば、アンケートから形態素解析をして作ったリストで、「顧客満足度が高いアンケートに多く登場する単語はどれだろう??」「顧客満足度が低いアンケートに多く登場する単語はどれだろう??」など、さまざまな分析を行います。

形態素解析とマルコフ連鎖を使った言語生成

形態素に分けただけだとつまらないので、言語モデルを使って生成タスクに挑戦しましょう。


マルコフ連鎖とは、マルコフ過程のうち離散的なものであり、「現在の状態のみで未来の状態が決まる」というモデルのことです。

マルコフ連鎖の特性を使って、類似文章の作成をしてみたいと思います。

使うライブラリは、MeCabとMarcovifyです。pythonでコードを書いております。

マルコフ連鎖による類似文章の自動生成

日本語の文章の自動生成には、二つの技術が必要です。

一つは、形態素解析です。

形態素解析とは、テキストを形態素と呼ばれる単位に分け、各形態素に対して品詞を付与する処理のことです。

先ほどまでで取り組みましたね。

二つ目は、マルコフ連鎖です。

マルコフ連鎖の理論に関しては、別のコンテンツで扱うことにしますが、「確率仮定の1種類であるマルコフ過程のうち、各時刻において起こる状態変化に関して遷移確率が過去の状態によらず、現在の状態のみで未来の状態が決まるモデル」のことです。

マルコフ連鎖では、文章の流れを作ります。形態素解析で分割した単語を、再構築していくことです。

画像に alt 属性が指定されていません。ファイル名: %E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2022-07-29-21.57.08.png
雑な例

単語ごとにバラバラにした後に、文章が作り直されていることがわかります。

当然ですが、意味が通らない場合もありますが、学習した文章の「癖」を反映することができるので、好きな作家の文章を入力データに入れると、それっぽい文章が自動生成できるかもしれません。

これは、1ブロックに1つの単語が入っているので、1階マルコフ連鎖と呼びます。

k階マルコフ連鎖

k階マルコフ連鎖というのは、1つのブロックに形態素をk個入れてマルコフ連鎖を行うということです。

当然ですが、kが1に近いほどオリジナリティのある文章を作れますが、意味が通らないことが大半です。

一方で、kが大きいほど入力した文章とさほど変わらない文章が生成されますが、当然意味が通じる場合が多いです。



2階マルコフ連鎖:(私 は) (は 統計学)というように形態素2個分ごと動かす

CODE

pip install markovify

まずは、マルコフ連鎖に使うライブラリ markovify をインストールしましょう。

今回は、英語でマルコフ連鎖をやってみます。

驚くべきことに英語は単語ごとに分かちがきされているので、形態素解析をするまでもありません。

まずは、長文のテキストファイルを作りましょう。

今回は、赤毛のアン(anne of green gables)の冒頭をテキストデータにしてみました。少し載せておきます。

MRS. Rachel Lynde lived just where the Avonlea main road dipped down into a little hollow, fringed with alders and ladies’ eardrops and traversed by a brook that had its source away back in the woods of the old Cuthbert place; it was reputed to be an intricate, headlong brook in its earlier course through those woods, with dark secrets of pool and cascade; but by the time it reached Lynde’s Hollow it was a quiet, well-conducted little stream, for not even a brook could run past Mrs. Rachel Lynde’s door without due regard for decency and decorum; it probably was conscious that Mrs. Rachel was sitting at her window, keeping a sharp eye on everything that passed, from brooks and children up, and that if she noticed anything odd or out of place she would never rest until she had ferreted out the whys and wherefores thereof.


text_modelのmake_short_sentenceというメソッドを使っております。

こんな出力結果5つが出ました。

「ん??」って感じですね。文法がめちゃくちゃで読めないということにはならないようですが、長文になればなるほどやはり意味はよくわかりません。

We mean to give in.
(管理人訳:私たちは諦めるつもりです)




The sun was coming in at the kitchen door and stepped in when bidden to do so.
(管理人訳:太陽がキッチンの勝手口から入ってきて、どうぞと言われてその通りに足を踏み入れた)




It was unsupposable that Marilla was making fun of her, but Mrs. Rachel would have been cheerful if it had been done without her advice being asked, and must perforce be disapproved.
(管理人訳:マリラが彼女をからかったということは考えられないが、レイチェル夫人は自分の助言を求められないで行われたのなら嬉しかったであっただろうし、強制的に棄却しなければならないのだろう。)




Her cousin lives there and Mrs. Rachel, in spite of—or perhaps because of—their dissimilarity.
(管理人訳:彼女の従兄弟はそこに住んでいる。そしてレイチェル夫人はその異質さにもかかわらず、いやひょっとするとその異質さ故に)




Mrs. Rachel, before she had received a severe mental jolt.
(管理人訳:酷い精神的苦痛を受ける前のレイチェル夫人)



日本語のマルコフ連鎖もいずれ扱います。

自然言語処理について興味が出た方は、自然言語処理をご覧ください。

自然言語処理について、どんどんコンテンツを投稿する予定です。

形態素解析した後のテキストのベクトル化については、【N-gram】テキストをベクトルで表現するには | 自然言語処理をご覧ください。

ベクトル化した文章の類似度を測る、「コサイン類似度」については、【python】コサイン類似度は高校数学の知識で理解できます!をご覧ください。

FOLLOW ME !