mcpField

Sentiment Analyzer

github.com/eddiebe147データ・データベース47 回インストール
リポジトリ

Sentiment Analyzer について

Sentiment Analyzerは、基本的な極性分類からアスペクト別の感情分析や感情検出まで、テキスト分析の手法選択とワークフロー構築を支援するスキルです。データや精度要件に応じて、ルールベース、事前学習済みモデル、ファインチューニング、LLMを比較できます。

主な機能

  1. 01分析手法とトレードオフの比較
  2. 02感情分析パイプラインと前処理の計画
  3. 03アスペクト別の感情分析
  4. 04時間やグループごとの感情追跡
  5. 05感情、皮肉、比較表現の検出
  6. 06結果の検証と不確実性の報告

活用シーン

  1. 01SNSやレビュー向け手法の選定
  2. 02製品の特定機能に対する感情の把握
  3. 03複数文書における意見の推移追跡
  4. 04人手で曖昧な予測を確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/eddiebe147/claude-settings --skill sentiment-analyzer

インストール後、Claude Code で/sentiment-analyzerを入力して読み込まれたか確認します。

詳細

感情分析

感情分析スキルは、テキストに含まれる感情のトーンや意見を理解する感情分析システムの実装を案内します。シンプルなポジティブ/ネガティブ分類から、きめ細かなアスペクトベースの感情分析や感情検出まで、このスキルでは感情分析機能の全領域を扱います。

感情分析は、見かけ以上に複雑です。皮肉、文脈、ドメイン固有の言葉遣い、文化的なニュアンスは、いずれも単純な手法では対応が難しい要素です。このスキルでは、精度要件に応じて、処理が速いルールベースのシステム、ファインチューニング済み分類器、LLM ベースの分析など、適切な手法を選ぶ方法を説明します。

顧客レビュー、ソーシャルメディアでの言及、サポートチケット、アンケートの回答を分析する場合でも、このスキルを活用すれば、ユーザーの真の声を捉えた感情分析を実現できます。

主なワークフロー

ワークフロー 1:感情分析の手法を選ぶ
  1. 要件を定義します。
    • 粒度:2 クラス、3 クラス、連続値のいずれですか?
    • アスペクト:全体分析ですか、アスペクトベースですか?
    • 感情:感情極性ですか、特定の感情ですか?
    • 言語:単一言語ですか、多言語ですか?
    • 量:バッチ処理ですか、リアルタイム処理ですか?
  2. 選択肢を評価します。
    手法速度精度カスタマイズ性最適な用途
    ルールベース(VADER)非常に高速中程度限定的ソーシャルメディア、簡易分析
    事前学習済み(RoBERTa)高速良好ファインチューニング可能一般的なテキスト
    ファインチューニング済み高速最良データが必要ドメイン固有
    LLM(GPT-4、Claude)低速非常に優秀プロンプトベースきめ細かな分析、複雑な分析
  3. トレードオフに基づいて選択します。
  4. 実装を計画します。
ワークフロー 2:感情分析パイプラインを実装する
  1. テキストを前処理します。
    def preprocess_for_sentiment(text):
        # Preserve sentiment-relevant features
        text = normalize_unicode(text)
    
        # Handle social media conventions
        text = expand_contractions(text)  # don't -> do not
        text = normalize_elongation(text)  # loooove -> love
        text = handle_negation(text)       # Mark negation scope
    
        # Preserve but normalize emoji/emoticons
        text = convert_emoji_to_text(text)  # :) -> [HAPPY]
    
        return text
    
  2. 感情を分析します。
    class SentimentAnalyzer:
        def __init__(self, model_type="transformer"):
            if model_type == "transformer":
                self.model = pipeline("sentiment-analysis",
                                    model="cardiffnlp/twitter-roberta-base-sentiment")
            elif model_type == "vader":
                self.model = SentimentIntensityAnalyzer()
    
        def analyze(self, text):
            preprocessed = preprocess_for_sentiment(text)
            result = self.model(preprocessed)
            return {
                "text": text,
                "sentiment": result["label"],
                "confidence": result["score"]
            }
    
  3. 洞察を得るために集計します。
    • 感情の全体的な分布
    • 時系列での感情の変化
    • セグメント/トピック別の感情
  4. 結果を検証します。
