【自然言語処理】感情分析の進め方＆ハマりやすいポイント

<img width="726" alt="スクリーンショット 2019-09-02 10.11.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327405/20561932-bfd0-45a6-deab-5b35a8ce6238.png">

![スクリーンショット 2019-09-02 12.28.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327405/a990f845-36b3-d9ec-9a04-932570c7b2a9.png)


#はじめに

自然言語処理技術が口コミ等の解析に活用されるケースが一般的になりつつありますが、**「感情分析」**に関して日本語言語処理に関する具体的な手法を解説しているサイトは本記事を執筆した時点とても少ない印象です。

qiita内でも感情辞書を使って単語レベルで判断する記事は見かけますが、もう一歩踏み込んだ**ガチな感情分析**をやっているケースはありませんでした。

上記のような状況のため私自身論文を漁ったりしながら手探りで進めた結果、非常に苦労しましたので、自分なりに感情分析のやり方を備忘録としてまとめました。

至らない点も多々あるかと思いますので、コメントにてご指摘いただけますと幸いです。
【2021.1111追記】
**本記事の感情分析コードを希望される方は個別にご連絡ください。**
記事内やgit等では公開はしておりません。
【2021.0909追記】
手っ取り早く感情分析にチャレンジしたい方はこちらの記事を是非参考にしてください！
[Python で日本語文章の感情分析を簡単に試す (google colab で試す)](https://qiita.com/hnishi/items/0d32a778e375a99aff13)
[Huggingface Transformers 入門 (10) - 日本語の感情分析](https://note.com/npaka/n/ne0adde2d7ae8)

##感情辞書の手順（ざっくり）

①感情分析の全体像を理解
②感情辞書の選定
③文分割・形態素解析・係り受け解析
④否定語対応
⑤極性変化単語への対応
⑥慣用句対応
⑦反語表現対応
⑧要求表現対応
⑨副詞の重み付け
⑩未知語への対応

前提として、日本語のポジネガ表現を完全に網羅することが極めて難しいです。日本語は表現方法や言い回しの種類が多くが全てをカバーするにはどうしても限界があります。
ルールベースの感情分析モデルを作る際は、精度と工数はトレードオフな関係ですので、どこまでをオッケーなラインとするかの線引きも大事です。

#①感情分析の全体像を理解

一般的には、感情分析とは書かれた文章の意見を判断することを指します。<font color="Red">ポジティブ</font>な意見なのか、<font color="Blue">ネガティブ</font>な意見なのか、それとも<font color="Grean">ニュートラル</font>なのかを、一連の単語から判断し、分類することです。

感情分析が注目されているのは、自社の製品やサービスに対する世の中の意見を測るのに役立つためです。ユーザーはツイッターのようなSNSで不平不満をぶちまけたり、アマゾンにレビューを書いたり、ポジティブな感情とネガティブな感情の両方をソーシャルメディアで表現するものです。感情分析はそうした世の中の意見を感情値で定量化させることで、品質改善に役立てることができるため、非常に有効な手段と言えます。

##基本的なやり方

1. シンプルな感情辞書ベース
2. ディープラーニングによる教師あり学習
3. 既存のAPIを使う

###1. シンプルな感情辞書ベース

例えば「美味しい」はポジティブ、「不味い」はネガティブといった単語でポジネガ判定することをベースにした単純なロジックです。

【メリット】
・ポジネガ判定の結果が解釈しやすい
・単純な単語辞書レベルのポジネガ判定だけならコーディングが楽

【デメリット】
・ルールベースであるため、厳密性を求める場合多くのルールを作成する必要あり
・感情辞書に載っていない単語があると対応できない

###2. ディープラーニングによる教師あり学習

自動的に感情値に寄与する文字や熟語や表現を抽出します。
単純な例で行くと

>花が美しい→感情値：+1
ラーメンが美味しい→感情値：+1
美点→感情値：+1
美意識→感情値：+1
　・
　・
　・

というように機械学習の要領で学習させていくと
『「美」という語は感情値としてはプラスなんだな』と勝手に判断してくれます。

【メリット】
**・形態素解析や感情辞書作成やルール作成が不要**
つまり、コーティングがとても楽です。

【デメリット】
**・多くの正解データの準備する必要がある**
**・モデルのブラックボックス問題**

「モデルが導き出した感情値が、どんなふうに考えて出してきたのか分からない」と言う問題です。
「なんでこの文章がボジティブ？どこがポジティブ表現なの？」となる。
とは言っても自然言語かつ日本語なので、文章読めばなんとなく理解できますが。

今回の記事では**ディープラーニングについては扱いません**が、下記記事が参考になるかと思います。
[ディープラーニングを使って転職会議の企業クチコミデータを感情分析してみる](https://qiita.com/terrierscript/items/54daa5aedde599e2637c)

###3. 既存のAPIやサービスを使う

文章を入力すると感情分析してくれる便利なAPIやサービスが公開されています。
・[GCMのNATURAL LANGUAGE API](https://cloud.google.com/natural-language/?hl=ja)
・[UserLocal AIテキストマイニング](https://textmining.userlocal.jp)

#ここからが本題
感情分析とは何かということをざっくりご理解いただけたと思いますので、これからは具体的なポイントについて解説していきます。


#②感情辞書の選定
初めて感情分析にチャレンジする際に誰しもが通過する道です。

##メジャーな２つの感情極性辞書どっちを使えばいいの？

- 東北大の乾・岡崎研究室が公開されている「日本語評価極性辞書」
 - [日本語評価極性辞書](http://www.cl.ecei.tohoku.ac.jp/index.php?Open%20Resources%2FJapanese%20Sentiment%20Polarity%20Dictionary)
 
今回は東北大学 乾・岡崎研究室が公開している「日本語評価極性辞書（用言編）」と「日本語評価極性辞書（名詞編）」を使います。ネガティブなワードは「n」、ポジティブなワードは「p」、ニュートラルなワードは「e」で表現していきます。


- 東工大の高村教授が公開されている「単語感情極性対応表」
 - [単語感情極性対応表](http://www.lr.pi.titech.ac.jp/~takamura/pndic_ja.html)

めでたい:めでたい:形容詞:0.999645
賢い:かしこい:形容詞:0.999486
過小:かしょう:名詞:-0.942846
器量負け:きりょうまけ:名詞:-0.943603
固まる:かたまる:動詞:-0.943991

どっちがいいの？
結論からいうとどっちも微妙です。両方の辞書もオープンに公開してくれている点は非常にありがたいのですが・・・
主な理由としては
**・日本語評価極性辞書：感情極性のある単語を完全にカバーしているわけではない（収録語彙が少ない）**
**・単語感情極性対応表：肌感覚と異なる極性値が振られている単語がある**


私は、[日本語評価極性辞書](http://www.cl.ecei.tohoku.ac.jp/index.php?Open%20Resources%2FJapanese%20Sentiment%20Polarity%20Dictionary)の方が感覚的に良さげでしたのでこちらを改騙して利用しています。
改編する理由は、辞書に載っていない単語があったり、感情極性が自分のイメージと違ったりするためです。私の場合は「ラーメン」の口コミにFITするようにカスタマイズしました。

以降の内容は、**日本語評価極性辞書を使うことを前提**としていますのでご承知おきください。

#③文分割・形態素解析・係り受け解析

感情分析の下準備として①文分割②形態素解析③係り受け解析を施します。
自然言語処理について、ある程度知識のある方が多いと思いますので詳しい説明は省略しています。

###1.文分割
日本語の文章のどこからどこまでが１文なのかを判断します。
一般的には文末記号を定義して抽出します。
食べログの口コミを感情分析することを前提としましたので、私は下記の文字を文末記号として定義しました。
　EOS_DIC = ['。', '．', '！','？','!?', '!', '?' ]　
###2.形態素解析
基本は感情辞書をベースにしますので、「意味を持つ最小限の単位（＝単語）」に分解します。
形態素解器を使うことで、その単語がどの品詞なのかもわかります。

###3.係り受け解析
文節間の「修飾する（係る）」「修飾される（受ける）」の関係を調べる事です。
後で記述しますが、係り受け関係により感情値を変化させるのがポイントとなります。

形態素解析にはMecab、係り受け解析にはCaboChaを利用しました。


#④否定語対応
単純なポジネガ判定する際にありがちが否定語のあつかい。

例文①：らーめんが美味しくない

単純な単語レベルの感情値割り当てのみの場合、文章感情値は下記になります。

形態素：[らーめん,が,美味しく,ない]
標準形に直す：[らーめん,が,美味しい,ない]
単語感情値：[(ラーメン:0),(が:0),(美味しい:+1),(ない:0)]
文章感情値：+1

文意としては、マイナスなはずなのに「+1」になってしましました。

###【対策】
**極性のある単語のあとに否定語(ない,ず,ぬ）がきたら、極性を反転させる**

（例）
美味しい + ない　→　(+1)*(-1) = -1

この手法を適用すると、

標準形に直す：[らーめん,が,美味しい,ない]
単語感情値：[(ラーメン:0),(が:0),<font color="Red">(美味しい+ない:-1)</font>]
文章感情値：-1

このように文意と感情値が一致しました。

自然言語処理タスクでは、「助詞や助動詞」といった脇役な品詞の単語は、形態素解析の際に削除しがちですが感情分析においては、非常に重要なため残しておくのが懸命です。
今回は「ない」が助動詞にあたるため、もし仮に形態素解析の際に助動詞を除いてしまうと、「(らーめん,0),(美味しい,+1)」だけになってしまい、文意と感情値が異なってしまいます。


例文②：「息子はお子様ラーメンだけでは満足せず。」

標準形に直す：[息子,は,お子様,ラーメン,だけ,で,は,満足,する,ぬ]
単語感情値：[(息子:0),(は:0),(お子様:0),(ラーメン:0),(だけ:0),(で:0),(は:0),<font color="Red">(満足+ぬ:-1)</font>,(する,0)]
文章感情値：-1
※コーディングの際は「する」をスルーする処理を加えます。

###特殊な助動詞「ん」への対応
「ありません」の「ん」です。

例文③:このラーメンは美味しくありません。
「美味しい」という単語があるため、普通にやると感情値は+1になり、実際の文意と異なります。

「ありません」の「ん」は文法的には打ち消しの助動詞「ぬ」の撥音形で、助動詞「ます」に付くときだけは例外的に常用されます。
「ぬ」と同じ意味のため「ん」を「ぬ」置き換えることも検討しましたが、「ん」を全て「ぬ」に置換するとややこしくなります。

###【対策】
**「ありません」を「ないです」に置換する**

このラーメンは美味しくありません。
→このラーメンは美味しく**ないです。**

標準形に直す：[この,らーめん,は,美味しい,ない,です]
感情値を付与：[(この,0),(ラーメン,0),<font color="Red">(美味しい+ない,-1)</font>,(です,0)]
文章感情値：-1


#⑤極性変化単語への対応（対象によって極性が変る言葉）

単語に感情辞書を当てはめる手法だけでは、下記のような日本語表現に対応できません。

例文：このラーメンは味の割に値段が高い。

単純な単語レベルの感情値割り当てのみの場合、文章感情値は下記になります。

標準形に直す：[この,らーめん,は,味,の,割,に,値段,高い]
感情値を付与：[(この,0),(ラーメン,0)・・・(値段,0),(が,0),(高い,0)]
文章感情値：0

「値段が高い」という表現はネガティブですが、「値段」も「高い」もそれ自体ではネガティブとはいえません。単語単位ではなく複数語単位で感情極性値を付与する必要があります。

下記は複数単語単位で感情値を付与する表現の例です。

【ボジティブ】
テンションが高い・器が大きい・誤差が小さい・飽きが来ない

【ネガティブ】
音沙汰がない・値段が高い・我が強い・無駄が多い

このように、前にくる名詞によって、一般的に極性出現や極性反転などの現象が見られやすい形容詞のことを「極性不定形形容詞」と呼びます。

【極性不定形形容詞データセット】
高い,低い,大きい,小さい,重い,軽い,強い,弱い,多い,少ない,ない,すごい,激しい,深い,浅い,長い,短い

###【対策】
**①「値段＋高い,-1」となるよう該当しうる複数語感情辞書を作成する**
**②機械学習によって複数語の感情極性を判断する**

私は、地道な作業でしたが①を採用しました。

複数語による感情極性判断をすることにより

標準形に直す：[この,らーめん,は,味,の,割,に,値段,高い]
感情値を付与：[(この,0),(ラーメン,0)・・・<font color="Red">(値段＋高い,-1)</font>,(が,0)]
文章感情値：-1

となり、文意と感情値が一致します。

#⑥慣用句対応
文意とは異なる感情値になったときにありがちなのは、慣用句を考慮していなかった場合です。
二語以上の単語が結びつく、全く異なる意味を持つため、慣用句によって極性出現したり極性反転するケースがあります。

【ポジティブ】
・一味違う・五本の指に入る・顔が広い
【ネガティブ】
・頭に来る・腹が立つ・口が軽い

###【対策】
**慣用句表現も片っ端から辞書登録する**

neologdが良い感じにまとめてくれてる慣用句をありますが、ないものについては辞書登録すると良いです。

#⑦反語表現

反語とは
>断定を強調するために、言いたいことと反対の内容を疑問の形で述べる表現。「そんなことがあり得ようか（あるはずがない）」などの類。

例文①：
駅前にできたラーメン屋、食べログ2点台みたいでなんですが、本当に美味しいのでしょうか？

文意からすると、感情値は、ややネガティブよりのニュートラルですが、単純に感情値計算すると、

感情値を付与：[(駅前:0),(に:0)(できた:0)・・・・・(美味しい:+1),(の:0),(で:0),(しょ:0),(う:0),(か:0)]
文章感情値：+1

となってしまいます。

「でしょうか」はやっかいな単語です。
###【対策】

**極性単語＋「（でしょ：助動詞）,(う：助動詞),(か：助詞)」
になった場合に、極性単語の極性値を「０」にする**

文脈によってポジティブにもネガティブにもなり得るため、とりあえず「ニュートラル」になるように処理します。

[(美味しい:+1),(の:0),(で:0),(しょ:0),(う:0),(か:0)]
こつとしては、リストを後ろから探索すると、最短で極性単語（美味しい）にたどり着けます。
前から探索すると次のような場合にミスります。

例文：見た目は悪いのですが、本当に美味しいのでしょうか？
[(見た目,0）,(悪い,-1)・・・(本当に,0),(美味しい:+1),(の:0),(で:0),(しょ:0),(う:0),(か:0)]
このように、１文に極性単語が複数ある場合に前から探索すると「美味しい」ではなく「悪い」をニュートラルにするという間違った処理になってしまいます。
そのため、リストを後ろから探索して、確実に「でしょうか」の直前の単語をキャッチするという工夫が必要です。

[(見た目,0）,(悪い,-1)・・・(本当に,0),<font color="Red">(美味しい＋でしょうか,0)</font>,(の:0),)]

#⑧要求表現対応

例文：味をもっと改良してほしい。
文脈にもよりますが、たいていの場合は「〜てほしい」という表現はネガティブです。

例文の場合(改良,+1)があるためなにもしないと感情極性は正になってしまうため、「〜てほしい」という表現があった場合、(改良＋てほしい,-0.5)となるように処理します。

#⑨副詞への重みづけ
とてもや非常にのようにその後にくる言葉の効果を強調する表現には重みを加えます。
ポピュラーな手法としては、強調表現の副詞の後の単語の感情値を1.5倍にします。

とても美味しい
(とても+美味しい,1.5*1)
→感情値:1.5
非常にまずい
(非常+まずい,1.5*(-1))
→感情値:-1.5

#⑩未知語への対応（需要があればちゃんと書きます）
既存の感情辞書に含まれていないが感情極性がある単語については正しく判定できません。
そのため、未知語についても極性の有無を判断し、必要に応じて感情辞書に追加することで精度が向上します。

【やり方】
①ある感情極性のある単語に関してword2vec等で単語間類似度を計算し、類似度が閾値以上（目安0.8以上）の単語であれば前者の単語の極性値と同じと判断する。
②統計上にポジティブな文章の近くにはポジティブな単語、ネガティブな文章にはネガティブが単語が出現しやすいことを応用してその都度適宜判断する。

このあたりの手法は参考文献の論文を参照してもらえればと思います。

#まとめ

実際にいろいろと試行錯誤した結果、古典的なルールベースな手法でも日本語表現を正確に解釈することを極めれば、高い精度で文章に対して感情値を付与できることがわかりました。
①〜⑩まで全て必要かどうかは、要件にもよると思いますので必要に応じて実装することおすすめします。私の場合は最終的には必要最低限のものを選んで使っておりました。

感情分析の進め方がわからなかった自分と同じような悩みを持っていた人の力になることができましたら幸いです。
ここまで書いといてあれですが、ルールベースをコードで表現するのは結構めんどくさいので教師データが手に入るようでしたらディープラーニングでやることをおすすめます。

#参考文献

[隠れ変数モデルによる複数語表現の感情極性分類](https://ipsj.ixsq.nii.ac.jp/ej/index.php?action=pages_view_main&active_action=repository_action_common_download&item_id=10151&item_no=1&attribute_id=1&file_no=1&page_id=13&block_id=8)
[単語位置と強弱表現に着目したツイートの感情分析](https://ipsj.ixsq.nii.ac.jp/ej/index.php?action=pages_view_main&active_action=repository_action_common_download&item_id=153240&item_no=1&attribute_id=1&file_no=1&page_id=13&block_id=8)
[分野別感情極性辞書の作成及び評価](https://ipsj.ixsq.nii.ac.jp/ej/index.php?action=pages_view_main&active_action=repository_action_common_download&item_id=188670&item_no=1&attribute_id=1&file_no=1&page_id=13&block_id=8)
[皮肉検出における感情生起要因の有効性](https://www.ieice.org/publications/conference-FIT-DVDs/FIT2018/data/pdf/E-009.pdf)
[ツイートにおける周辺単語の感情極性値を用いた新語の感情推定](https://db-event.jpn.org/deim2017/papers/203.pdf)