電電のブログ

電電生だったひとのぼやき

自然言語処理の紹介

どうも電電です.先日無事に京都大学工学部電気電子工学科を卒業しました.
f:id:denden_seven:20190404154348p:plain:w300



このことについてはまた別でブログに書くかもしれないし,書かないかもしれません.書く暇があれば描きたいです.(ただのポエムになる可能性が高い)

そして今年から京都大学院の方に進学しました.
新たに修士1年生となったんですが,その重みに耐えれそうにないです.
これからは研究とかで忙しくなって「にゃーん」って呟いてそうな気がします.精進します.




閑話休題


さて僕は以前から褒めたもん
褒めたもん (@denden_by) | Twitter
という褒めてくれるアカウントを作成しています.
このアカウントはフォローして呟くと以下のような感じで



f:id:denden_seven:20190308002145p:plain:w300
こんな感じで褒めてくれます


褒めてくれます.

僕が寝ている間も褒めに褒めまくっているようでちょっとずつフォロワーが増えています.(フォロワーのみなさまありがとうございます)(メタモンかわいい)
このままでもいいんですが,以前から機械学習でこの褒めたもんを賢くしたい!!
とおもっており,試験的にババっと書いてみました.


まあ,と言ってもエンコーダーデコーダーなどを使った対話システムなんかは計算リソース的にちょっと難しいと思ったので,褒める判断の部分について行いました.
要は任意のツイートに対して褒めるべきか褒めるべきでないかを判断してもらいたいということです.


現在の褒めたもんの動きはフォロワーの呟きを一定時間ごとにスクロールして,その中に特定のワードがあればそれを元に褒めるという仕組みで動いています.しかしながらこれはあまりいい仕組みとは言えません.
なぜなら否定とかの言葉を考慮していないからです.時には煽りっぽく褒めてしまう時もあって難しい.

さらには「えらい」という単語ひとつとっても

えら‐い
「えら‐い」の辞書の結果
【偉い・豪い】
1.
《形》他(の水準)を抜いて、まさっている。
2.
[偉] 品行や経歴や才能が立派だ。すぐれた。
参照(google辞書)

のように異なる意味を持っており,褒めたもんは2番の意味で捉えて褒めているのに実際は異なるといったことがあり得ます.

f:id:denden_seven:20190308002150p:plain:w300
間違った褒め方

まずはこのような問題を解決したいというモチベーションで自然言語処理を勉強して実装しようというものです.

いきなり自然言語処理って言っても何かわからないと思うので,今回の記事では
まず自然言語処理についてちょっと話していこうと思います.

自然言語処理はそもそも人間が書いたり,話したりする”文章”というものをどうにかしてコンピューターに落とし込められないかというものです.
言葉というあやふやなものをどのようにしてプログラムに理解させたり,記述させたりするかというのがここで問題になります.

実際の流れを見ていきましょう.

自然言語処理についてはその方法はいくつかあるのですが,今の主流となっているものの流れは

  1. 分かち書き
  2. ベクトル化
  3. この文章ベクトルを用いて作成しておいたモデルを学習

という流れになっています.

1.分かち書き

分かち書きです.これは名前の通り文章などの連続の文字列を単語(名詞,動詞,冠詞など)に分けることです.
特にこれは日本語特有の悩みですが,日本語は英語やスペイン語のような単語の切れ目がなく,文章から単語を特定するのが難しいです.
(日 これはなんですか?)→パッとみただけでは区切れない
(英 what`s is this?)→what/is/this/?
(西 Que es esto?)→que/es/esto/?

なので単語の切り取りには苦労しますが,ここではMeCabという分かち書きプログラムを用いました.
このMeCabというプログラムは辞書データを加えることでより正確な単語の分割ができるのですが,今回は
東北大学の乾・鈴木研究室様のmecab-ipadic-neologdを使いました.
https://github.com/neologd/mecab-ipadic-neologd/wiki/About

これを用いることで

すもももももももものうち」を

f:id:denden_seven:20190404154723p:plain:w300
MeCab

のように分けることができます.これで各文章をそれぞれの単語ごとに分けることができました.

2.ベクトル化

次にこの単語ごとにバラバラにしたものを計算機が取り扱うためには

言葉を数字に置き換える必要があります.この時数字だとデータ量が圧縮されすぎるのでベクトルを用います.
つまり,単語のベクトル化というのはひとつの単語(例えば”テスト”)を
一定のルールに基づいて,数字の塊([1, 0.3, 0.2, 0, 0.4,,,])に変換します.
この一定のルールというのがとても大切でできるだけ意味の近い単語同士(”テスト”,”試験”)
は同じようなベクトルになってほしいです.


このベクトル化の手法は大きく分けると
bag-of-wordsとwords-to-vecの二つの手法が存在します.(doc to vecは話がややこしくなるので割愛)

bag-of-wordsは単語の出現度に注目することによってその特徴量を求めます.
ただ単純な方法では単語の頻出度合いや有無にしか注目しないので文脈情報や,単語の順番の情報が失われます.
参照【特別連載】 さぁ、自然言語処理を始めよう!(第2回: 単純集計によるテキストマイニング) | DATUM STUDIO株式会社


words-to-vecは相互の単語の位置からその単語の相関性をみて特徴量とします.(前と後ろの単語をみてそれをエンコーダーとして,入力し,デコーダーで予測したりします.)
参照https://www.tech-tech.xyz/machine-leaning-word2vec.html

今回はwords-to-vecを用いて単語のベクトル化を行い.一つの単語を128次元のベクトルに変換しました.
この作業を単語に対して行うと

”もも”→1*128次元のベクトル

のようになります.
この手法を先ほどの単語に用いると

"すもももももももものうち"→”すもも,も,もも,も,もも,の,うち”→7*1*128次元のベクトル
という風になります.

3.モデル学習とそのモデルを用いた出力

これでベクトルに変換することができたのでここからはモデル作成と学習を用います.

モデルに関してはエンコーダーデコーダーやアテンションなど込み入った話があるのですが,今回はパスします.より詳しく知りたい方は
ゼロから作るディープラーニング2を読んでみてください.とても詳細かつ丁寧に書いてあります.

今回は比較的簡単なLSTMモデルについて書いていきたいと思います.褒めたもんの実装にも使用したのはLSTMです.
このLSTMモデルの詳細な解説は
qiita.com
に非常に綺麗にまとまっています.

簡単に言うとLSTMはこれまでにNNが生かし切れなかった時系列の情報をモデルの中に記憶領域を作成することによって,過去の情報を保持したまま次の時系列情報を入力として使用できるというものです.
これにより得られた予測結果とラベルによって学習を行います.

まとめ

今回は自然言語処理について

f:id:denden_seven:20190408163919p:plain:w300
まとめ

にわけて解説しました.


ポイントとしては,日本語特有のわかち書き,単語のベクトル化の部分が
他の技術と大きく異なるのかと思います.
褒めたもんの部分も書こうかと思ったんですが,長くなりすぎてわかりにくかったので分けてみました.次回
ここで紹介した技術を用いて褒めたもんに適用してみたいと思います