ワークフロー 3:アスペクトベースの感情分析
  1. 追跡するアスペクトを特定します。
    • 製品の特徴(価格、品質、サービス)
    • 体験の側面(速度、精度、親しみやすさ)
    • ドメインに合わせたカスタムアスペクト
  2. テキストからアスペクトを抽出します。
    def extract_aspects(text, aspect_list):
        # Find mentions of known aspects
        found_aspects = []
        for aspect in aspect_list:
            if aspect.lower() in text.lower():
                found_aspects.append(aspect)
    
        # Also extract using NER or LLM for unknown aspects
        extracted = extract_noun_phrases(text)
        return found_aspects + extracted
    
  3. アスペクトごとに感情を分析します。
    def aspect_sentiment(text, aspects):
        results = {}
        for aspect in aspects:
            # Extract sentences mentioning aspect
            relevant = extract_aspect_context(text, aspect)
    
            # Analyze sentiment of relevant text
            if relevant:
                sentiment = analyze_sentiment(relevant)
                results[aspect] = sentiment
    
        return results
    
  4. ドキュメント全体にわたるアスペクト別の感情を集計します。

クイックリファレンス

アクションコマンド/トリガー
感情を分析する「[テキスト]の感情を分析」
手法を選ぶ「[ユースケース]に最適な感情分析」
アスペクトベース分析「[レビュー]の特徴別の感情」
感情を検出する「[テキスト]の感情を検出」
皮肉に対処する「感情分析で皮肉に対処する方法」
結果を集計する「感情の傾向を要約」

ベストプラクティス

  • 感情の手がかりを保持する:重要な手がかりが失われるような前処理は避けてください。

    • 句読点を保持します(!! と . の違い)。
    • 大文字・小文字のパターンを保持します。
    • 絵文字/顔文字を保持します(テキストに変換)。
    • 否定表現を明示的に処理します。
  • モデルをドメインに合わせる:事前学習済みモデルにはドメインによる偏りがあります。

    • Twitter 向けモデルと製品レビュー向けモデルでは、動作が異なります。
    • ファインチューニングするか、ドメインに適したモデルを選びます。
    • デプロイ前に、実際のデータでテストします。
  • 否定表現を適切に処理する:「悪くない」はネガティブではありません。

    • ルールベース:否定の作用範囲を示します。
    • ニューラルモデル:通常は自動的に処理します。
    • 否定表現のケースを明示的にテストします。
  • 文脈を考慮する:感情は文脈によって変わります。

    • 「安い」は、低価格帯の商品ではポジティブ、高級品ではネガティブです。
    • ニュアンスを捉えるには、アスペクトベースの分析を使用します。
    • 可能であれば、周囲の文脈も含めます。
  • 人間による検証を行う:機械による感情分析と人間による感情分析は同じではありません。

    • サンプルを抽出し、結果を手動で検証します。
    • 一致度の指標を計算します。
    • 不一致を踏まえて反復的に改善します。
  • 不確実性を報告する:すべてのテキストに明確な感情が含まれるわけではありません。

    • ニュートラルは有効なクラスです。
    • 信頼度の低い予測にはフラグを付けます。
    • あいまいなケースでは、予測を控えることも検討します。

高度な手法

LLM を使ったきめ細かな感情分析

複雑な分析には言語モデルを使用します。

