Building a Movie Recommender with Machinebox (and Rust!)

Kevin Hoffman
3 min readFeb 9, 2018

--

In my previous post I talked about how you can use the textbox from Machinebox to parse natural language input in your applications. I’ve just completed support for the suggestionbox image in my Rust crate so in this post I’m going to talk about how to use that to build a movie recommender.

The suggestion box lets you create and store models. For each of those models, you can request predictions from among choices. The machine learns by recording the reward for a particular prediction. The machine decides which options it will present to the client and then improves its ability to predict by inferring patterns from which items are rewarded compared to the others that were presented.

Before I get into the code, I want to diverge a little on the topic of recommendation engines. From what I’ve been able to tell, the suggestionbox machine is not designed to work like an Amazon product recommender where the corpus of choices is all products and the corpus of clients is all possible users.

Rather, suggestionbox models are smaller sets of choices that you want to train in order to improve some statistic or assist with some finite task. In my case, I want to train this model to pick movies for me to watch as I am incapable of making up my own mind.

The important part here is that the model is not the list of all known movies. It might be a few hundred movies hand-picked by my movie expert friend, or a critic, or maybe a published list of the top 100 movies of all time.

In addition to this small model of curated movies, I might also maintain a model that has categories and make predictions and reward categories based on viewing patterns. I could also create a distinct model with nothing but “Christmas action movies” — it all depends on what I want to get out of the model. Before I create a model, I need to decide what I want that model to help me do; what I want the predictions to facilitate. It’s also super easy to iterate on my model and make changes over time to improve my results.

For my sample application, I created a small set of a dozen movies consisting largely of movies from my childhood. You can see the JSON file in the github repository here. The following code loads this model from the JSON file on disk, creates in the suggestionbox, and then goes through 1,000 predictions. Upon each prediction, this code looks for “Die Hard” and rewards it and picks the first element if Die Hard is not included.

fn suggestion_sample() -> Result<(), machinebox::Error> {
let mut model_file = File::open("examples/movie_model.json")?;
let movie_model = Model::from_file(&mut model_file)?;
println!(
"Loaded {} choices from the movie demo model",
movie_model.choices.len()
);
let sb = Suggestionbox::new("http://localhost:8080");
let _ = sb.delete_model("movie_demo"); // Remove before we start
let _res = sb.create_model(&movie_model)?;
let request = PredictionRequest {
inputs: vec![
Feature::number("age", 42.0),
Feature::list("favorite_genres",
vec!["action", "christmas", "adventure"]),
Feature::keyword("country", "USA"),
],
};
println!("Picking Die Hard from 1,000 predictions...");
for _iter in 0..1000 {
let predict = sb.predict("movie_demo", &request)?;
let diehard =
predict.choices.iter().find(|c| c.id == "diehard");
match diehard {
Some(ref prediction) => {
sb.reward("movie_demo",
&prediction.reward_id, 1.0)?;
}
None => {
sb.reward("movie_demo",
&predict.choices[0].reward_id, 1.0)?;
}
}
}

Because every prediction request had the same set of features (someone who loves Christmas action-adventure movies from the USA), and each prediction results in rewarding Die Hard, we should be able to make one final prediction and see what we get:

let response = sb.predict("movie_demo", &request)?;
println!("Prediction response post-training: {:#?}", response);
let stats = sb.get_model_stats("movie_demo")?;
println!("model stats - {:#?}", stats);

When we dump out the final prediction, we’ll see that Die Hard comes up with the highest score (naturally, since we gamed the system to make that happen). While I might agree with this recommendation, this is not realistic. With a larger variety of predict-reward scenarios, we’d be able to get more accurate predictions. The suggestionbox console actually comes with a simulator where you can create simulated users and determine how they choose. You can watch the simulation in real-time and see how it effects the model learning!

Feel free to play with the example in the Github repo to come up with more creative ways to train the model to get useful movie recommendations.

I am super excited about not having to write any of the predictive learning algorithms myself. I’m excited about having to do almost no work whatsoever in order to embed predictive models into my applications just by firing up a docker image and hitting it with a simple client SDK and hopefully you are too!

--

--

Kevin Hoffman
Kevin Hoffman

Written by Kevin Hoffman

In relentless pursuit of elegant simplicity. Tinkerer, writer of tech, fantasy, and sci-fi. Converting napkin drawings into code for @CapitalOne

No responses yet