В моем предыдущем посте я говорил о том, как вы можете использовать textbox из Machinebox для синтаксического анализа ввода на естественном языке в ваших приложениях. Я только что завершил поддержку изображения suggestionbox в моем ящике Rust, поэтому в этом посте я расскажу о том, как использовать его для создания рекомендателя фильмов.

Поле предложений позволяет создавать и сохранять модели. Для каждой из этих моделей вы можете запросить прогнозы из числа возможных вариантов. Машина учится, записывая вознаграждение за конкретный прогноз. Машина решает, какие варианты она представит клиенту, а затем улучшает свою способность предсказывать, выявляя закономерности, на основе которых вознаграждаются предметы по сравнению с другими, которые были представлены.

Прежде чем перейти к коду, я хочу немного разойтись по теме рекомендательных систем. Насколько я могу судить, машина suggestionbox не предназначена для работы в качестве рекомендателя продуктов Amazon, где набор вариантов - все продукты, а корпус клиентов - все возможные пользователи.

Скорее, suggestionbox модели - это меньшие наборы вариантов, которые вы хотите тренировать, чтобы улучшить некоторые статистические данные или помочь с некоторой конечной задачей. В моем случае я хочу научить эту модель выбирать фильмы для просмотра, так как я не могу принимать собственные решения.

Важным моментом здесь является то, что модель - это не список всех известных фильмов. Это может быть несколько сотен фильмов, отобранных моим другом-экспертом по кино или критиком, или опубликованный список 100 лучших фильмов всех времен.

В дополнение к этой небольшой модели кураторских фильмов я мог бы также поддерживать модель, которая имеет категории и делать прогнозы и вознаграждать категории на основе шаблонов просмотра. Я мог бы также создать отличную модель из ничего, кроме «рождественских боевиков» - все зависит от того, что я хочу получить от модели. Прежде чем создавать модель, мне нужно решить, в чем я хочу, чтобы эта модель мне помогала; то, что я хочу, чтобы предсказания облегчили. Также очень легко повторить мою модель и со временем внести изменения, чтобы улучшить мои результаты.

В качестве примера приложения я создал небольшой набор из дюжины фильмов, в основном состоящих из фильмов моего детства. Вы можете увидеть файл JSON в репозитории github здесь. Следующий код загружает эту модель из файла JSON на диск, создает в suggestionbox, а затем выполняет 1000 прогнозов. При каждом прогнозе этот код ищет Крепкий орешек, награждает его и выбирает первый элемент, если Крепкий орешек не включен.

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)?;
            }
        }
    }

Поскольку каждый запрос прогноза имеет один и тот же набор функций (кто-то, кто любит рождественские приключенческие фильмы из США), и каждое предсказание приводит к вознаграждению Крепкий орешек, мы должны иметь возможность сделать один окончательный прогноз и посмотреть, что мы получим:

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);

Когда мы выкинем окончательный прогноз, мы увидим, что Крепкий орешек набирает наивысший балл (естественно, поскольку мы играли в систему, чтобы это произошло). Хотя я могу согласиться с этой рекомендацией, это нереально. Благодаря большему количеству сценариев прогнозирования и вознаграждения мы сможем получать более точные прогнозы. Консоль suggestionbox фактически поставляется с симулятором, в котором вы можете создавать симулированных пользователей и определять, как они выбирают. Вы можете наблюдать за симуляцией в реальном времени и увидеть, как это влияет на обучение модели!

Не стесняйтесь играть с примером в репозитории Github, чтобы придумать более творческие способы обучения модели для получения полезных рекомендаций по фильмам.

Я очень рад, что мне самому не придется писать какие-либо алгоритмы прогнозирующего обучения. Я очень рад, что мне почти не нужно делать вообще никакой работы, чтобы встраивать прогнозные модели в свои приложения, просто запустив образ докера и нажав его с помощью простого клиентского SDK, и, надеюсь, вы тоже!