В этом блоге мы хотели бы представить вам пример использования пакета forester. Мы представим сценарий использования пакета на фоне реальной истории. Он также будет включать примеры кода, анализ результатов и комментарии. Концепция пакета описана в предыдущих сообщениях блога, представляющих пакет и описывающих его более подробно.

Представим, что мы молодой домовладелец, переезжающий из Лиссабона в Варшаву, и из-за отсутствия сбережений решаем продать свою квартиру, чтобы купить новую в Польше. Наше решение поспешно, потому что в следующем месяце мы начинаем нашу новую работу в качестве исследователя в MI².AI и ничего не знаем о рынке недвижимости в Португалии. К счастью, как опытные специалисты по данным, нам удалось собрать информацию о недвижимости и создать лиссабонский набор данных. Это немного, но в нашем случае придется. Первые наблюдения представлены ниже.

Во-первых, мы хотим узнать, что происходит внутри нашего удаленного набора данных и достаточно ли он хорош для нашего анализа. Обычно мы начинаем писать утомительный сценарий исследовательского анализа данных, однако пакет forester предлагает нам функцию, которая предоставляет основную информацию о наборе данных. В этом случае мы импортируем пакет, загружаем набор данных и создаем отчет data_check() с использованием имени набора данных и имени нашего целевого столбца, которое называется Цена. Необходимый код и результаты видны ниже.

library(forester)
data(lisbon)
check <- check_data(lisbon, 'Price')

Из приведенного выше отчета мы можем узнать, что набор данных не идеален, и мы можем обнаружить некоторые проблемы, связанные со значениями столбцов.

  1. Во-первых, мы определяем статические столбцы (каждое наблюдение имеет одинаковое значение), а именно: Страна, Район и Муниципалитет.
  2. Мы также обнаруживаем, что AreaNet сильно коррелирует с AreaGross, и то же самое происходит с парой PropertyType — PropertySubType. Это означает, что эти столбцы предоставляют одинаковую информацию для нашей будущей модели.
  3. Наконец, мы обнаруживаем, что столбец с именем Id может не предоставлять никакой информации, поскольку он является столбцом индекса.

Чтобы решить эти основные проблемы с нашим набором данных, мы решили удалить вышеупомянутые столбцы, чтобы получить лучшие результаты. Отчет о проверке данных также дает нам примечание о дублирующихся столбцах, пропущенных значениях, выбросах и необычном распределении столбца «Цена», однако эти параметры допустимы в нашем случае, поэтому мы их проигнорируем.

lisbon <- select(lisbon,
                -c('Country', 'District', 'Municipality',
                   'AreaNet', 'PropertyType', 'Id'))

На данный момент мы уже немного знаем о нашем наборе данных, поэтому пришло время создать первые модели. Для этого мы используем функцию train(), которая охватывает весь конвейер AutoML. Обычно мы предоставляем только два необходимых параметра, но, поскольку мы хотим получить быстрые исходные результаты, и мы уже запустили data_check(), мы решили пропустить некоторые модули (мы отключили алгоритм случайного поиска, байесовская оптимизация и печать сообщений).

output_1 <- train(data         = lisbon,
                  y            = 'Price',
                  bayes_iter   = 0,
                  random_evals = 0,
                  verbose      = FALSE)

head(output_1$score_test)

Вывод функции train() сложен, но мы сосредоточимся на ранжированном списке. В таблице ниже можно увидеть все обученные модели с несколькими метриками, рассчитанными на тестовом подмножестве. Первая модель набрала 0,77 балла по показателю R2, что является относительно высоким показателем. Лучше всего не только R2, но и MSE (среднеквадратическая ошибка) и MAE (среднее абсолютное отклонение). Мы уже могли использовать эту модель для прогнозирования цены дома, но давайте посмотрим, сможем ли мы добиться еще большего успеха, установив другие параметры.

Мы хотим улучшить модели, изменив их гиперпараметры. Выполнение этого вручную потребует много усилий и опыта. К счастью, функция train() позволяет делать это автоматически. Мы устанавливаем для bayes_iter и random_evals значение 20, которое запускает соответствующие методы настройки во время обучения.

output_2 <- train(data         = lisbon,
                  y            = 'Price',
                  bayes_iter   = 20,
                  random_evals = 20,
                  verbose      = FALSE,
                  sort_by      = 'mse')

output_2$score_test

С помощью байесовской оптимизации мы улучшили показатель R2 для лучшей модели с 0,77 до 0,91. Существует также значительное улучшение MSE. Это модель xgboost, обученная с помощью байесовской оптимизации. Это выглядит очень многообещающе, но чтобы быть уверенным в его надежности, давайте объясним, как были достигнуты эти результаты.

К счастью, пакет forester предоставляет интерфейс для простой интеграции с пакетом DALEX, который является хорошо известным решением для объяснимого искусственного интеллекта (XAI). Всего за несколько шагов мы можем создать пояснитель и график важности признаков, который показывает нам, какие столбцы были наиболее важными для модели.

library('DALEX')
ex <- forester::explain(models    = output_2$best_models[[1]],
                        test_data = output_2$test_data,
                        y         = output_2$y)

model_parts <- DALEX::model_parts(ex$xgboost_bayes)
plot(model_parts, max_vars = 5)

Из графика выше видно, что наиболее важными факторами для модели xgboost были площадь квартиры, количество ванных комнат, широта — что означает удаленность от центра города, состояние квартиры и ее цена за квадратный метр. Все эти факторы кажутся нам также очень разумными, поэтому мы можем диагностировать, что модель ведет себя понятно, и мы ей доверяем.

На этом этапе мы проверили наши данные, обучили множество моделей и объяснили лучшую из них. Но мы хотим, чтобы вся эта информация была в одном месте! Для этого мы можем создать отчет с помощью функции report(). Он создает файл PDF или HTML, в котором информация о данных и моделях представлена ​​в формальной и понятной форме. Отчет будет подробно описан в следующем блоге.

report(output_2)

Теперь, когда у нас есть модель, мы можем предсказать стоимость нашего дома. Мы создаем наблюдение со всей необходимой информацией о нашей квартире. Мы выбираем лучшую модель, созданную пакетом forester, и делаем прогноз цены на наше наблюдение, которая равняется 214 156 евро. Теперь мы можем сохранить модель на будущее и добавить прогнозируемую цену в наше объявление!

x <- data.frame(
        'Condition' = 'Used',
        'PropertyType' = 'Homes',
        'PropertySubType' = 'Apartment',
        'Bedrooms' = 3,
        'Bathrooms' = 2,
        'AreaGross' = 320,
        'Parking' = 1,
        'Latitude' = 38.7323,
        'Longitude' = -9.1186,
        'Parish' = 'Estrela',
        'Price.M2' = 4005,
        'Country' = 'Portugal',
        'District' = 'Lisbon',
        'Municipality' = 'Lisbon',
        'AreaNet' = 160,
        'Id' = 111,
        'Price' = 0)

predictions <- predict_new(output_2, data = x)
predictions$xgboost_bayes

save(output_2)

В следующем сообщении блога мы хотели бы подробно описать основную функцию пакета forester, которая называется train(). Мы сосредоточимся на том, чтобы показать вам, как работают определенные шаги и как пользователь может формировать процесс обучения.

Если вас интересуют другие сообщения об объяснимом, справедливом и ответственном ML, подпишитесь на #ResponsibleML на Medium.
Чтобы увидеть больше контента, связанного с R, посетите https://www.r-bloggers.com.