Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions beginner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
- **Prerequisites:** Python and basic statistics.
- **Interactive Lab:** [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/AIMLCLUBOCT/Workshops/blob/main/beginner/notebooks/03_intro_machine_learning.ipynb) [`03_intro_machine_learning.ipynb`](./notebooks/03_intro_machine_learning.ipynb)

### 4. NLP & Sentiment Analysis: Text Classification with Scikit-Learn
- **Topics:** Text cleaning, tokenization, TF-IDF feature extraction, Multinomial Naive Bayes, and interactive model inference.
- **Duration:** 2.5 Hours
- **Prerequisites:** Python and introductory classification concepts.
- **Interactive Lab:** [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/AIMLCLUBOCT/Workshops/blob/main/beginner/notebooks/04_nlp_sentiment_analysis.ipynb) [`04_nlp_sentiment_analysis.ipynb`](./notebooks/04_nlp_sentiment_analysis.ipynb)

---

## 🚀 How to Run
Expand Down
217 changes: 217 additions & 0 deletions beginner/notebooks/04_nlp_sentiment_analysis.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# \ud83d\udcdd Workshop 4: Natural Language Processing & Sentiment Analysis Starter\n",
"\n",
"[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/AIMLCLUBOCT/Workshops/blob/main/beginner/notebooks/04_nlp_sentiment_analysis.ipynb)\n",
"\n",
"**AI & Machine Learning Club \u2013 Oriental College of Technology, Bhopal**\n",
"\n",
"Welcome to this hands-on NLP tutorial! In this lab, you will learn:\n",
"1. Text preprocessing: cleaning, normalizing, and tokenizing natural language.\n",
"2. How **TF-IDF (Term Frequency-Inverse Document Frequency)** turns words into mathematical feature vectors.\n",
"3. Training a **Multinomial Naive Bayes** classifier for sentiment prediction.\n",
"4. Evaluating model performance using Confusion Matrix & Classification Report.\n",
"5. Live interactive inference on custom sentences."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Setup & Environment Dependencies\n",
"Let's import the necessary libraries (`scikit-learn`, `pandas`, `numpy`, and `matplotlib`)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import re\n",
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.feature_extraction.text import TfidfVectorizer\n",
"from sklearn.naive_bayes import MultinomialNB\n",
"from sklearn.metrics import classification_report, confusion_matrix, ConfusionMatrixDisplay\n",
"\n",
"print('Libraries imported successfully!')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Load Sample Sentiment Dataset\n",
"We use a dataset containing balanced positive and negative reviews."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"data = [\n",
" # Positive reviews (1)\n",
" ('This AI workshop was extremely informative and well-structured!', 1),\n",
" ('The practical coding demonstrations helped clarify the core concepts.', 1),\n",
" ('Brilliant hands-on lab! I learned so much about neural networks.', 1),\n",
" ('The mentors were patient, encouraging, and answered all questions.', 1),\n",
" ('Loved the step-by-step approach to machine learning fundamentals.', 1),\n",
" ('The project starter code was clean, reproducible, and easy to run.', 1),\n",
" ('Great session! Really looking forward to the next hackathon.', 1),\n",
" ('Outstanding explanations of linear algebra and loss functions.', 1),\n",
" ('I highly recommend this club workshop to all engineering students.', 1),\n",
" ('Awesome experience building my first sentiment classification model!', 1),\n",
" # Negative reviews (0)\n",
" ('The pacing was way too fast and hard to follow for beginners.', 0),\n",
" ('Disappointed with the sound quality in the seminar hall.', 0),\n",
" ('Too much theory on slides and not enough interactive coding time.', 0),\n",
" ('The prerequisites were not clearly stated and I felt completely lost.', 0),\n",
" ('The example code had errors and failed to run on my local machine.', 0),\n",
" ('The workshop started late and ended before covering all topics.', 0),\n",
" ('Unhelpful explanations, it felt rushed and disorganized.', 0),\n",
" ('The presentation was boring and repetitive.', 0),\n",
" ('Could not get the environment setup properly in time.', 0),\n",
" ('Poor communication regarding the schedule and lab location.', 0)\n",
"]\n",
"\n",
"df = pd.DataFrame(data, columns=['review', 'sentiment'])\n",
"print(f'Total reviews: {len(df)}')\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Text Preprocessing Function\n",
"Raw text data contains punctuation, irregular casing, and noise. We normalize text into clean tokens."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def clean_text(text: str) -> str:\n",
" text = text.lower() # Lowercase\n",
" text = re.sub(r'[^a-zA-Z0-9\\s]', ' ', text) # Strip punctuation\n",
" text = re.sub(r'\\s+', ' ', text).strip() # Normalize whitespace\n",
" return text\n",
"\n",
"df['cleaned_review'] = df['review'].apply(clean_text)\n",
"df[['review', 'cleaned_review']].head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Train / Test Split & TF-IDF Vectorization\n",
"We separate training data (75%) from holdout test data (25%) and vectorize using unigrams and bigrams."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"X_train, X_test, y_train, y_test = train_test_split(\n",
" df['cleaned_review'], df['sentiment'], test_size=0.25, random_state=42, stratify=df['sentiment']\n",
")\n",
"\n",
"vectorizer = TfidfVectorizer(ngram_range=(1, 2), stop_words='english')\n",
"X_train_vec = vectorizer.fit_transform(X_train)\n",
"X_test_vec = vectorizer.transform(X_test)\n",
"\n",
"print(f'Training shape: {X_train_vec.shape}')\n",
"print(f'Testing shape: {X_test_vec.shape}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Model Training & Evaluation\n",
"We fit a **Multinomial Naive Bayes** classifier and evaluate precision, recall, and the confusion matrix."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"model = MultinomialNB(alpha=1.0)\n",
"model.fit(X_train_vec, y_train)\n",
"\n",
"preds = model.predict(X_test_vec)\n",
"print('Classification Report:')\n",
"print(classification_report(y_test, preds, target_names=['Negative', 'Positive']))\n",
"\n",
"# Display Confusion Matrix\n",
"cm = confusion_matrix(y_test, preds)\n",
"disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=['Negative', 'Positive'])\n",
"disp.plot(cmap='Blues')\n",
"plt.title('Sentiment Confusion Matrix')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. Interactive Live Inference\n",
"Test the classifier with your own review sentences!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def predict_sentiment(text: str):\n",
" cleaned = clean_text(text)\n",
" vec = vectorizer.transform([cleaned])\n",
" pred = model.predict(vec)[0]\n",
" proba = model.predict_proba(vec)[0]\n",
" sentiment = '\ud83d\ude0a Positive' if pred == 1 else '\ud83d\ude1e Negative'\n",
" confidence = proba[pred] * 100\n",
" print(f'Input: \"{text}\"')\n",
" print(f'Sentiment: {sentiment} (Confidence: {confidence:.2f}%)\\n')\n",
"\n",
"predict_sentiment('The instructors explained every concept with fantastic examples!')\n",
"predict_sentiment('I had a terrible experience with the code errors and confusing slides.')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. \ud83d\ude80 Student Extension Challenge\n",
"Now it's your turn to experiment!\n",
"- **Challenge 1:** Try comparing `MultinomialNB` with `LogisticRegression` or `LinearSVC`.\n",
"- **Challenge 2:** Inspect `vectorizer.get_feature_names_out()` and discover which words have the strongest TF-IDF weights.\n",
"- **Challenge 3:** Connect this classifier to a simple Streamlit interface in `beginner/`!"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Loading