テキストパターン解析によるアスペクトベース感情の効率的な抽出方法
はじめに
顧客レビュー、アンケート回答、SNSでの意見など、テキストデータには製品やサービスに対するユーザーの多様な評価が含まれています。これらの評価を分析する際、単にポジティブかネガティブかを判定するだけでは不十分な場合があります。例えば、「このノートPCのキーボードは打ちやすいが、バッテリー持ちは悪い」というレビューでは、キーボードはポジティブ、バッテリーはネガティブと、異なる対象(アスペクト)に対して異なる感情が述べられています。
このような場合、特定の「アスペクト」(製品の機能、サービスの側面など)がどのような感情と共に語られているかを詳細に把握する「アスペクトベース感情分析(Aspect-Based Sentiment Analysis: ABSA)」が有効です。ABSAは、テキスト中からアスペクトを特定し、さらにそのアスペクトに対する感情(ポジティブ、ネガティブ、ニュートラルなど)を抽出するタスクです。
ABSAを実現するためのアプローチはいくつかありますが、本記事では特に、テキストの構造(単語間の関係性)に着目した「テキストパターン解析」による情報抽出手法に焦点を当てます。Pythonと自然言語処理ライブラリを活用し、具体的なコード例を通して、この手法の実装方法と実務への応用について解説します。
アスペクトベース感情分析におけるパターン解析の基本
アスペクトベース感情分析において、テキストパターン解析が果たす役割は主に以下の2点です。
- アスペクトの特定: テキスト中で、評価の対象となっている名詞や名詞句(例:「カメラ」「バッテリー持ち」「サポート」)を特定します。
- 感情語の特定とアスペクトへの紐付け: 特定されたアスペクトに対して、どのような感情を表す形容詞や動詞(例:「素晴らしい」「ひどい」「速い」「遅い」)が結びついているかを特定し、その関係性を捉えます。
多くの場合、アスペクトとそれに係る感情語は、文中で比較的近くに位置したり、特定の文法的な関係性を持ったりします。例えば、「[アスペクト] は [感情語] です」や、「[感情語] [アスペクト]」といったパターンがよく見られます。これらのパターンを捉えるために、単語の品詞情報や、単語間の依存関係(係り受け構造)が非常に有効です。
依存関係解析とは、文中の単語が文法的にどのように修飾し合ったり、支配し合ったりしているかを解析する技術です。これにより、「バッテリー持ち」という名詞が「悪い」という形容詞の主語となっている、あるいは「悪い」という形容詞が「バッテリー持ち」という名詞を修飾している、といった関係性を構造的に把握できます。
SpaCyを用いた依存関係解析とパターン抽出
Pythonの主要なNLPライブラリであるSpaCyは、高速かつ高精度な依存関係解析機能を提供しており、アスペクトベース感情分析におけるパターン解析に適しています。
SpaCyを使って依存関係を解析する基本的な流れは以下の通りです。
- 日本語モデルをロードする。
- 対象となるテキストをSpaCyで処理し、
Doc
オブジェクトを生成する。 Doc
オブジェクト内の各トークン(単語)の情報を参照する(テキスト、品詞、依存関係ラベル、係り元/係り先など)。
具体的なコードを見てみましょう。
import spacy
# 日本語モデルをロード
# モデルをダウンロードしていない場合は、事前にターミナル等で
# python -m spacy download ja_core_news_sm
# を実行してください。
try:
nlp = spacy.load("ja_core_news_sm")
except OSError:
print("日本語モデル 'ja_core_news_sm' が見つかりません。ダウンロードしてください。")
print("python -m spacy download ja_core_news_sm")
exit()
text = "このスマホのカメラは素晴らしいが、バッテリー持ちはひどいです。"
# SpaCyでテキストを処理
doc = nlp(text)
# 各トークンの情報を表示
print("text\tpos\tdep\thead.text")
print("-" * 30)
for token in doc:
# token.text: 単語テキスト
# token.pos_: 品詞 (Universal POS)
# token.dep_: 依存関係ラベル
# token.head.text: 係り先の単語テキスト
print(f"{token.text}\t{token.pos_}\t{token.dep_}\t{token.head.text}")
実行結果(依存関係ラベルや係り先はモデルバージョンによって異なる場合がありますが、構造は概ね同様です):
text pos dep head.text
------------------------------
この DET det スマホ
スマホ NOUN nsubj 素晴らしい
の ADP case スマホ
カメラ NOUN nsubj 素晴らしい
は ADP case カメラ
素晴らしい ADJ ROOT 素晴らしい
が CCONJ cc 素晴らしい
、 PUNCT punct が
バッテリー NOUN compound 持ち
持ち NOUN nsubj ひどい
は ADP case 持ち
ひどい ADJ conj 素晴らしい
です AUX aux ひどい
。 PUNCT punct です
この結果から、「カメラ」と「素晴らしい」がどちらも「素晴らしい」に係っていること、「バッテリー持ち」と「ひどい」が「ひどい」に係っていることが分かります。より詳細な依存関係を追うことで、アスペクト(名詞)とそれに修飾される感情語(形容詞など)のペアを抽出できます。
アスペクトと感情語のペア抽出ロジック
アスペクトと感情語のペアを抽出するための基本的なロジックは、依存関係グラフ上でアスペクト候補(名詞など)と感情語候補(形容詞など)の関係性を探索することです。
よくあるパターンとして、以下が考えられます。
- アスペクト(名詞)が感情語(形容詞)の主語(
nsubj
など)になっている。 - 感情語(形容詞)がアスペクト(名詞)を直接修飾している(形容詞+名詞)。
- アスペクトと感情語が、助詞などを介して係り合っている。
今回は、シンプルに「名詞が、それに係っている形容詞や形容動詞の主語となっているパターン」、または「名詞が、それに係っている形容詞や形容動詞によって修飾されているパターン」を抽出してみましょう。
まず、アスペクト候補として名詞、感情語候補として形容詞や形容動詞を特定します。そして、それぞれの候補間で依存関係を調べます。
def extract_aspect_sentiment_pairs(doc):
"""
SpaCy Docオブジェクトからアスペクトと感情語のペアを抽出する
簡単なパターンマッチングによる
"""
pairs = []
aspect_candidates = [token for token in doc if token.pos_ in ["NOUN", "PROPN"]] # 名詞、固有名詞をアスペクト候補に
sentiment_candidates = [token for token in doc if token.pos_ in ["ADJ", "ADV", "VERB", "AUX"]] # 形容詞、副詞、動詞、助動詞を感情語候補に (広めに取る)
for aspect in aspect_candidates:
# アスペクトに直接係っている単語を調べる
for child in aspect.children:
# 子要素が感情語候補かつ、アスペクトがその感情語のnsubjになっている場合
if child in sentiment_candidates and aspect.dep_ in ["nsubj", "obl", "obj", "iobj"] and child.head == aspect:
# このパターンは逆に、形容詞が名詞を修飾している場合が多い
# ここではシンプルに「アスペクトに直接係っている感情語候補」をペアとする
# 依存関係の種類によってはより複雑な判定が必要
pairs.append((aspect.text, child.text, child.dep_)) # (アスペクト, 感情語, 依存関係ラベル)
# アスペクトの係り先(head)の単語を調べる
head = aspect.head
# 係り先が感情語候補の場合
if head in sentiment_candidates:
# アスペクトがその感情語の主語になっている場合など
if aspect.dep_ in ["nsubj", "obl", "obj", "iobj"] and head.dep_ == "ROOT" or head.dep_ == "conj": # 主語や目的語などとして係っていて、係り先が文の根や並列関係の場合
pairs.append((aspect.text, head.text, aspect.dep_)) # (アスペクト, 感情語, 依存関係ラベル)
# 感情語がアスペクトを修飾している場合 (例: 「良い カメラ」)
elif head.dep_ == "amod" and head in sentiment_candidates: # 形容詞などによる名詞修飾
pairs.append((aspect.text, head.text, head.dep_))
# シンプルな辞書による感情極性判定(ここでは例として簡単な辞書を使用)
# 実際にはより網羅的で洗練された感情辞書や機械学習モデルが必要です
sentiment_dict = {
"素晴らしい": "Positive", "ひどい": "Negative", "良い": "Positive", "悪い": "Negative",
"速い": "Positive", "遅い": "Negative", "高い": "Negative", "安い": "Positive",
"使いやすい": "Positive", "使いにくい": "Negative"
}
result = []
for aspect, sentiment_word, dep in pairs:
polarity = sentiment_dict.get(sentiment_word, "Neutral")
result.append({
"aspect": aspect,
"sentiment_word": sentiment_word,
"dependency_label": dep,
"polarity": polarity
})
return result
# テキストを処理してペアを抽出
doc = nlp(text)
extracted_info = extract_aspect_sentiment_pairs(doc)
print("\nExtracted Aspect-Sentiment Pairs:")
for item in extracted_info:
print(item)
上記のコードは簡略化されたパターンマッチングですが、「カメラ」と「素晴らしい」、「バッテリー持ち」と「ひどい」といったペアを抽出できる可能性があります。抽出されたペアに対して、別途用意した感情辞書や機械学習モデルを用いて感情極性を判定することで、アスペクトごとの感情を特定します。
例として、上記コードを実行すると(モデルの特性により変動し得ますが)、「カメラ」が「素晴らしい」に係り、その関係性が抽出され、感情極性が「Positive」と判定される可能性があります。「バッテリー持ち」についても同様です。
実務への応用
このパターン解析に基づくアスペクトベース感情抽出手法は、以下のような実務課題に応用できます。
- 顧客レビュー分析: 大量の製品レビューから、個別の機能(ディスプレイ、性能、デザインなど)に対するユーザーの評価(良い、悪い)を自動的に抽出し、製品改善やマーケティング戦略の立案に役立てる。
- アンケート自由回答の分析: サービスに関するアンケートの自由記述欄から、特定の項目(例:サポート対応、価格、使いやすさ)に対する意見を収集・分析する。
- SNSトレンド分析: 特定のブランドやイベントに関するSNS上の投稿から、注目されている側面やそれに対する世論(ポジティブ/ネガティブ)をリアルタイムに把握する。
- 議事録からの論点抽出: 会議の議事録から、特定の議題(アスペクト)に対する参加者の賛否や意見(感情や評価)を抽出する。
考慮事項と限界
テキストパターン解析によるアスペクトベース感情抽出はシンプルで直感的ですが、いくつかの考慮事項と限界があります。
- パターンの網羅性: 人間の言語表現は多様であり、定義したパターンだけでは全てのアスペクト-感情ペアを捕捉することは困難です。特に比喩、皮肉、遠回しな表現などには対応しきれません。
- 依存関係解析の精度: NLPライブラリによる依存関係解析の精度に影響されます。解析が間違っている場合、正しいペアを抽出できません。
- 感情辞書の質: 使用する感情辞書の網羅性や極性定義の適切さが、感情判定の精度に直結します。ドメイン固有の感情表現に対応するためには、専用の辞書が必要になる場合があります。
- 文脈依存性: 同じ単語でも文脈によって意味や感情が変わることがあります(例:「速い」が肯定的な場合と否定的な場合)。パターンだけでは文脈を捉えきれないことがあります。
- ルールのメンテナンス: 定義したパターンや辞書は、新しい表現や流行に応じて継続的にメンテナンスする必要があります。
より高度なアスペクトベース感情分析を実現するためには、本手法をベースとしつつ、機械学習モデル(例:Transformerベースのモデルを使った分類や系列ラベリング)や、より洗練されたルールベースのアプローチ(構文解析ツリーのトラバーサル、より複雑なパターンの定義)を組み合わせることも検討すべきです。
まとめ
本記事では、テキストパターン、特に単語間の依存関係を利用したアスペクトベース感情の抽出手法について解説しました。PythonとSpaCyを用いることで、テキストから評価対象(アスペクト)とそれに対する感情語を特定し、アスペクトごとの感情を分析するための基礎を築くことができます。
この手法は、比較的少ない教師データでも実装可能であり、特定の明確な表現パターンが多いドメインにおいては強力なツールとなります。一方で、言語の多様性に対応するためには、パターンの拡張や他の手法との組み合わせが重要です。
実務でテキストデータからより詳細な情報を引き出したいとお考えのエンジニアの皆様にとって、本記事がアスペクトベース感情分析への第一歩となる知識や実装のヒントとなれば幸いです。