Self-Directed ML Curriculum · In progress
CineML
A machine learning curriculum I set for myself, working from data cleaning up through neural networks and recommender systems, deliberately using the same 5,000 movies at every stage instead of a new toy dataset for each topic.
- Role
- Solo project
- Status
- 7 of 9 stages done, 8th underway
- Stack
- Python · scikit-learn · PyTorch · pandas · Surprise
- Dataset
- TMDB 5000 Movies
One dataset, on purpose
Most ML learning material hands you a different dataset for every technique: irises for classification, handwritten digits for neural networks, house prices for regression. Each one is chosen to make its technique look good, which is efficient for explaining the algorithm and useless for building judgment. You never develop a feel for any of the data, so you can't tell whether a result is impressive or whether the dataset was just easy.
CineML runs every stage on the same ~5,000 movies: budgets, revenue, genres, cast, crew, ratings, and reviews. By the third stage I knew what the data actually looked like: which fields were sparse, which correlations were real, where the outliers hid. That meant when a model performed well I could usually say why, and when it performed badly I could tell whether the problem was the model or the data.
The stage where the neural network lost
Stage 5 built sentiment classification the classical way: TF-IDF to turn review text into numbers, then logistic regression on top. It worked well.
Stage 6 was deep learning, so I rebuilt the same sentiment task as a neural network in PyTorch, fully expecting it to win. It didn't. The neural network was less accurate than the logistic regression it was supposed to improve on.
The reason is the dataset size. Neural networks earn their advantage by learning representations from large amounts of data; with only a few thousand examples there isn't enough signal to justify the extra capacity, and a well-chosen classical model with sensible features is simply the better tool. TF-IDF plus logistic regression is a strong baseline precisely because it doesn't need to learn what words mean from scratch.
Why this is the most useful thing in the project
It's easy to come out of an ML course believing newer means better. Having actually built both and watched the sophisticated one lose is a much more durable lesson than reading that it might. The real skill isn't knowing how to build a neural network; it's knowing when not to.
Other things that surprised me
- Class balance mattered more than model choice. In the NLP stage, how evenly the categories were split across training and test data had a severe effect on results, enough that correcting the imbalance was a bigger improvement than swapping models.
- Genre prediction is harder than it sounds. Films carry several genres at once, so it isn't one label per item; the model has to decide how many to assign, and it consistently over- or under-predicts.
- Tuning beat intuition. Random Forest was the best classifier, but running a systematic parameter search improved its accuracy, recall, and F1 together. Gradient Boosting won on the regression side; plain linear regression was mediocre.
- Clustering found things I didn't ask for. Left to group the films unsupervised, it separated out blockbusters (mostly Action and Adventure) and, separately, older classics that earned well and rated highly. Nobody labelled those groups; the structure was already in the data.
Engineering, not just notebooks
Stage 4 was the one with no new algorithms in it. It was about turning experiments into something reusable: chaining the scaling, encoding, fitting, and prediction steps into a single pipeline so the same transformations apply identically to training and new data, then saving the trained models to disk.
That stage is why there's a predict.py in the repository rather
than only notebooks. You can hand it a movie's details and get a profitability
prediction back with a confidence score, loading the saved model instead of
retraining. It's a small thing, but it's the difference between an experiment
and something another person can run.
Stage 7: where the one-dataset rule had to bend
Stage 7 is recommendation systems, the natural endpoint for a movie dataset, and it's the stage that broke the rule the whole project is built on.
Collaborative filtering learns from who rated what. It doesn't care
what a film is about; it cares that people who liked the ones you liked also
liked this other one. The TMDB set has an average rating per film and no
individual users at all, so there is no user-item matrix in it to factorise.
No amount of feature engineering conjures one. The collaborative half runs on
MovieLens ratings instead: an SVD matrix factorisation over
roughly 800 MB of real user-item ratings, trained with Surprise.
The content-based half stays on the original data, and it's the more satisfying one because it reuses earlier stages rather than starting over. It takes the plot overviews, vectorises them with the same TF-IDF vectoriser saved back in stage 5, and ranks films by cosine similarity between those vectors. The sentiment stage's artefact became the recommender's feature extractor, which is exactly the compounding that a single-dataset curriculum is supposed to produce.
The lesson in having to bring a second dataset
I set the one-dataset rule to build familiarity, and it held for six stages. Stage 7 is where it stopped being a virtue: some techniques have a shape of data they require, and if your data isn't that shape, the honest move is to admit it rather than to force a proxy and call the result a recommender. Knowing which question a dataset simply cannot answer is its own skill.
Where it's going
Stage 7 is in progress: both recommenders run, and what's left is evaluation and turning them into something callable rather than notebook cells. Stage 8 is a stretch list: fine-tuning a transformer, computer vision, and deploying a model behind an API rather than leaving it in a notebook.
The project is deliberately unfinished. It's a curriculum, and the point is the progression rather than a finished product at the end.