| title | Sentiment Lab |
|---|---|
| emoji | 🔮 |
| colorFrom | pink |
| colorTo | indigo |
| sdk | docker |
| app_port | 7860 |
| pinned | false |
A comparative study of five machine learning models for classifying sentiment in mobile phone reviews, built on a custom-scraped corpus of 10,000+ reviews from GSMArena. The project trains, evaluates, and serves predictions through a Flask web dashboard, comparing two independent labeling pipelines (a classical rule-based approach and a transformer-based approach) across the same data.
Live demo: huggingface.co/spaces/UroojFatima-22/Sentiment-Analysis
- Scrapes user reviews for popular phones across four brand categories (Samsung, iPhone, Xiaomi, Mixed)
- Cleans the raw text through an 11-step preprocessing pipeline
- Generates two parallel sets of sentiment labels using independent methods:
- VADER + TextBlob (lexicon-based, fast)
- RoBERTa transformer (
cardiffnlp/twitter-roberta-base-sentiment-latest)
- Trains five different classifiers on each labeled dataset:
- Multinomial Naive Bayes
- Logistic Regression
- Linear SVM
- K-Means clustering (unsupervised, with majority-vote cluster mapping)
- Bi-LSTM RNN (PyTorch)
- Evaluates every model on a held-out test set with accuracy, precision, recall, F1, and confusion matrices
- Serves a Flask web app with two interfaces:
- A dashboard for running individual models or comparing all five
- A live prediction page that shows what all five models predict for a typed-in review, in real time
- Python 3.10+
- scikit-learn for the classical models, TF-IDF, and K-Means
- PyTorch for the Bi-LSTM RNN
- Transformers (Hugging Face) for the BERT-based labeler
- NLTK, VADER, TextBlob for preprocessing and rule-based labeling
- Flask for the web app
- Chart.js for the comparison visualization
.
├── app/
│ ├── app.py # Flask backend (routes + model loading)
│ ├── templates/ # index.html + predict.html
│ └── static/css/style.css # Dashboard styling
├── scrapers/
│ ├── gsmarena_scraper.py # Scrapes review pages
│ └── phone_urls.py # Phone URL configuration
├── preprocessing/
│ ├── parser.py # raw_txt -> parsed_reviews.xlsx
│ ├── cleaner.py # Text cleaning pipeline
│ ├── labeler.py # VADER + TextBlob labeler
│ └── labeler_bert.py # RoBERTa labeler
├── models/
│ ├── train.py # Trains all 5 models on both datasets
│ └── evaluate.py # Evaluates everything on the test set
├── data/ # Generated by the pipeline (gitignored)
│ ├── raw_txt/ # Scraped reviews per brand
│ └── processed/ # Excel files at each pipeline stage
├── config.py # Central configuration
└── requirements.txt
This project does not ship with data or trained models. You'll need to run the pipeline once to generate them.
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # macOS/Linux
pip install -r requirements.txtpython -m nltk.downloader punkt punkt_tab stopwords wordnetThe full pipeline produces the data and models the app needs. Run these in order:
# 1. Scrape reviews from GSMArena (slow — uses a polite delay between requests)
python scrapers/gsmarena_scraper.py
# 2. Parse the raw .txt files into a structured Excel file
python preprocessing/parser.py
# 3. Clean the text (lowercase, remove URLs, handle contractions, lemmatize, etc.)
python preprocessing/cleaner.py
# 4a. Label with VADER + TextBlob (fast)
python preprocessing/labeler.py
# 4b. Label with RoBERTa (slow — uses GPU if available)
python preprocessing/labeler_bert.py
# 5. Train all 5 models on both labeled datasets
python models/train.py
# 6. (Optional) Evaluate all 10 trained models on their held-out test sets
python models/evaluate.pyAfter step 5, you'll have ten saved models in total — five per labeling pipeline, in models/saved_vader/ and models/saved_bert/.
python app/app.pyOpen http://127.0.0.1:5000 in your browser.
Pick a dataset, label source (VADER or BERT), brand filter, and a model. Click Run Model to see accuracy, precision, recall, F1, and the confusion matrix on the held-out test set. Click Compare All 5 to render a side-by-side bar chart of every model's metrics.
All metrics are computed on the 20% test split that the models never saw during training, so the numbers reflect actual generalization rather than memorization.
Type any review. The app runs all five models on your input and shows a consensus view: which sentiment the majority predicted, how the votes split, and each individual model's verdict. A cleaned-text preview shows what the models actually received after preprocessing.
All paths, hyperparameters, and thresholds are centralized in config.py. Notable settings:
TEST_SIZE = 0.2— train/test split ratioRANDOM_STATE = 42— deterministic splitting across all scriptsPOSITIVE_THRESHOLD/NEGATIVE_THRESHOLD— VADER compound score cutoffs for label assignmentMODELS_DIR_VADER/MODELS_DIR_BERT— output directories for each labeling pipeline
- The pipeline is fully reproducible: same
random_stateeverywhere, same TF-IDF settings shared between classical models and K-Means, same hyperparameters intrain.py. - BERT labels are higher-quality (manual audit indicates ~83% accuracy on this corpus) but harder to predict from bag-of-words features, so BERT-trained models show lower raw accuracy than VADER-trained ones. Macro-F1 is the more honest metric for comparing across labeling pipelines because it weights all three sentiment classes equally rather than rewarding majority-class predictions.
- The Flask app loads all ten models at startup, which takes a few seconds. After that, predictions and evaluations are fast.
MIT © Urooj Fatima