Sentiment Analysis
Overview
Sentiment analysis determines emotional tone and opinions in text, enabling understanding of customer satisfaction, brand perception, and feedback analysis.
Approaches
- Lexicon-based: Using sentiment dictionaries
- Machine Learning: Training classifiers on labeled data
- Deep Learning: Neural networks for complex patterns
- Aspect-based: Sentiment about specific features
- Multilingual: Non-English text analysis
Sentiment Types
- Positive: Favorable, satisfied
- Negative: Unfavorable, dissatisfied
- Neutral: Factual, no clear sentiment
- Mixed: Combination of sentiments
Implementation with 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)
Methods Comparison
- Lexicon-based: Fast, interpretable, limited context
- Machine Learning: Requires training data, good accuracy
- Deep Learning: Complex patterns, needs large dataset
- Hybrid: Combines multiple approaches
Applications
- Customer feedback analysis
- Product reviews monitoring
- Social media sentiment
- Brand perception tracking
- Chatbot sentiment detection
Deliverables
- Sentiment distribution analysis
- Classified sentiments for all texts
- Confidence scores
- Feature importance for classification
- Trend analysis visualizations
- Aspect-based sentiment breakdown
- Executive summary with insights
1---2name: sentiment-analysis3description: Classify text sentiment using NLP techniques, lexicon-based analysis, and machine learning for opinion mining, brand monitoring, and customer feedback analysis4---5
6# Sentiment Analysis
7
8## Overview
9
10Sentiment analysis determines emotional tone and opinions in text, enabling understanding of customer satisfaction, brand perception, and feedback analysis.
11
12## Approaches
13
14- **Lexicon-based**: Using sentiment dictionaries
15- **Machine Learning**: Training classifiers on labeled data
16- **Deep Learning**: Neural networks for complex patterns
17- **Aspect-based**: Sentiment about specific features
18- **Multilingual**: Non-English text analysis
19
20## Sentiment Types
21
22- **Positive**: Favorable, satisfied
23- **Negative**: Unfavorable, dissatisfied
24- **Neutral**: Factual, no clear sentiment
25- **Mixed**: Combination of sentiments
26
27## Implementation with Python
28
29```python
30import pandas as pd
31import numpy as np
32import matplotlib.pyplot as plt
33import seaborn as sns
34from sklearn.feature_extraction.text import TfidfVectorizer
35from sklearn.naive_bayes import MultinomialNB
36from sklearn.pipeline import Pipeline
37from sklearn.model_selection import train_test_split
38from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
39import re
40from collections import Counter
41
42# Sample review data
43reviews_data = [
44 "This product is amazing! I love it so much.",
45 "Terrible quality, very disappointed.",
46 "It's okay, nothing special.",
47 "Best purchase ever! Highly recommend.",
48 "Worst product I've ever bought.",
49 "Pretty good, satisfied with the purchase.",
50 "Excellent service and fast delivery.",
51 "Poor quality and bad customer support.",
52 "Not bad, does what it's supposed to.",
53 "Absolutely fantastic! Five stars!",
54 "Mediocre product, expected better.",
55 "Love everything about this!",
56 "Complete waste of money.",
57 "Good value for the price.",
58 "Very satisfied, will buy again!",
59 "Horrible experience from start to finish.",
60 "It works as described.",
61 "Outstanding quality and design!",
62 "Disappointed with the results.",
63 "Perfect! Exactly what I wanted.",
64]
65
66sentiments = [
67 'Positive', 'Negative', 'Neutral', 'Positive', 'Negative',
68 'Positive', 'Positive', 'Negative', 'Neutral', 'Positive',
69 'Negative', 'Positive', 'Negative', 'Positive', 'Positive',
70 'Negative', 'Neutral', 'Positive', 'Negative', 'Positive'
71]
72
73df = pd.DataFrame({'review': reviews_data, 'sentiment': sentiments})
74
75print("Sample Reviews:")
76print(df.head(10))
77
78# 1. Lexicon-based Sentiment Analysis
79from nltk.sentiment import SentimentIntensityAnalyzer
80try:
81 import nltk
82 nltk.download('vader_lexicon', quiet=True)
83 sia = SentimentIntensityAnalyzer()
84
85 df['vader_scores'] = df['review'].apply(lambda x: sia.polarity_scores(x))
86 df['vader_compound'] = df['vader_scores'].apply(lambda x: x['compound'])
87 df['vader_sentiment'] = df['vader_compound'].apply(
88 lambda x: 'Positive' if x > 0.05 else ('Negative' if x < -0.05 else 'Neutral')
89 )
90
91 print("\n1. VADER Sentiment Scores:")
92 print(df[['review', 'vader_compound', 'vader_sentiment']].head())
93except:
94 print("NLTK not available, skipping VADER analysis")
95
96# 2. Textblob Sentiment (alternative)
97try:
98 from textblob import TextBlob
99
100 df['textblob_polarity'] = df['review'].apply(lambda x: TextBlob(x).sentiment.polarity)
101 df['textblob_sentiment'] = df['textblob_polarity'].apply(
102 lambda x: 'Positive' if x > 0.1 else ('Negative' if x < -0.1 else 'Neutral')
103 )
104
105 print("\n2. TextBlob Sentiment Scores:")
106 print(df[['review', 'textblob_polarity', 'textblob_sentiment']].head())
107except:
108 print("TextBlob not available")
109
110# 3. Feature Extraction for ML
111vectorizer = TfidfVectorizer(max_features=100, stop_words='english')
112X = vectorizer.fit_transform(df['review'])
113y = df['sentiment']
114
115print(f"\n3. Feature Matrix Shape: {X.shape}")
116print(f"Features extracted: {len(vectorizer.get_feature_names_out())}")
117
118# 4. Machine Learning Model
119X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
120
121# Naive Bayes classifier
122nb_model = MultinomialNB()
123nb_model.fit(X_train, y_train)
124y_pred = nb_model.predict(X_test)
125
126print("\n4. Machine Learning Results:")
127print(f"Accuracy: {accuracy_score(y_test, y_pred):.2f}")
128print("\nClassification Report:")
129print(classification_report(y_test, y_pred))
130
131# 5. Sentiment Distribution
132fig, axes = plt.subplots(2, 2, figsize=(14, 8))
133
134# Distribution of sentiments
135sentiment_counts = df['sentiment'].value_counts()
136axes[0, 0].bar(sentiment_counts.index, sentiment_counts.values, color=['green', 'red', 'gray'], alpha=0.7, edgecolor='black')
137axes[0, 0].set_title('Sentiment Distribution')
138axes[0, 0].set_ylabel('Count')
139axes[0, 0].grid(True, alpha=0.3, axis='y')
140
141# Pie chart
142axes[0, 1].pie(sentiment_counts.values, labels=sentiment_counts.index, autopct='%1.1f%%',
143 colors=['green', 'red', 'gray'], startangle=90)
144axes[0, 1].set_title('Sentiment Proportion')
145
146# VADER compound scores distribution
147if 'vader_compound' in df.columns:
148 axes[1, 0].hist(df['vader_compound'], bins=20, color='steelblue', edgecolor='black', alpha=0.7)
149 axes[1, 0].axvline(x=0.05, color='green', linestyle='--', label='Positive threshold')
150 axes[1, 0].axvline(x=-0.05, color='red', linestyle='--', label='Negative threshold')
151 axes[1, 0].set_xlabel('VADER Compound Score')
152 axes[1, 0].set_ylabel('Frequency')
153 axes[1, 0].set_title('VADER Score Distribution')
154 axes[1, 0].legend()
155
156# Confusion matrix
157cm = confusion_matrix(y_test, y_pred)
158sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=axes[1, 1],
159 xticklabels=np.unique(y_test), yticklabels=np.unique(y_test))
160axes[1, 1].set_title('Classification Confusion Matrix')
161axes[1, 1].set_ylabel('True Label')
162axes[1, 1].set_xlabel('Predicted Label')
163
164plt.tight_layout()
165plt.show()
166
167# 6. Most Informative Features
168feature_names = vectorizer.get_feature_names_out()
169
170# Get feature importance from Naive Bayes
171for sentiment_class, idx in enumerate(np.unique(y)):
172 class_idx = list(np.unique(y)).index(idx)
173 top_features_idx = np.argsort(nb_model.feature_log_prob_[class_idx])[-5:]
174
175 print(f"\nTop features for '{idx}':")
176 for feature_idx in reversed(top_features_idx):
177 print(f" {feature_names[feature_idx]}")
178
179# 7. Word frequency analysis
180positive_words = ' '.join(df[df['sentiment'] == 'Positive']['review'].values).lower()
181negative_words = ' '.join(df[df['sentiment'] == 'Negative']['review'].values).lower()
182
183# Clean and tokenize
184def get_words(text):
185 text = re.sub(r'[^a-z\s]', '', text)
186 words = text.split()
187 return [w for w in words if len(w) > 2]
188
189pos_word_freq = Counter(get_words(positive_words))
190neg_word_freq = Counter(get_words(negative_words))
191
192# Visualization
193fig, axes = plt.subplots(1, 2, figsize=(14, 5))
194
195# Positive words
196top_pos_words = dict(pos_word_freq.most_common(10))
197axes[0].barh(list(top_pos_words.keys()), list(top_pos_words.values()), color='green', alpha=0.7, edgecolor='black')
198axes[0].set_xlabel('Frequency')
199axes[0].set_title('Top Words in Positive Reviews')
200axes[0].invert_yaxis()
201
202# Negative words
203top_neg_words = dict(neg_word_freq.most_common(10))
204axes[1].barh(list(top_neg_words.keys()), list(top_neg_words.values()), color='red', alpha=0.7, edgecolor='black')
205axes[1].set_xlabel('Frequency')
206axes[1].set_title('Top Words in Negative Reviews')
207axes[1].invert_yaxis()
208
209plt.tight_layout()
210plt.show()
211
212# 8. Trend analysis (simulated over time)
213dates = pd.date_range('2023-01-01', periods=len(df))
214df['date'] = dates
215df['rolling_sentiment_score'] = df['vader_compound'].rolling(window=3, center=True).mean()
216
217fig, ax = plt.subplots(figsize=(12, 5))
218ax.plot(df['date'], df['rolling_sentiment_score'], marker='o', linewidth=2, label='Rolling Avg (3-day)')
219ax.scatter(df['date'], df['vader_compound'], alpha=0.5, s=30, label='Daily Score')
220ax.axhline(y=0, color='black', linestyle='--', alpha=0.3)
221ax.fill_between(df['date'], df['rolling_sentiment_score'], 0,
222 where=(df['rolling_sentiment_score'] > 0), alpha=0.3, color='green', label='Positive')
223ax.fill_between(df['date'], df['rolling_sentiment_score'], 0,
224 where=(df['rolling_sentiment_score'] <= 0), alpha=0.3, color='red', label='Negative')
225ax.set_xlabel('Date')
226ax.set_ylabel('Sentiment Score')
227ax.set_title('Sentiment Trend Over Time')
228ax.legend()
229ax.grid(True, alpha=0.3)
230plt.tight_layout()
231plt.show()
232
233# 9. Aspect-based sentiment (simulated)
234aspects = ['Quality', 'Price', 'Delivery', 'Customer Service']
235aspect_sentiments = []
236
237for aspect in aspects:
238 keywords = {
239 'Quality': ['quality', 'product', 'design', 'material'],
240 'Price': ['price', 'cost', 'expensive', 'value'],
241 'Delivery': ['delivery', 'fast', 'shipping', 'arrived'],
242 'Customer Service': ['service', 'support', 'customer', 'help']
243 }
244
245 # Count mentions and associated sentiment
246 aspect_reviews = df[df['review'].str.contains('|'.join(keywords[aspect]), case=False)]
247 if len(aspect_reviews) > 0:
248 avg_sentiment = aspect_reviews['vader_compound'].mean()
249 aspect_sentiments.append({
250 'Aspect': aspect,
251 'Avg Sentiment': avg_sentiment,
252 'Count': len(aspect_reviews)
253 })
254
255aspect_df = pd.DataFrame(aspect_sentiments)
256
257fig, axes = plt.subplots(1, 2, figsize=(14, 5))
258
259# Aspect sentiment scores
260colors_aspect = ['green' if x > 0 else 'red' for x in aspect_df['Avg Sentiment']]
261axes[0].barh(aspect_df['Aspect'], aspect_df['Avg Sentiment'], color=colors_aspect, alpha=0.7, edgecolor='black')
262axes[0].set_xlabel('Average Sentiment Score')
263axes[0].set_title('Sentiment by Aspect')
264axes[0].axvline(x=0, color='black', linestyle='-', linewidth=0.8)
265axes[0].grid(True, alpha=0.3, axis='x')
266
267# Mention count
268axes[1].bar(aspect_df['Aspect'], aspect_df['Count'], color='steelblue', alpha=0.7, edgecolor='black')
269axes[1].set_ylabel('Number of Mentions')
270axes[1].set_title('Aspect Mention Frequency')
271axes[1].grid(True, alpha=0.3, axis='y')
272
273plt.tight_layout()
274plt.show()
275
276# 10. Summary report
277print("\n" + "="*50)
278print("SENTIMENT ANALYSIS SUMMARY")
279print("="*50)
280print(f"Total Reviews: {len(df)}")
281print(f"Positive: {len(df[df['sentiment'] == 'Positive'])} ({len(df[df['sentiment'] == 'Positive'])/len(df)*100:.1f}%)")
282print(f"Negative: {len(df[df['sentiment'] == 'Negative'])} ({len(df[df['sentiment'] == 'Negative'])/len(df)*100:.1f}%)")
283print(f"Neutral: {len(df[df['sentiment'] == 'Neutral'])} ({len(df[df['sentiment'] == 'Neutral'])/len(df)*100:.1f}%)")
284if 'vader_compound' in df.columns:
285 print(f"\nAverage VADER Score: {df['vader_compound'].mean():.3f}")
286 print(f"Model Accuracy: {accuracy_score(y_test, y_pred):.2%}")
287print("="*50)
288```
289
290## Methods Comparison
291
292- **Lexicon-based**: Fast, interpretable, limited context
293- **Machine Learning**: Requires training data, good accuracy
294- **Deep Learning**: Complex patterns, needs large dataset
295- **Hybrid**: Combines multiple approaches
296
297## Applications
298
299- Customer feedback analysis
300- Product reviews monitoring
301- Social media sentiment
302- Brand perception tracking
303- Chatbot sentiment detection
304
305## Deliverables
306
307- Sentiment distribution analysis
308- Classified sentiments for all texts
309- Confidence scores
310- Feature importance for classification
311- Trend analysis visualizations
312- Aspect-based sentiment breakdown
313- Executive summary with insights