This project builds an end-to-end NLP pipeline that maps a mobile application review to one of five sentiment levels, represented by its 1–5 star rating. It combines Unicode-aware text normalization, trainable FastText subword embeddings, and stacked bidirectional GRU/LSTM models.
The repository demonstrates more than model fitting: it includes distributed preprocessing, exploratory analysis, statistically grounded cross-validation, memory-bounded training, artifact management, a typed inference API, a production-style CLI, Docker packaging, and automated tests.
| Project dimension | Implementation |
|---|---|
| Dataset | 197,595 application reviews across 622 packages |
| Task | Five-class ordinal sentiment classification |
| Text representation | 130-dimensional FastText subword vectors |
| Input | Up to 150 tokens per review, masked after zero-padding |
| Models | Stacked bidirectional LSTM and GRU networks |
| Evaluation | Stratified K-fold accuracy, macro-F1, 95% CI, confusion matrix |
| Serving interface | Python API, CLI, and Docker entry point |
Important
Star ratings are used as a proxy for sentiment. The source dataset is strongly imbalanced—about 77.8% of the cleaned reviews are five-star ratings—so accuracy must be interpreted alongside macro-F1 and class-level errors.
The retained legacy experiment figure indicates the following benchmark after one training epoch:
| Architecture | Approximate plotted accuracy | Difference |
|---|---|---|
| Bidirectional LSTM | ≈83.27% | baseline |
| Bidirectional GRU | ≈83.42% | ≈+0.15 pp |
The fold-level arrays were not serialized, so these are visual estimates—not precision benchmark
claims. The original implementation used a 10-fold non-stratified split and a 94% interval; the
current pipeline upgrades evaluation to stratified K-fold validation, per-fold FastText fitting,
macro-F1, and 95% confidence intervals. Run make evaluate to produce a reproducible result set in
artifacts/evaluation/.
View the retained legacy experiment figure
The original figure's confusion-matrix axis captions are reversed. The current evaluation code uses true ratings on rows and predicted ratings on columns.
flowchart LR
A[Hugging Face dataset] --> B[PySpark validation and cleaning]
B --> C[(Processed reviews)]
C --> D[Unicode tokenization]
D --> E[FastText subword model]
E --> F[150 × 130 embedding batches]
F --> G1[Stacked BiLSTM]
F --> G2[Stacked BiGRU]
G1 --> H[Stratified evaluation]
G2 --> H
H --> I[Selected BiGRU model]
I --> J[Python API / CLI / Docker]
The training loader vectorizes only the active batch. For this dataset, eagerly materializing the
complete tensor would require roughly 14.4 GiB as float32; bounded batches make the same pipeline
usable on ordinary development machines.
See Architecture for module responsibilities and design decisions.
![]() |
![]() |
| Class distribution | Review activity over time |
The imbalance is material: five-star reviews dominate the target distribution, while two- and three-star feedback is comparatively rare. Training therefore supports balanced class weights, and evaluation reports macro-F1 so minority classes have equal influence on the summary score.
.
├── .github/workflows/ # Continuous integration
├── artifacts/ # Local models and evaluation outputs (Git-ignored)
├── data/
│ ├── raw/ # Downloaded source Parquet
│ ├── interim/ # Inspectable normalized corpus
│ └── processed/ # Validated modeling dataset
├── docs/
│ ├── assets/ # Portfolio visualizations
│ ├── ARCHITECTURE.md # Technical design
│ └── MODEL_CARD.md # Intended use, metrics, risks, limitations
├── src/sentiment_analyzer/
│ ├── cli.py # Unified workflow interface
│ ├── data.py # Download and Spark preprocessing
│ ├── embeddings.py # FastText vectorizer
│ ├── modeling.py # BiLSTM/BiGRU construction
│ ├── batching.py # Memory-bounded Keras batches
│ ├── training.py # Final training workflow
│ ├── evaluation.py # Stratified cross-validation
│ └── inference.py # Stable prediction API
├── tests/ # Fast unit tests
├── Dockerfile
├── Makefile
└── pyproject.toml
Python 3.11 or 3.12 and Java 17+ are recommended. Java is required only for the PySpark stages.
git clone https://github.com/Dochikhoa2006/Sentiment-Analysis-Extended-RNNs.git
cd Sentiment-Analysis-Extended-RNNs
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -e ".[all]"# Download LocalDoc/application_reviews from Hugging Face
sentiment-analyzer download
# Validate, clean, and convert labels from 1–5 to 0–4
sentiment-analyzer prepare
# Fit the FastText subword vectorizer
sentiment-analyzer embeddings
# Train the selected class-balanced BiGRU model
sentiment-analyzer train --architecture gru --epochs 5
# Classify a review
sentiment-analyzer predict --text "The latest update is fast and easy to use."Example output:
5/5 — strongly satisfied (confidence: 91.3%)
The confidence above illustrates the CLI format; the actual result depends on the trained artifacts and random seed.
sentiment-analyzer evaluate \
--architectures lstm gru \
--folds 5 \
--epochs 1Cross-validation intentionally fits FastText inside every training fold to prevent vocabulary and embedding leakage from the held-out fold. This is computationally expensive but methodologically clean.
from pathlib import Path
from sentiment_analyzer.inference import SentimentPredictor
predictor = SentimentPredictor.from_artifacts(
Path("artifacts/fasttext_vectorizer.joblib"),
Path("artifacts/sentiment_bigru.keras"),
)
prediction = predictor.predict("Useful app, but the login flow is unreliable.")
print(prediction.to_dict())The image contains the inference code but deliberately excludes large model files. Train locally or retrieve trusted artifacts, then mount the artifact directory read-only:
docker build -t app-review-sentiment .
docker run --rm -it \
-v "$(pwd)/artifacts:/app/artifacts:ro" \
app-review-sentiment predict \
--text "Simple, responsive, and reliable."make install-dev
make lint
make testContinuous integration runs linting and unit tests on Python 3.11 and 3.12. Generated datasets, models, and experiment outputs remain outside Git; only code, documentation, and curated figures are versioned.
The project uses LocalDoc/application_reviews, which contains approximately 198k reviews and is distributed under CC BY-NC 4.0. The dataset is downloaded at runtime and is not redistributed here.
Review text can contain personal, offensive, or culturally specific language. Predictions should not be used for automated moderation, individual profiling, or consequential decisions. See the model card for detailed limitations and evaluation expectations.
Repository code and documentation are licensed under CC BY 4.0. The dataset has separate CC BY-NC 4.0 terms. Trained artifacts may be subject to the source dataset's non-commercial restriction; verify those terms before distribution or deployment.
If this work supports your research or portfolio review, please cite:
Do, Chi Khoa (2026). App Review Sentiment Intelligence:
FastText with Bidirectional Recurrent Neural Networks.
https://github.com/Dochikhoa2006/Sentiment-Analysis-Extended-RNNs



