// Python · Deep Learning · NLP
Deep learning models that predict cryptocurrency market sentiment from Twitter. 20,000 tweets, two model architectures — CNN and MLP — trained and evaluated with no pretrained weights.
// Data Pipeline
// Results
Both models were evaluated on a held-out test set of 100 tweets. The MLP outperformed the CNN, likely due to the bag-of-words representation being a better fit for short, noisy tweet text.
// Live Predictions
Manual tests used during evaluation — both models predicted correctly.
// Software Stack
Built with Keras on TensorFlow. Data collected via Tweepy. Sentiment labels generated automatically using VADER.
Twitter API client. Searched for crypto-opinion keywords — "crypto will", "crypto can", "crypto is" — filtering out retweets and links to target opinionated text.
Rule-based sentiment analyzer from NLTK. Used to auto-classify 20,000 tweets as positive or negative, producing training labels without manual annotation.
Both models built with Keras Sequential API. CNN uses Embedding → Conv1D → MaxPooling → Dense. MLP uses bag-of-words frequency vectors as input.
Tokenization, stopword removal, and VADER sentiment analysis. Preprocessing pipeline strips punctuation, non-alphabetic tokens, and common English stop words.
Vectorization strategy for the MLP. Each tweet is encoded as a frequency vector over the full vocabulary — 26,836 dimensions — fed directly into a dense layer.
Custom vocabulary built from the corpus, retaining only words appearing in 2+ tweets. Rare and misspelled words are excluded before training.
// How It Works
Two separate pipelines — one per model — share the same preprocessing and labeling steps.
Tweepy's cursor API streams tweets matching keyword filters over a date range. Each tweet is cleaned — punctuation stripped, stopwords removed, links and retweet markers dropped — then written to reviews.txt. A vocabulary counter tracks word frequency; words appearing fewer than twice are excluded from vocab.txt.
VADER's polarity scorer produces positive, negative, and neutral scores for each cleaned tweet. If the negative score dominates, the tweet is labeled 0. If positive dominates, it's labeled 1. Neutral tweets are discarded. Labels are saved to classify.txt, aligned line-by-line with reviews.txt.
Tweets are integer-encoded and padded to uniform length. An embedding layer maps each word to a 100-dim vector. A Conv1D layer with 32 filters and kernel size 8 extracts local n-gram features, followed by max pooling, a dense ReLU layer, and a sigmoid output. Trained for 50 epochs with binary cross-entropy.
Tweets are encoded as frequency vectors over the full 26,836-word vocabulary using texts_to_matrix(mode='freq'). A single hidden layer of 50 ReLU units feeds into a sigmoid output. Trained for 100 epochs. Higher accuracy than the CNN — the global word-frequency representation works well for short social media text.
// Reflection
Things that weren't obvious until I built it.
Filtering by #crypto pulled mostly startup promotion and bot activity — essentially useless for sentiment. Switching to phrase filters like "crypto will" and "crypto can" targeted tweets that actually expressed an opinion about the market.
Manually annotating 20,000 tweets wasn't an option. VADER's polarity scores provided automatic classification — positive, negative, or neutral — turning raw collected text into a usable training set without any manual annotation.
95% test accuracy vs. 90% — the simpler model won. The poster notes this may be due to the structural differences between the two architectures and how each represents tweet text. Bag-of-words frequency vectors suited the MLP better than the CNN's sequence-based embedding approach.