じゃらんnetに投稿された宿クチコミを用いた感情極性分析・含意関係認識の一例

より良い顧客体験を生み出すには、カスタマーに好評を博したサービスや製品の特徴や要因を知る必要があります。Megagon Labs Tokyo は旅行情報サイトじゃらんnet』上で公開されている宿泊施設へのクチコミと、それを基に加工・作成した文章にラベル付け(アノテーション)を行ったJapanese Realistic Textual Entailment Corpus (以下JRTEコーパス)を開発し、日本語自然言語処理における学術コミュニティ向けに公開しました。本記事ではJRTEコーパスと、利用例として簡単な機械学習を紹介します。

 

オンラインサービスにおけるクチコミは、サービスや製品の利用を検討しているユーザには不可欠な存在です。土地勘のない地域がどのような特徴をもっているか、初めて利用する施設のどのような点が他者から好評を博しているかといった知識があれば、私たちは納得して選べるようになります。クチコミには様々な感想・意見・要望が含まれていますが、残念ながら大量のクチコミから欲しい情報を素早く得ることは未だに簡単ではありません。この問題を解決していくために知識の自動抽出・整理に役立つコーパスを作ることにしました。

JRTEコーパスの内容

JRTEコーパスには、宿の特徴有無、感情極性、含意関係の3つのラベルが用意されています。このコーパスはこのデータ用に人工的に作られた文ではなく、クチコミとして書かれた文を基にしているのが最大の特徴です。また、一般的にコーパスを利用するには手続きを含め時間を要するものですが、学術目的であれば即時ご利用いただける点においても学術発展観点では価値のある言語資源であると私たちは考えています。

宿の特徴の有無ラベルと感情極性ラベル

宿の特徴が含まれているかどうかを2値で (あり=1, なし=0)、 感情極性ラベルを3値で (ポジティブ=1, ネガティブ=-1, ニュートラル=0 )をラベル付与しています。 それぞれのラベルの分類タスクをRHR, Nと本稿ではよびます。 以下にデータの例を示します。 このデータを使って分類器を構築することで、「好評な宿の特徴に関する言及」を取り出せるようになります。

RET_2
宿の特徴の有無ラベルと感情極性ラベルの例

なお、一般公開されている感情極性ラベル付き日本語コーパスには以下のようなものがあります。

含意関係ラベル

仮説Hが成り立つとき前提Pも常に成り立つかどうか(含意するかどうか)というラベルを2値で (含意=1, 非含意=0) 付与しています。 このラベルの分類タスクをRTEと本稿ではよびます。 以下にデータの例を示します。 このデータを使って分類器を構築することで、「表現は異なるが同じことを述べている言及」を探せるようになります。

「部屋からの眺めが良い」からといってそれは海とは限らないのでラベルは0です。 一方、「部屋はオーシャンビュー」ならば「部屋から海が見える」は含意するのでラベルは1です。

RTE_1
含意関係ラベルの例

なお、一般公開されている含意関係ラベル付き日本語コーパスには以下のようなものがあります。

 

JRTEコーパスの活用例の紹介

モデルの学習

コーパスを使って分類器を作る方法は色々考えられますが、ここでは一般公開されている東北大のBERTモデルをタスクに応じてFine-tuningするという方法を行ってみます。 (BERT自体の解説に関してはオージス総研の解説記事が参考になります)

まず、JRTEコーパスサンプルスクリプトを入手し、ライブラリをインストールします。

$ git clone https://github.com/megagonlabs/jrte-corpus_example 
$  cd jrte-corpus_example 
$ git clone https://github.com/megagonlabs/jrte-corpus 
$ pip3 install poetry 
$ poetry install --no-root 

次に、学習スクリプトでFine-tuningを行ってモデルを作ります。GPU (NVIDIA V100-SXM2)でPN, RHRの学習時間は1分半程度、RTEの学習時間は5分程度でした。

