開発環境
環境構築
以下で環境構築をして、必要なライブラリをインストールします
uv venv
.\.venv\Scripts\activate
uv pip install torch --index-url https://download.pytorch.org/whl/cu124
uv pip install transformers pandas deberta-emotion-predictor
ラベル判定
以下のように引数から指定したテキストを判定するコードを作成します
import argparse
import torch
from deberta_emotion_predictor import DeBERTaEmotionPredictor
import warnings
import os
import sys
class EmotionAnalyzer:
"""
日本語テキストの感情分析を行うための本番用クラス。
モデルのロードを一度だけ行い、複数のテキストを効率的に処理します。
"""
def __init__(self, device: str = None, verbose: bool = True):
"""
アナライザーを初期化し、モデルをメモリにロードします。
Args:
device (str, optional): 使用するデバイス ('cuda' or 'cpu')。Noneの場合は自動検出。
verbose (bool, optional): モデルロード時にメッセージを表示するかどうか。
"""
self.verbose = verbose
if self.verbose:
print("--- 感情分析モデルの準備を開始 ---")
try:
if device is None:
self.device = "cuda" if torch.cuda.is_available() else "cpu"
else:
self.device = device
if self.verbose:
print(f"使用デバイス: {self.device}")
print("モデルをロードしています...(初回はダウンロードに時間がかかります)")
self.predictor = DeBERTaEmotionPredictor(device=self.device)
# 感情ラベルと確率カラム名をクラス変数として定義
self.emotion_labels = ['Joy', 'Sadness', 'Anticipation', 'Surprise', 'Anger', 'Fear', 'Disgust', 'Trust']
self.prob_columns = [f"{label}_positive_probability" for label in self.emotion_labels]
if self.verbose:
print("--- モデル準備完了 ---")
except Exception as e:
print(f"モデルの初期化中に致命的なエラーが発生しました: {e}", file=sys.stderr)
# モデルロードの失敗は致命的なので、プログラムを終了させる
raise
def analyze(self, text: str) -> list[tuple[str, float]]:
"""
単一のテキストから感情を分析し、結果を確率の高い順に返します。
Args:
text (str): 分析したい日本語の文章。
Returns:
list[tuple[str, float]]: (感情ラベル, 確率) のタプルが格納されたリスト。
例: [('Joy', 0.98), ('Trust', 0.01), ...]
"""
if not isinstance(text, str) or not text.strip():
return []
try:
results_df = self.predictor.predict_emotions(text)
if results_df.empty:
return []
result_series = results_df.iloc[0]
# 扱いやすいように、簡単な感情名と確率のペアを作成
emotion_probabilities = {}
for label, col_name in zip(self.emotion_labels, self.prob_columns):
emotion_probabilities[label] = result_series[col_name]
# 確率の高い順にソートしてリストとして返す
sorted_results = sorted(emotion_probabilities.items(), key=lambda item: item[1], reverse=True)
return sorted_results
except Exception as e:
print(f"テキスト「{text[:30]}...」の推論中にエラーが発生しました: {e}", file=sys.stderr)
return []
def main():
"""
コマンドラインからテキストを受け取り、感情分析を実行して結果を表示するメイン関数。
"""
parser = argparse.ArgumentParser(
description="日本語テキストから8つの感情を分析します(本番用コード)。",
formatter_class=argparse.RawTextHelpFormatter # ヘルプの改行を保持
)
parser.add_argument(
"text",
nargs='*', # 複数のテキスト引数を受け取れるようにする
default=[],
help="分析したい日本語の文章。複数指定可能。\n例: \"これは嬉しい\" \"なんてことだ\""
)
parser.add_argument(
"-f", "--file",
type=str,
help="テキストが1行ずつ書かれたファイルへのパス。\nファイル内の各行を個別に分析します。"
)
args = parser.parse_args()
# テキストが一つも指定されなかった場合は使い方を表示して終了
if not args.text and not args.file:
parser.print_help()
print("\nエラー: 分析対象のテキストを引数で指定するか、--fileオプションでファイルを指定してください。")
return
try:
analyzer = EmotionAnalyzer()
except Exception:
print("アナライザーの起動に失敗したため、処理を終了します。", file=sys.stderr)
return
texts_to_process = args.text
if args.file:
try:
with open(args.file, 'r', encoding='utf-8') as f:
# ファイルから読み込んだ各行の改行文字などを除去し、空行は無視する
texts_to_process.extend([line.strip() for line in f if line.strip()])
except FileNotFoundError:
print(f"エラー: 指定されたファイルが見つかりません: {args.file}", file=sys.stderr)
return
# 2. テキストごとに感情を分析し、結果を表示
for i, text in enumerate(texts_to_process):
print("\n" + "#"*50)
print(f"分析対象 {i+1}: 「{text}」")
print("#"*50)
results = analyzer.analyze(text)
if results:
top_label, top_score = results[0]
print(f" 最も可能性の高い感情: {top_label} ({top_score:.2%})")
print("\n --- 各感情の確率 ---")
for label, score in results:
print(f" - {label:<15}: {score:.2%}")
else:
print(" 感情を判定できませんでした。")
print("#"*50)
if __name__ == '__main__':
main()
以下のように実行します
python .\text_emotion_recognition_koala.py "ストラッ トフォード・オン・エイヴォンは、シェイクスピアの生まれたところですが、毎年多くの観光客が訪れます。"
結果は以下のようになります
################################################## 分析対象 1: 「ストラットフォード・オン・エイヴォンは、シェイクスピアの生まれたところですが、毎年多くの観光客が訪れます。」 ################################################## 感情:Joy の推論を開始 (1/1) 感情:Sadness の推論を開始 (1/1) 感情:Anticipation の推論を開始 (1/1) 感情:Surprise の推論を開始 (1/1) 感情:Anger の推論を開始 (1/1) 感情:Fear の推論を開始 (1/1) 感情:Disgust の推論を開始 (1/1) 感情:Trust の推論を開始 (1/1) 最も可能性の高い感情: Surprise (59.25%) --- 各感情の確率 --- - Surprise : 59.25% - Anticipation : 2.84% - Joy : 0.57% - Fear : 0.43% - Sadness : 0.30% - Disgust : 0.23% - Trust : 0.12% - Anger : 0.01% ##################################################