センチメント分析
センチメント分析とは、ブログやSNSなどWeb上で収集できるデータを使って、個人の感情について分析することです。それぞれの文書がポジティブかネガティブかをクラス分けし、それらを膨大に集めることで、利用者が持っている商品に対する感情を知ることができます。
センチメント分析は、Hugging FaceのTransformersライブラリで試せるので、その方法を説明します。以降では、Google Colabを想定しています。
前準備
まずは、Transformersライブラリをインストールします。
!pip install transformers
!pip install fugashi # MeCabのラッパー(日本語のセンチメント分析で使用)
!pip install ipadic # IPA辞書(日本語のセンチメント分析で使用)
transformersでセンチメント分析
Transformersライブラリには、pipelineと呼ばれるAPIが用意されており、これを使うことで僅か2行でセンチメント分析を試すことができます。pipeline自体はセンチメント分析以外の様々なタスクのインスタンス化にも対応しており、センチメント分析を使用するときは、引数として"sentiment-analysis"を渡します。
from transformers import pipeline
classifier = pipeline("sentiment-analysis")
sentence = "I want to learn robotics"
result = classifier(sentence)[0]
print(f"label: {result['label']}, with score: {round(result['score'], 4)}")
# 出力
label: POSITIVE, with score: 0.9273
pipelineでインスタンス化した分類器(classifiler)に、文章を入力したときの結果をresultに格納してます。出力は上記の通りで、ポジティブとして認識されました。入力した文章("I want to learn robotics")には明示的に感情を表す語彙は入っていませんが、ポジティブとネガティブの2分類なら、圧倒的ポジティブ発言であることは間違いないことは何方も理解できるでしょう。分類器も正しく認識してくれました。
日本語で試す方法
日本語の文章に対してセンチメント分析をしてみましょう。日本語でセンチメント分析をする際は、追加でfugashiとipadicをインストールする必要があります。インストールしていない方はインストールしておきましょう。
先ほど、pipelineの引数に"sentiment-analysis"だけを渡しましたが、日本を扱うには、その他に、modelとtokenizerを渡す必要があります。
tokenizerとは
推論モデルに入力するデータは意味ごとに分割された文字列(=トークン)である必要があります。英語であれば、単語間に空白があるので、空白で分割して入力するだけですが、日本語の場合は単語間に空白が無いので、なんらかの仕組みを使ってトークン化する必要があります。
例えば、「明日は晴れです」は「明日/は/晴れ/です」のように分割する必要があるのです。
そして、トークン化の際は専用のライブラリを使うことで実現でき、日本語のトークン化ではMeCabと呼ばれるライブラリが一般的に使用されます。
ここでは、MeCabのラッパーのfugashiと、辞書のipadicが必要になるので、前準備でインストールしました。
日本を試すには、modelとtokenizerとして、"daigo/bert-base-japanese-sentiment"を指定する必要があります。なぜmodelとtokenizerに同じものを与えているのか疑問を持つと思いますが、それは内部的に上手くやってくれているということで、ここでは気にしないことにします。
以下は、2つの文章を入力して、それぞれ分類結果を表示するプログラムです。
from transformers import pipeline
classifier = pipeline(
task="sentiment-analysis",
model="daigo/bert-base-japanese-sentiment",
tokenizer="daigo/bert-base-japanese-sentiment"
)
sentence1 = "嬉しいです"
sentence2 = "残念です"
result1 = classifier(sentence1)[0]
result2 = classifier(sentence2)[0]
print(f"label: {result1['label']}, with score: {round(result1['score'], 4)}")
print(f"label: {result2['label']}, with score: {round(result2['score'], 4)}")
# 出力
label: ポジティブ, with score: 0.8611
label: ネガティブ, with score: 0.9846
正しく認識されました!
少し長い文章のセンチメント分析をしてみます。
入力した文章は文才の無い私が適当に作成したもので、片方の文章はネガティブな中で前向きな発言をした例(のつもり)で、もう片方は、ネガティブな中で後ろ向きな発言をした例(のつもり)です。入力文章と結果を以下の表に示します。
入力文章 | 識別結果 | スコア |
ここ数日は雨が続いていて、やる気がおきず進捗なし。明日は天気になってほしい。 | ポジティブ | 0.9442 |
ここ数日は雨が続いていて、やる気がおきず進捗なし。きっと明日も雨だろう。 | ネガティブ | 0.8824 |
私の意図を正しく理解してくれたのか、それとも偶然か分かりませんが、一応私の望み通りの認識をしてくれました。もっと長い文章で感情認識をできると、面白いかもしれませんね。長い文章を色々な長さで区切って、文全体としての感情や、部分部分における感情などを出力できるプログラムを作るのも楽しいかもしれません。