关于 Sentiment Analysis
用于分析文本情绪和观点的技能,适用于反馈、评论与品牌分析。介绍词典、机器学习、深度学习、方面级及多语言方法,并列出可生成的分析结果。
主要功能
- 01词典与机器学习方法
- 02深度学习与混合方法
- 03正面、负面、中性和混合分类
- 04方面级与多语言分析
- 05置信度评分与趋势可视化
适用场景
- 01分析客户反馈
- 02监测产品评论
- 03评估社交媒体情绪
- 04追踪品牌认知
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ aj-geddes/ useful-ai-prompts --skill sentiment-analysis安装后在 Claude Code 中输入/sentiment-analysis确认已加载。
附带文件templates/notebook-template.pyscripts/scaffold-analysis.sh
详细介绍
情感分析
概述
情感分析用于确定文本中的情绪倾向和观点,从而了解客户满意度、品牌认知并分析反馈。
方法
- 基于词典:使用情感词典
- 机器学习:使用标注数据训练分类器
- 深度学习:利用神经网络识别复杂模式
- 基于方面:分析针对特定特征的情感
- 多语言:分析非英语文本
情感类型
- 正面:赞许、满意
- 负面:不赞许、不满意
- 中性:陈述事实,没有明确情感
- 混合:多种情感并存
使用 Python 实现
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
import re
from collections import Counter
# Sample review data
reviews_data = [
"This product is amazing! I love it so much.",
"Terrible quality, very disappointed.",
"It's okay, nothing special.",
"Best purchase ever! Highly recommend.",
"Worst product I've ever bought.",
"Pretty good, satisfied with the purchase.",
"Excellent service and fast delivery.",
"Poor quality and bad customer support.",
"Not bad, does what it's supposed to.",
"Absolutely fantastic! Five stars!",
"Mediocre product, expected better.",
"Love everything about this!",
"Complete waste of money.",
"Good value for the price.",
"Very satisfied, will buy again!",
"Horrible experience from start to finish.",
"It works as described.",
"Outstanding quality and design!",
"Disappointed with the results.",
"Perfect! Exactly what I wanted.",
]
sentiments = [
'Positive', 'Negative', 'Neutral', 'Positive', 'Negative',
'Positive', 'Positive', 'Negative', 'Neutral', 'Positive',
'Negative', 'Positive', 'Negative', 'Positive', 'Positive',
'Negative', 'Neutral', 'Positive', 'Negative', 'Positive'
]
df = pd.DataFrame({'review': reviews_data, 'sentiment': sentiments})
print("Sample Reviews:")
print(df.head(10))
# 1. Lexicon-based Sentiment Analysis
from nltk.sentiment import SentimentIntensityAnalyzer
try:
import nltk
nltk.download('vader_lexicon', quiet=True)
sia = SentimentIntensityAnalyzer()
df['vader_scores'] = df['review'].apply(lambda x: sia.polarity_scores(x))
df['vader_compound'] = df['vader_scores'].apply(lambda x: x['compound'])
df['vader_sentiment'] = df['vader_compound'].apply(
lambda x: 'Positive' if x > 0.05 else ('Negative' if x < -0.05 else 'Neutral')
)
print("\n1. VADER Sentiment Scores:")
print(df[['review', 'vader_compound', 'vader_sentiment']].head())
except:
print("NLTK not available, skipping VADER analysis")
# 2. Textblob Sentiment (alternative)
try:
from textblob import TextBlob
df['textblob_polarity'] = df['review'].apply(lambda x: TextBlob(x).sentiment.polarity)
df['textblob_sentiment'] = df['textblob_polarity'].apply(
lambda x: 'Positive' if x > 0.1 else ('Negative' if x < -0.1 else 'Neutral')
)
print("\n2. TextBlob Sentiment Scores:")
print(df[['review', 'textblob_polarity', 'textblob_sentiment']].head())
except:
print("TextBlob not available")
# 3. Feature Extraction for ML
vectorizer = TfidfVectorizer(max_features=100, stop_words='english')
X = vectorizer.fit_transform(df['review'])
y = df['sentiment']
print(f"\n3. Feature Matrix Shape: {X.shape}")
print(f"Features extracted: {len(vectorizer.get_feature_names_out())}")
# 4. Machine Learning Model
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# Naive Bayes classifier
nb_model = MultinomialNB()
nb_model.fit(X_train, y_train)
y_pred = nb_model.predict(X_test)
print("\n4. Machine Learning Results:")
print(f"Accuracy: {accuracy_score(y_test, y_pred):.2f}")
print("\nClassification Report:")
print(classification_report(y_test, y_pred))
# 5. Sentiment Distribution
fig, axes = plt.subplots(2, 2, figsize=(14, 8))
# Distribution of sentiments
sentiment_counts = df['sentiment'].value_counts()
axes[0, 0].bar(sentiment_counts.index, sentiment_counts.values, color=['green', 'red', 'gray'], alpha=0.7, edgecolor='black')
axes[0, 0].set_title('Sentiment Distribution')
axes[0, 0].set_ylabel('Count')
axes[0, 0].grid(True, alpha=0.3, axis='y')
# Pie chart
axes[0, 1].pie(sentiment_counts.values, labels=sentiment_counts.index, autopct='%1.1f%%',
colors=['green', 'red', 'gray'], startangle=90)
axes[0, 1].set_title('Sentiment Proportion')
# VADER compound scores distribution
if 'vader_compound' in df.columns:
axes[1, 0].hist(df['vader_compound'], bins=20, color='steelblue', edgecolor='black', alpha=0.7)
axes[1, 0].axvline(x=0.05, color='green', linestyle='--', label='Positive threshold')
axes[1, 0].axvline(x=-0.05, color='red', linestyle='--', label='Negative threshold')
axes[1, 0].set_xlabel('VADER Compound Score')
axes[1, 0].set_ylabel('Frequency')
axes[1, 0].set_title('VADER Score Distribution')
axes[1, 0].legend()
# Confusion matrix
cm = confusion_matrix(y_test, y_pred)
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=axes[1, 1],
xticklabels=np.unique(y_test), yticklabels=np.unique(y_test))
axes[1, 1].set_title('Classification Confusion Matrix')
axes[1, 1].set_ylabel('True Label')
axes[1, 1].set_xlabel('Predicted Label')
plt.tight_layout()
plt.show()
# 6. Most Informative Features
feature_names = vectorizer.get_feature_names_out()
# Get feature importance from Naive Bayes
for sentiment_class, idx in enumerate(np.unique(y)):
class_idx = list(np.unique(y)).index(idx)
top_features_idx = np.argsort(nb_model.feature_log_prob_[class_idx])[-5:]
print(f"\nTop features for '{idx}':")
for feature_idx in reversed(top_features_idx):
print(f" {feature_names[feature_idx]}")
# 7. Word frequency analysis
positive_words = ' '.join(df[df['sentiment'] == 'Positive']['review'].values).lower()
negative_words = ' '.join(df[df['sentiment'] == 'Negative']['review'].values).lower()
# Clean and tokenize
def get_words(text):
text = re.sub(r'[^a-z\s]', '', text)
words = text.split()
return [w for w in words if len(w) > 2]
pos_word_freq = Counter(get_words(positive_words))
neg_word_freq = Counter(get_words(negative_words))
# Visualization
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# Positive words
top_pos_words = dict(pos_word_freq.most_common(10))
axes[0].barh(list(top_pos_words.keys()), list(top_pos_words.values()), color='green', alpha=0.7, edgecolor='black')
axes[0].set_xlabel('Frequency')
axes[0].set_title('Top Words in Positive Reviews')
axes[0].invert_yaxis()
# Negative words
top_neg_words = dict(neg_word_freq.most_common(10))
axes[1].barh(list(top_neg_words.keys()), list(top_neg_words.values()), color='red', alpha=0.7, edgecolor='black')
axes[1].set_xlabel('Frequency')
axes[1].set_title('Top Words in Negative Reviews')
axes[1].invert_yaxis()
plt.tight_layout()
plt.show()
# 8. Trend analysis (simulated over time)
dates = pd.date_range('2023-01-01', periods=len(df))
df['date'] = dates
df['rolling_sentiment_score'] = df['vader_compound'].rolling(window=3, center=True).mean()
fig, ax = plt.subplots(figsize=(12, 5))
ax.plot(df['date'], df['rolling_sentiment_score'], marker='o', linewidth=2, label='Rolling Avg (3-day)')
ax.scatter(df['date'], df['vader_compound'], alpha=0.5, s=30, label='Daily Score')
ax.axhline(y=0, color='black', linestyle='--', alpha=0.3)
ax.fill_between(df['date'], df['rolling_sentiment_score'], 0,
where=(df['rolling_sentiment_score'] > 0), alpha=0.3, color='green', label='Positive')
ax.fill_between(df['date'], df['rolling_sentiment_score'], 0,
where=(df['rolling_sentiment_score'] <= 0), alpha=0.3, color='red', label='Negative')
ax.set_xlabel('Date')
ax.set_ylabel('Sentiment Score')
ax.set_title('Sentiment Trend Over Time')
ax.legend()
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 9. Aspect-based sentiment (simulated)
aspects = ['Quality', 'Price', 'Delivery', 'Customer Service']
aspect_sentiments = []
for aspect in aspects:
keywords = {
'Quality': ['quality', 'product', 'design', 'material'],
'Price': ['price', 'cost', 'expensive', 'value'],
'Delivery': ['delivery', 'fast', 'shipping', 'arrived'],
'Customer Service': ['service', 'support', 'customer', 'help']
}
# Count mentions and associated sentiment
aspect_reviews = df[df['review'].str.contains('|'.join(keywords[aspect]), case=False)]
if len(aspect_reviews) > 0:
avg_sentiment = aspect_reviews['vader_compound'].mean()
aspect_sentiments.append({
'Aspect': aspect,
'Avg Sentiment': avg_sentiment,
'Count': len(aspect_reviews)
})
aspect_df = pd.DataFrame(aspect_sentiments)
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# Aspect sentiment scores
colors_aspect = ['green' if x > 0 else 'red' for x in aspect_df['Avg Sentiment']]
axes[0].barh(aspect_df['Aspect'], aspect_df['Avg Sentiment'], color=colors_aspect, alpha=0.7, edgecolor='black')
axes[0].set_xlabel('Average Sentiment Score')
axes[0].set_title('Sentiment by Aspect')
axes[0].axvline(x=0, color='black', linestyle='-', linewidth=0.8)
axes[0].grid(True, alpha=0.3, axis='x')
# Mention count
axes[1].bar(aspect_df['Aspect'], aspect_df['Count'], color='steelblue', alpha=0.7, edgecolor='black')
axes[1].set_ylabel('Number of Mentions')
axes[1].set_title('Aspect Mention Frequency')
axes[1].grid(True, alpha=0.3, axis='y')
plt.tight_layout()
plt.show()
# 10. Summary report
print("\n" + "="*50)
print("SENTIMENT ANALYSIS SUMMARY")
print("="*50)
print(f"Total Reviews: {len(df)}")
print(f"Positive: {len(df[df['sentiment'] == 'Positive'])} ({len(df[df['sentiment'] == 'Positive'])/len(df)*100:.1f}%)")
print(f"Negative: {len(df[df['sentiment'] == 'Negative'])} ({len(df[df['sentiment'] == 'Negative'])/len(df)*100:.1f}%)")
print(f"Neutral: {len(df[df['sentiment'] == 'Neutral'])} ({len(df[df['sentiment'] == 'Neutral'])/len(df)*100:.1f}%)")
if 'vader_compound' in df.columns:
print(f"\nAverage VADER Score: {df['vader_compound'].mean():.3f}")
print(f"Model Accuracy: {accuracy_score(y_test, y_pred):.2%}")
print("="*50)
方法比较
- 基于词典:速度快、可解释性强,但上下文理解有限
- 机器学习:需要训练数据,准确率较高
- 深度学习:能识别复杂模式,需要大型数据集
- 混合:结合多种方法
应用
- 客户反馈分析
- 产品评论监测
- 社交媒体情感分析
- 品牌认知跟踪
- 聊天机器人情感检测
交付内容
- 情感分布分析
- 所有文本的情感分类
- 置信度分数
- 分类特征重要性
- 趋势分析可视化
- 基于方面的情感细分
- 包含见解的执行摘要
评论
支持 Markdown