def llm_sentiment_analysis(text, aspects=None):
    prompt = f"""Analyze the sentiment of the following text.

Text: "{text}"

Provide:
1. Overall sentiment (positive/negative/neutral/mixed)
2. Confidence (0-1)
3. Key positive aspects mentioned
4. Key negative aspects mentioned
5. Notable emotional tones (joy, frustration, surprise, etc.)

{"Also rate sentiment specifically for these aspects: " + ", ".join(aspects) if aspects else ""}

Respond in JSON format."""

    response = llm.complete(prompt)
    return json.loads(response)
感情検出

ポジティブ/ネガティブを超えて、具体的な感情を検出します。

from transformers import pipeline

# Multi-label emotion classification
emotion_classifier = pipeline(
    "text-classification",
    model="SamLowe/roberta-base-go_emotions",
    top_k=None
)

def detect_emotions(text):
    results = emotion_classifier(text)[0]
    # Filter to significant emotions
    significant = [r for r in results if r["score"] > 0.1]
    return sorted(significant, key=lambda x: x["score"], reverse=True)

# Example output:
# [{"label": "admiration", "score": 0.45},
#  {"label": "joy", "score": 0.32},
#  {"label": "gratitude", "score": 0.28}]
比較感情分析

感情の比較を検出します。

def comparative_sentiment(text):
    """
    Detect: "A is better than B" patterns
    """
    prompt = f"""Analyze this text for comparative sentiment.

Text: "{text}"

If the text compares entities, identify:
1. Entity A (the preferred/better one)
2. Entity B (the less preferred/worse one)
3. Dimension of comparison (price, quality, etc.)
4. Strength of preference (slight, moderate, strong)

If no comparison, respond with: {{"comparison": false}}

Respond in JSON."""

    return llm.complete(prompt)
感情の時系列追跡

時間の経過に伴う感情を分析します。

def sentiment_timeline(documents, time_field, window="day"):
    """
    Track sentiment trends over time.
    """
    # Analyze each document
    results = []
    for doc in documents:
        sentiment = analyze_sentiment(doc["text"])
        results.append({
            "timestamp": doc[time_field],
            "sentiment": sentiment["score"],
            "text": doc["text"]
        })

    # Aggregate by time window
    df = pd.DataFrame(results)
    df["window"] = df["timestamp"].dt.floor(window)

    trends = df.groupby("window").agg({
        "sentiment": ["mean", "std", "count"],
        "text": lambda x: list(x)[:3]  # Sample texts
    })

    return trends
皮肉の検出

感情分析の前に皮肉に対処します。

def detect_sarcasm(text):
    """
    Detect potential sarcasm indicators.
    """
    indicators = {
        "exaggeration": bool(re.search(r'\b(best|worst|ever|always|never)\b', text.lower())),
        "air_quotes": '"' in text,
        "ellipsis": "..." in text,
        "positive_negative_mix": has_mixed_signals(text),
        "hashtags": "#sarcasm" in text.lower() or "#not" in text.lower()
    }

    # Use model for detection
    sarcasm_score = sarcasm_model.predict(text)

    return {
        "is_sarcastic": sarcasm_score > 0.5,
        "confidence": sarcasm_score,
        "indicators": indicators
    }

def sentiment_with_sarcasm(text):
    sarcasm = detect_sarcasm(text)
    base_sentiment = analyze_sentiment(text)

    if sarcasm["is_sarcastic"] and sarcasm["confidence"] > 0.7:
        # Flip sentiment
        return flip_sentiment(base_sentiment)
    return base_sentiment

避けるべきよくある落とし穴

  • ドメイン固有のテキストに汎用モデルを使用する
  • 感情に関連する特徴(絵文字、句読点)を前処理で取り除く
  • 否定の処理を無視する
  • 中立を、意見がない状態と明示的な中立状態の区別なく扱う
  • モデルの出力を人間の判断と照らし合わせて検証しない
  • データに皮肉が含まれないと思い込む
  • 集計時に極端な感情を過度に重視する
  • 確信度や不確実性を示さずに感情を報告する

コメント