俺・・・感情がねえんだ・・・ ←色んな感情推定器で本当に感情が無いのか分析してみる

#はじめに

人間のコミュニケーションは言語だけではなく、表情・仕草など数多くの非言語情報が含まれています。機械的・プログラム的に人の行動を分析・解釈するときには、そのような非言語情報も加味し意味づけを行っていくことでより多くの情報を取得することができます。画像処理、自然言語処理、音声認識など各分野でこれらの技術は研究開発されていて、マーケティングやロボットとの交流システムなど数多くのフィールドで応用されることが期待されています。今後も大きく発展していくことでしょう。

[前回の記事(「たけのこの里」を「きのこの山」に『正しく』自動で修正して差し上げるプログラム)](https://qiita.com/honehoney/items/a8c7ba2c53a70c88502e) では、文章中の**誤り**を修正するためにテキストからの感情推定APIというものを使ってみました。このような自然言語処理技術を活用することで、話者の抱いている感情を推定し、その感情によって違った反応を返すことができるようになります。例えば、話者が悲しんでいるときに、チャットボットがその感情を推定して慰めてくれるなど、適切なコミュニケーションを取らせるようにすることができます。

一方で、世の中には自分の感情が無いと主張される方が一定数いらっしゃいます。
例えば以下のような方々です。

###†代表例1†

>「話しかけないでくれ・・・俺・・・感情がねえんだ・・・」
>「笑うって なんだ・・・？ 」
>
>　　　  -[零(33)](http://jigokuno.jugem.jp/?cid=69)- (『女に惚れさす名言集』, 2011)

###†代表例2†
>一応スペック
>
>俺
>
>中学生、(14.6才)
>
>趣味、特になし(最低限の情報を知るため新聞やニュースをみるが)
>
>感情、無し
>
>小学生六年生から周りが馬鹿らしく感じ感情が薄れて行く
>今はほとんど残っていない
>機会みたいなものだ
>冷たい自分をみると悲しくなる
>
>
>　　　-[ID:Qm9QaLSN0](https://www.logsoku.com/r/2ch.net/news4vip/1360806210/)- (『俺、中学生だけど正直感情が無くて全てが滑稽に思える』, 2013)

これらの方々の中には感情が無いということで、「他人と適切なコミュニケーションをできていないのではないか」「自分は他の人とは違うのではないか」「実は転生した能力者なのではないか」など数々の不安に苛まれる方もいらっしゃるのでは無いかと思います。

しかし幸い、Google・Microsoft・NTTなど数々の最先端を走る企業が、その最新の研究成果を感情推定APIという形で公開してくれています。それらを活用してこれらの人々に対して徹底的に感情解析を行い比較することで、本当に無感情なのかどうか確認することができます。
もし感情があると推定されたならば、「あなたにもきちんと感情があるんだよ」「特殊な人間なんかじゃない、**ただのごく普通の一般人**だよ」**「コミュニケーションができないのは他に原因がある可能性もあるよ」**と優しく伝えることで安心感を与えて差し上げることができるのではないかと思い、今回様々な感情推定APIを試してみることにしました。

以下、それぞれの使い方と、実際に使ってみた感想を記載します。

# 比較する感情推定サービス

以下の4種類の感情推定APIを利用し結果を比較します。全て無料で使えますのでその使い方もご説明します。

- [Google Cloud Natural Language API](https://cloud.google.com/natural-language?hl=ja)
- [Microsoft Azure Text Analytics API](https://azure.microsoft.com/ja-jp/services/cognitive-services/text-analytics/) 
- [COTOHA API](https://api.ce-cotoha.com/contents/index.html)
- [ユーザーローカル テキスト感情認識 API](https://emotion-ai.userlocal.jp/) (Web版デモサイトでの利用)

#各感情推定APIの使い方

###Google Cloud Natural Language API

<details><summary>クリックで展開</summary><div>

####前準備
まずGoogle Cloud Platformに登録しておきます。クレジットカードなども登録します。(一年は無料期間があります。)

「APIとサービス」メニューから「ライブラリ」を選択。「Cloud Natural Language API」を探し、有効化しておきます。次に「APIとサービス」メニューから「認証情報」を選択し、「認証情報の作成」からAPIキーを作成してメモしておきます。

####実装

[Google Colabratory](https://colab.research.google.com/notebooks/intro.ipynb?hl=ja)で
「ノートブックを新規作成」しておきます。

「コードを追加」して以下のコードを記載、実行します。(実行は左側の三角▷ボタン)

```python

import getpass

APIKEY = getpass.getpass()
```

passを聞かれるので、先ほどのAPIKEYを入力してENTERを押しておきます。

次にさらに「コードの追加」をして、以下のコードを記載、実行すると感情推定の結果が表示されます

```python

import requests 
 
key = APIKEY
 
#感情分析したいテキスト
text = "話しかけないでくれ・・・俺・・・感情がねえんだ・・・"
 
#APIのURL
url = 'https://language.googleapis.com/v1/documents:analyzeSentiment?key=' + key
 
#基本情報の設定
header = {'Content-Type': 'application/json'}
body = {
    "document": {
        "type": "PLAIN_TEXT",
        "language": "JA",
        "content": text
    },
    "encodingType": "UTF8"
}
 
#json形式で結果を受け取る。
response = requests.post(url, headers=header, json=body).json()
print(response)
#分析の結果をコンソール画面で表示
print("総合magnitude:",response["documentSentiment"]["magnitude"])
print("総合score:",response["documentSentiment"]["score"])
for i in response["sentences"]:
    print(i["text"]["content"],"magnitude:",i["sentiment"]["magnitude"],", score:",i["sentiment"]["score"])

```
</div>

###Microsoft Azure Text Analytics API

<details><summary>クリックで展開</summary><div>

簡単に使いたい場合は以下でデモを試せます。
https://azure.microsoft.com/ja-jp/services/cognitive-services/text-analytics/

コードとして実装する場合は以下から7日間有効な試用版のキーを入手できます。
https://azure.microsoft.com/ja-jp/try/cognitive-services/#lang

以下のクイックスタートを参考に、Colaboratoryでコードを作成し、実行します。ただし感情解析のバージョンは最新のv3.0-preview.1を使います。(クイックスタートではv2.1)
https://docs.microsoft.com/ja-jp/azure/cognitive-services/text-analytics/quickstarts/python

```python

import requests
# pprint is used to format the JSON response
from pprint import pprint

import os

subscription_key = "<paste-your-text-analytics-key-here>"
endpoint = "<paste-your-text-analytics-endpoint-here>"

sentiment_url = endpoint + "/text/analytics/v3.0-preview.1/sentiment"

documents = {"documents": [
    {"id": "1", "language": "ja",
        "text": "話しかけないでくれ・・・俺・・・感情がねえんだ・・・"},
]}

headers = {"Ocp-Apim-Subscription-Key": subscription_key}
response = requests.post(sentiment_url, headers=headers, json=documents)
sentiments = response.json()
pprint(sentiments)

```
</div>

### COTOHA API

<details><summary>クリックで展開</summary><div>

COTOHA APIからDeveloper登録してID,PASSを取得しておきます。
https://api.ce-cotoha.com/contents/index.html
各API 1日に1000回まで、つまり月最大3万回まで利用できます。

以下をColaboratoryに記載し、ID,PASSを書き換えれば実行できます。

```python

import requests
import json
import sys
from pprint import pprint

BASE_URL = "https://api.ce-cotoha.com/api/dev/"
CLIENT_ID = "COTOHA APIで取得したID"
CLIENT_SECRET = "COTOHA APIで取得したPASS"


def auth(client_id, client_secret):
    token_url = "https://api.ce-cotoha.com/v1/oauth/accesstokens"
    headers = {
        "Content-Type": "application/json",
        "charset": "UTF-8"
    }

    data = {
        "grantType": "client_credentials",
        "clientId": client_id,
        "clientSecret": client_secret
    }
    r = requests.post(token_url,
                      headers=headers,
                      data=json.dumps(data))
    return r.json()["access_token"]

def sentiment(sentence, access_token):
    base_url = BASE_URL
    headers = {
        "Content-Type": "application/json",
        "charset": "UTF-8",
        "Authorization": "Bearer {}".format(access_token)
    }
    data = {
        "sentence": sentence,
    }
    r = requests.post(base_url + "nlp/v1/sentiment",
                      headers=headers,
                      data=json.dumps(data))
    return r.json()


if __name__ == "__main__":
    sentence = "話しかけないでくれ・・・俺・・・感情がねえんだ・・・"
    access_token = auth(CLIENT_ID, CLIENT_SECRET)

    sentiment_result  = sentiment(sentence,access_token)

    pprint(sentiment_result)

```

</div>

###ユーザーローカル

<details><summary>クリックで展開</summary><div>

こちらは無料版はWebだけの提供であるため、下記デモサイトから利用します。
https://emotion-ai.userlocal.jp/

</div>

#結果抜粋&比較

1. 「話しかけないでくれ・・・俺・・・感情がねえんだ・・・」
2. 「笑うって なんだ・・・？ 」
3. 「一応スペック(略)」

をそれぞれの感情推定器にかけて結果を比較してみます。
以下、結果は長いので折りたたんでいます。クリックで展開します。

###1. 「話しかけないでくれ・・・俺・・・感情がねえんだ・・・」の各推定結果

<details><summary>クリックで展開</summary><div>

####Google Cloud Natural Language API
```
総合magnitude: 0.7
総合score: 0.7
```
GoogleのSentimentについては
score: -1.0（ネガティブ）～1.0（ポジティブ）
magnitude(感情の強度): 0.0～+inf 
で感情が表されます。「悲しい」「怒っている」などは区別せずネガティブかポジティブか、とその強さのみ表すようです。[解釈例](https://cloud.google.com/natural-language/docs/basics?hl=ja#interpreting_sentiment_analysis_values)として「"score": 0.8、"magnitude": 3.0」が明らかにポジティブとされてますので今回は弱めポジティブといったとこでしょうか。
**結果: ややポジティブ**

####Microsoft Azure Text Analytics API
```
'sentenceScores': {'negative': 0.55,
                   'neutral': 0.37,
                   'positive': 0.08},
'sentiment': 'negative'
```
MicrosoftのSentimentについてはnegativeっぽさ、neutralっぽさ,positiveっぽさが合計1となるように判定されます。今回はネガティブっぽさが一番強く判定されたようです。デモサイトだと下記画像のように表示されます。
<img width="553" alt="スクリーンショット 2020-03-03 23.51.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583240/ebfc6fba-b1fb-5ee0-e2e3-a8c15c73809e.png">
**結果: ややネガティブ**

####COTOHA API
```
 'result': {'emotional_phrase': [],
            'score': 0.36632366672980926,
            'sentiment': 'Neutral'}
```
COTOHA APIはPositive, Negative, Neutralのいずれかと、その信頼度を示すようです。特徴的なのはemotional_phraseという項で、今回は出現していませんが、感情に関わる用語とその感情のラベルが抜き出されるため、利用用途によっては使えそうです。サンプルだと以下のようなものが記載されています。

```
    "emotional_phrase":[
      {
        "form":"謳歌",
        "emotion":"喜ぶ,安心"
      }
```
今回はNeutralかつ信頼度低めのスコアなので、**無感情っぽいけど違うかも**という判定ですかね。ある意味割と正解に近いんじゃないかこれ。

**結果: 無感情(かも)**

####ユーザーローカル

<img width="1011" alt="スクリーンショット 2020-03-04 0.10.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583240/42b23291-0d23-5d8f-3acb-c32c80edbb2e.png">
Web上の結果。5種類の感情に分類されるようです。使いやすそう。今回は**怒りかつ好き**という感情を持っているようです。文字通り読めば怒りはわかるけど**好き**ってなんだ。

**結果: 怒りかつ好き**

</div>

###2.「笑うって なんだ・・・？」の各推定結果

<details><summary>クリックで展開</summary><div>

####Google Cloud Natural Language API
```
総合magnitude: 0.1
総合score: -0.1
```
**結果: 弱い無感情。弱い無感情って何だろう・・・**

####Microsoft Azure Text Analytics API
```
'sentenceScores': {'negative': 0.91,
                   'neutral': 0.04,
                   'positive': 0.05},
'sentiment': 'negative'}
```
**結果: ネガティブ**

####COTOHA API
```
 'result': {'emotional_phrase': [{'emotion': 'PN', 'form': '笑う'}],
            'score': 0.2729609019529442,
            'sentiment': 'Neutral'},
```
こちらの結果も**無感情だけど自信なし**ですね。

**結果: 無感情(かも)**

####ユーザーローカル
<img width="992" alt="スクリーンショット 2020-03-04 0.29.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583240/4c0b524f-b26c-3b0a-4ceb-0d2e9db6553f.png">
また**好き**かよ・・・**喜び**も増えてカオスに。

**結果: 好きかつ怒りかつ喜び**

</div>

###3.「一応スペック 俺(略)」の各推定結果

<details><summary>クリックで展開</summary><div>

####Google Cloud Natural Language API
```
総合magnitude: 1.8
総合score: 0.1
```
強め無感情。って何だろう・・・

**結果: 強め無感情**

####Microsoft Azure Text Analytics API
```
'documentScores': {'negative': 0.56,
                   'neutral': 0.28,
                   'positive': 0.16},
'sentiment': 'negative'}
```

**結果: ややネガティブ**

####COTOHA API
```
 'result': {'emotional_phrase': [{'emotion': 'N', 'form': '悲しくなる'},
                                 {'emotion': 'PN', 'form': '冷たい'},
                                 {'emotion': '悲しい', 'form': '馬鹿らしく'},
                                 {'emotion': 'PN', 'form': '最低限'}],
            'score': 0.6473423833981717,
            'sentiment': 'Negative'}
```

**結果: ネガティブ**

####ユーザーローカル
<img width="993" alt="スクリーンショット 2020-03-04 0.43.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583240/3c14336d-83ad-43d4-ff91-e823feb28ca5.png">
これはそれっぽい結果な気がする。

**結果: やや恐れ**

</div>

#結果まとめ

ポジティブ、ネガティブ判定の結果をを下記の表にまとめました。
※カッコ内は勝手につけたポジネガ点数

|| Google |  Microsoft  |  COTOHA | ユーザーローカル|
|:----------:|:------------:|:-----------:|:----------:|:----------:|
|1.俺感情ねえんだ|ややポジティブ (+1)|ややネガティブ (-1)|無感情(信頼度低) (0)|怒りかつ好き(0)|
|2.笑うって何だ|弱め無感情(0)|ネガティブ(-1)|無感情(信頼度低)(0)|好きかつ怒りかつ喜び(+1)|
|3.一応スペック|強め無感情(0)|ややネガティブ(-1)|ネガティブ(-1)|やや恐れ(-1)|
|総評|ポジティブが出たのが謎。強め無と弱め無の区別がわからない|全体的にネガティブ。正解っぽい気がする。|信頼性が低い無と判定->ある意味正解っぽいが、感情を直接表すフレーズがないと強めに判定されないかも|複数感情が入り混じってよくわからない時がある|

というわけで3例しか試してないんですが、結果はかなりバラバラとなりました。各社個性が出ますね。
今回は4社の結果を合計して感情を判定し、零さんは合計0で無感情、スペック俺の方は-3でネガティブということにしておきます。さすが零(33)さんは中学生なぞと比べて年季が違う。

それぞれ使ってみての所感ですが、個人的にはMicrosoftのものが全体ネガティブっぽいと判定していて、一番それらしいかなと感じました。実用的にも、ポジネガとニュートラルそれぞれのスコアが出る方が使いやすいんじゃないかなと感じます。
COTOHA APIが無感情として判定しているのは正解っぽいようでいて、単に感情を表すフレーズがないために基準がなく判定できていないという結果にも見えました。無感情というよりは無判定というべきか。感情を表すフレーズを抜き出してくれるのは便利ですが、必ずしも感情フレーズを言わないパターンも多々あるので、実用的かどうかは検証が必要そうです。
Googleのポジネガと強弱は実はあんまり実用的じゃない気がします。弱めのネガティブとか強めの無感情とかどうしたらいいのかよくわかりませんでした。ちょっと実装考える必要がありそう。
ユーザーローカルは、相反する感情が入り乱れ過ぎててよくわからないです。使いどころがわからない・・・。

以上、各感情解析API使い方と使ってみての感想でした。
みなさまもお近くに「俺・・・感情がねえんだ・・・」とかいう方がいましたら、本当に感情がないのかどうか検証して結果をやさしく伝えてあげてください。