$ poetry run python3 ./train.py -i ./jrte-corpus/data/pn.tsv -o ./model-pn --task pn 
$ poetry run python3 ./train.py -i ./jrte-corpus/data/rhr.tsv -o ./model-rhr --task rhr 
$ poetry run python3 ./train.py -i './jrte-corpus/data/rte.*.tsv' -o ./model-rte --task rte 

モデルの動作確認

ここで、transformer-cliserveを使って分類サーバを立てて、モデルを試してみます。

$ poetry run transformers-cli serve --task sentiment-analysis --model ./model-pn --port 8900 
$ curl -X POST -H "Content-Type: application/json" "http://localhost:8900/forward" -d '{"inputs":["ご飯が美味しいです。", "3人で行きました。" , "部屋は狭かったです。"] }' 
{"output":[{"label":"pos","score":0.8015708923339844},{"label":"neu","score":0.47732535004615784},{"label":"neg","score":0.42699119448661804}]} 

3文の入力に対して、それぞれポジティブ、ニュートラル、ネガティブと、(正しく)ラベルが付与されています。

$ poetry run transformers-cli serve --task sentiment-analysis --model ./model-rhr --port 8901 
$ curl -X POST -H "Content-Type: application/json" "http://localhost:8901/forward" -d '{"inputs":["ご飯が美味しいです。", "3人で行きました。"] }' 
{"output":[{"label":"yes","score":0.9653761386871338},{"label":"no","score":0.8748807907104492}]} 

2文の入力に対して、それぞれ関係あり、関係なしと、(正しく)ラベルが付与されています。

$ poetry run transformers-cli serve --task sentiment-analysis --model ./model-rte --port 8902 
$ curl -X POST -H "Content-Type: application/json" "http://localhost:8902/forward" -d '{"inputs":[["風呂がきれいです。", "食事が美味しいです" ] , [ "暑いです。", "とても暑かった"]] }' 
{"output":[{"label":"NE","score":0.9982748627662659},{"label":"E","score":0.9790723323822021}]} 

2文の文ペアの入力に対して、それぞれ非含意、含意と、(正しく) ラベルが付与されています。 もちろん、あらゆる入力に対して正しいラベルを付与するというわけではなく、誤ったラベルが付与されることもあります。

モデルの性能評価

それでは、評価用データを用いて精度を検証してみましょう。

$ poetry run python3 ./train.py --evaluate -i ./jrte-corpus/data/pn.tsv --base ./model-pn --task pn -o ./model-pn/evaluate_output.txt 
$ awk '{if($1==$2){ok+=1} } END{ print(ok, NR, ok/NR) }' ./model-pn/evaluate_output.txt 
464 553 0.83906 

$ poetry run python3 ./train.py --evaluate -i ./jrte-corpus/data/rhr.tsv --base ./model-rhr --task rhr -o ./model-rhr/evaluate_output.txt 
$ awk '{if($1==$2){ok+=1} } END{ print(ok, NR, ok/NR) } ' ./model-rhr/evaluate_output.txt 
490 553 0.886076 

$ poetry run python3 ./train.py --evaluate -i './jrte-corpus/data/rte.*.tsv' --base ./model-rte --task rte -o ./model-rte/evaluate_output.txt 
$ awk '{if($1==$2){ok+=1} } END{ print(ok, NR, ok/NR) } ' ./model-rte/evaluate_output.txt 
4903 5529 0.886779 

それぞれのモデルのAccuracyを計算することができました。

 

以上、簡単にJRTEコーパスを用いた分類モデルの構築方法の一例をご紹介しました。 モデルの構造やパラメータを工夫したり、間違えやすいデータを別途収集してラベル付けして学習データに追加したりすることで更に精度の向上が図れます。また、JRTEコーパスは日本語のためモデルのエラー解析が容易であり、テキスト分類に馴染みのない方に向けたチュートリアルとしても活用いただけます。

最後に

Megagon Labsは今後も日本語自然言語処理における幅広い学術コミュニティの研究力向上に貢献するため、公的研究機関や大学の研究者や学生の皆さんの活動に有益な研究用データを公開してまいります。

 

Share:

More Blog Posts: