Driven by my curiousity of how Netflix, YouTube and Spotify serve personalized recommendations, I decided to learn how to create my own recommender system.
Machine Learning Problem: Given a person’s preferences in past recipes, could I predict other new recipes they might enjoy?
I created Seasonings, a Recipe Recommender System. The motivation behind this web app is to help users discover personalized and new recipes, and prepare for grocery runs! I received a lot early positive feedback and plan future improvements to the UX and model.
I plan to use this whenever I need a jolt of inspiration in the kitchen!
All code is available on GitHub.
Background & Presentation Deck
Here are some concepts I discovered while creating my Recipe Recommendation System, and may be useful for anyone building their first recommender system.
While the MovieLens, and Yelp public dataset are both instructive, if you want to create a recommender system, I encourage you to reach for your own data set.
To appreciate the ins-and-outs of recommender system, you need a large cross section of items and user ratings. I would implore you to gather enough data, so that you can tease out interesting results before validating its performance.
The main hyper-parameter of singular value decomposition (SVD) is the number of components.
svd = TruncatedSVD(n_components=100)
A rule of thumb is to use a number of components such that you retain a reasonable amount of svd.explained_variance_ratio_
, such as 80%-90%.
While SVD provides ranked suggestions, some predicted ratings may only be a 2 or a 3. I didn't want to recommend a recipe with a predicted rating of 3, because that's below average compared to Chef John's other recipes. Therefore, I added a rule to ensure that recipes recommended were over a specific threshold >=4.
In evaluating my model, SVD performs better when the user vector is large. This is obvious, but cannot be overstated, as my app can only take up to 20 recipe ratings during the onboarding flow. In full recommender systems, ratings are continually updated from subsequent sessions, which is why Netflix learns your preferences the more you use it!
Also, as a corollary, SVD generally performed better for users with less ratings, as it was able to recommend new recipes. Nevertheless, it was useful to train the model, such that the decomposed matrix $M$ could be used on new user matrix $U$.
Users turn to recommendations for not only recipes that are homogeneous to their preferences, but also for serendipitous recipes they might not immediately think of. In my opinion, it's a strength to make content discovery less algorithmic, and more human-like.
Hybrid recommenders address this problem by solving the shortcomings of individual recommenders. For example:
It's no surprised that the algorithm that won Cinematch (Netflix's challenge), used an ensemble of multiple models. Hybrid recommenders can get very complex, with feature weighted linear stacking of the various recommenders, but that was out of scope for my first recommender system.
For recommender systems, rank based metrics are preferred over RMSE or accuracy. At the end of the day, it's about recommending new recipes that my user will like, in a ranked fashion, over predicting the exact rating.
I leaned on precision at K and recall at K, and these metrics were higher when the user had more than 3 ratings.
I had a lot of fun building this, and I gained a greater appreciation of what's going on underneath the hood of all the recommender systems I see on a daily basis. YouTube, please keep recommending me cute cat videos!