prabalGaur commited on
Commit
097f1ac
·
verified ·
1 Parent(s): fdaeae0

Upload community_contributions/bharat_puri/exercise.py with huggingface_hub

Browse files
community_contributions/bharat_puri/exercise.py ADDED
@@ -0,0 +1,349 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """week8_exercie.ipynb
3
+
4
+ Automatically generated by Colab.
5
+
6
+ Original file is located at
7
+ https://colab.research.google.com/drive/1jJ4pKoJat0ZnC99sTQjEEe9BMK--ArwQ
8
+ """
9
+
10
+ !pip install -q pandas datasets matplotlib seaborn
11
+ !pip install datasets==3.0.1
12
+ !pip install anthropic -q
13
+
14
+ import pandas as pd
15
+ import numpy as np
16
+ import matplotlib.pyplot as plt
17
+ import seaborn as sns
18
+ from datasets import load_dataset
19
+ from sklearn.model_selection import train_test_split
20
+ from sklearn.feature_extraction.text import TfidfVectorizer
21
+ from sklearn.linear_model import LogisticRegression
22
+ #chec perfomance
23
+ from sklearn.metrics import classification_report, confusion_matrix
24
+ from sklearn.utils import resample
25
+ import os
26
+ from anthropic import Anthropic
27
+ import re
28
+
29
+
30
+
31
+ pd.set_option("display.max_colwidth", 100)
32
+
33
+ # # Initialize client using environment variable
34
+ # client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
35
+
36
+ # # Quick test
37
+ # print("Anthropic client initialized " if client else " Anthropic not detected.")
38
+
39
+ from google.colab import userdata
40
+ userdata.get('ANTHROPIC_API_KEY')
41
+
42
+ api_key = userdata.get('ANTHROPIC_API_KEY')
43
+ os.environ["ANTHROPIC_API_KEY"] = api_key
44
+
45
+ client = Anthropic(api_key=api_key)
46
+
47
+ # List models
48
+ models = client.models.list()
49
+
50
+ print("Available Anthropic Models:\n")
51
+ for m in models.data:
52
+ print(f"- {m.id}")
53
+
54
+ #dataset = load_dataset("McAuley-Lab/Amazon-Reviews-2023", "raw_review_Appliances", split="full[:5000]")
55
+
56
+
57
+
58
+ # Loading a sample from the full reviews data
59
+ dataset = load_dataset("McAuley-Lab/Amazon-Reviews-2023", "raw_review_Appliances", split="full[:5000]")
60
+
61
+ # creating a DF
62
+ df = pd.DataFrame(dataset)
63
+ df = df[["title", "text", "rating"]].dropna().reset_index(drop=True)
64
+
65
+ # Renaming th columns for clarity/easy ref
66
+ df.rename(columns={"text": "review_body"}, inplace=True)
67
+
68
+ print(f"Loaded {len(df)} rows with reviews and ratings")
69
+ df.head()
70
+
71
+ #inspect the data
72
+ # Basic info
73
+ print(df.info())
74
+ print(df.isnull().sum())
75
+
76
+ # Unique ratings dist
77
+ print(df["rating"].value_counts().sort_index())
78
+
79
+ # Check Random reviews
80
+ display(df.sample(5, random_state=42))
81
+
82
+ # Review length distribution
83
+ df["review_length"] = df["review_body"].apply(lambda x: len(str(x).split()))
84
+
85
+ #Summarize the review length
86
+ print(df["review_length"].describe())
87
+
88
+ # pltt the rating distribution
89
+ plt.figure(figsize=(6,4))
90
+ df["rating"].hist(bins=5, edgecolor='black')
91
+ plt.title("Ratings Distribution (1–5 stars)")
92
+ plt.xlabel("Rating")
93
+ plt.ylabel("Number of Reviews")
94
+ plt.show()
95
+
96
+ # review length
97
+ plt.figure(figsize=(6,4))
98
+ df["review_length"].hist(bins=30, color="lightblue", edgecolor='black')
99
+ plt.title("Review Length Distribution")
100
+ plt.xlabel("Number of Words in Review")
101
+ plt.ylabel("Number of Reviews")
102
+ plt.show()
103
+
104
+ #cleaning
105
+ def clean_text(text):
106
+ text = text.lower()
107
+ # remove URLs
108
+ text = re.sub(r"http\S+|www\S+|https\S+", '', text)
109
+ # remove punctuation/special chars
110
+ text = re.sub(r"[^a-z0-9\s]", '', text)
111
+ # normalize whitespace
112
+ text = re.sub(r"\s+", ' ', text).strip()
113
+ return text
114
+
115
+ df["clean_review"] = df["review_body"].apply(clean_text)
116
+
117
+ df.head(3)
118
+
119
+ """'#sentiment analysis"""
120
+
121
+ # Rating labellings
122
+ def label_sentiment(rating):
123
+ if rating <= 2:
124
+ return "negative"
125
+ elif rating == 3:
126
+ return "neutral"
127
+ else:
128
+ return "positive"
129
+
130
+ df["sentiment"] = df["rating"].apply(label_sentiment)
131
+
132
+ df["sentiment"].value_counts()
133
+
134
+ #train/tets split
135
+ X_train, X_test, y_train, y_test = train_test_split(
136
+ df["clean_review"], df["sentiment"], test_size=0.2, random_state=42, stratify=df["sentiment"]
137
+ )
138
+
139
+ print(f"Training samples: {len(X_train)}, Test samples: {len(X_test)}")
140
+
141
+ # Convert text to TF-IDF features
142
+ vectorizer = TfidfVectorizer(max_features=2000, ngram_range=(1,2))
143
+
144
+ X_train_tfidf = vectorizer.fit_transform(X_train)
145
+
146
+ X_test_tfidf = vectorizer.transform(X_test)
147
+
148
+ print(f"TF-IDF matrix shape: {X_train_tfidf.shape}")
149
+
150
+ #trian classfier
151
+
152
+ # Train lightweight model
153
+ clf = LogisticRegression(max_iter=200)
154
+
155
+ clf.fit(X_train_tfidf, y_train)
156
+
157
+ y_pred = clf.predict(X_test_tfidf)
158
+
159
+ print("Classification Report:\n", classification_report(y_test, y_pred))
160
+ print("\nConfusion Matrix:\n", confusion_matrix(y_test, y_pred))
161
+
162
+ sample_texts = [
163
+ "This blender broke after two days. Waste of money!",
164
+ "Works exactly as described, very satisfied!",
165
+ "It’s okay, does the job but nothing special."
166
+ ]
167
+
168
+ sample_features = vectorizer.transform(sample_texts)
169
+ sample_preds = clf.predict(sample_features)
170
+
171
+ for text, pred in zip(sample_texts, sample_preds):
172
+ print(f"\nReview: {text}\nPredicted Sentiment: {pred}")
173
+
174
+ """#Improving Model Balance & Realism"""
175
+
176
+ # Separate by sentiment
177
+ pos = df[df["sentiment"] == "positive"]
178
+ neg = df[df["sentiment"] == "negative"]
179
+ neu = df[df["sentiment"] == "neutral"]
180
+
181
+ # Undersample positive to match roughly others
182
+ pos_down = resample(pos, replace=False, n_samples=len(neg) + len(neu), random_state=42)
183
+
184
+ # Combine
185
+ df_balanced = pd.concat([pos_down, neg, neu]).sample(frac=1, random_state=42).reset_index(drop=True)
186
+
187
+ print(df_balanced["sentiment"].value_counts())
188
+
189
+ #retain classfier
190
+ X_train, X_test, y_train, y_test = train_test_split(
191
+ df_balanced["clean_review"], df_balanced["sentiment"],
192
+ test_size=0.2, random_state=42, stratify=df_balanced["sentiment"]
193
+ )
194
+
195
+ vectorizer = TfidfVectorizer(max_features=2000, ngram_range=(1,2))
196
+
197
+ X_train_tfidf = vectorizer.fit_transform(X_train)
198
+
199
+ X_test_tfidf = vectorizer.transform(X_test)
200
+
201
+ clf = LogisticRegression(max_iter=300, class_weight="balanced")
202
+ clf.fit(X_train_tfidf, y_train)
203
+
204
+ print("Balanced model trained successfully ")
205
+
206
+ #evaluate agan
207
+ y_pred = clf.predict(X_test_tfidf)
208
+
209
+ print("Classification Report:\n", classification_report(y_test, y_pred))
210
+
211
+ print("\nConfusion Matrix:\n", confusion_matrix(y_test, y_pred))
212
+
213
+ """#Agents"""
214
+
215
+ # Base class for all agents
216
+ class BaseAgent:
217
+ """A simple base agent with a name and a run() method."""
218
+
219
+ def __init__(self, name):
220
+ self.name = name
221
+
222
+ def run(self, *args, **kwargs):
223
+ raise NotImplementedError("Subclasses must implement run() method.")
224
+
225
+ def log(self, message):
226
+ print(f"[{self.name}] {message}")
227
+
228
+ #DataAgent for loading/cleaning
229
+ class DataAgent(BaseAgent):
230
+ """Handles dataset preparation tasks."""
231
+
232
+ def __init__(self, data):
233
+ super().__init__("DataAgent")
234
+ self.data = data
235
+
236
+ def run(self):
237
+ self.log("Preprocessing data...")
238
+ df_clean = self.data.copy()
239
+ df_clean["review_body"] = df_clean["review_body"].str.strip()
240
+ df_clean.drop_duplicates(subset=["review_body"], inplace=True)
241
+ self.log(f"Dataset ready with {len(df_clean)} reviews.")
242
+ return df_clean
243
+
244
+ #analisyis agent-->using the tianed sentiment model *TF-IDF +Logistic Regression) to classfy Reviews
245
+ class AnalysisAgent(BaseAgent):
246
+ """Analyzes text sentiment using a trained model."""
247
+
248
+ def __init__(self, vectorizer, model):
249
+ super().__init__("AnalysisAgent")
250
+ self.vectorizer = vectorizer
251
+ self.model = model
252
+
253
+ def run(self, reviews):
254
+ self.log(f"Analyzing {len(reviews)} reviews...")
255
+ X = self.vectorizer.transform(reviews)
256
+ predictions = self.model.predict(X)
257
+ return predictions
258
+
259
+ #ReviewerAgent. Serves as the summary agnt using the anthropic API to give LLM review insights
260
+ class ReviewerAgent(BaseAgent):
261
+ """Summarizes overall sentiment trends using Anthropic Claude."""
262
+
263
+ def __init__(self):
264
+ super().__init__("ReviewerAgent")
265
+ # Retrieve your key once — it’s already stored in Colab userdata
266
+ api_key = os.getenv("ANTHROPIC_API_KEY")
267
+ if not api_key:
268
+ from google.colab import userdata
269
+ api_key = userdata.get("ANTHROPIC_API_KEY")
270
+
271
+ if not api_key:
272
+ raise ValueError("Anthropic API key not found. Make sure it's set in Colab userdata as 'ANTHROPIC_API_KEY'.")
273
+
274
+ self.client = Anthropic(api_key=api_key)
275
+
276
+ def run(self, summary_text):
277
+ """Generate an insights summary using Claude."""
278
+ self.log("Generating summary using Claude...")
279
+
280
+ prompt = f"""
281
+ You are a product insights assistant.
282
+ Based on the following summarized customer reviews, write a concise 3–4 sentence sentiment analysis report.
283
+ Clearly describe the main themes and tone in user feedback on these home appliance products.
284
+
285
+ Reviews Summary:
286
+ {summary_text}
287
+ """
288
+
289
+ response = self.client.messages.create(
290
+ model="claude-3-5-haiku-20241022",
291
+ max_tokens=250,
292
+ temperature=0.6,
293
+ messages=[{"role": "user", "content": prompt}]
294
+ )
295
+
296
+ output = response.content[0].text.strip()
297
+ self.log("Summary generated successfully ")
298
+ return output
299
+
300
+ # Instantiate agents
301
+ data_agent = DataAgent(df)
302
+ analysis_agent = AnalysisAgent(vectorizer, clf)
303
+ reviewer_agent = ReviewerAgent()
304
+
305
+ # Clean data
306
+ df_ready = data_agent.run()
307
+
308
+ # Classify sentiments
309
+ df_ready["predicted_sentiment"] = analysis_agent.run(df_ready["review_body"])
310
+
311
+ # Prepare summary text by sentiment group
312
+ summary_text = df_ready.groupby("predicted_sentiment")["review_body"].apply(lambda x: " ".join(x[:3])).to_string()
313
+
314
+ # Generate AI summary using Anthropic
315
+ insight_summary = reviewer_agent.run(summary_text)
316
+
317
+ print(insight_summary)
318
+
319
+ """#Evaluation & Visualization"""
320
+
321
+ # Evaluation & Visualization ===
322
+
323
+ # Count predicted sentiments
324
+ sentiment_counts = df_ready["predicted_sentiment"].value_counts()
325
+
326
+ print(sentiment_counts)
327
+
328
+ # Plot sentiment distribution
329
+ plt.figure(figsize=(6,4))
330
+ sns.barplot(x=sentiment_counts.index, y=sentiment_counts.values, palette="viridis")
331
+ plt.title("Sentiment Distribution of Reviews", fontsize=14)
332
+ plt.xlabel("Sentiment")
333
+ plt.ylabel("Number of Reviews")
334
+ plt.show()
335
+
336
+ # Compute average review length per sentiment
337
+ df_ready["review_length"] = df_ready["review_body"].apply(lambda x: len(x.split()))
338
+
339
+ avg_length = df_ready.groupby("predicted_sentiment")["review_length"].mean()
340
+
341
+ print(avg_length)
342
+
343
+ # Visualize it
344
+ plt.figure(figsize=(6,4))
345
+ sns.barplot(x=avg_length.index, y=avg_length.values, palette="coolwarm")
346
+ plt.title("Average Review Length per Sentiment")
347
+ plt.xlabel("Sentiment")
348
+ plt.ylabel("Average Word Count")
349
+ plt.show()