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.

github

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

  1. 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).
  2. Tokenize with a 15k-word vocabulary, pad sequences to 150 tokens.
  3. Train an LSTM (Embedding → SpatialDropout1D → LSTM → Dropout → Dense) with early stopping on validation loss.
  4. Evaluate on a held-out 20% test set with precision, recall, F1 per class.
  5. 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

Headline numbers

Training reviews100kbalanced sample
Total dataset515kBooking.com
Macro F10.86
Accuracy85%
Neg. recall89%
Model size3.8MBbrowser-ready

Model architecture

Textreview
Tokenizer15k vocab
Embedding64 dim
LSTM32 units
Densesigmoid
Output± sentiment
1
CollectBooking.com dataset

515k European hotel reviews with 1-10 star ratings, split into positive and negative text.

2
Cleanpandas

Drop ambiguous reviews, strip whitespace, filter short texts, balance classes (50k per class).

3
TokenizeKeras Tokenizer

Build 15k-word vocabulary from training set. Convert text to integer sequences, pad to 150 tokens.

4
TrainKeras LSTM

Embedding(64) → SpatialDropout1D → LSTM(32) → Dropout → Dense(sigmoid). Early stopping on val loss.

5
Evaluatescikit-learn

Precision, recall, F1 per class. Confusion matrix on held-out 20% test set.

6
DeployTensorFlow.js

Custom 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.

Loading model in browser...
Try an example:

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).
PythonKerasTensorFlowLSTMNLPTensorFlow.jsscikit-learn