はじめに
SNSの投稿やカスタマーレビューなのユーザーの投稿の感情分析の信頼度をどうやって高められるか?を検証したいと思ったのでプログラムを作成することにしました。
最終的には、LLMと連動した感じで動かしたいなと考えているのですが、今回は、複数のBERTモデルを組み合わせて日本語テキストの感情分析を行う検証プログラムを実装してみました。
テキストがポジティブ、ネガティブ、中立のどの感情を持っているかを分析し、その強度も評価できるようにしてみました。
ソースコード
gistで公開しています。検証するために作成したコードなので適当です。
プログラムについて
-
マルチモデルアプローチ
- 3つの事前学習済みBERTモデルを使用
- モデル間で判定が分かれた場合の特別処理
- 高確信度の結果を優先
-
詳細な感情分析
- ポジティブ/ネガティブ/中立の判定
- 感情の強度評価(Strong/Moderate/Weak)
- スコアの差に基づく信頼性評価
-
その他
- バッチ処理による高速化
- GPU対応
- 複数のJSON形式に対応
- 詳細な分析結果のJSON出力
実装の詳細
1. モデルの設定
プログラムでは以下の3つのBERTモデルを使用しています:
models = {
"bert_japanese_sentiment": {
"model_name": "LoneWolfgang/bert-for-japanese-twitter-sentiment",
},
"koheiduck_bert_japanese_sentiment": {
"model_name": "koheiduck/bert-japanese-finetuned-sentiment",
},
"bert_finetuned_japanese_sentiment": {
"model_name": "christian-phu/bert-finetuned-japanese-sentiment",
},
}
これらのモデルは日本語テキストの感情分析に特化して学習されています。
2. 感情分析の流れ
テキストの読み込みと前処理
def load_texts_from_json(filepath):
"""JSONファイルからテキストリストを読み込む"""
try:
with open(filepath, "r", encoding="utf-8") as f:
json_data = json.load(f)
texts = []
for item in json_data:
if isinstance(item, str):
texts.append(item)
elif isinstance(item, dict) and "text" in item:
texts.append(item["text"])
else:
print(f"Warning: Skipping invalid item format: {item}")
return texts
# 前処理
# この関数で何かしら処理をする
def preprocess_text(texts):
"""テキストの前処理を行う"""
parsed_texts = []
for text_idx, text in enumerate(texts):
lines = []
for txt in text.split("\n"):
txt = txt.strip()
lines.append(txt.strip())
parsed_texts.append("".join(lines))
return parsed_texts
このメソッドは以下のJSON形式に対応しています:
- 文字列の配列:
["テキスト1", "テキスト2"]
- オブジェクトの配列:
[{"text": "テキスト1"}, {"text": "テキスト2"}]
感情分析の実行
感情分析は以下の手順で行われます:
- バッチ処理による予測
def predict_sentiment(model_key, tokenizer, model, texts):
"""感情分析の予測を実行"""
# バッチサイズ32で処理
batch_size = 32
for i in range(0, len(lines), batch_size):
batch_lines = lines[i : i + batch_size]
inputs = tokenizer(
batch_lines,
return_tensors="pt",
padding=True,
truncation=True,
max_length=512,
)
- 感情の評価
def evaluate_sentiment(scores):
"""感情分析スコアを評価して最終的な判定を行う"""
# 閾値の設定、いろいろと調整してみるとよい
STRONG_THRESHOLD = 0.7 # 強い感情
MEDIUM_THRESHOLD = 0.5 # 中程度の感情
SCORE_DIFFERENCE_THRESHOLD = 0.15 # スコアの差
HIGH_CONFIDENCE_THRESHOLD = 0.8 # 高確信度
- 結果の集計
def summarize_sentiments(all_evaluations):
"""全テキストの感情分析結果を集計"""
# 基本的な感情の集計
sentiment_counts = {"positive": 0, "neutral": 0, "negative": 0}
# 感情の強度も含めた詳細な集計
detailed_counts = {
"positive": {"Strong": 0, "Moderate": 0, "Weak": 0},
"neutral": {"Strong": 0, "Moderate": 0, "Weak": 0},
"negative": {"Strong": 0, "Moderate": 0, "Weak": 0},
}
使い方
1. 環境準備
必要なライブラリをインストールします:
pip install torch transformers numpy
2. 入力ファイルの準備
以下のような形式のJSONファイルを用意します:
[
"とても良い一日でした!",
"今日は少し疲れました。",
"特に何も感じません。"
]
3. プログラムの実行
python japanese_sentiment_eveluator.py --jsonfile data/input.json
input.json
は、必ず、data/
ディレクトリの中に保存されている必要があります。
4. 出力結果
プログラムは入力ファイル名に _analysis.json
を付加した名前で結果を出力します。
出力には以下の情報が含まれます:
- メタデータ(分析したテキスト数、使用したモデル)
- 全体の要約(感情の分布、強度の分布)
- 各テキストの詳細な分析結果
コードの展開
コードは検証用で書いたので、今後の展開として以下のことが考えられるかなと思います。
-
LLMとの連携
- LLMを活用したハイブリッド分析
-
モデルの追加
- 事前学習済みモデルの追加
- 特定ドメイン用のファインチューニング
-
処理の最適化
- 並列処理による高速化
- メモリ使用量の最適化
-
機能の拡張
- リアルタイム分析機能
- Web APIとしての実装
- 視覚化機能の追加
まとめ
複数のBERTモデルを組み合わせることで、より信頼性の高い感情分析を実現できているかもと思い検証してみました。LLMによる検証と合わせて結果を評価してみたいなと思います。予定では、SNSの投稿、カスタマーレビューなどの評価に使えるようなイメージで進化させようかなと思います。