Делаем прогнозирование плана с помощью BigQuery ML

BigQuery ML – это способ машинного обучения непосредственно в интерактивном хранилище данных петабайтного масштаба в облаке Google. Вы можете обучать модели машинного обучения миллионам строк за несколько минут, не перемещая данные.

Примечание: BigQuery ML теперь поддерживает извлечение обученной модели в виде TensorFlow SavedModel. Таким образом, вы можете просто экспортировать модель, а затем развернуть ее в Cloud AI Platform Predictions. Тем не менее, эта статья по-прежнему полезна в качестве напоминания о том, как просматривать веса и повторять, что BQML является открытой системой.

Однако, обучив свою модель, вы должны предсказывать с ее помощью. Из коробки BigQuery поддерживает пакетное предсказание — это подходит для приложений отчетности и приборной панели. Однако запросы BigQuery обычно имеют задержку 1-2 секунды, и поэтому возможность пакетного прогнозирования не может быть использована для онлайн-прогнозирования (например, из веб-или мобильного приложения).

Иногда ваши прогнозы должны немедленно возвращаться

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

Полный код этой статьи находится на GitHub.

Создайте модель

Давайте начнем с создания простой модели прогнозирования для прогнозирования задержек прибытия самолетов (подробнее см. Эту статью). Я буду использовать эту модель, чтобы проиллюстрировать процесс.

CREATE OR REPLACE MODEL flights.arrdelay
OPTIONS
  (model_type='linear_reg', input_label_cols=['arr_delay']) AS
SELECT
  arr_delay,
  carrier,
  origin,
  dest,
  dep_delay,
  taxi_out,
  distance
FROM
  `cloud-training-demos.flights.tzcorr`
WHERE
  arr_delay IS NOT NULL

Это заняло у меня около 6 минут, обучило 6 миллионам строк и 267 МБ данных и стоило около $ 1,25. (Бесплатный уровень BigQuery может покрыть это для вас; чтобы снизить стоимость, используйте меньшую таблицу).

Пакетный прогноз с моделью

Как только у вас есть обученная модель, пакетное предсказание можно сделать в самом BigQuery. Например, чтобы найти прогнозируемые задержки прибытия для рейса из DFW в LAX для диапазона задержек вылета, вы можете выполнить этот запрос:

SELECT * FROM ml.PREDICT(MODEL flights.arrdelay, (
SELECT 
  'AA' as carrier,
  'DFW' as origin,
  'LAX' as dest,
  dep_delay,
  18 as taxi_out,
  1235 as distance
FROM
  UNNEST(GENERATE_ARRAY(-3, 10)) as dep_delay
))

В приведенном выше запросе я жестко кодирую входные значения для carrier, origin и т. Д. И использую функцию GENERATE_ARRAY для генерации задержек вылета в диапазоне от -3 минут до 10 минут. Это дает таблицу с прогнозируемыми задержками прибытия для каждой задержки вылета:

Прогнозируемая задержка прибытия, если рейс из Далласа в Лос-Анджелес отправляется на 3 минуты раньше (dep_delay = -3) до 10 минут позже (dep_delay = 10)

Пакетный прогноз стоит недорого. Приведенный выше запрос обработал 16 КБ и стоил 0,000008 цента.

Хотя этот механизм прогнозирования работает для автономных прогнозов, вы не можете реально использовать его для онлайн-прогнозирования. Если прогнозы должны отображаться в результате взаимодействия с пользователем на веб-сайте или в мобильном приложении, вы не можете позволить себе 1-2-секундную задержку, связанную с каждым вызовом BigQuery. Обычно вам нужны задержки порядка нескольких миллисекунд, и поэтому вам нужно более быстрое решение для вывода.

Веса и масштабирование

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

Вам нужно вытащить 3 части информации:

  • Веса для каждого из ваших числовых столбцов, которые вы можете получить с помощью этого запроса:
SELECT
  processed_input AS input,
  model.weight AS input_weight
