Redesigning Recommendations with Rouxcommender

Rianne McCartney
May 7 · 6 min read

When you have a rapidly expanding menu, how do you ensure that your customers are seeing the most relevant choices for them?

Our tech team is split up into different tribes at Gousto. Unsurprisingly, the Menu Tribe is responsible for all of the goings-on surrounding our menu, a pretty key bit of the business. As a tribe, we have ambitious goals to increase the amount of choice on the menu. With this, the role of serving personalised menus, according to the individual customer’s preferences, will become more crucial. First step — improve our recommendations algorithm.

Background
Currently, you may not notice this, but when you click on any of the categories within our menu, they are ordered according to what we predict you would prefer, based on your order history. So hopefully, if our current recommender has been doing its job properly, the top few recipes will be right up your street, but towards the bottom becomes a bit ‘meh’.

Girl staring at table to food
Top choices from our recommender

80% of our customers see the menu in this way at the moment, but we then have 20% of customers we can’t provide recommendations for as we don’t know enough about them.

Current Model

Our existing recommendations system has been in place for several years and has limitations. We run all users through our recommendations model once a week which means it takes a long time to run and we’re not fully utilising all of the data we have available. For example, if you tell us that you’re doing Veganuary on 1st January, we won’t reflect that in your recommendations until the following week. Ideally, we want to be able to show you tofu and veggie burgers straight away so that you know what’s on offer for your first box in January.

The Science

Recommender systems are used by various online companies in order to help users find compelling content from a large corpora (a big bunch of items). You’ve probably had recommendations provided for you by platforms such as Netflix, YouTube and Twitter.

Ultimately, what we want to do is help our users find the recipes that they’d most enjoy. We can do this by taking a ‘content-based’ approach, so we identify similar items that the user has ordered in the past. The benefit of this is that it is highly personalised and based on the user’s preference. However, this method can often result in low diversity in the recommendations it produces as it is a closed feedback loop. What this means is that if you order the Ultimate Cheeseburger With Bacon & Rosemary Fries (amazing), we’ll then show you more similar recipes — maybe the Chipotle Beef Burger (also good) and the American Chicken Burger With Bacon Jam 🤤. If you are then only shown these items, you will only ever order these items unless you make a special effort to browse other areas of the menu. Then the recommender sees that you’ve chosen another burger, the cycle continues and you are only ever shown burgers for the rest of your life. I mean, this is good because burgers are great, but you would probably need to take up marathon running to combat all those calories.

Our burger scenario isn’t great for Gousto, we don’t want our users to think that we only have burgers available when the reality is that we have loads of recipes that they’re potentially interested in. If a user keeps seeing the same recipes and then start having the perception that Gousto ranges are limited, they’ll soon get bored and churn. Alternatively, the search for the recipes they actually want is too difficult and they give up before they’ve ordered.

The solution? Collaborative filtering? This looks at what other similar users like in order to make recommendations. So if you’ve never seen a Pad Thai on the menu before, we can’t be sure whether you’ll like it or not. But if we have a customer that’s made similar choices to you before, and they’ve been raving about the Pad Thai, we can guess that you might like it too.

This adds some level of diversity but doesn’t solve all of the problems. If all similar customers order the same things, then they’ll just end up in a slightly bigger, more active echo chamber. It might also have the effect of drowning out your personal taste, and only recommending popular options.

Our current recommender system combines the two approaches above:

  • Content-based
  • Collaborative Filtering

We train two separate recommenders and then average the predictions. We then get it to tell us the probability of a user choosing a specific recipe, and then a shortlist of the top 15 recipes.

Once we’ve done all of this, we then need to check that it works. We run an accuracy metric called Basket Match. How many of the recipes we recommended did you actually put in your basket? This kinda works for our current menu of 50 recipes, however, we have big aims to extend the menu choice and relying solely on this metric won’t work once we’re up to 100+ recipes.

As we offer more choice on the menu, how can our recommendations algorithm support getting the right recipes in front of the right customers?

Rouxcommender

Meet Rouxcommender. Rouxcommender is our shiny new recommendations system that learns about Gousto customers and decides on how we should order the recipes on the menu. We currently have Goustav who creates efficient menus through data science, and Rica who creates optimum recipe combinations.

With Rouxcommender, we wanted to create a new API to serve recommendations to the menu. Neither Goustav or Rica are served via APIs, so doing so for Rouxcommender is a new and exciting challenge for the team.

Three robots
Three robots
Goustav, Rica and Rouxcommender

The Approach

Our Turnips squad is responsible for this initiative and we’re a cross-functional team; so whilst the Data Science engineers focus on Rouxcommender, the back end engineers will be busy redesigning the recommendations platform. This is a massive project which will have significant code changes and will affect all customers, so we’re taking an iterative approach. Firstly we have to expose our current recommendations algorithm via an API to allow for on-demand retrieval. Customer data will be fed to the algorithm via asynchronous methods which will reduce bottlenecks during the training of the algorithms. We will also be caching the results of the recommendations to reduce refreshing for the same user.

Once the data is available, back to the DS engineers to build the brand new, fancy recommender. For this, we will be using deep neural networks. These are essentially modelled after how neurons in the human brain work and the technology to support this has vastly improved over the past few years.

It will be comprised of two parts, the user model and the recipe model. Each part will cluster similar users and similar recipes and group them all together in a little gang, e.g the ‘Curry gang’ or ‘Family that hates coriander and mushrooms gang’. If it is a new recipe or user that doesn’t belong to a gang, there is an extra layer in the model that will sort this out. All of this is then fed into a series of neural network layers to compute predictions.

Once we’re at this stage, we have just 1 model instead of multiple ones that we need to average out. Much simpler.

Initially, the recommender will be using basic information that we already have available, however, we have big plans for what we can do with it. If you rate a recipe a 5, we want our recommender to know about it so we can start showing you more similar things. If you leave a comment to say a recipe was disgusting, we want to know about this so we stop showing you similar things. Eventually, we should be able to know your dinner options better than you know yourself.

Gousto Engineering & Data