A machine learning project that classifies the emotion expressed in a piece of text (e.g., joy, sadness, anger, fear, love, surprise) using classical NLP preprocessing and ML classifiers. The final model is deployed as an interactive Streamlit web app.
🔗 Live Demo: emotiondetector-bipan.streamlit.app
This project takes raw text data, cleans and preprocesses it using standard NLP techniques, converts it into numerical features using Bag of Words and TF-IDF, and trains multiple machine learning models to predict the emotion behind the text. The best-performing model is then saved and used to power a simple web UI where users can type a sentence and get an instant emotion prediction.
- File:
train.txt - Format: Semicolon-separated (
;) text file with two columns —textandemotion - Each row contains a sentence and its corresponding emotion label.
The raw text was cleaned using the following steps, in order:
- Lowercasing – Converts all text to lowercase for consistency.
- Removing Punctuation – Strips punctuation marks using Python's
stringmodule. - Removing Numbers – Removes digit characters from the text.
- Removing Emojis & Special Characters – Keeps only ASCII characters.
- Removing Stopwords – Removes common English stopwords (e.g., "the", "is", "and") using NLTK's stopword list.
After cleaning, the text was split into training (80%) and testing (20%) sets using train_test_split with random_state=42.
Two vectorization techniques were used to convert text into numerical form:
| Technique | Description |
|---|---|
| Bag of Words (CountVectorizer) | Represents text as raw word frequency counts. |
| TF-IDF (TfidfVectorizer) | Weighs words by importance, reducing the influence of frequently occurring but less informative words. |
Three model + feature combinations were trained and evaluated on accuracy:
| Model | Feature Extraction | Accuracy |
|---|---|---|
| Multinomial Naive Bayes | Bag of Words (CountVectorizer) | 76.81% |
| Multinomial Naive Bayes | TF-IDF | 66.09% |
| Logistic Regression | TF-IDF | 🏆 86.28% |
Logistic Regression combined with TF-IDF features achieved the highest accuracy of 86.28%, outperforming both Naive Bayes variants. This is the model used in the deployed Streamlit application.
Why did Logistic Regression + TF-IDF perform best?
- TF-IDF down-weights common, less-informative words while emphasizing distinctive ones.
- Logistic Regression can learn more nuanced decision boundaries between classes compared to Naive Bayes' independence assumption, which tends to oversimplify relationships between words.
├── app.py # Streamlit web app for live predictions
├── train.txt # Dataset (text;emotion pairs)
├── requirements.txt # Python dependencies
├── README.md # Project documentation
├── models/
│ ├── model_LR.pkl # Saved trained Logistic Regression model
│ ├── tfidf_vectorizer.pkl # Saved TF-IDF vectorizer (fitted on training data)
│ └── emotion_numbers.pkl # Saved label mapping (emotion name <-> number)
└── notebooks/
└── NLP-with-ML.ipynb # Main notebook: preprocessing, training, evaluation
-
Clone the repository
git clone https://github.com/Bipan101/Emotion-Detector.git cd Emotion-Detector -
Install dependencies
pip install -r requirements.txt
-
Run the Streamlit app
streamlit run app.py
-
Open the local URL shown in your terminal (usually
http://localhost:8501) in your browser.
- User types a sentence into the text box.
- The input goes through the same preprocessing pipeline used during training (lowercasing, punctuation/number/emoji removal, stopword removal).
- The cleaned text is vectorized using the saved TF-IDF vectorizer.
- The saved Logistic Regression model predicts the emotion class.
- The predicted label is decoded back to its original emotion name and displayed, along with a confidence score bar chart.
- Python 3
- Pandas / NumPy – Data handling
- NLTK – Stopword removal, tokenization
- Scikit-learn – Vectorization (CountVectorizer, TfidfVectorizer), models (MultinomialNB, LogisticRegression), evaluation
- Streamlit – Web app interface
- Matplotlib / Seaborn – Visualization (EDA)
- Experiment with more advanced models (SVM, Random Forest, XGBoost).
- Try word embeddings (Word2Vec, GloVe) or transformer-based models (BERT) for potentially higher accuracy (out of scope here, as this project focuses on classical NLP + ML rather than deep learning).
- Add cross-validation and hyperparameter tuning (e.g.,
GridSearchCV) for more robust model selection. - Handle class imbalance if present in the emotion labels.
Bipan Neupane
- GitHub: @Bipan101
- Portfolio: bipanneupane.com.np
This project is open source and available under the MIT License.