Hotel Review Sentiment (LSTM)
Scope note: learning project, not a production system. I trained the model from scratch and wrote the TensorFlow.js converter manually.
Goal
Train a binary sentiment classifier on real hotel reviews and deploy it client-side so predictions run in the browser with no backend.
Approach
- Split Booking.com reviews into positive/negative samples from their separate text fields. Filter ambiguous and short texts, then balance the classes (50k per class).
- Tokenize with a 15k-word vocabulary, pad sequences to 150 tokens.
- Train an LSTM (Embedding → SpatialDropout1D → LSTM → Dropout → Dense) with early stopping on validation loss.
- Evaluate on a held-out 20% test set with precision, recall, F1 per class.
- Convert the Keras model to TensorFlow.js for client-side inference (custom converter — the official one was broken by protobuf version conflicts).
Guiding questions
- Can a small LSTM trained from scratch reach useful accuracy on real hotel reviews?
- How does class balancing affect recall on negative reviews (the harder class)?
- Is client-side inference practical for a 3.8MB model?
Data
- Kaggle — 515K Hotel Reviews Data in Europe: 515,738 Booking.com reviews from 1,493 European hotels.
- Training code and evaluation scripts live in the project repository.
Headline numbers
Model architecture
Booking.com dataset515k European hotel reviews with 1-10 star ratings, split into positive and negative text.
pandasDrop ambiguous reviews, strip whitespace, filter short texts, balance classes (50k per class).
Keras TokenizerBuild 15k-word vocabulary from training set. Convert text to integer sequences, pad to 150 tokens.
Keras LSTMEmbedding(64) → SpatialDropout1D → LSTM(32) → Dropout → Dense(sigmoid). Early stopping on val loss.
scikit-learnPrecision, recall, F1 per class. Confusion matrix on held-out 20% test set.
TensorFlow.jsCustom script converts Keras weights and topology to TFJS format (official converter had protobuf conflicts). Runs client-side.
Live demo
Type a hotel review below — the model runs in your browser, nothing is sent to a server.
Conclusion
- The LSTM reaches 86% macro F1 on a held-out balanced test set, with 89% recall on negatives — the harder class.
- The full pipeline goes from raw CSV to a 3.8MB browser model: cleaning, tokenization, training with balanced sampling, threshold-independent evaluation, and custom conversion to TensorFlow.js (the official converter was broken due to protobuf version conflicts, so I wrote one manually).