COTOHA API で照応解析してもギブミーチョコレート出来ていない問題


Background

【Qiita x COTOHA APIプレゼント企画】
が気になったので少し使ってみようと思いました。

自然言語処理で有名なライブラリはMeCabかKNPですが、恥ずかしながらCOTOHA APIをこのイベントで始めてし知りました。

Motive

ちょっと個人的にもハードルが高めかもしれませんが、照応解析APIを最初に使ってみました。
この解析は文章中の代名詞(「私」「あなた」「彼」など)・指示語(「あれ」「これ」)をそれらしい人物や物体に置き換える処理のことです。
使う理由としては、時間に余裕があれば誰が何をしたかを明確化してから処理をしたいための初期段階として使いたかったからです。

イベントは3月中旬っすか。。。

間に合うかな。

Environment

Development

スクリプトコード (クリックするとコードが表示されます。)
import requests
import json
import time
import sys

#--- この4つパラメータはPortalで取得 ---
PUBLISH_URL = "--- get your parameter ---"
CLIENT_ID = "--- get your parameter ---" 
CLIENT_SECRET = "--- get your parameter ---" 
BASE_URL = "--- get your parameter ---"

def getToken():
    header = {"Content-Type": "application/json"}
    contents = {
        "grantType": "client_credentials",
        "clientId": CLIENT_ID,
        "clientSecret": CLIENT_SECRET
    }
    raw_res = requests.post(PUBLISH_URL, headers=header, json=contents)
    response = raw_res.json()
    return response["access_token"]

def coreference(token, sentence):
    header = {
        "Authorization": "Bearer {}".format(token),
        "Content-Type": "application/json"
    }
    contents = {
        "document": sentence
    }
    raw_res = requests.post(
        BASE_URL +
        "nlp/v1/coreference",
        headers=header,
        json=contents)
    response = raw_res.json()
    return response

if __name__ == "__main__":

    if len(sys.argv) != 2:
        sys.exit()
    message = sys.argv[1]

    token = getToken()
    time.sleep(0.5)

    print(coreference(token, message))


流れとしては
トークン取得 -> それぞれの使いたいAPIをコール
の2つです。

curl をpythonでは同じことをしています。

$ curl -X POST -H "Content-Type:application/json" -d '{
  "grantType": "client_credentials",
  "clientId": "[clientid]",
  "clientSecret": "[clientsecret]"
}' [Access Token Publish URL
]
$ curl -H "Content-Type:application/json;charset=UTF-8" -H "Authorization:Bearer [access_token]" -X POST -d '{
"document": -- ここに解析したい文章を入力 --
}' "[Developer API Base URL]/nlp/v1/coreference"

Consequence

てことで二つの文章を使って解析してみます。

  • 山田君はカップ麺を買った。彼は美味しそうに食べていた。
  • 山田君は斉藤君にカップ麺を渡した。彼は美味しそうに食べていた。
$ python main.py 山田くんはカップ麺を買った。彼は美味しそうに食べていた。
{'result': {'coreference': [{'representative_id': 0, 'referents': [{'referent_id': 0, 'sentence_id': 0, 'token_id_from': 0, 'token_id_to': 0, 'form': '山田'}, {'referent_id': 1, 'sentence_id': 0, 'token_id_from': 10, 'token_id_to': 10, 'form': '彼'}]}], 'tokens': [['山田', 'くん', 'は', 'カップ', '麺', 'を', '買', 'っ', 'た', '。', '彼', 'は', '美味し', 'そう', 'に', '食べ', 'て', 'い', 'た', '。']]}, 'status': 0, 'message': 'OK'}
$ python main.py 山田君は斉藤君にカップ麺を渡した。彼は美味しそうに食べていた。
{'result': {'coreference': [{'representative_id': 0, 'referents': [{'referent_id': 0, 'sentence_id': 0, 'token_id_from': 0, 'token_id_to': 0, 'form': '山田'}, {'referent_id': 1, 'sentence_id': 0, 'token_id_from': 13, 'token_id_to': 13, 'form': '彼'}]}], 'tokens': [['山田', '君', 'は', '斉藤', '君', 'に', 'カップ', '麺', 'を', '渡', 'し', 'た', '。', '彼', 'は', '美味し', 'そう', 'に', '食べ', 'て', 'い', 'た', '。']]}, 'status': 0, 'message': 'OK'}

Consideration

山田君はカップ麺を買った。彼は美味しそうに食べていた。
では
'coreference': [{'representative_id': 0, 'referents': [{'referent_id': 0, 'sentence_id': 0, 'token_id_from': 0, 'token_id_to': 0, 'form': '山田'}, {'referent_id': 1, 'sentence_id': 0, 'token_id_from': 10, 'token_id_to': 10, 'form': '彼'}]
山田-彼が結びついているのが分かります。

しかし、
山田君は斉藤君にカップ麺を渡した。彼は美味しそうに食べていた。
では
'coreference': [{'representative_id': 0, 'referents': [{'referent_id': 0, 'sentence_id': 0, 'token_id_from': 0, 'token_id_to': 0, 'form': '山田'}, {'referent_id': 1, 'sentence_id': 0, 'token_id_from': 13, 'token_id_to': 13, 'form': '彼'}]
山田-彼が結びついていて斉藤-彼となっていません。
これだとカップ麺を渡しても山田君が食べたことになります。
まさに、剛田思考です

Comparation -> KNP

KNPだったどうかを試してみます。
http://lotus.kuee.kyoto-u.ac.jp/~ryohei/zero_anaphora/index.cgi

こちらは
斉藤-彼
になっているので正しく認識しているっぽいです。

ですが、
山田君は斉藤君にカップ麺を渡した。美味しそうに食べていた。
と代名詞を削除して解析すると、山田-彼となって正しく認識されないです。

Conclusion

今回照応解析したのは直接照応と呼ばれるもので明示的に代名詞が書かれている場合ですが、文章中には書かれていないことがよくあります。
http://adsmedia.hatenablog.com/entry/2017/02/20/084846
間接照応・外界照応・ゼロ照応などがあります。

ゲノムが2000年代に全て解析されたけどprotainってどうやって作っているのかは全てわかっていないです。
型はあるけど組み合わせで無数にできるためです。

自然言語も同様に一つの文章から単語の種類まで判別はできるものの、照応解析のようにまだ調べることが
多いです。
方法の一つとして文章中にない単語を書くにはユーザが各自でソースを集めて機械学習にかけないと厳しいかもしれんす。
いろいろなキャラクターの中で80%の可能性で斉藤君がカップ麺を食べる、のようなイメージです。

PostScript

次は構文解析を使って、分析かプロダクトを作ってみます。