FROM
  ml.WEIGHTS(MODEL flights.arrdelay) AS model
  • Масштабирование для каждого из ваших числовых столбцов, которые вы можете получить с помощью этого запроса:
ВЫSELECT
  input, min, max, mean, stddev
FROM
  ml.FEATURE_INFO(MODEL flights.arrdelay) AS model
  • Словарь и веса для каждого из ваших категориальных столбцов, которые вы можете получить с помощью этого запроса (если вы не знакомы с UNNEST, см. Эту статью).:
SELECT
  processed_input AS input,
  model.weight AS input_weight,
  category.category AS category_name,
  category.weight AS category_weight
FROM
  ml.WEIGHTS(MODEL flights.arrdelay) AS model,
  UNNEST(category_weights) AS category

Предполагая, что вы прочитали результаты всех трех этих запросов в трех отдельных фреймов данных Pandas, вот функция, которая вычислит прогноз:

def compute_prediction(rowdict, numeric_weights, scaling_df, categorical_weights):
input_values = rowdict
# numeric inputs
pred = 0
for column_name in numeric_weights['input'].unique():
wt = numeric_weights[ numeric_weights['input'] == column_name ]['input_weight'].values[0]
if column_name != 'INTERCEPT':
meanv = scaling_df[ scaling_df['input'] == column_name ]['mean'].values[0]
stddev = scaling_df[ scaling_df['input'] == column_name ]['stddev'].values[0]
scaled_value = (input_values[column_name] - meanv)/stddev
else:
scaled_value = 1.0
contrib = wt * scaled_value
pred = pred + contrib
# categorical inputs
for column_name in categorical_weights['input'].unique():
category_weights = categorical_weights[ categorical_weights['input'] == column_name ]
wt = category_weights[ category_weights['category_name'] == input_values[column_name] ]['category_weight'].values[0]
pred = pred + wt
return pred

Я делаю следующее:
Прохожу через каждый из числовых столбцов и нахожу вес, связанный с этим столбцом. Затем я вытаскиваю среднее и стандартное отклонение и использую их для масштабирования входного значения. Произведение этих двух величин и есть вклад, связанный с этим столбцом. Затем я прохожу через категориальные столбцы. Для каждого категориального столбца существует отдельный вес, связанный с каждым значением, которое принимает столбец. Итак, я нахожу вес, связанный с входным значением, – это становится вкладом. Сумма всех вкладов – это прогноз.

Приведенный выше код предполагает, что вы обучили регрессионную модель. Если вы обучили модель классификации, вам нужно применить логистическую функцию к прогнозу, чтобы получить вероятность (чтобы избежать переполнения, обработайте вероятность для pred < -500 как ноль):

prob = (1.0/(1 + np.exp(-pred)) if (-500 < pred) else 0)

Вот пример прогнозирования задержки прибытия конкретного рейса:

rowdict = {
'carrier': 'AA',
'origin': 'DFW',
'dest': 'LAX',
'dep_delay': -3,
'taxi_out': 18,
'distance': 1235
}
predicted_arrival_delay = compute_prediction(
rowdict, numeric_weights, scaling_df, categorical_weights)

Это дает следующие столбцы и их вклад:

col = dep_delay wt = 36.5569545237 scaled_value= -0.329782492822 contrib= -12.0558435928
col = taxi_out wt = 8.15557957221 scaled_value = 0.213461991601 contrib = 1.74090625815
col = distance wt = -1.88324519311 scaled_value=0.672196648431 contrib=-1.26591110699
col= __INTERCEPT__ wt = 1.09017737502 scaled_value = 1.0 contrib = 1.09017737502
col=carrier wt=-0.0548843604154 значение =AA contrib= -0.0548843604154
col = origin wt = 0.966535564037 value = DFW contrib = 0.966535564037
col = dest wt = 1.26816262538 value = LAX contrib = 1.26816262538

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

Полный код этой статьи находится на GitHub. Наслаждайтесь!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *