КулЛиб - Классная библиотека! Скачать книги бесплатно 

Машинное обучение. Паттерны проектирования [Валлиаппа Лакшманан] (pdf) читать онлайн

Книга в формате pdf! Изображения и текст могут не отображаться!


 [Настройки текста]  [Cбросить фильтры]
Machine Learning Design Patterns
Solutions to Соттоп Challenges in Data
Preparation, Model Building, and MLOps

Valliappa Lakshmanan, Sara Roblnson,
and Michael Мипп

Beijing • Boston • Farnham • Sebastopol • Tokyo

O'REILLY

Валлиаппа Лакшманан

Сара Робинсон
Майкл Мунн

Машинное обучение
Паттерны проектированиS1

Санкт-Петербург

«БХВ-Петербург»

2022

УДК

ББК

004.4'236
32.973.26-018
Л\9

Лакшманан, В.
Л\9

Машинное обучение. Патrерны проектирования: Пер. с англ./
В. Лакшманан, С. Робинсон, М. Мунн.

448

СПб.: БХВ-Петербург,

-

2022. -

с.: ил.

ISBN 978-5-9775-6797-8
Приводимые в книге патrерны проектирования отражают лучшие практические

подходы к решению типичных задач машинного обучения. Указанные паттерны,
реализованные

в

программном

коде,

сконцентрировали

опыт

сотен

в простые и легкодоступные советы. Книга содержит подробный разбор

экспертов

30

патrер­

нов, служащих для представления данных и задач, тренировки моделей, отказо­

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

Для программистов в области машинного обучения
у дк

ББК

004.4'236
32.973.26-018

Научный редактор:
Архитектор решений,
руководитель группы разработки компании КРОК

Дмитрий Бардин

Группа подготовки издания:
Руководитель проекта

Евгений Рыбаков

Зав. редакцией

Людмила Гауль

Компьютерная верстка

Оль?и Сергиенко

Оформление обложки

Зои Канторович

©2022 BHV
Authorized Russian translation ofthe English edition of Machine Learning Design Panerns
ISBN 9781098115784 © 2021 Valliappa Lakshmanan, Sara RoЬinson, and Michael Munn.
This translation is puЫished and sold Ьу permission ofO'Reilly Media, lnc., which owns or controls all rights to
and sell the same.
Авторизованный перевод с английского языка на русский издания

puЫish

Machine Learning Design Panerns

ISBN 9781098115784 © 2021 Valliappa Lakshmanan, Sara RoЬinson, Michael Munn.
Перевод опубликован и продается с разрешения компании-правообладателя O'Reilly Media, lnc.

Подписано в печать 02.02.22.
Формат 70х100 1 / 16 . Печать офсетная. Усл. печ. л. 36,12.
Тираж 1200 экз. Заказ № 3478.
"БХВ-Петербург", 191036, Санкт-Петербург, Гончарная ул., 20.
Отпечатано с готового оригинал-макета

ООО "Принт-М",

ISBN 978-1-098-11578-4
ISBN 978-5-9775-6797-8

142300, М.О , г. Чехов, ул. Полиграфистов, д. 1

(англ.)

© Valliappa Lakshmanan, Sara Robinson, Michael Munn, 2021

(рус.)

© Перевод

на русский язык, оформление

ООО "БХВ-Петербурr", ООО "БХВ".

2022

Оглавление

Об авторах."".""" ... "."."" ... "."" ... "."" ..... "".".""."."".""." ..... "."" .... "... "".""" ... ".... 15

Предисловие ."".""."".""." ... "... "."""."".""." ... ""." ... "... "... "".""."" .. "" ... ""."" ... ""17

Для кого эта книга предназначена? .............................................................................................. 17

Чего в книге нет .............................................................................................................................

17

Примеры исходного кода .............................................................................................................. 19
Условные обозначения, принятые в книге

.................................................................................. 19

Благодарности ................................................................................................................................ 20

Глава 1. Потребность в паттернах машинного обучения"".""""""."""."."""""23
Что такое паттерны? ...................................................................................................................... 23
Как пользоваться этой книгой ...................................................................................................... 25
Терминология машинного обучения

........................................................................................... 25

Модели и фреймворки ............................................................................................................. 26
Данные и инженерия признаков ............................................................................................. 28
Рабочий поток машинного обучения

..................................................................................... 30

Инструментарий для работы с данными и моделями ........................................................... 31
Роли ........................................................................................................................................... 32

.................................................................. 34
...................................................................................................................... 35
Воспроизводимость ................................................................................................................. 37
Смещение данных .................................................................................................................... 38
Масштаб .................................................................................................................................... 40
Несколько целевых установок ............................................................................................... .40
Резюме ............................................................................................................................................ 41

Распространенные проблемы машинного обучения
Качество данных

Глава 2. Паттерны для представления данных""""""""""."".""""""."""""""" 43
Простые представления данных ................................................................................................... 45

Числовые входные значения .................................................................................................. .46
Почему желательно выполнять нормализацию ........................................................ .46
Зачем нормализовать числовые значения из промежутка

[-1; 1]? ..................................... .46

Линейная нормализация .............................................................................................. .47
Не выбрасывайте 'выбросы' ........................................................................................48
Нелинейные преобразования ....................................................................................... 50

Массив чисел ................................................................................................................. 52
Категориальные входные значения ........................................................................................ 53
Кодирование с одним активным состоянием ............................................................. 5 3
Кодирование с использованием фиктивных переменных

или кодирование с одним активным состоянием? ............................................................ 54
Массив категориальных переменных

......................................................................... 56

6

Оглавление

ПАТТЕРН

1.

Хешированный признак ......................................................................................... 57

................................................................................................................... 57
.................................................................................................................................... 58
Почему это работает ................................................................................................................ 60
Входные значения за пределами словаря ................................................................... 60
Высокая кардинальность .............................................................................................. 60
Холодный пуск ............................................................................................................. 60
Компромиссы и альтернативы ................................................................................................ 61
Коллизия корзин ........................................................................................................... 61
Асимметрия ................................................................................................................... 62
Агрегатный признак ..................................................................................................... 62
Гиперпараметрическая настройка ............................................................................... 63
Криптографический хеш .............................................................................................. 63
Порядок операций ........................................................................................................ 65
Пустые хеш-корзины .................................................................................................... 65
ПАТТЕРН 2. Векторные вложения .............................................................................................. 65
Постановка задачи ................................................................................................................... 65
Решение .................................................................................................................................... 67
Векторные вложения текста ........................................................................................ 69
Векторные вложения снимков ..................................................................................... 72
Почему это работает ................................................................................................................ 72
Компромиссы и альтернативы ................................................................................................ 75
Выбор размерности вложения ..................................................................................... 75
Автокодировщики ........................................................................................................ 76
Контекстно-языковые модели ..................................................................................... 77
Векторные вложения на хранилище данных .............................................................. 79
ПАТТЕРН 3. Синтетический признак ......................................................................................... 80
Постановка задачи ................................................................................................................... 80
Решение .................................................................................................................................... 80
Соединения признаков в BigQuery ML ....................................................................... 83
Соединение признаков в TensorFlow .......................................................................... 84
Почему это работает ................................................................................................................ 85
Компромиссы и альтернативы ................................................................................................ 86
Манипулирование числовыми признаками ................................................................ 86
Манипулирование высокой кардинальностью .......................................................... 87
Потребность в регуляризации ..................................................................................... 88
ПАТТЕРН 4. Мультимодальный вход ......................................................................................... 89
Постановка задачи ................................................................................................................... 89
Решение .................................................................................................................................... 91
Компромиссы и альтернативы ................................................................................................ 92
Табличные данные самыми разными способами ....................................................... 93
Мультимодальное представление текста ................................................................... 94
Постановка задачи

Решение

Как работает мешок слов ............................................................................................. 9 5
Мультимодальное представление снимков ................................................................ 99
Сверточная нейронная сеть

....................................................................................... 100

Мультимодальные представления признаков и интерпретируем ость модели

Резюме

..... 105
.......................................................................................................................................... 105

Оглавление

Глава

3. Паттерны для

ПАТТЕРН

5.

представления задачи

7

...................................................... 107

Переформулировка ............................................................................................... 108

................................................................................................................. 108
.................................................................................................................................. 108
Почему это работает .............................................................................................................. 11 О
Улавливание неопределенности ................................................................................ 110
Изменение целевой установки ................................................................................... 112
Компромиссы и альтернативы .............................................................................................. 113
Сгруппированные результаты ................................................................................... 113
Другие подходы к улавливанию неопределенности ............................................... 114
Прецизионность предсказаний .................................................................................. 115
Ограничение предсказательного диапазона ............................................................. 115
Искаженность в метке ................................................................................................ 117
Многозадачное обучение ........................................................................................... 118
ПА ТТЕРН 6. Мультиметка ......................................................................................................... 119
Постановка задачи ................................................................................................................. 119
Решение .................................................................................................................................. 120
Сигмоидная активация против активации с функцией мягкого максимума .......................... 121
Компромиссы и альтернативы .............................................................................................. 122
Сигмоидный результат для моделей с двумя классами .......................................... 122
Какую функцию потери следует использовать? ...................................................... 123
Разбор сигмоидных результатов ............................................................................... 124
Соображения в отношении наборов данных ............................................................ 125
Входные данные с перекрывающимися метками .................................................... 126
Один против всех ........................................................................................................ 127
ПА ТТЕРН 7. Ансамбли ............................................................................................................... 128
Постановка задачи ................................................................................................................. 128
Решение .................................................................................................................................. 129
Бэггинг ......................................................................................................................... 130.
Бустинг ........................................................................................................................ 13 1
Стэкинг ........................................................................................................................ 132
Почему это работает .............................................................................................................. 134
Бэггинг ......................................................................................................................... 134
Бустинг ........................................................................................................................ 135
Стэкинг ........................................................................................................................ 136
Компромиссы и альтернативы .............................................................................................. 136
Увеличенное время тренировки и проектирования ................................................. 137
Отсев в качестве бэггинга .......................................................................................... 13 7
Снижение модельной интерпретируем ости ............................................................. 13 7
Выбор правильного инструмента для задачи ........................................................... 138
Другие ансамблевые методы ..................................................................................... 138
ПАТТЕРН 8. Каскад .................................................................................................................... 139
Постановка задачи ................................................................................................................. 139
Решение .................................................................................................................................. 140
Компромиссы и альтернативы .............................................................................................. 145
Детерминированные входные данные ...................................................................... 145
Одиночная модель ...................................................................................................... 145
Внутренняя согласованность ..................................................................................... 146
Предварительно натренированные модели .............................................................. 146
Постановка задачи

Решение

8

Оглавление

Изменение контекста вместо каскада

........... " ........ " .......... " ..... " .. " ......................... 14 7
................................................................................... 14 7
ПАТТЕРН 9. Нейтральный класс ............................................................................................... 147
Постановка задачи ................................................................................................................. 148
Решение .................................................................................................................................. 148
Почему это работает .............................................................................................................. 149
Синтетические данные ............................................................................................... 149
В реальном мире .................................................................. " ..................................... 150
Компромиссы и альтернативы .............................................................................................. 151
Когда эксперты расходятся во мнениях ................................................................... 151
Удовлетворенность клиента ...................................................................................... 152
В качестве подхода к улучшению векторных вложений ........... " .. " .. " ................... 152
Переформулировка с использованием нейтрального класса .................................. 152
ПАТТЕРН 10. Перебалансировка .............................................................................................. 153
Постановка задачи ................................................................................................................. 153
Решение .................................................................................................................................. 154
Выбор метрики оценивания ....................................................................................... 155
Понижающий отбор ................................................................................................... 156
Взвешенные классы .................................................................................................... 158
Смещенность выходного слоя .................................................................................... 159
Повышающий отбор ................................................................................................... 159
Компромиссы и альтернативы .................. " .............................. " ........... " ............................. 161
Переформулировка и каскад ...................................................................................... 161
Обнаружение аномалий ............................................................................................. 164
Число примеров миноритарного класса ........ "" ........ "." ... " ............................ "."" .. 166
Сочетание разных технических приемов ... " ................ " ............................... " .... "." 166
Выбор архитектуры модели ....................................................................................... 167
Важность объяснимости ............................................................................................ 168
Резюме .......................................................................................................................................... 170
Регрессия в редких ситуациях

Глава

4. Паттерны для

тренировки моделей ......................................................... 173

Типичный цикл тренировки

.......... " .......................................................... " ............................... 173
.................................................................................... 173
Цикл тренировки в Keras ............... "" ......................... " ......................................................... 174
Паттерны для выполнения тренировки ................................................................................ 175
ПА ТТЕРН 11. Полезное переобучение ............................................. " ...................................... 175
Постановка задачи ................................................................................................................. 175
Решение .................................................................................................................................. 177
Почему это работает .............................................................................................................. 178
Компромиссы и альтернативы .............................................................................................. 179
Интерполяция и теория хаоса .................................................................................... 180
Методы Монте-Карло ................................................................................................. 180
Дискретизации под управлением данных ......... "". "." " ............. " ............. " .......... ". 181
Глубокий метод Галеркина ......................................................................................... 182
Неограниченные области ........................................................................................... 182
Дистиллирование знаний нейронной сети ............................................................... 183
Переобучение на пакете данных ............................................................................... 183
ПА ТТЕРН 12. Контрольные точки ................................. " ............. " .......................................... 185
Постановка задачи ................................................................................................................. 185
Решение .................................................................................................................................. 185
Контрольные точки в РуТогсh .................................... ".""." ... " ...... "." ... " ..... " ....... ""187
Стохастический градиентный спуск

Оглавление

9

Почему это работает .............................................................................................................. 188

189
189
Тонкая настройка ........................................................................................................ 192
Переопределение эпохи ............................................................................................. 193
ПА ТТЕРН 13. Трансферное обучение ....................................................................................... 197
Постановка задачи ................................................................................................................. 197
Решение .................................................................................................................................. 198
Узкий слой ................................................................................................................... 199
Реализация трансферного обучения .......................................................................... 203
Предварительно натренированные векторные вложения ....................................... 204
Почему это работает .............................................................................................................. 205
Компромиссы и альтернативы .............................................................................................. 207
Тонкая настройка против извлечения признаков .................................................... 207
Фокус внимания на снимковых и текстовых моделях ............................................ 209
Векторные вложения слов и предложений ............................................................... 21 О
ПАТТЕРН 14. Распределительная стратегия ............................................................................ 211
Постановка задачи ................................................................................................................. 211
Решение .................................................................................................................................. 212
Синхронная тренировка ............................................................................................. 212
Параллелизм распределенных данных в PyTorch .......................................................... 214
Асинхронная тренировка ........................................................................................... 215
Почему это работает .............................................................................................................. 217
Компромиссы и альтернативы .............................................................................................. 219
Параллелизм модели .................................................................................................. 219
Параллелизм модели или параллелизм данных? .......................................................... 220
Микросхемы ASIC для более высокой производительности
при меньших затратах ................................................................................................ 220
Выбор размера пакета ................................................................................................ 221
Минимизация ожидания ввода-вывода .................................................................... 222
ПАТТЕРН 15. Гиперпараметрическая настройка ..................................................................... 223
Постановка задачи ................................................................................................................. 223
Ручная настройка ................................................................................................................... 224
Поиск по сетке и комбинаторный взрыв .................................................................. 225
Решение .................................................................................................................................. 226
Почему это работает .............................................................................................................. 228
Нелинейная оптимизация ........................................................................................... 229
Байесова оптимизация ................................... ,............................................................ 230
Компромиссы и альтернативы .............................................................................................. 231
Полноуправляемая гиперпараметрическая настройка .... " ...................................... 231
Генетические алгоритмы ............................................................................................ 234
Резюме .......................................................................................................................................... 235
Компромиссы и альтернативы ..............................................................................................
Досрочная остановка ..................................................................................................

Глава 5. Паттерны для отказоустойчивой обработки""""""""""""""".""""".237
Функция обслуживания без поддержки состояния

......................................... 237
..............................................................................238
Постановка задачи ................................................................................................................. 239
Решение .................................................................................................................................. 241
Экспорт модели .......................................................................................................... 241
Предсказательный вывод на языке Python ............................................................... 242
Создание сервиса ........................................................................................................ 243

ПАТТЕРН

16.

Функции без поддержки состояния

10

Оглавление

Почему это работает .............................................................................................................. 243

............................................................................................. 243
............................................................................................... 244
Языковая нейтральность ............................................................................................ 245
Мощная экосистема .................................................................................................... 245
Компромиссы и альтернативы .............................................................................................. 246
Прикладная функция обслуживания ......................................................................... 246
Несколько сигнатур .................................................................................................... 248
Онлайновое предсказание .......................................................................................... 248
Предсказательная библиотека ................................................................................... 250
ПАТТЕРН 17. Пакетное обслуживание ..................................................................................... 250
Постановка задачи ................................................................................................................. 250
Решение .................................................................................................................................. 251
Почему это работает .............................................................................................................. 252
Компромиссы и альтернативы .............................................................................................. 254
Пакетные и потоковые конвейеры ............................................................................ 255
Кэшированные результаты пакетного обслуживания ............................................. 256
Лямбда-архитектура ................................................................................................... 257
ПА ТТЕРН 18. Непрерывное оценивание модели ..................................................................... 258
Постановка задачи ................................................................................................................. 258
Решение .................................................................................................................................. 259
Концепция ................................................................................................................... 259
Развертывание модели ............................................................................................... 260
Сохранение предсказаний .......................................................................................... 261
Улавливание эмпирического наблюдения ................................................................ 262
Оценивание результативности модели ..................................................................... 262
Непрерывное оценивание .......................................................................................... 264
Почему это работает .............................................................................................................. 265
Компромиссы и альтернативы .............................................................................................. 265
Триггеры для перетренировки ................................................................................... 266
Бессерверные триггеры ............................................................................................. 266
Плановая перетренировка .......................................................................................... 267
Валидация данных с помощью TFX ......................................................................... 268
Оценивание интервала перетренировки ................................................................... 269
ПАТТЕРН 19. Двухфазные предсказания ................................................................................. 270
Постановка задачи ................................................................................................................. 270
Решение .................................................................................................................................. 272
Фаза 1: построение офлайновой модели ................................................................... 274
Какие модели подходят для периферии? ..................................................................... 277
Фаза 2: построение облачной модели ....................................................................... 277
Компромиссы и альтернативы .............................................................................................. 279
Автономная однофазная модель ............................................................................... 279
Офлайновая поддержка для специфических вариантов исполыования ................ 281
Автомасштабируемость

Полная управляемость

Манипулирование многочисленными предсказаниями почти в режиме

реального времени ...................................................................................................... 281
Непрерывное оценивание для офлайновых моделей

.............................................. 282
..................................................................................... 282
Постановка задачи ................................................................................................................. 283
Решение .................................................................................................................................. 283
Как проносить сквозные ключи в Keras ................................................................... 284
Добавление возможности предсказания по ключу в существующую модель ...... 285

ПАТТЕРН

20.

Предсказания по ключу

Оглавление

11

Компромиссы и альтернативы .............................................................................................. 286

...................................................................................... 286
.......................................................................................... 286
Резюме .......................................................................................................................................... 287
Асинхронное обслуживание
Непрерывное оценивание

Глава

6.

Паттерны обеспечения воспроизводимости ........................................... 289

................................................................................................. 290
................................................................................................................. 290
Решение .................................................................................................................................. 291
Компромиссы и альтернативы .............................................................................................. 292
Преобразования в TeпsorFlow и Keras ...................................................................... 293
Эффективные преобразования с помощью библиотеки tf.transfonn ...................... 296
Преобразования текста и снимков ............................................................................ 297
Альтернативные подходы .......................................................................................... 298
ПАТТЕРН 22. Повторяемая разбивка ........................................................................................ 298
Постановка задачи ................................................................................................................. 299
Решение .................................................................................................................................. 299
Компромиссы и альтернативы .............................................................................................. 301
Единый запрос ............................................................................................................ 301
Случайная разбивка .................................................................................................... 302
Разбивка по нескольким столбцам ............................................................................ 302
Повторяемая разбивка ................................................................................................ 303
Последовательная разбивка ....................................................................................... 304
Стратифицированная разбивка .................................................................................. 306
Неструктурированные данные .................................................................................. 306
ПА ТТЕРН 23. Мостовая схема .................................................................................................. .307
Постановка задачи ................................................................................................................. 307
Решение .................................................................................................................................. 308
Схема с наведенным мостом ..................................................................................... 308
Аугментированные данные ........................................................................................ 309
Компромиссы и альтернативы .............................................................................................. 313
Объединенная схема ................................................................................................... 313
Каскадный метод ........................................................................................................ 313
Манипулирование новыми признаками ................................................................... 314
Манипулирование увеличениями прецизионности ................................................. 314
ПА ТТЕРН 24. Оконный предсказательный вывод ................................................................... 315
Постановка задачи ................................................................................................................. 315
Решение .................................................................................................................................. 317
Компромиссы и альтернативы .............................................................................................. 319
Сокращение вычислительных затрат ........................................................................ 320
Потоковый SQL .......................................................................................................... 321
Модели на основе последовательностей .................................................................. 323
Признаки с поддержкой состояния ........................................................................... 324
Упаковывание предсказательных запросов ............................................................. 325
ПАТТЕРН 25. Конвейер рабочего потока ................................................................................. 325
Постановка задачи ................................................................................................................. 325
Решение .................................................................................................................................. 326
Разработка конвейера TFX ......................................................................................... 329
Исполнение конвейера на платформе Cloud А! Platform ........................................ 330

ПА ТТЕРН

21.

Преобразователь

Постановка задачи

Оглавление

12

Почему это работает .............................................................................................................. 332
Компромиссы и альтернативы ............................................ " ..................................... "" ....... 333

.................. " ........................................................... "" .... " ... 333
CI/CD с конвейерами ..... " ... " ................................................. " .. " .......... 335
Платформы Apache Airflow и Kubeflow Pipelines.""""".""""""""""""" .. "".""".336
Конвейер разработки и промышленный конвейер .. """."."" .. """"."""".""."".""337
Отслеживание линии преемственности в конвейерах ML""""""""""" ... " .. """".337
ПАТТЕРН 26. Хранилище признаков." ........ " ... " ........ "" ...... " ... " ... " ............... " ...... " ............... 338
Постановка задачи .... " ...................... " ... " ............................ " ...... " .................... " .... " ............ 338
Решение ................................... " ............... " ........ " ............................................... " ................. 340
Хранилище Feast .................................. " ... " ............................ " ........ """ ..... " .... " ....... 342
Определение источников потоковых данных при создании экземпляра FeatureSet """""".345
Получение данных из хранилища Feast ........................... " ......................... " ............ 348
Почему это работает ....................................... " ..................................................................... 350
Компромиссы и альтернативы ." ...................... " ................................................................... 353
Альтернативные реализации ......... " ... " .................... " ........................... " .................. 353
Паттерн "Преобразователь" ." .......... "" ... " ... " ... " ... " ........ " ............... "" .................... .353
ПАТТЕРН 27. Управление версиями" ............... " .......... " ...... " ... " ... " .............. " ....................... .354
Постановка задачи ...................................................... " ......................................................... 354
Решение ............... " ...................... " ......................................................................................... 355
Типы пользователей модели .............. "." ................................................................... 356
Управление версиями модели с помощью сервиса .. ""."" .... " .. """ .. "" .. " ... ""." .. "356
Управление версиями для манипулирования новыми данными .. " .. " .. " .. " ... """"""" .. ""359
Компромиссы и альтернативы .................... " ........................................................................ 359
Другие бессерверные инструменты управления версиями."." .. """""""." .......... "360
Инструмент Tensorflow Serving ....................................... " ........................................ 360
Несколько функций обработки .............. " ............. " .................................................. 361
Новые модели против новых версий моделей ." .......... ".""""""""""""""."" ... "".362
Резюме .......................................................................................................................................... 363
Разработка компонентов

Интеграция

Глава

7.

Ответственный искусственный интеллект ............................................ 365

ПАТТЕРН

28.

Эвристический эталон ............................................... " ............................... "." ... 366

...... " ..... " ........................................... " ... " ........................... "." ................ 366
.................. "" ............................................. " ................................................. "." ....... 367
Компромиссы и альтернативы" ............... " ... "." ................................................................... 370
Проверка разработки ................ " ............... " .................. " ..................... " .................... 370
Эксперты-люди ........................................................................................................... 371
Величина полезности ................................ " ............................ "" ............................... 372
ПАТТЕРН 29. Объяснимые предсказания ............ " .......... " ........... " ......................................... 372
Постановка задачи ........................................................................ " ........ " ............................. 373
Решение .... " ...................... " ........ " ........................................ " ................................................ 374
Базовый уровень модели ....... " .................. "" ...... " ..... " ...... ""." ......... " ...................... 377
Определение базовых уровней ........................................... " ........................ " ............ 378
Эвристические эталоны и модельные базовые уровни " ... " ... """ .... "" .. " ... "."""""""".380
Библиотека SHAP ... " ... "" ... " ... " ... " ..... " ... " ............. "."" ............................................ 380
Объяснения из развернутых моделей .... " ....................... " ........................................ 382
Компромиссы и альтернативы .. " .......... " ..... " ............................ " ........................ " ............... 386
Искаженность отбора данных .................... " ..................................... " ................... ".386
Контрфактический анализ и объяснения на основе примеров" ..... " ... " ............ "".387
Пределы объяснений ................................... " ... " .................. " ...... " ............................ 389
Постановка задачи
Решение

Оглавление

ПА ТТЕРН

30.

13

Призма объективности ....................................................................................... 390

................................................................................................................. 390
Решение .................................................................................................................................. 393
До тренировки ............................................................................................................. 394
Искаженность в других формах данных ........................................................................ 398
После тренировки ....................................................................................................... 398
Компромиссы и альтернативы ............................................................................................. .402
Инструментарий Fairness lndicators .......................................................................... 402
Автоматизирование оценивания данных ................................................................. .403
Списки разрешений и запретов ................................................................................ .403
Аугментация данных ................................................................................................. .404
Модельные карточки .................................................................................................. 405
Объективность против объяснимости ..................................................................... .406
Резюме ......................................................................................................................................... .406
Постановка задачи

Глава

8.

Взаимосвязанность паттернов .................................................................. 409

Справочник паттернов

............................................................................................................... .409
......................................................................................................... 413
Паттерны в рамках проектов машинного обучения ................................................................ .416
Жизненный цикл машинного обучения .............................................................................. .417
Обнаружение .............................................................................................................. .417
Разработка .................................................................................................................. .420
Развертывание ............................................................................................................. 421
Готовность к искусственному интеллекту .......................................................................... .424
Тактическая фаза: ручная разработка ....................................................................... 424
Стратегическая фаза: эффективное использование конвейеров ........................... .425
Трансформационная фаза: полноавтоматизированные процессы ......................... .427
Взаимодействие паттернов

Распространенные паттерны с группировкой по варианту использования

............................................................................................................................. .428
......................................................................................... .428
Компьютерное зрение ........................................................................................................... .429
Предсказательная аналитика ................................................................................................ .429
Рекомендательные системы ................................................................................................. .43 1
Обнаружение мошенничества и аномалий ......................................................................... .43 1

и типу данных

Понимание естественного языка

Предметный указатель ............................................................................................... 433

Об авторах

Валлиаппа (Лак) Лакшманан

(Valliappa (Lak) Lakshmanan)-

глобальный руково­

дитель отдела аналитики данных и решений в области искусственного интеллекта

в

Google Cloud.

Руководимый им коллектив строит программно-информационные

решения для деловых задач, используя продукты

Google Cloud

для анализа данных

и машинного обучения. Он является основателем программы погружения в про­
блематику машинного обучения

в Лаборатории передовых решений компании

Google (Google's Advanced Solutions Lab ML). До работы в компании Google Лак
был директором по исследованию данных в Climate Corporation и научным иссле­
дователем в NOAA.
Сара Робинсон

Cloud

(Sara

RoЬinson)

-

адвокат разработчиков в коллективе

Google

со специализацией в машинном обучении. Она вдохновляет разработчиков и

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

бакалавра, полученную в Университете Брандейса
в компании

Google

Майкл Мунн

была представителем

(Michael Munn)- инженер
Google, в которой он

шинного обучения в

Google Cloud,

(Brandeis University). До работы
разработчиков из коллектива Firebase.
по техническим решениям в области ма­
работает с заказчиками инфраструктуры

помогая им разрабатывать и развертывать модели машинного обуче­

ния. Также преподает программу погружения в проблематику машинного обучения

в Лаборатории передовых решений

(Advanced Solutions Lab ML).

Имеет доктор­

скую степень по математике, полученную в Университете Нью-Йорка (City Univer-

sity ofNew York).

До прихода в

Google

он работал профессором-исследователем.

Предисловие

Для кого эта книга предназначена?
Обзорные книги по машинному обучению
ны ответам на вопросы о том, что и как

(machine learning, ML) обычно посвяще­
делается в ML. В них также может быть

приведено объяснение математических аспектов новых методов, которые поступа­
ют из исследовательских лабораторий искусственного интеллекта (ИИ), и пред­

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

в себе наработанный опыт в попытке ответить на вопрос: почему тот или иной
метод работает? Указанный вопрос лежит в основе приемов и хитростей, которые
опытные практики

ML

эффективно задействуют, применяя технологию машинного

обучения к реальным практическим задачам.

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

вам

пригодится в случае,

инженером данных или инженером

если вы являетесь

ML,

На­

ML.

исследователем данных,

который ищет вторую книгу по практиче­

скому машинному обучению. Если вы уже знаете основы, то наша книга познако­
мит вас с каталогом идей, отдельные из которых вы (специалист-практик

ML)

можете распознать, и даст этим идеям название, дабы вы могли уверенно к ним об­
ращаться.

Если вы изучаете информатику и собираетесь работать в 1Т -индустрии, эта книга

дополнит ваши знания и подготовит вас к профессиональному миру. Она поможет
вам научиться создавать высококачественные системы

ML.

Чего в книге нет
Эта книга в первую очередь предназначена для практикующих инженеров

ML,

ра­

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

дете здесь очень мало материала, например, об архитектуре МL-моделей (к приме­
ру, о двунаправленных кодировщиках, о механизме внимания или о слоях коротко­

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

Предисловие

18
уже

построенную

GRUCell),

кем-то

модельную

архитектуру

(например,

ResNet-50

или

чем писать собственную классификацию изображений или рекуррент­

ную нейронную сеть.

Вот несколько конкретных примеров областей, от которых мы намеренно держим­
ся подальше, потому что считаем, что эти темы больше подходят для курсов кол­
леджей и научных исследователей

+

ML.

Алгоритмы машинного обучения.
Например, мы не рассматриваем различия между случайными лесами и нейрон­
ными сетями. Об этом говорится в учебниках по машинному обучению.

+

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

Adam

и

ReLU -

по нашему опыту, потенциал для улучшения

результативности при выборе разных вариантов в таких вещах, как правило, не­
значителен.

+

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

ResNet

либо любую другую, ко­

торая окажется самой используемой в то время, когда вы будете читать эту кни­

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

этой проблематике.

+

Модельные слои.
В этой книге вы не найдете ни сверточных, ни рекуррентных нейронных сетей.
Они дисквалифицированы вдвойне

-

во-первых, за то, что являются строитель­

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

+

Сценарии тренировки сетей.
Простой вызов model. fit () в

Keras -

это все, что нужно будет сделать специали­

сту-практику.

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

В качестве аналогии возьмем, к примеру, структуры данных. В обучающем курсе

по структурам данных подробно рассматривают реализации разных структур дан­
ных. Научный исследователь структур данных должен будет находить способы

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

Предисловие

1

19

ревьями. Эта книга написана для прагматичного специалиста-практика в области
машинного обучения.

Примеры исходного кода
Мы предоставляем исходный код для машинного обучения (иногда написанный

с использованием Keras/ТensorFlow, а иногда с помощью Руthоn-библиотеки

learn

или языка

BigQuery ML)

и для обработки данных (в

scikit-

как один из путей

SQL)

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

рия1 на

GitHub,

в котором вы найдете полностью работающие модели. Мы настоя­

тельно рекомендуем вам опробовать эти примеры.
Указанный исходный код имеет по отношению к рассматриваемым концепциям и

методам второстепенное значение. Наша цель состояла в том, чтобы тема и прин­

ципы оставались актуальными независимо от изменений в
и мы могли бы, например, легко обновить репозиторий

TensorFlow или Keras
GitHub, включив в его со­

став другие МL-фреймворки, оставив при этом текст книги неизменным. И, следо­

вательно, книга останется одинаково информативной в случае, если вашим первич­
ным

фреймворком

является

фреймворк, такой как

H20.ai

Руthоn-библиотека

или

R.

PyTorch

или

даже

не-Руthоn­

Мы, безусловно, приветствуем ваш вклад в ре­

позиторий в виде одного или нескольких приведенных в книге паттернов с исполь­

зованием вашего любимого фреймворка.

Условные обозначения, принятые в книге
В книге используются следующие типографские условные обозначения:

+ Курсив указывает новые термины.
+

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

+ ЖИрнwй

моноширикю.1Й шрифт показывает команды либо другой текст, который дол­

жен быть

напечатан

пользователем

буквально,

а также

зарезервированные

в языке инструкции и ключевые слова.

+ моноширинный шрифт

курсивом показывает текст, который должен быть заменен зна­

чениями пользователя либо значениями, определяемым по контексту, а также

il

комментарии в листингах.

1 См.

Данный элемент обоэна"ет nодс------+-----<

127

127
69
Рис.

2.24.

127

127

Преобразование сетки ЗхЗ в сетку 2х2 со скользящими окнами
и сведением на основе максимума

Мы приходим к окончательному скалярному значению

127.

И хотя оно то же самое,

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

Фреймворк

Keras

предоставляет сверточные слои для строительства моделей, кото­

рые разбивают снимки на меньшие оконные блоки. Допустим, мы создаем модель

для классифицирования цветных снимков размером 28х28 с собаками и кошками.
Раз уж эти снимки цветные, каждый из них будет представлен как 28х28хЗ-раз­
мерный массив, поскольку каждый пиксел имеет три цветовых канала. Вот как мы

бы определили входные данные для этой модели, используя сверточный слой и

Sequential:
Conv2D(filters=l6,

kernel_size=З,

activation='relu', input_shape=(28,28,3))

API

102

Глава

2

В этом примере мы разбиваем входные снимки на блоки размером ЗхЗ, перед тем
как пропустить их через слой сведения на основе максимума. Архитектура модели,

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

API Keras.

Вот как мы бы совместили наши пиксельные значения с представлением в виде
скользящего окна с помощью конкатенатного слоя

Keras:

# Определить входной слой для вводимого снимка (одинаковой
# как для пиксельного, так и для ттиточного представления)
image_input = Input(shape=(28,28,3))

формы

# Определить пиксельное представление
pixel_layer = Flatten() (image_input)

# Определить
tiled_layer
tiled_layer
tiled_layer

ттиточное представление

Conv2D(filters=16, kernel size=З,
acti va tion=' rel u' ) (image _ input)
MaxPooling2D() (tiled_layer)
tf.keras.layers.Flatten() (tiled layer)

# Конкатенировать в единый слой
merged_image_layers = keras.layers.concatenate([pixel layer, tiled_layer])
В целях определения модели, которая принимает это представление в качестве
мультимодального признака, мы можем подать конкатенированный слой в выход­

ной слой:

merged_dense = Dense(lб, activation='relu') (merged_image_layers)
merged_output = Dense(l) (merged_dense)
model = Model(inputs=image_input, outputs=merged_output)
Выбор варианта представления изображений для использования в своей модели,
включая

мультимодальное

представление,

во

многом

зависит от типа

снимковых

данных, с которыми мы работаем. Чем детальнее наши снимки, тем больше вероят­
ность того, что мы захотим представить их в виде плиток либо скользящих окон,
состоящих из плиток. Дriя набора данных

MNIST

будет достаточно представления

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

медицинскими

снимками,

мы

повысим

точность,

сочетая

несколько

представлений. Зачем сочетать несколько представлений снимков? Представляя

снимки в виде пиксельных значений, мы обеспечиваем модель возможностью вы­
являть на снимке более высокоуровневые точки фокусировки, например домини­
рующие высококонтрастные объекты. Плиточные представления помогают моде­

лям выявлять более мелкие, менее контрастные края и контуры.

Паттерны для представления данных

103

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

2.19

примеру модели, в которой используются кадры перекрестка

для предсказания на нем нарушения правила дорожного движения. Наша модель
может самостоятельно извлекать целый ряд закономерностей из снимков дорожно­

го движения, но могут иметься и другие данные, способные повысить точность на­
шей модели. Например, то или иное поведение (правый поворот на красный) не

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

Если мы собираем снимковые данные с многочисленных перекрестков, то осве­
домленность нашей модели о местоположении снимка также может быть полезной.
Сейчас мы выявили три дополнительных табличных признака, которые могли бы
улучшить нашу снимковую модель:



время суток;



погода;



местоположение.

Давайте подумаем о возможных представлениях для каждого из этих признаков.

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

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

ратуру, но в этом случае видимость может быть полезнее. Еще один вариант пред­

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

Если мы собираем данные из многих мест, то, скорее всего, также захотим закоди­

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

признаков (город, страна, штат и т. д.) в зависимости от числа мест, из которых мы
собираем кадры.

Предположим, что в этом примере мы хотели бы использовать следующие таблич­
ные признаки:



время



видимость (visiЬility)- вещественный признак;



ненастная погода

(time)

как час дня

-

целочисленный признак;

(inclement weather)-

категориальный признак (дождь, снег,

нет);

• ID

местоположения

местоположениями.

(location) -

категориальный признак с пятью возможными

104

Глава

2

Вот как может выглядеть подмножество этого набора данных для последнего при­
мера:

data

=

'time': [9,10, 2 ],
'visiЬility': [0.2, 0.5, 0.1],
'inclement_weather': [[0,0,1), [0 ,0,1), [1,0,0) ] ,
'location': [[0,1,0,0,0), [0,0,0,1,0], [1,0,0,0, 0 ] ]

Тепрь мы можем совместить эти табличные признаки в единый массив по каждому

примеру, вследствие чего массив на входе в нашу модель будет содержать

10

эле­

ментов. Входной массив для первого примера будет выглядеть так:

[9,

О

.2,

О,

О,

1,

О,

1,

О,

О,

О]

Мы могли бы подать эти данные на вход плотного (oense) полносвязаного слоя, а на

выходе из модели было бы одно-единственное значение между О и

1, указывающее

на наличие либо отсутствие в экземпляре нарушения правила дорожного движения.

В целях совмещения всего изложенного с нашими снимковыми данными мы будем

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

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

2.25.

Снимки

Табличные данные

Time
Visibility
lncliment_weather
Location

Сверточный
СЛОЙ

keras.layers.concatenate

Результат работы модели :
violation__proЬability
Рис.

2.25.

0.9

Конкатенирование слоев с целью манипулирования признаками

со снимковыми и табличными метаданными

Паттерны для представления данных

105

Мультимодальные представления признаков
и интерпретируемость модели

Модели на основе глубокого обучения по самой своей сути труднообъяснимы. Если
мы построим модель, которая имеет точность

99%,

мы все равно не будем знать

конкретно, как именно наша модель делает предсказания и, следовательно, являет­

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

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

ния предсказаний.

Существует несколько технических приемов,

которые служат для

объяснения

снимковых моделей, например, выделяя пикселы, сигнализировавшие о сделанном
моделью предсказании. Однако, когда в одной модели мы совмещаем многочис­
ленные

представления

данных,

эти

признаки

начинают

зависеть

друг

от

друга.

В результате бывает трудно объяснить принцип, по которому модель делает пред­

сказания. Проблематика обеспечения объяснимости рассматривается в главе

7.

Резюме
В этой главе мы узнали о разных подходах к представлению модельных данных. Мы
начали с рассмотрения приемов манипулирования числовыми входными данными и

нормализации этих входных данных, которые помогают ускорять время тренировки

модели и повышать ее точность. Затем мы рассмотрели приемы инженерии призна­
ков на категориальных входных данных, в частности, с помощью кодирования с од­

ним активным состоянием и использования массивов категориальных значений.

В остальной части главы мы обсудили четыре паттерна для представления данных.
Первым был "Хешированный признак"

(Hashed Feature),

который предусматривает

кодирование категориальных входных данных в виде уникальных строковых зна­

чений. Мы рассмотрели несколько разных подходов к хешированию с использова­
нием набора данных об аэропортах из

главе был паттерн

BigQuery. Вторым рассмотренным
(Embeddings)- технический

"Векторные вложения"

в этой

прием

представления входных данных с высокой кардинальностью, таких как данные

с многочисленными возможными категориями или текст. Векторные вложения
представляют данные в многомерном пространстве, в котором размерность зависит

от данных и задачи предсказания. Затем мы рассмотрели паттерн "Синтетический
признак"

(Feature Cross)-

подход, который соединяет два признака для извлече­

ния связей, трудноуловимых путем кодирования признаков по отдельности. Нако­

нец, мы рассмотрели представления с использованием паттерна "Мультимодаль­
ный вход"

(Multimodal Input),

обратившись к приемам объединения входных дан­

ных разных типов в одной и той же модели и приемам представления одного

признака самыми разными способами.
Эта глава была посвящена подготовке входных данных для моделей. В следующей

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

ГЛАВАЗ

Паттерны
для представления задачи

В главе

2

рассматривались паттерны, каталогизирующие мириады приемов, кото­

рыми могут представляться входные переменные, подаваемые в модели машинного

обучения. В этой главе рассматриваются разные типы задач машинного обучения и
анализируются варианты архитектур моделей в зависимости от конкретной задачи.

Типы данных на входе и на выходе
тектуру модели.

Например,

-

два ключевых фактора, влияющих на архи­

выходные данные в задачах машинного обучения

с учителем могут варьироваться в зависимости от характера решаемой задачи:

классификационной или регрессионной. Для тех или иных типов входных данных
существуют специальные нейросетевые слои: сверточные слои для снимков, речи,

текста и других данных с пространственно-временной корреляцией, рекуррентные

слои для последовательных данных и т. д. По проблематике этих типов слоев воз­
никла колоссальная по объему литература, которая сконцентрирована вокруг спе­
циальных технических приемов, таких как сведение на основе максимума, внима­

ние и т. д. Кроме того, были разработаны специальные классы технических реше­
ний для распространенных задач, таких как рекомендации (например, матричная

факторизация)

ARIMA).

или

прогнозирование

на

основе

временного

ряда

(например,

Наконец, группа более простых моделей вместе с распространенными

идиомами может использоваться для решения более сложных задач, например

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

от областей активных научных исследований, мы будем игнорировать паттерны и
идиомы,

связанные

со специализированными областями

машинного обучения.

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

(Reframing)

ML.

берет решение, которое интуитивно вос­

принимается как регрессионная задача, и представляет его как классификационную
задачу (и наоборот). Паттерт "Мультиметка"

(Multilabel)

хорошо работает в случае,

когда тренировочные примеры могут принадлежать более чем одному классу. Пат­
терн "Каскад"

(Cascade)

предназначен для ситуаций, когда задача машинного обу­

чения может быть выгодно подразделена на серию (или каскад) задач. Паттерн
"Ансамбли" (EnsemЫes) решает задачу путем тренировки

и агрегирования их ответов. Паттерн "Нейтральный класс"

нескольких моделей

(Neutral Class)

помогает

Глава

108

3

в том, как обращаться с ситуациями, когда эксперты расходятся во мнениях. Пат­

терн "Перебалансировка"

(Rebalancing)

рекомендует подходы к манипулированию

сильно искаженными или несбалансированными данными.

ПАТТЕРН

5.

Переформулировка

Паттерн "Переформулировка"

(Reframing)

связан с изменением представления дан­

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

как классификационную задачу (и наоборот).

Постановка задачи
Первый шаг создания любого технического решения по машинному обучению со­
стоит в формулировке задачи. О каком классе задач идет речь? Принадлежит ли
она классу задач обучения с учителем? Или же обучения без учителя? Какие при­
знаки в ней используются? Если зто задача обучения с учителем, то какие в ней
используются метки? Какая величина ошибки будет допустимой? Разумеется, отве­
ты

на

эти

вопросы должны

рассматриваться

в

контексте тренировочных данных,

решаемой задачи и метрик успеха.

Например, предположим, что мы хотим построить модель машинного обучения,

чтобы предсказывать количество осадков в некотором месте. Возникает вопрос
о том, как какому типу относить эту задачу: регрессии или же классификации? Что ж,
поскольку мы пытаемся предсказать количество осадков (например,

0,3

см), имеет

смысл рассматривать ее как задачу прогнозирования на основе временного ряда:
какое количество осадков с учетом текущей и исторической климатической и

погодной закономерностей мы должны ожидать в данной области ближайшие

15

минут? С другой стороны, поскольку метка (количество осадков) является веще­

ственным числом, мы могли бы построить регрессионную модель. Когда мы нач­
нем разрабатывать и тренировать нашу модель, то обнаружим (возможно, догады­
ваясь), что предсказывать погоду труднее, чем кажется поначалу. Наши предска­

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

набора признаков иногда идет дождь, который можно оценить как
иногда

-

как

0,5

0,3

см осадков, а

см. Что следует сделать для улучшения предсказаний? Нужно ли

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

Любая из этих корректировок могла бы улучшить нашу модель. Но постойте. Разве
регрессия является единственным способом формулировки этой задачи? По всей
видимости, мы сможем переформулировать нашу целевую установку машинного
обучения, что позволит повысить результативность нашей задачи.

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

0,3

см, а иногда

-

Паттерны для представления задачи

с

0,5

109

см. Тем не менее даже если бы регрессионная модель смогла усвоить два воз­

можных количества осадков, она ограничена предсказанием только одного числа.

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

заключается

(рис.

3. l ).

в

моделировании

дискретного

распределения

вероятностей

Вместо того чтобы предсказывать количество осадков в качестве вещест­

венного результата, мы моделируем результат как многоклассовую классифика­
цию, продуцирующую вероятность того, что количество осадков в ближайшие

15

минут будет находиться в определенном диапазоне количества осадков.

1 ,7мм

Входы

Рис.

3.1.

МL·модель

Осадки , (мм)

Выход

0-0.05

0,009

0,5-1,0

0,01

1,0-1 .5

0,07

1 , 5-2 . О

0,85

2,0-2,5

0,05

2,5-3,0

0,01

3,0+

0,001

Вместо того чтобы предсказывать осадки как результат регрессии . мы можем моделировать

дискретное распределение вероятностей. используя многоклассовую классификацию

И регрессионный подход, и новый переформулированный подход как классифика­
ция дают предсказание осадков на следующие

15

минут. Однако классификацион­

ный подход позволяет модели не выбирать среднее значение распределения осад­
ков, а улавливать распределение вероятностей осадков в различных количествен­

ных величинах. Моделирование распределения, таким образом, выгодно тем, что
осадки не демонстрируют типичную колоколообразную кривую нормального рас­

пределения, а вместо этого подчиняются распределению Твиди

(Tweedie ) 1,

которое

допускает преобладание точек на нуле. И действительно, это как раз тот подход,

который был принят в научно-исследовательской работе, опубликованной в базе

данных

Google Research 2 •

В ней предсказывалось количество осадков в данном мес­

те с использованием категориального распределения на основе

1

См . https://oгeil.ly/C8JIК.

2

См. https://oгeil.ly/PGAEw .

512

способов. Дру-

110

Глава

3

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

с большой дисперсией. Недавняя работа, которая превосходит все эталонные кри­

терии в предсказании структуры сворачивания белка3, тоже предсказывает расстоя­
ние между аминокислотами

64

способами как классификационную задачу, в кото­

рой расстояния сгруппированы в

64

корзины.

Еще одна причина переформулировать задачу возникает, когда целевая установка
оказывается лучше в модели другого типа. Например, предположим, что мы пыта­

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

вить клик-наживку 4 • И, возможно, было бы лучше переформулировать ее в регрес­
сионную задачу предсказания части видео, которая будет просмотрена.

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

плотности распределения вероятностей (probaЬility

density function, PDF).

Дискре­

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

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

классификацию как дискретное распределение вероятностей,
улавливать бимодальную структуру предсказаний (рис.

3.2);

модель способна

а если бы предсказы­

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

Улавливание неопределенности
Давайте еще раз обратимся к набору данных о рождаемости и к задаче о предсказа­
нии веса младенца. Поскольку вес младенца является положительным веществен­
ным значением, эта задача интуитивно воспринимается как регрессионная. Однако

обратите внимание, что в том или ином наборе входных данных метка weight

3

См. https://oreil.ly/-Hi3k.

4

То есть. назойливые реЮJамные сообщения и посты на веб-странице, которые заставляют no ним щел­
- Прим. перев.

кать.

Паттерны для представления задачи

Входы

Модель

111

ML

Рис. 3.2. Переформулировка задачи в классификационную с моделированием
распределения вероятностей позволяет предсказаниям улавливать бимодальный результат.
Предсказание не ограничивается одним значением, как в регрессии

pounds (вес в фунтах) может принимать множество разных значений. Мы видим, что
распределение веса младенцев для конкретного набора входных значений (младен­

цы-мальчики, рожденные 25-летними матерями на 38-й неделе беременности) при­
близительно подчиняется нормальному распределению с центром около

(3,4

кг). Исходный код для создания графика рис.

3.3

7,5

фунта

можно найти в репозитории 5

этой книги.
Распределение веса младенцев

Select

0.40
0.35
0.30
0.25

wetght_pounds ,
ts_мale,

gestatton_weeks,
l"lother _ age,
riother _гасе,

0.20

FГOl'I

'btgquery-puЫ tc -data. sамр le . nata 1 Ну'

г-+ 0.15

Wheгe

0.10
0.05

wetght_ pounds IS NOT NULL
AND ts _мale = true
AND gestatton_weeks = 38
AND мother _age = 25
AND мother _гасе = 1
Рис.

3.3.

0.00~-....,..-

2

4

6

8

10

12

Вес в фунтах

С учетом того или иного набора входных данных (например, младенцы-мальчики,

рожденные 25-летними матерями на 38-й неделе беременности) переменная

weight _pounds

принимает диапазон значений, приблизительно подчиняющийся нормальному распределению
с центром в

7,5

фунта

Однако тут следует обратить внимание на ширину распределения

распределение достигает пика
(на самом деле

(2,95

33%)

кг) или больше

7,5

-

того, что данный младенец будет весить меньше

8,5

даже если

фунта, существует нетривиальная вероятность

фунта (около

3,9

6,5

фунта

кг)! Ширина этого распределения указы­

вает на неустранимую ошибку, присущую задаче предсказания веса младенца. Дей­

ствительно, наилучший корень из среднеквадратической ошибки

error, RMSE),
ее

как

(рис.

(root mean square

который мы можем получить в этой задаче, если сформулировать

регрессионную

задачу,

равен

стандартному

отклонению

распределения

3.3).

См . https://github.com/GoogleCloudPlatform/ml-design-patterns/OЗ_proЫem_representation/
reframing.ipynb.

5

112

Глава

3

Если бы мы сформулировали эту задачу как регрессионную, нам пришлось бы
установить результат предсказания с погрешностью как

7,5± 1,0

(каково бы ни было

стандартное отклонение). Тем не менее ширина распределения будет варьироваться
для разных комбинаций входных данных, и поэтому усвоение ширины

-

это еще

одна задача машинного обучения. Например, на 36-й неделе беременности для ма­
терей того же возраста стандартное отклонение составляет

1, 16

фунта

(0,53

кг).

КванmWlьная регрессия, которую мы рассмотрим позже при обсуждении данного
паттерна, пытается сделать именно это, но непараметрически.

Если бы распределение было мультимодальным (с несколькими пиками), то аргу­
менты в пользу переформулировки задачи как классификационной были бы еще
убедительнее. Однако полезно понимать, что из-за закона больших чисел, пока мы
улавливаем все релевантные входные данные, многие распределения, с которыми

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

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

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

нировочных примеров. Эти дискретизированные предсказания более гибкие с точ­

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

ным результатам. То есть мы получаем дискретную функцию плотности распреде­
ления вероятностей (probaЬility

density function, PDF),

дающую относительную

вероятность любого отдельно взятого веса. Конечно же, здесь следует соблюдать

осторожность

-

классификационные модели могут быть чрезвычайно некалибро­

ванными (например, модель будет чересчур уверенной и ошибочной).

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

-

1 до 5 для

построить мо­

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

и

10

пользователя

оценками этого

(user_id)

пользователя

и

наряду с предыдущими

предсказывает фильм

из

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

обучение, при котором она запоминает ряд ключевых характеристик (таких как до­
ход, потребительский сегмент и т. д.) пользователей, которые, вероятно, будут
смотреть данный фильм.

Паттерны для представления задачи

113

Модель, переформулированная как регрессионная задача, теперь предсказывает
представление пользовательского пространства для данного фильма. Дr~я предос­
тавления рекомендаций мы выбираем набор фильмов, наиболее подходящих под
известные характеристики пользователя. Таким образом, вместо модели, обеспечи­

вающей вероятность того, что пользователю понравится фильм, как в случае клас­
сификации, мы получим кластер фильмов, просмотренных зртелями, похожими на
этого пользователя.

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

сию

мы

получаем возможность легко адаптиро­

вать нашу рекомендательную модель для рекомендаций трендовых видео, класси­

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

интерпретацию;

например,

вместо

предсказаний

городских

районов

можно использовать широтно-долготную пару. Предположим, мы хотим предска­
зывать город, в котором произойдет следующая вирусная вспышка, или район

Нью-Йорка, где резко повысятся цены на недвижимость. Было бы проще предска­
зывать широту и долготу и выбирать ближайший к этому местоположению город
или район, чем предсказывать сам город или район.

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

-

это многозадачное обучение, которое объединяет обе задачи (классифика­

ционную и регрессионную) в модель с использованием нескольких направлений

(leads)

предсказания. При любом подходе к переформулировке очень важна осве­

домленность о присущих вашим данным пределах или риске внесения искаженно­

сти в метку 6 технического решения.

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

денному потребуется неотложная помощь, то приведенных в табл.

3.1

категорий

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

6

случаев,

чем

предсказывать

одно

значение

из

континуума

вещественных

Искаженность в метке во3никает. когда набор помеченных данных нс полностью представляет весь уни­
- Прим. перев.

версум потенциальных меток.

Глава

114

3
Таблица

3.1. Сгруппированные результаты для веса младенца

Категория

Описание

Большой вес при рождении

Более

Средний вес при рождении

От

5,5 до 8,8 фунта (от 2,5 до 4 кг)

Малый вес при рождении

От

3,31

Очень малый вес при рождении

Менее

8,8 фунта (более 4 кг)

до

3,31

5,5 фунта

(от

1,5 до 2,5 кг)

фунта (менее

1,5 кг)

чисел. Точно так же было бы легче предсказывать цель, состоящую из двоичного
нуля и единицы, например для цели "вес ниже нормы?"

(is_underweight) вместо че­
(high_weight), "средний вес" (avg_
малый вес" (very_low_ weight). Опираясь

тырех отдельных категорий "большой вес"

weight),

"малый вес"

(low_weight)

на категориальные результаты,

и "очень

наша модель меньше мотивируется на получение

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

В прилагаемом к этому разделу блокноте 7 мы тренируем как регрессионную, так и
многоклассовую

RМSE

= 1,3

классификационную модели.

Регрессионная

модель достигает

на валидационном наборе данных, в то время как классификационная

модель имеет точность

67%.

Сравнивать эти две модели трудно по той причине,

что одной метрикой оценивания является RМSE, а другой

-

точность. В конце

концов, выбор варианта дизайна регулируется вариантом использования. Если ме­
дицинские решения

основываются на значениях, сгруппированных в корзины, то

наша модель должна быть классификационной и использовать эти корзины. Однако
если требуется более четкое предсказание веса младенца, то имеет смысл использо­
вать регрессионную модель.

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

чтобы предсказывать только среднее значение, мы можем оценивать условный

10, 20, 30, ... ,

90-й процентиль того, что должно быть предсказано. Квантильная

регрессия является продолжением линейной регрессии. С другой стороны, пере­

формулировка задачи может работать с более сложными моделями машинного
обучения.
Еще один, более сложный подход заключается в использовании фреймворка, напо­

добие

TensorFlow Probabllity8,

для вычисления регрессии. Однако мы должны мо­

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

7

См. https://github.com/GoogleCloudPlatfoгm/ml-design-patteгns/ЫoЬ/masteг/03_ргоЫеm_гepгesentation/

гefгaming.ipynb.
8

См. https://oгeil.ly/AEtLG.

Паттерны для представления задачи

115

ожидается, что результаты будут нормально распределены вокруг среднего значе­
ния, завися от данных на входе, то выходной слой модели будет таким:
tfp.layers.DistributionLarnЬda(lamЬda

t: tfd.Normal(loc=t, scale=l))

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

Переформулировка задачи, в свою очередь, не требует от нас моделирования апо­
стериорного распределения вероятностей.
Во время тренировки любой модели машинного обучения принципиально большое
значение имеют данные. Более сложные связи, как правило, требуют большего
числа тренировочных данных, чтобы найти эти неуловимые закономерности.
С учетом этого факта важно учитывать то, как потребности в данных соотносятся
с регрессионной и/или классификационной моделями. Общее эмпирическое правило классификационных задач состоит в том, что для каждой категории меток мы
1О раз больше модельных признаков. Эмпирическое правило для

должны иметь в

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

ность в массивных данных только возрастает. Следовательно, могут появиться
пределы данных,

которые следует учитывать при

рассмотрении типа

используе­

мой модели или, в случае классификации, числа категорий меток.

Прецизионность предсказаний
Задумываясь о переформулировке регрессионной модели как многоклассовой клас­

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

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

3.4

показано, как дискретные распре­

деления вероятностей будут выглядеть в качестве классификации с

4

или



кате­

гориями.

Заостренность функции плотности распределения вероятностей (probaЬility

function, PDF)
остренная PDF

density

указывает на прецизионность задачи как регрессионной. Более за­
указывает на меньшее стандартное отклонение выходного распре­

деления, в то время как более широкая

PDF -

на большее стандартное отклонение

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

3.5).

Ограничение предсказательного диапазона
Еще одна причина переформулировать задачу заключается в необходимости огра­
ничивать диапазон предсказания на выходе. Допустим, например, что реалистич­
ные выходные значения для регрессионной задачи находятся в промежутке

[3; 20).

Если мы натренируем регрессионную модель, в которой выходной слой представ­

лен линейной активационной функцией, то всегда существует вероятность того,

116

Глава

Входы

3

Модель

Рис.

3.4.

Осадки, (мм)

Выход

>8,8

0,001

5,5 < х < 8,8

0,36

3 , 31= 9, 'Healthy', 'NeedsAttention') AShealth,
plurality,
mother_age,
gestation_weeks,
ever born
FRCМ

'bigquery-puЫic-data.samples.natality'

WНERE

apgar_lmin = 8, 'Neutral', 'NeedsAttention')) AS health,
plurality,
mother_age,

См. https://github.com/GoogleCloudPlatform/ml-design-patterns/ЫoЬ/master/OЗ_proЬlem_representation/
neutral.ipynb.

28

Паттерны для представления задачи

151

gestation_weeks,
ever born
FRCМ

WВERE

'bigquery-puЫic-data.samples.natality'

apgar_lmin с:

~ Мажоритарный класс
::i;
Q)

Ji
:а:
:а:

s

!:;
:s::

Миноритарный класс

"
Рис.

3.18.

Матрица путаницы для модели , натренированной на несбалансированном наборе данных
без корректировки набора данных или модели

В этом примере модель правильно угадывает мажоритарный класс в
но правильно угадывает миноритарный класс только в

12%

95%

случаев,

случаев. Как правило,

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

близкие к

100%.

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

метрику оценивания. Затем можно задействовать различные технические приемы
манипулирования

изначально

несбалансированными наборами

данных как

на

Паттерны для представления задачи

155

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

класса и часто предусматривает применение аугментаций 30 для генерирования до­
полнительных образцов. Мы также взглянем на подходы к переформулировке зада­
чи: ее замену регрессионной задачей, анализ значений ошибок модели по каждому
примеру либо кластеризацию.

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

полноту или F-меру, чтобы получить общую картину того, как работает модель.
Прецизионность

(precision)

измеряет процент положительных классификаций, ко­

торые бьти правильными из всех сделанных моделью положительных предсказа­
ний. И наоборот, полнота

(recall)

измеряет долю фактических положительных

примеров, которые были идентифицированы моделью правильно. Самое большое
различие между этими двумя метриками кроется в используемом для их вычисле­

ния знаменателе. Для метрики прецизионности знаменателем является суммарное
число сделанных моделью предсказаний положительного класса. Для метрики пол­

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

1,0, но на практике
Fl)- это метри­

эти две меры часто расходятся друг с другом. F-мера (или оценка
ка, которая варьируется между О до



учитывает как прецизионность, так и пол­

ноту. Она рассчитывается следующим образом:

2

·(прецизионность· полнота/ (прецизионность+ полнота)).

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

1ООО

примеров,

ны быть помечены как мошеннические транзакции.

модель правильно предсказывает

930/950

50

из которых долж­

Для этих примеров наша

не мошеннических примеров и

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

15150 (30%),

а F-мера-

35%.

15/50 мо­
на рис. 3 .19.

15/3 5 (42% ),

полнота

-

Эти метрики гораздо лучше справляются со своей

работой, улавливая неспособность нашей модели правильно идентифицировать
мошеннические транзакции, по сравнению с метрикой точности
составляет

945/1 ООО (94,5% ).

(accuracy),

которая

Поэтому в случае моделей, натренированных на не­

сбалансированных наборах данных, предпочтительно использовать метрики, от­
личные от точности. На самом деле при выполении оптимизации под эти метрики
точность может даже снижаться, и это нормально, поскольку прецизионность, пол-

30

Аугментация (augmentation) -

это пропорциональное расширение или увеличение каких-либо характери­

стик данных по отношению к изначальным данным.

-

Прим. перев.

156

Глава

3
Предсказанные метки

~

li;

Не мошенническая

Мошенническая

Не мошенническая

930

20

Мошенническая

35

15


ф

j)
ж

ж

~

s
Рис.

3.19.

Образцы nредсказаний для модели обнаружения мошенничества

нота и F-мера в данном случае являются более качественными индикаторами ре­
зультативности модели.

Обратите внимание на то, что при оценивании моделей, натренированных на не­

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

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

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

5% мошенничества/95%

не мошенничества.

Если мы ищем метрику, которая улавливает результативность модели по всем по­
роговым значениям, то метрика усредненной прецизионности-полноты является

более информативной 3 1 для модельного оценивания, чем площадь под RОС-кривой

(area under the ROC curve, AUC).

Это обусловлено тем, что усредненная прецизион­

ность-полнота делает больший акцент на том, сколько предсказаний модель сдела­
ла правильно из суммарного числа, которое она отнесла к положительному классу.

Она придает больший вес положительному классу, что важно для несбалансиро­
ванных наборов данных. Метрика

AUC,

одинаково

к улучшениям

и

менее

чувствительна

с другой стороны, трактует оба класса
модели,

что

не

является

опти­

мальным в ситуациях с несбалансированными данными.

Понижающий отбор
Понижающий отбор

(downsampling)-

это техническое решение для манипулиро­

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

дели32. В целях ознакомления с тем , как он работает, давайте взглянем на синтети-

31

См. https://oгeil.ly/5iJX2.

32

То есть используем меньше примеров с преобладающим классом. - Прим. перев.

Паттерны для представления задачи

ческий набор данных обнаружения мошенничества из

157

Kaggle 33 ' 34 • Каждый пример

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

после нее. Набор данных содержит

6,3

млн примеров, из которых только

ляются мошенническими транзакциями. Это число составляет всего

8 тыс. яв­
лишь О, 1% все­

го набора данных.
Хотя крупный набор данных нередко улучшает способность модели выявлять зако­
номерности, он менее полезен, когда данные значительно несбалансированы. Если

мы натренируем модель 35 на всем этом наборе данных

(6,3

млн строк) без каких­

либо модификаций, то, скорее всего, увидим вводящую в заблуждение точность

99,9%

как следствие того, что модель каждый раз угадывает не мошеннический

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

Мы возьмем все

8 тыс.

мошеннических примеров и отложим их в сторону, чтобы

использовать во время тренировки модели. Затем возьмем небольшую случайную
выборку не мошеннических транзакций. Далее мы объединим ее с

8 тыс.

мошенни­

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

библиотеки

pandas:

data = pd.read_csv('fraud_data.csv')
# Разбить на отдельные кадры данных для
fraud = data[data['isFraud'] == 1]
not fraud = data[data['isFraud'] == 0]

мошеннических/не мошеннических транзакций

# Взять случайную выборку не мошеннических строк
not_fraud_sample = not_fraud.sample(random_state=2, frac=.005)
#

Положить их обратно вместе и перетасовать

df
pd.concat ( [not fraud_sample, fraud])
df = shuffle(df, random_state=2)
После этого наш набор данных будет содержать

25%

мошеннических транзакций,

являясь гораздо более сбалансированным, чем изначальный набор данных, в кото­
ром только О, 1% приходится на миноритарный класс. При понижающем отборе не­

плохо поэкспериментировать с точным используемым балансом. Здесь мы приме-

33

См. https://oreil.ly/WqUM.

Указанный набор данных был создан на основе исследования, предложенного в работе Эдгара Лопес­
"PaySim: финансовый мобильный денежный симулятор
для обнаружения мошенничества" (Lopez-Rojas Е" Elmir А .. Axelsson S. PaySim: а financial moЬile money
simulator for fraud detection 11 28th European Modeling and Simulation Symposiшn. EMSS. Larnaca. Cyprus
(2016). - Р. 249-255).

34

Рохаса, Ахмада Эльмира и Стефана Аксельссона

35

См. https://github.com/GoogleCloudPlatform/ml-design-patteгns/ЫoЬ/masteг/03 _problem_гepгesentation/

гebalancing.ipynb.

Глава

158

3

няли разбивку

25/75,

но для достижения приличной точности может потребоваться

разбивка, более близкая к

50/50.

Понижающий отбор обычно сочетают с паттерном "Ансамбли", соблюдая следую­
щие шаги:

1.

Подвергнуть мажоритарный класс понижающему отбору и использовать все
экземпляры миноритарного класса.

2.

Натренировать модель и добавить ее в ансамбль.

3.

Повторить.

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

словое значение. В этом случае взятие случайной выборки из мажоритарного клас­

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

Взвешенные классы
Еще один подход к манипулированию несбалансированными наборами данных за­
ключается в изменении веса, который наша модель придает примерам из каждого

класса. Обратите внимание, что здесь термин "вес" используется в другом контек­
сте, чем веса (или параметры), усваиваемые моделью во время тренировки, которые
вы не можете устанавливать вручную. Взвешивая классы, мы говорим нашей моде­

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

В

Keras

мы можем передать параметр class _ weights в модель, когда тренируем ее

с помощью метода fit ().Параметр class_weights является словарем dict с соотне­

сением каждого класса с весом, который

Keras

должен назначать примерам из этого

класса. Но как определить точные веса для каждого класса? Весовые значения

класса должны относиться к балансу каждого класса в наборе данных. Например,
если миноритарный класс составляет только О, l % набора данных, то разумно за­
ключить, что наша модель должна трактовать примеры из этого класса как имею­

щие

l ООО-кратно

больше веса, чем из мажоритарного класса. На практике принято

делить это весовое значение на

примера составлет

1,0.

2

по каждому классу, вследствие чего средний вес

Следовательно, имея набор данных, в котором О, 1% значе­

ний представляет миноритарный класс, мы могли бы вычислить веса классов с по­
мощью следующего фрагмента исходного кода:

num_minority_examples = 1
num_majority_examples = 999
total examples
num_minority_examples + num_majority_examples

Паттерны для представления задачи

minority_class_weight
majority_class_weight

159

l/(num_minority_examples/total_examples)/2
l/(num_majority_examples/total_examples)/2

#

Передать веса в

#

Ключом является индекс ка)f(l!ого класса.

Keras в словаре dict.

keras_class_weights = (0: majority_class_weight, 1: minority_class_weight)
Затем мы передаем эти веса в модель во время тренировки:

model.fit(
train_data,
train_labels,
class_weight=keras_class_weights
В

BigQuery ML

мы можем установить AUTO_CLASS_WEIGHTS = тrue в блоке OPTIONS при

создании модели, чтобы разные классы взвешивались на основе их частоты встре­
чаемости в тренировочных данных.

Хотя бывает полезно следовать эвристике баланса классов для установки весов
классов, деловое приложение модели также вполне может предписывать веса клас­

сов, которые мы выбираем для назначения. Допустим, у нас есть модель, которая

классифицирует снимки дефектных продуктов. Если стоимость доставки дефектно­
го продукта в



раз превышает стоимость неправильного классифицирования нор­

мального продукта, то в качестве веса нашего миноритарного класса мы выбрали
бы

10.
Смещенность выходного слоя

В сочетании с назначением весов классов также полезно инициализировать выход­

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

ность в выходном слое? Когда у нас есть несбалансированные наборы данных,
установка выходной смещенности будет помогать модели быстрее сходиться. Это
обусловлено тем, что смещенность последнего (предсказывающего) слоя натрени­

рованной модели будет выводить в среднем логарифм отношения миноритарных
примеров к мажоритарным в наборе данных. После установки смещенности, мо­

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

По умолчанию в

Keras

используется смещенность, равная нулю. Это соответствует

смещенности, которую мы хотели бы использовать для идеально сбалансированно­
го набора данных, где

log(l/l)

=О. Для вычисления правильной смещенности с уче­

том баланса набора данных следует использовать:

bias = log(num_minority_examples / num_majority_examples)

Повышающий отбор
Еще одним распространенным техническим приемом манипулирования несбалан­

сированными наборами данных является повышающий отбор

(upsampling).

В этом

160

Глава

случае

мы

3

увеличиваем

представительство

миноритарного

класса,

одновременно

реплицируя примеры миноритарного класса и генерируя дополнительные синтети­

ческие примеры 36 • Он нередко выполняется в сочетании с понижающим отбором
мажоритарного класса. Такой подход с сочетанием понижающего и повышающего

отборов был предложен в

2002

году и получил название "Техника избыточного от­

бора синтетического меньшинства"

SMOTE37 ).
ские

Метод

примеры,

SMOTE

(Synthetic Minority Over-sampling Technique,

предоставляет алгоритм, который строит эти синтетиче­

анализируя

признаковое

пространство

примеров

миноритарных

классов в наборе данных, а затем генерирует аналогичные примеры в этом призна­

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

новременно (также именуемого числом ближайших соседей), подход на основе
случайно генерирует новый пример миноритарного класса между этими

SMOTE
точками.

Давайте посмотрим на набор данных

Pima lndian Diabetes Dataset38

о заболеваемо­

сти сахарным диабетом в племени Пима, чтобы увидеть, как это работает на высо­
ком уровне.
сахарным
В табл.

3 .3

34%

этого набора данных содержат примеры пациентов, страдавших

диабетом,

поэтому

мы

будем

считать

этот

класс

миноритарным.

показано подмножество столбцов для двух примеров миноритарного

класса.

Таблица

Подмножество признаков для двух тренировочных примеров
из миноритарного класса (имеет сахарный диабет)
в наборе данных о заболеваемости сахарным диабетом в племени Пима, Индия

3.3.

Глюкоза

Артериальное давление

Толщина кожи

Индекс массы тела

148

72

35

33,6

183

64

о

23,3

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

3.4,

рассчитанный по срединной точке

между каждым значением столбца.
Таблица

3.4. Синтетический пример, созданный на основе

двух миноритарных тренировочных примеров с использованием метода

SMOTE

Глюкоза

Артериальное давление

Толщина кожи

Индекс массы тела

165,5

68

17,5

28,4

Технический прием

SMOTE

в первую очередь касается табличных данных, но ана­

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

36

То есть используем больше примеров с редкими классами, по мере необходимости задействуя бутстрапи­

рование.

-

Прим. перев.

37

См. https://oreil.ly/CFJPz.

38

См. https://oreil.ly/ljqnc.

Паттерны для представления задачи

1

161

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

нашего набора данных содержат снимки бенгальских кошек,

10%

то мы можем сгенерировать дополнительные вариации бенгальских кошек в на­
шем

наборе

данных

ImageDataGenerator в

путем

Keras.

аугментации

снимка,

воспользовавшись

классом

Получив значения для нескольких параметров, этот

класс будет генерировать несколько вариаций одного и того же изображения, вра­

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

Компромиссы и альтернативы
Для строительства моделей с изначально несбалансированными наборами данных
существует несколько других альтернативных решений, включая переформулиров­
ку задачи и манипулирование случаями обнаружения аномалий. Мы также обсудим
несколько важных соображений для несбалансированных наборов данных: сово­
купный размер набора данных, оптимальные архитектуры моделей для разных
типов задач и объяснение логики предсказания миноритарного класса.

Переформулировка и каскад
Переформулировка задачи

-

еще один подход к работе с несбалансированными

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

ческие приемы, описанные в разд. "Паттерн

5.

Переформулировка" главы

3,

и на­

тренировав каскад моделей. Например, предположим, что у нас есть регрессионная

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

выбросных значений. Тогда мы могли бы преобразовать эту задачу в классифика­
ционную, поместив большинство данных в одну корзину, а выбросы

-

в другую.

Представьте, что мы строим модель для предсказания веса младенца, используя

набор натальных данных

BigQuery.

С помощью библиотеки

pandas

мы можем соз­

дать гистограмму выборки из данных о весе младенцев, чтобы увидеть распределе­
ние веса:

%%Ьigquerydf

SELECT

weight_pounds
FRGf
'Ьigquery-puЫic-data.samples.natality'
LIМIT

10000

df.plot(kind='hist')
На рис.

3.20

показана результирующая гистограмма.

Если мы подсчитаем число младенцев весом
ных, то их будет примерно

(5,44

кг) составляют только

3 фунта (1,36 кг) во всем наборе дан­
96 тыс. (0,06% данных). Младенцы весом 12 фунтов
0,05% набора данных. В целях получения хорошей

Глава

162

3

-

зsоо

3000

Вес в фунтах

2500
1!!
2000
о
t;

"' 1500



1000

500
о

Рис.

3.20.

6

4

2

8

и

10

14

Гистограмма, изображающая распределение веса младенцев для

в наборе натальных данных



тыс. примеров

BigQuery

результативности регрессии по всему диапазону мы можем объединить понижаю­
щий отбор с паттернами "Переформулировка" и "Каскад". Сначала мы разобьем
данные на три группы: "недостаточный вес", "средний вес" и "избыточный вес".
Это можно сделать с помощью следующего запроса:
SELECТ

CASE
WНEN
WНEN

weight_pounds < 5.5
weight_pounds > 9.5

ТНЕN
ТНЕN

"underweight"
"overweight"

ELSE

"average"
END

AS weight,
COUNТ(*) AS num_examples,
round(count(*) / sum(count(*)) over(), 4)

аз

percent_of_dataset

FRQo{

' bigquery-puЫic-data.samples.natality '

GROUP

ВУ

1
Результаты приведены в табл .

3.5.

Таблица 3.5. Процент каждой весовой категории,
присутствующей в наборе натальных данных
Вес

num_examples

percent_of_dataset

Средний

123781044

0.8981

Недостаточный

9649724

0.07

Избыточный

4395995

0.0319

Для демонстрационных целей мы возьмем

100 тыс.

примеров из каждого класса,

чтобы натренировать модель на обновленном сбалансированном наборе данных:

Паттерны для представления задачи

163

SEI.ECТ

is_male,
gestation_weeks,
mother_age,
weight_pounds,
weight
~(
SEI.ECТ

*,
ROW_NUMBER() OVER (PARTITION
FRa(

ВУ

weight ORDER

ВУ

RAND()) AS row num

(

SEI.ECТ

is_male,
gestation_weeks,
mother_age,
weight_pounds,
CASE
WНEN
WНEN

weight_pounds < 5.5
weight_pounds > 9.5

ТНЕN
ТНЕN

"underweight"
"overweight"

ELSE

"average"
END

AS weight,
~

'Ыgquery-puЫic-data.samples.natality'
LIМIT

4000000) )
WВERE

row num < 100000
Мы можем сохранить результаты этого запроса в таблице и, имея более сбаланси­
рованный набор данных, теперь можем натренировать классификационную модель
для назначения младенцам меток "недостаточный вес", "средний вес" или "избы­
точный вес":

OR REPLACE MODEL
'project.dataset.baby_weight_classification'
input label_cols=['weight']) AS

СRЕАТЕ

OPТIONS(model_type='logistic_reg',

SEI.ECТ

is_male,
weight_pounds,
mother_age,
gestation_weeks,
weight
FRa(

'project.dataset.baby_weight'
Еще один подход заключается в использовании паттерна "Каскад" для тренировки
трех отдельных регрессионных моделей для каждого класса. Затем мы можем при-

164

Глава

3

менить наше техническое решение, передавая первоначальной классификационной
модели пример и используя результат классифицирования, чтобы принимать реше­
ние о том, в какую регрессионную модель отправлять этот пример дЛЯ численного
предсказания.

Обнаружение аномалий
Для несбалансированных наборов данных существуют два подхода к манипулиро­
ванию регрессионными моделями:

+
+

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

В целях более глубокого понимания каждого технического решения предположим,

что мы тренируем модель на собранных датчиком данных, чтобы предсказывать
температуру. В этом случае нам нужно, чтобы результат работы модели был число­
вым значением.

В случае первого подхода

-

использование ошибки в качестве сигнала -

после

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

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

он требует от нас наличия новых легкодоступных данных, благодаря которым мы
получаем

возможность

сравнивать

поступающие

данные

с

модельным

предска­

занием. Как следствие, он лучше всего подходит для задач с участием потоковой

передачи данных или данных временного ряда.
Во втором подходе

-

кластеризация данных

-

мы начинаем со строительства мо­

дели с помощью кластеризационного алгоритма, технического приема моделирова­

ния, который организует наши данные в кластеры. Кластеризация

-

это метод

неконтролируемого обучения, означающий, что он занимается поиском закономер­
ностей в наборе данных, ничего не зная о метках эмпирических наблюдений.

Распространенным алгоритмом кластеризации является алгоритм
рый можно реализовать с помощью
исходного

k средних,

кода

демонстрирует

BigQuery ML.

процесс

на наборе натальных данных

тренировки

BigQuery

k

средних, кото­

Приведенный ниже фрагмент
модели,

основанной

знаков:

OR REPLACE MODEL
'project-name.dataset-name.baby_weight'
num clusters=4) AS
SELECT
weight_pounds,
mother_age,
gestation_weeks

на

с использованием трех при­

СRЕАТЕ

OPТICNS(model_type='kmeans',

Паттерны для представления задачи

165

FRCМ
'bigquery-puЫic-data.samples.natality'

10000

LIМIT

Результирующая модель соберет наши данные в четыре группы. После создания
модели

мы

сможем

генерировать

предсказания

на

новых данных

и

смотреть

на

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

дующий ниже запрос, передав ему вымышленный усредненный пример из набора
данных:

SELECT

*
FRCМ

ML.PREDICT (MODEL 'project-name.dataset-name.baby_weight',
SELECТ

7.0 as weight_pounds,
28 as mother_age,
40 as gestation_weeks

Результаты запроса в табл.

3.6

показывают расстояние между этой точкой данных

и сгенерированными моделью кластерами, именуемыми центроидами.

Таблица

3.6.

Расстояние между примером средневесовой точки данных

и каждым кластером, сгенерированным моделью, основанной на

CENTROID_ID NEAREST_CENTROIDS_DISTANCE.CENTROID_ID

средних

NEAREST_CENTROIDS_DISTANCE.DISTANCE

0,2999862781213737 4

4

4

1

1,2370167418282159

2

1,376651161584178

3

1,6853517159990536

Как видно из малого расстояния

k

(0,29),

этот пример четко вписывается в центроид

4.

Указанный результат можно сравнить с результатами, которые мы получим, если

отправим в модель выброс, т. е. пример с недостаточным весом (табл.

3.7).

Здесь расстояние между этим примером и каждым центроидом довольно велико.

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

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

Глава З

166

3. 7. Расстояние между примером точки данных с недостаточным весом
и каждым кластером, сгенерированным моделью, основанной на k средних

Таблица

CENTROID_ID

NEAREST_CENTROIDS_DISTANCE.CENTROID _ID

NEAREST_CENTROIDS_DIST ANCE.DISTANCE

3

3

3,061985789261998

4

3,3124603501734966

2

4,330205096751425

1

4,658614918595627

Число примеров миноритарного класса
Хотя миноритарный класс в первом примере обнаружения мошенничества состав­

лял всего О, 1% данных, набор данных был крупным настолько, что для работы
у нас все же было

8 тыс.

мошеннических точек данных. В случае наборов данных

с еще меньшим числом примеров миноритарного класса понижающий отбор может

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

архитектуры модели. Общее эмпирическое правило состоит в том, что если у вас
лишь сотни примеров миноритарного класса, то для манипулирования дисбалансом

набора данных можно рассмотреть техническое решение, которое отличается от
понижающего отбора.

Также стоит отметить, что естественным эффектом удаления подмножества мажо­
ритарного класса является потеря хранящейся в этих примерах некоторой инфор­
мации. Данная потеря может немного снизить способность модели выявлять мажо­

ритарный класс, но часто выгоды от понижающего отбора все же этот эффект пере­
вешивают.

Сочетание разных технических приемов
Описанные выше технические приемы понижающего отбора и взвешивания клас­
сов можно совместить в целях достижения оптимальных результатов. Для этого

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

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

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

торые она помечает как "не мошенническая". В добавление к этому, как упомина­
ется в

SMOTE,

подход по генерированию синтетических примеров из миноритар-

Паттерны для представления задачи

167

ного класса нередко сочетается с удалением случайной выборки примеров из ма­
жоритарного класса.

Понижающий отбор также часто сочетается с паттерном "Ансамбли". Используя
этот подход, вместо полного удаления случайной выборки из мажоритарного клас­
са мы используем разные его подмножества для тренировки нескольких моделей, а

затем совмещаем эти модели. В целях иллюстрации предположим, что у нас есть

набор данных со

100

примерами миноритарного класса и

тарного класса. Вместо удаления

900

разбили мажоритарные примеры случайно на
чтобы

идеально

сбалансировать

1ООО

примерами мажори­

примеров из мажоритарного класса мы бы

набор



групп по

100

Затем

мы

данных.

примеров в каждой,
бы

натренировали

l О классификаторов, каждый с теми же 100 примерами из миноритарного класса и
l 00 разными, случайно отобранными значениями из мажоритарного класса. Проил­
люстрированный на рис. 3.11 технический прием бэггинга хорошо вписывается
в этот подход.

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

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

в любой ситуации, когда мы хотим избежать ложных утверждений о данных (лож­
ноположительных результатов). Если же дороже обходится упущение потенциаль­

ной положительной классификации, даже если мы можем ошибаться, то мы опти­
мизируем нашу модель под метрику полноты.

Выбор архитектуры модели
В зависимости от задачи предсказания существуют разные архитектуры, которые
следует учитывать при решении задач с помощью паттерна "Перебалансировка".
Если мы работаем с табличными данными и строим классификационную модель

для обнаружения аномалий, то, как иллюстрирует одна научно-исследовательская

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

дачах, связанных с малыми и несбалансированными наборами данных.

scikit-learn

и

TensorFlow

XGBoost,

имеют соответствующие методы для реализации моделей,

основанных на деревьях решений.

Мы можем создать двоичный классификатор в

фрагмент исходного кода:

#

Построить модель

model = xgb.XGBClassifier(
objective='binary:logistic'

39

См. https://oreil.ly/EnAab.

XGBoost,

написав следующий

168
#

Глава

3

Натренировать модель

model.fit(
train_data,
train labels
Понижающий отбор и веса классов могут использоваться в каждом из этих фрейм­
ворков для дальнейшей оптимизации модели с использованием паттерна "Переба­

лансировка". Например, в целях добавления взвешенных классов в приведенный
выше классификатор

XGBC!assifier

мы добавим параметр scale _pos _ weight, рассчи­

танный на основе баланса классов в наборе данных.
Если мы занимаемся обнаружением аномалий в данных временного ряда, то моде­
ли на основе долгой кратковременной памяти

(long short-term memory, LSTM)

хорошо работают для выявления закономерностей, присутствующих в последова­
тельностях. Кластеризационные модели являются неплохим вариантом для таблич­

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

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

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

Важность объяснимости
Во время строительства моделей для выявления редких случаев в данных, таких как

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

действует на правильных сигналах, а также объяснять поведение модели конечным
пользователям. Существует несколько инструментов, которые помогают интерпре­

тировать модели и объяснять предсказания, включая фреймворк с открI?пым ис­

ходным кодом SНАР 41 , инструмент

в составе инфраструктуры

What-Ifl 2
Google Cloud43 •

и инструментарий ExplainaЫe

AI

Объяснения моделей могут принимать различные формы, одна из которых называ­

ется атрибуционными значениями. Атрибуционные значения говорят нам о том,
насколько каждый признак в модели повлиял на модельное предсказание. Положи­

тельные атрибуции означают, что тот или иной признак подтолкнул модельное

40

См. https://oreil.ly/2ai2k.

41

См. https://github.com/slundberg/shap.

42

См. https://oreil.lyNtзD.

43

См. https://oreil.ly/IDocn.

Паттерны для представления задачи

169

предсказание вверх, а отрицательные атрибуции означают, что этот признак под­

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

рые

больше

всего

сигнализировали

о

предсказании.

В

табличных

моделях

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

После тренировки модели в

TensorFlow на

синтетическом наборе данных

обнаружению мошенничества и ее развертывания в ExplainaЫe
структуры

Google Cloud

ня экземпляров. На рис.

AI

Kaggle

по

облачной инфра­

давайте взглянем на несколько примеров атрибуций уров­

3 .21

представлены два примера транзакций, которые наша

модель правильно определила как мошеннические, вместе с их признаковыми ат­

рибуциями.
Модельное предсказание:

ty~

0,9968869090080261

1

1

step
oldbalance~st

illТ\oont

1
1
02

00
Модельное предсказание:

04

Об

08

0,8914304971694946

!у~

step

oldbal•nc~

"


1

oldЬ/Jlance~st
lll!!Wllal1nc~ri11

newbalanceDest



illТ\ount

-Q 1

Рис.

3.21.

00

о

l

ОЗ

04

05

Об

07

Признаковые атрибуции, полученные из инструмента ExplainaЫe

AI

для двух правильно классифицированных мошеннических транзакций

В первом примере, где модель предсказала 99%-ную вероятность мошенничества,

старый остаток на изначальном счете до совершения транзакции был самым боль­

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

89%,

где сумма сделки была идентифицирована

170

Глава З

как самый большой сигнал мошенничества. Однако остаток на изначальном счете

сделал модель менее уверенной в своем предсказании мошенничества и объясняет,
почему предсказательная уверенность чуть ниже на



процентных пунктов.

Объяснения важны для любого типа модели машинного обучения, но мы видим их
особую полезность для моделей, которые следуют паттерну "Перебалансировка".
Когда мы имеем дело с несбалансированными данными, важно заглядывать за пре­
делы метрик точности и ошибки модели в той части, которая касается подтвержде­
ния того, что она действует на содержательных сигналах в наших данных.

Резюме
Эта глава была посвящена разным подходам к представлению задачи предсказания

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

применять свою модель, вы помогаете себе принимать правильное решение отно­
сительно типа создаваемой модели и о том, как форматировать результат предска­
зания. Итак, мы начали с паттерна "Переформулировка"

(Reframing),

который опи­

сывает подходы к замене вашей задачи с регрессионной на классификационную
(или наоборот) с целью улучшения качества модели. Это делается за счет перефор­
матирования столбца метки в данных. Далее мы описали паттерн "Мультиметка"

(Multilabel),

который обращается к случаям, когда подаваемая на вход модели пе­

ременная может ассоциироваться с более чем одной меткой. В этом случае следует

использовать сигмоидную активационную функцию на выходном слое с двоичной
перекрестно-энтропийной потерей.

В то время как паттерны "Переформулировка" и "Мультиметка" сконцентрированы
на форматировании результата работы модели, паттерн "Ансамбли" (EnsemЫes)
обращается к архитектуре и предусматривает различные методы сочетания не­

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

ленных моделей в одну систему. Паттерн "Каскад"

(Cascade)

также является подхо­

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

в котором первоначальные классификационные метки хаотичны и одинаково важны.
Далее мы рассмотрели паттерн "Нейтральный класс"

(Neutral Class),

который реша­

ет задачу представления на выходном уровне. Указанный паттерн совершенствует

двоичный классификатор, добавляя третий "нейтральный" класс. Это полезно в тех
случаях, когда вы хотите улавливать произвольные или менее поляризующие клас­

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

Наконец, паттерн "Перебалансировка"

(Rebalancing)

предоставляет технические

Паттерны для представления задачи

171

решения для случаев, когда у вас есть изначально несбалансированный набор дан­
ных. Указанный паттерн предлагает использовать понижающий отбор, взвешенные
классы или специальные технические приемы переформулировки задачи с целью
отыскания решений для наборов данных с несбалансированными классами меток.
Главы

2

и

3

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

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

перейдем к очередному шагу рабочего потока процессов машинного обучения
паттернам для тренировки моделей.

-

ГЛАВА4

Паттерны

для тренировки моделей

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

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

меры прироста информации. В генетических алгоритмах параметры модели пред­
ставлены в виде генов, и метод оптимизации предусматривает участиетехнических

приемов, которые основываются на теории эволюции. Однако наиболее распро­
страненным подходом к определению параметров моделей машинного обучения
является градиентный спуск.

Стохастический градиентный спуск
На крупных наборах данных градиентный спуск применяется к мини-пакетам
входных данных для тренировки чего угодно, начиная от линейных моделей и бус­

тированных деревьев до глубоких нейронных сетей

( deep neural networks, DNN)
и опорно-векторных машин (support vector machines, SVM). Он называется стохас­
тическим градиентным спуском (stochastic gradient descent, SGD), а расширения
стохастического градиентного спуска (такие как Adam и Adagrad) являются

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

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

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

Глава

174

4

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

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

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

Цикл тренировки в

Keras

Типичный цикл тренировки в

Keras выглядит так:

model = keras.Model ( ... )
model.compile(optimizer=keras.optimizers.Adam(),
loss=keras.losses . categorical_crosse ntropy(),
metric s= [ 'accuracy' ) )
history = mode l.fit (x_train, y_train,
ba t ch_s i ze=64,
epochs=З,

validation_data= (x_val, y_val))
results = model.evaluate(x_test, y_test, batch_size=l28))
model. save ( .. . )
Здесь в модели используется оптимизатор

Adam

для выполнения стохастического

градиентного спуска на перекрестной энтропии над тренировочным набором дан­
ных, который сообщает окончательную точность, полученную на тестовом наборе
данных. Процедура подгонки модели прокручивает в цикле тренировочный набор
данных

3 раза

(каждый обход тренировочного набора данных называется эпохой),

при этом модель каждый раз видит пакеты, состоящие из

64 тренировочных приме­

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

4.1 ).

Вместо использования предварительно построенной функции fi t ( ) мы могли бы
также написать пользовательский цикл тренировки , который прокручивает пакеты
Каждая эпоха обрабатывается блоками

\

no batch size примеров

-

·~'va'V':.~'va'V·~'vaюllЗ
Рис.
по

4.1. Типичный цикл тренировки состоит иэ трех эпох. Каждая эпоха обрабатывается блоками
batch s ize примеров . В конце третьей эпохи модель оценивается на тестовом наборе данных
- и сохраняется для потенциального развертывания в качестве веб-службы

Паттерны для тренировки моделей

175

в явной форме, но нам это не потребуется ни для одного обсуждаемого в данной
главе паттерна.

Паперны для выполнения тренировки
Все описанные в этой главе паттерны так или иначе связаны с модифицированием

типичного

цикла

Overfitting)

мы отказываемся от использования валидационного или тестового на­

тренировки.

В

паттерне

"Полезное

переобучение"

(Useful

бора данных, потому что намеренно хотим добиться переобучения на тренировоч­

ном наборе данных. В паттерне "Контрольные точки"

(Checkpoints)

мы периодиче­

ски сохраняем полное состояние модели, чтобы иметь доступ к частично натрени­

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

виртуальные эпохи, в которых решаем выполнять внутренний цикл функции f i t ()
не на полном тренировочном наборе данных, а на фиксированном числе трениро­

вочных примеров. В паттерне "Трансферное обучение"

(Transfer Leaming)

мы бе­

рем часть ранее натренированной модели, замораживаем веса и встраиваем эти не­
тренируемые слои в новую модель, которая решает ту же задачу, но на меньшем

наборе данных. В паттерне "Распределительная стратегия"

(Distribution Strategy)

цикл тренировки выполняется в требуемом масштабе на нескольких воркерах, час­

то с кэшированием, аппаратным ускорением и параллелизацией. Наконец, в пат­

терне "Гиперпараметрическая настройка"

(Hyperparameter Tuning)

сам цикл трени­

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

ПАТТЕРН

11.

Полезное переобучение

В паттерне "Полезное переобучение"

(Useful Overfitting)

мы отказываемся от ис­

пользования механизмов обобщения, потому что намеренно хотим добиться пере­

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

Постановка задачи
Цель модели машинного обучения

-

обобщать и делать надежные предсказания на

новых, ранее не встречавшихся данных. Если ваша модель переобучена на трениро­
вочных данных (например, она продолжает уменьшать тренировочную ошибку за
пределами точки, в которой валидационная ошибка начинает увеличиваться), тогда
ее способность к обобщению страдает, как и ваши будущие предсказания. Базовые

1

Переподгонка (overfitting) возникает, когда МL-модель слишком плотно прилегает к тренировочным дан­

ным и поэтому не способна давать точные предсказания на ранее не встречавшихся данных. Неплохой ана­
логией является визит к портному: переподгонка

наоборот.

-

Прим. перев.

-

костюм подогнан слишком плотно, недоподгонка

-

Глава

176

4

учебники по машинному обучению советуют избегать переобучения, используя
методы досрочной (ранней) остановки и регуляризации.
Рассмотрим, однако, ситуацию симулирования поведения физических или динами­

ческих систем, подобных тем, которые встречаются в климатологии, вычислитель­

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

(partial differential equation,

РОЕ). Хотя уравнения, управляющие многими из этих систем, могут быть выраже­

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

Рассмотрим ситуацию, показанную на рис.

4.2.

Наблюдения, собранные из физиче­

ской среды, используются на входе (или в качестве первоначальных стартовых ус­

ловий) в основанную на законах физики модель, которая выполняет итерационные
численные вычисления для расчета высокоточного состояния системы. Предполо­

жим, что все наблюдения имеют конечное число возможностей (например, темпе­

ратура будет изменяться от

60

до

80

°С с шагом

0,01

°С). Тогда можно будет соз­

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

9

Модель

.---1'. ~ .на ос__,нове .---1'. '
~ ~ики
~ -:i

Наблюдения

Qвычислить

.

Высокоточное

CJ / ------.. _______
решение

f) тренировочные

"Г1".

МL-модель

Быстрая аnnроксимация

Натренировать

1

О Предсказательный вывод
Рис. 4.2. Одна из ситуаций, когда переобучение допустимо, заключается в том,
что все пространство наблюдений в области определения может быть сведено в таблицу
и имеется физическая модель, способная вычислять высокоточное решение

Модель

ML

должна запомнить эту высокоточно рассчитанную и неперекрываю­

щуюся справочную таблицу входных и выходных данных. Выбор в пользу разбив­
ки такого набора данных на тренировочный и оценочный наборы будет контрпро-

Паттерны для тренировки моделей

177

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

боре данных.

Решение
В этом сценарии нет "ранее не встречавшихся" данных, для которых необходимо

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

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

и т. д.) на каждом атмосферном уровне. Существует конечное число возможных
типов гидрометеоров и конечное число высот, которые численная модель предска­

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

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

В этой ситуации на первый план выходит машинное обучение. Его можно исполь­

зовать для создания модели, которая аппроксимирует решения 2 модели прямого
излучательного переноса (рис.
технологии

ML

4.3).

Эта аппроксимация с привлечением средств

может быть сделана достаточно близкой к модельному решению,

которое изначально было достигнуто с помощью более классических методов. Ее
преимущество заключается в том, что предсказательный вывод с применением ап­

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

потребовало бы численных методов). В то же время тренировочный набор данных
слишком велик (несколько терабайт) и слишком громоздок для использования

в качестве справочной таблицы в производстве.

2

См. https://oreil.ly/lkYKm.

Глава

178

4
Набор дифференциапьных уравнений в частных производных

Рис.

4.3. Архитектура

использования нейронной сети для моделирования решения уравнения
в частных производных для

/(r, t,

п)

Существует важное различие между тренировкой МL-модели для аппроксимирова­
ния решения такой динамической системы и тренировкой МL-модели для предска­

зания веса младенца на данных о рождаемости, собранных в течение многих лет.
А именно динамическая система представляет собой набор уравнений, управляе­
мых законами электромагнитного излучения

-

нет ни ненаблюдаемой переменной,

ни шума и ни статистической изменчивости. Для конкретного набора входных дан­
ных существует лишь один высокоточно рассчитываемый результат. В трениро­

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

чтобы наша МL-модель вписывалась в тренировочные данные как можно лучше,
став "переобученной".

Это противоречит типичному подходу к тренировке модели

ML,

при котором важ­

ны соображения смещенности, дисперсии и ошибки обобщения. Традиционно по­
нимаемый процесс тренировки предусматривает наличие возможности, при кото­

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

Переобучение на тренировочном наборе данных в таком ключе приводит к тому,
что модель дает ошибочные предсказания на новых, ранее не встречавшихся точках
данных. Но мы заведомо знаем, что ранее не встречавшихся данных не будет, по­

этому

модель аппроксимирует решение

набора дифференциальных уравнений

в частных производных (РОЕ) над полным входным спектром. Если ваша нейрон­
ная сеть способна усваивать набор параметров, где функция потери равна нулю, то
этот набор параметров определяет фактическое решение рассматриваемого диффе­
ренциального уравнения.

Почему это работает
Если все возможные входные данные можно свести в таблицу, то, как показано
пунктирной кривой на рис.

4.4,

переобученная модель все равно будет делать те же

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

Паттерны для тренировки моделей

179

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

разрешающей способностью, с которой входное пространство было разделено
сеткой.

1
11

"
Рис.

4.4.

Переобучение не вызывает озабоченности, если модель натренирована

на всех возможных входных точках, потому что предсказания одинаковы для обеих кривых

Можно ли найти модельную функцию, которая будет сколь угодно близкой к ис­
тинным меткам? Объяснение того, почему это работает, вытекает из теоремы рав­

номерной аппроксимации, относящейся к глубокому обучению, которая утвержда­
ет, что любая функция (и ее производные) может быть аппроксимирована нейрон­

ной сетью по меньшей мере с одним скрытым слоем и любой "сплющивающей"
активационной функцией, такой как сигмоида. Из нее следует, что независимо от

данной нам функции, до тех пор, пока она ведет себя относительно хорошо, суще­
ствует нейронная сеть только с одним скрытым слоем, которая аппроксимирует эту

функцию так близко, как мы хотим3 •
Основанные на глубоком обучении подходы к решению дифференциальных урав­

нений или сложных динамических систем призваны представлять функцию, опре­
деленную в неявной форме дифференциальным уравнением или системой уравне­
ний, с использованием нейронной сети.

Переобучение полезно при соблюдении двух следующих условий:



нет шума, поэтому метки точны для всех случаев;



в вашем распоряжении имеется полный набор данных (у вас есть все возможные

примеры), в этом случае переобучение становится интерполированием набора
данных.

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

3

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

потому, что такая нейронная сеть существует (вот почему выручает изменение архитектуры модели путем
добавления слоев

-

это делает ландшафт потери более поддающимся стохастическому градиентному спуску).

180

Глава

4

обучение не является проблемой, потому что нет ранее не встречавшихся данных.

Однако паттерн "Полезное переобучение" полезен и за пределами этого узкого ва­
рианта использования.

Во

многих реальных ситуациях, даже если приходится

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

Интерполяция и теория хаоса
Модель машинного обучения функционирует как приближение (аппроксимация)
справочной таблицы входных данных к выходным. Если справочная таблица мала,
ее следует использовать именно как справочную таблицу! Нет необходимости ап­
проксимировать ее моделью машинного обучения. Аппроксимация

ML

полезна

в ситуациях, когда справочная таблица слишком велика для ее эффективного ис­
пользования. Именно в случае громоздкости справочной таблицы предпочтитель­
нее трактовать ее как тренировочный набор данных для МL-модели, которая ап­
проксимирует эту справочную таблицу.

Обратите внимание: мы исходили из того, что наблюдения будут иметь конечное
число возможностей. Например, мы постулировали, что температура будет изме­

ряться в приращениях

0,01

°С и находиться между

60

и

80

°С. Это справедливо,

если наблюдения фиксируются цифровыми приборами. Если это не так, то модель

ML

необходима для интерполирования между записями из справочной таблицы.

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

примеров. Такая интерполяция работает только в том случае, если лежащая в ее
основе система не является хаотической. В хаотических системах, даже если сис­
тема

детерминирована,

малые

различия

в

начальных

условиях

могут

привести

к кардинально разным исходам.

Тем не менее на практике каждое отдельное хаотическое явление имеет конкрет­

ный порог разрешающей способности4, за пределами которого существует возмож­
ность, что модели будут прогнозировать его в течение коротких промежутков вре­
мени.

Следовательно,

если

справочная

таблица

достаточно

детализирована

и

понятны пределы разрешающей способности, можно получить полезные аппрок­
симации.

Методы Монте-Карло
В реальности сведение в таблицу всех вероятных входных значений может оказать­
ся практически неосуществимым, и вы, возможно, воспользуетесь подходом, осно­

ванным на методах Монте-Карло 5 , для выборки из входного пространства для соз­
дания набора входных значений, в особенности там, где не все возможные комби­
нации входных значений физически возможны.

4

См. https://oreil.ly/F-dгtT.

5

См. https://oreil.ly/pTgS9.

Паттерны для тренировки моделей

В таких случаях переобучение технически возможно (на рис.
кружки

аппроксимированы

неверными

оценками,

4.5

показанными

181

незаполненные

кружками

с

кре­

стиками).
1 ...



1

\

Рис.

4.5.

Если данные входного nространства не сведены в таблицу и вместо этого из него

отбираются пробы, то вам нужно nозаботиться об ограничении модельной сложности

Однако даже здесь вы увидите, что МL-модель будет интерполировать между из­
вестными ответами. Вычисление всегда является детерминированным, и только
входные точки подвергаются случайному отбору. Следовательно, эти известные

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

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

Дискретизации под управлением данных
Хотя получение решения в замкнутой форме является возможным для некоторых
наборов дифференциальных уравнений в частных производных

(PDE),

определение

решений с использованием численных методов более распространено. Численные
методы

PDE уже

являются обширной областью научных исследований, и этой теме

посвящено много книг6 , курсов 7 и журналов 8 • Одним из распространенных подхо­
дов является использование конечно-разностных методов, подобных методам Рун­

ге

-

Кутты

(Runge -

Kutta),

для решения обыкновенных дифференциальных

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

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

между ячейками сетки должно быть достаточно малым9 , чтобы можно было

6

См. https://oreil.ly/RJ\VVQ.

7

См. https://oreil.ly/wcl_n.

8

См. https://msp.org/apde.

9

См. https://oreil.lyГfxHD-.

182

Глава

4

захватывать наименьший размер признака в решении. Поэтому для достижения

l О-кратного

увеличения разрешающей способности снимка требуется



ООО-крат­

ное увеличение вычислительной мощности, поскольку сетка должна быть масшта­
бирована в четырех измерениях с учетом пространства и времени.
Однако существует возможность использовать не методы Монте-Карло, а машин­

ное обучение, отбирая образцы точек для создания управляемых данными дискре­
тизаций наборов дифференциальных уравнений в частных производных. В статье
"Автоматическое

усвоение

дискретизаций,

(Leaming data-driven discretizations for PDEs) 10

управляемых

Бар-Синай

данными,

(Bar-Sinai)

для

PDE"

и соавт. демон­

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

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

численную симуляцию в минимизировании абсолютной ошибки, в некоторых мес­

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

Такие методы, как глубокий метод Галеркина

(deep Galerkin method),

могут исполь­

зовать глубокое обучение, чтобы обеспечивать бессеточную аппроксимацию реше­

ния данного дифференциального уравнения в частных производных. При подобном
подходе решение дифференциального уравнения сводится к задаче цепной оптими­
зации (см. разд. "Паттерн

8.

Каскад" главы

3).

Глубокий метод Галеркина
Глубокий метод Галеркина 11

-

это алгоритм глубокого обучения для решения

дифференциальных уравнений в частных производных. Указанный алгоритм анало­
гичен по духу методам Галеркина, используемым в области численного анализа,
в котором решение аппроксимируется с помощью нейронной сети, а не линейной

комбинации базисных функций.

Неограниченные области
И в методах Монте-Карло, и в управляемых данными методах дискретизации исхо­

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

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

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

10

См. https://oreil.ly/djDkК.

11

См. https://oreil.ly/rQy4d.

Паттерны для тренировки моделей

1

183

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

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

зультатом на участках вне области, которые не подверглись отбору проб в фазе
тренировки. А это может создавать проблемы в использовании

ML

для решения

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

выборку для тренировки.

Дистиллирование знаний нейронной сети
Еще одна ситуация, когда переобучение оправдано, заключается в дистиллирова­

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

малые модели сложнее. Хотя меньшая модель обладает достаточной емкостью для

представления знаний, она может не обладать достаточной емкостью для эффек­
тивного обучения знаний.

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

из большей модели. Это задача проще и может быть усвоена меньшей моделью.
Как и при аппроксимировании числовой функции МL-моделью, цель состоит в том,

чтобы меньшая модель была добросовестным представителем предсказаний боль­
шей модели машинного обучения. На этом втором тренировочном шаге можно ис­

пользовать паттерн "Полезное переобучение"

(Useful Overfitting).

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

Переобучение на малом пакете

-

хорошая проверка на вменяемость 12 как модели,

так и конвейера ввода данных. Если модель компилируется и исходный код выпол­
няется без ошибок, это не означает, что вы вычислили то, что у вас есть, или что

целевая установка тренировки

сконфигурирована правильно.

Сложная

модель

должна быть способной к переобучению на достаточно малом пакете данных
в предположении, что все настроено правильно. Поэтому, если вы не можете пере­
обучить любую модель на малом пакете, то стоит перепроверить код модели, кон-

12

См. https://oreil.ly/AcLtu.

184

Глава

4

вейер ввода данных и функцию потери на наличие каких-либо ошибок или простых

дефектов. Переобучение на пакете данных

-

полезный технический прием во вре­

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

Вы можете протестировать свой код модели

Keras,

используя tf. data. Dataset, кото­

рый вы написали для своего конвейера ввода данных. Например, если ваш конвей­

ер ввода тренировочных данных называется trainds, то мы будем использовать

batch ( J для извлечения одного пакета данных. Полный исходный код для данного
примера 14 можно найти в репозитории, прилагаемом к этой книге:

SIZE = 256
single_batch = trainds.batch(BATCH SIZE) .take(l)

ВАТСН

Затем, во время тренировки модели, вместо того чтобы вызывать полный набор
данных

trainds внутри метода fit (), мы используем созданный нами один­

единственный пакет:

model.fit(single_batch.repeat(),
validation_data=evalds,

... )
Обратите внимание, что мы применяем метод repeat (), чтобы не исчерпывать дан­
ные во время тренировки на этом единственном пакете. За счет этого обеспечивает­

ся возможность многократно брать по одному пакету во время тренировки. Все ос­
тальное (валидационный набор данных, модельный код, сгенерированные признаки
и т. д.) остается прежним.
Вместо извлечения произвольной выборки из тренировочного набора данных мы

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

13

См. https://oreil.ly/A 7DFC.

См. https://gith u b.com/GoogleCloud Platform/m l-design-patterns/ЫoЬ/master/04_ hacking_training_loop/
distri bution _ strategies. ipyn Ь.
14

Паттерны для тренировки моделей

ПАТТЕРН

12.

185

Контрольные точки

В контрольных точках мы периодически сохраняем полное состояние модели, что­

бы иметь частично натренированные модели, которые могут служить окончатель­

ной моделью (в случае досрочной остановки) либо выступать в качестве отправной
точки для продолжения тренировки (в случае тонкой настройки и аварийного отка­

за машины).

Паттерн

"Контрольные точки"

(Checkpoints)

обеспечивает такую

функциональность.

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

Это обусловлено тем, что более сложные модели, как правило, имеют более на­

страиваемые параметры. По мере роста размеров модели время, необходимое для
подгонки одного пакета примеров, тоже увеличивается. По мере увеличения разме­
ра данных (и при условии, что размеры пакетов фиксированы) число пакетов тоже
увеличивается. Следовательно, с точки зрения вычислительной сложности этот
двойной удар означает, что тренировка будет занимать много времени.
На момент написания этой книги тренировка модели перевода с английского языка

на немецкий на новейшем модуле тензорного процессора

TPU)

(tensor processing unit,
2 ча­

с использованием относительно малого набора данных занимает около

сов 15. На реальных наборах данных, вроде тех, которые используются для трени­
ровки умных устройств, тренировка может длиться несколько дней.
Когда у нас тренировка длится так долго, шансы на аварийный отказ машины не­
приятно высоки. В таком случае при возникновении проблемы нужно иметь воз­
можность запустить работу не с самого начала, а продолжить ее с промежуточной
точки.

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

состояние модели и перезапускаться. Однако при этом мы должны обеспечивать
сохранение не только самой модели, но и ее промежуточного состояния. Что это
означает?

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

ванная модель содержит не всё свое состояние, а только информацию, необходи­
мую для создания функции предсказания. Например, для дерева решений это будут
окончательные правила по каждому промежуточному узлу и предсказанное значе-

15

См. https://oreil.ly/vDR,·e.

186

Глава

4

ние для каждого листового узла. Для линейной модели это будут окончательные
значения весов и смещенностей. Для полносвязной нейронной сети нам также нуж­

но добавить активационные функции и веса скрытых соединений.
Какие данные о состоянии модели нам нужны при восстановлении из контрольной
точки, которые экспортированная модель не содержит? Экспортированная модель

не содержит эпоху и номер пакета, которые модель в данный момент обрабатывает,
что, очевидно, важно для возобновления тренировки. Но цикл тренировки модели
может содержать больше информации. Для того чтобы эффективно выполнять гра­
диентный спуск, оптимизатор может изменять скорость обучения по расписанию.
Состояние этой скорости обучения отсутствует в экспортируемой модели. Кроме
того, в модели может иметься стохастическое поведение, например отсев. Оно тоже

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

Сохранение полного состояния модели с целью обеспечения возможности возоб­
новления тренировки с заданной точки называется фиксацией состояния в кон­

трольной точке

(checkpointing),

а сохраненные модельные файлы называются кон­

трольными точками. Как часто мы должны фиксировать состояния в контрольных
точках? Состояние модели изменяется после каждого пакета из-за градиентного
спуска. Поэтому, если мы не хотим потерять проделанную работу, то должны фик­
сировать состояние после каждого пакета. Однако контрольные точки огромны,

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

мисс между отсутствием какой-либо фиксации состояния вообще и фиксацией со­
стояния после каждого пакета.

В целях фиксирования состояния модели в контрольной точке в рамках

Keras

мето­

ду f i t () следует предоставить функцию обратного вызова:

checkpoint_path = '{}/checkpoints/taxi' .format(OUTDIR)
cp_callback
tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
save_weights_only=False,
verbose=l)
history = model.fit(x_train, y_train,
batch_size=64,
epochs=З,

validation_data=(x_val, y_val),
verbose=2,
callbacks=[cp_callback])
С добавлением фиксации состояния в контрольной точке цикл тренировки стано­
вится таким, каким он показан на рис.

4.6.

Паттерны для тренировки моделей

187

(')
:::т

т

n

"8"""



5

Рис.

4.6.

При фиксировании состояния в контрольной точке сохраняется полное состояние модели
в конце каждой эпохи

Контрольные точки в
На момент написания этой книги библиотека

PyTorch

PyTorch

напрямую не поддерживает

контрольные точки. Однако она поддерживает экстернализацию состояния боль­
шинства объектов. В целях реализации контрольных точек в PyTorch следует за­
просить, чтобы эпоха, состояние модели, состояние оптимизатора и любая другая
информация, необходимая для возобновления тренировки, были сериализованы
вместе с моделью:

torch. save ( {
' epoch ' : epoch,
'model_state_dict': model.state_dict(),
'optimizer_state_dict': optimizer.state_dict(),
'loss': loss,
},

РАТН)

Во время загрузки из контрольной точки вам нужно создать необходимые классы,
а затем загрузить их из контрольной точки:

model = •••
optimizer =
checkpoint = torch.load(PATH)
model.1oad_state_dict(check point['mode1_state dict'])
opti.mizer.1oa.d_state_dict(c heckpoint['opti.mizer_state_ dict'])
epoch = checkpoint [ 'epoch' ]
loss = checkpoint['loss']
Этот уровень является более низким, чем в

TensorFlow,

но он обеспечивает гиб­

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

Глава

188

4

Почему это работает

TensorFlow

и

Keras

автоматически возобновляют тренировку с контрольной точки,

если контрольные точки находятся в выходном пути. Следовательно, для того что­

бы начать тренировку с нуля, вы должны начать с нового выходного каталога (или
удалить предыдущие контрольные точки из выходного каталога). Это работает, по­

тому что фреймворки машинного обучения учитывают наличие файлов контроль­
ных точек.

Несмотря на то что контрольные точки предназначены в первую очередь для под­
держания отказоустойчивости, наличие частично натренированных моделей от­

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

ровой площадки

"о ~1

Tensorflow 16 (рис. 4.7).

Epoch

000,000

DATA

FEATURES

Whк.hdatasetdo

Whicll {Y'OPP.ft1es do
you wan\ 10 feed in?

YO\J want to use?

l.e:;i1mrig rate

0.03

11:1:н(!а111

+ -

Nон;е.

ВМсh

З

HIDDEN LAYERS

+ -

+ -

5neurons

Зneurons

. ,. "
D ~'',, о --. .">у,:
/
" LJ ',,_-О -~/ -- - о--~_.,,,

10%

35

"='

[} - /
о

srle 30

REGENERATE

о

ОUТР\П

+ _

Test loss

,...,,,.-

518

-- о

о
m.•~»>tll;·ar;VI\)'

1Wff.i!>1$, '1юwn ь~

Ttii.s ,, t'М o.Ap.J
lrom~~

COIOlS shows
dal.a neuron and

!l'{jll!r

Wt)lфl

О

4.7.

О

Traюиigloss0517

1ntUfO(I

~11'-lt

Рис.

PrnЬlemt'jpe

ratti

RеШ

Х•
Ral10 oftra1n1ng to

Ht>gula.'lz.atюn

Actr..;;tюn

V= one_month_ago ]
df_prev_week = df_evals[df_evals.time >= one_week_ago ]
В целях проведения вышеуказанных оцениваний в непрерывном режиме можно

запланировать работу блокнота (или контейнерезированной формы) по расписа-

Паттерны для отказоустойчивой обработки

265

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

Почему это работает
Во время разработки моделей машинного обучения присуrствует неявное допуще­
ние о том,

что тренировочные,

валидационные и тестовые данные

одного и того же распределения (рис.

5.4).

поступают из

Когда мы развертываем модели в произ­

водстве, то из указанного допущения вытекает, что будущие данные окажуrся по­

хожими на прошлые. Однако, как только модель будет запущена в производство
"в дикой природе", это статическое предположение о данных может оказаться не­

действительным. На самом деле многие промышленные МL-системы сталкиваются

с быстро меняющимися нестационарными данными, а модели со временем приоб­
ретают черты застарелости, что негативно сказывается на качестве предсказаний.

Распределение веса младенцев

Тренировать

0.40
0.35
о.за

Разработка

0.25
0.20
0.15
0.10
0.05
0.00

модели

Тестировать

2

4

6

8

10

12

Вес в фунтах
Рис.

5.4.

При разработке МL-модели тренировочные, валидационные и тестовые данные поступают

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

Непрерывное оценивание модели обеспечивает каркас для оценивания результа­
тивности развернуrой модели исключительно на новых данных. Это позволяет нам
как можно раньше обнаруживать застарелость модели. Указанная информация по­
могает определять частоту перетренировки модели или время, когда следует пол­

ностью заменять ее новой версией.
Захватывая входные и выходные данные предсказания и сравнивая их с эмпириче­

ским наблюдением, можно количественно отслеживать результативность модели

или измерять качество работы разных версий модели с помощью А/В-тестирования
в текущей среде, независимо от качества работы версий в прошлом.

Компромиссы и альтернативы
Цель непрерывного оценивания состоит в том, чтобы обеспечивать средства для
мониторинга результативности моделей и поддержания моделей в производствен­

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

Глава

266

5

перетренировку модели. И здесь важно учитывать допустимые пределы для резуль­
тативности модели, создаваемые ими компромиссы и роль плановой перетренировки.

Существуют также технические приемы и инструменты, такие как

TFX,

которые

помогают упреждающе обнаруживать дрейф данных и дрейф концепции, осущест­
вляя непосредственный мониторинг распределения во входных данных.

Триггеры для перетренировки
Результативность модели обычно со временем деградирует. Непрерывноеоценива­
ние

позволяет

высокоточно

структурированно

измерять

степень

ее

устаревания

и обеспечивает триггер для перетренировки модели. Значит ли это, что вы должны
перетренировывать свою модель, как только ее результативность начинает падать?

Все зависит от обстоятельств. Ответ на этот вопрос тесно связан с бизнес-кейсом
использования и должен обсуждаться наряду с метриками оценивания и оценива­
нием модели. В зависимости от сложности модели и конвейеров

ETL

стоимость

перетренировки бывает дорогостоящей. Следует учитывать компромисс между тем,
какая

величина ухудшения результативности является приемлемой, и ее стои­

мостью.

Бессерверные триггеры

Cloud Functions,

А WS

Lambda

и

Azure Functions

предоставляют бессерверные под­

ходы к автоматизированию перетренировки посредством триггеров. Тип триггера

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

нениями данных в базе данных или даже НТТРS-запросом. После того как событие
запущено, исходный код функции исполняется.

В контексте перетренировки триггер облачного события будет представлен значи­
тельным изменением или падением точности модели. Функция, или действие, будет
заключаться в вызове тренировочного конвейера для перетренировки модели и раз­

вертывания новой версии. В разд. "Паттерн
вы

6

25.

Конвейер рабочего потока" гла­

описан принцип выполнения этого процесса. Конвейеры рабочих потоков со­

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

чтобы определять необходимость ее замены.

Сам порог может быть установлен как абсолютное значение; например, перетрени­
ровка модели происходит, когда точность модели падает ниже

95%.

Как вариант,

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

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

Паттерны для отказоустойчивой обработки

267

сопровождение и переключение между разными версиями моделей. При более низ­
ком пороге затраты на тренировку снижаются, но модели становятся более застаре­
лыми. На рис.

5.5

отражен компромисс между порогом результативности и тем, как

он влияет на число заданий по перетренировке моделей.
Перетренировка Перетренировка Перетренировка

lп;J;i;~~ JГ~~ЬJ~-Поw
~
м

~ '--~~~~~~~~~·

Время

Время

Рис.

5.5.

Установка более высокого порога для результативности модели обеспечивает

более качественную промышленную модель, но потребует более частых перетренировок,

что бывает дорогостоящим

Если конвейер перетренировки моделей автоматически запускается таким порогом,

то важно также отслеживать и валидировать триггеры. Незнание момента, когда

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

дели, чтобы лучше понимать и отлаживать производственную модель.

Плановая перетренировка
Непрерывное оценивание дает ключевой сигнал для понимания времени, когда не­

обходимо перетренировывать модель. Этот процесс перетренировки нередко осу­
ществляется путем тонкой настройки предыдущей модели с использованием лю­

бых вновь собранных тренировочных данных. Там, где непрерывное оценивание
можно

выполнять

каждый день,

плановая

перетренировка может происходить

только каждую неделю или каждый месяц (рис.

5.6).

После тренировки новой версии модели ее результативность сравнивается с теку­

щей версией модели . Обновленная модель развертывается в качестве замены толь­
ко в том случае, если она по результативности превосходит предыдущую модель по

отношению к тестовому набору текущих данных.
Плановая перетре нировка

Неnрерывное
оценивание
д
,.----~----~-_/'-.....__-~----~-~

1ов"" 1
Рис.

5.6.

1

1

1

~

Непрерывный мониторинг обеспечивает оценивание модели каждый день

по мере сбора новых данных . Периодическая перетренировка и сравнение моделей
используются для оценивания в дискретные моменты времени

268

Глава

5

И как часто следует планировать перетренировку по расписанию? Расписание пе­

ретренировки будут зависеть от бизнес-кейса использования, распространенности
новых данных и стоимости (временной и денежной) исполнения конвейера пере­
тренировки. Иногда временной горизонт модели естественным образом определяет

момент, когда следует планировать работу по перетренировке. Например, если цель
модели состоит в предсказывании корпоративных заработков в следующем кварта­
ле, поскольку вы будете получать новые метки эмпирических наблюдений только
раз в квартал, то нет смысла тренировать чаще. Однако если объем и встречаемость
новых данных велики, то было бы выгодно выполнять перетренировку чаще. Са­
мой экстремальной версией перетренировки является онлайновое машинное обуче­

ние16. Некоторые приложения машинного обучения, такие как размещение рекламы
или рекомендации в новостной ленте, требуют принятия решений в режиме реаль­
ного времени и могут постоянно улучшать результативность путем перетренировки

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

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

API. Такие инструменты, как службы Cloud Composer/Apache Airflow и AI Platform
Pipelines, полезны для создания, планирования запусков и мониторинга рабочих
процессов ML от предобработки сырых данных и тренировки до гиперпарамет­
рической настройки и развертывания. Мы обсудим это в разд. "Паттерн 25. Кон­
вейер рабочего потока" главы 6.
Валидация данных с помощью

TFX

Распределение данных с течением времени может изменяться (рис.

5.7).

Например,

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

модельными признаками, такими как возраст матери или срок беременности, меня­
ется по отношению к модельной метке, весу младенца. Этот дрейф данных отрица­

тельно влияет на способность модели обобщать на новых данных. Одним словом,
модель приобрела черты застарелости, и ее нужно перетренировать на свежих дан­
ных.

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

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

16 См. https://oreil.ly/Mj-DA.

Паттерны для отказоустойчивой обработки

269

0,5
0,4
0,3
0,2
0,1
о.о
о

-2

2

6

4

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

Рис.

предсказания, по сравнению с данными, использованными для тренировки

Компонент валидации данных

TFX Data Validation является полезным инструмен­
TFX 17 - это сквозная платформа с открытым ис­

том для достижения этой цели.

ходным кодом для развертывания моделей машинного обучения разработки компа­

нии

Google.

Компонент

Data Validation

можно применять для сравнения примеров

данных, используемых в тренировке, с данными, собранными во время обработки
запросов. Проверки валидности обнаруживают аномалии в данных, асимметрию

между тренировкой и обслуживанием или дрейф данных.

tion

создает визуализации данных с помощью

Facets 18 ,

с открытым исходным кодом для машинного обучения.

TensorFlow Data Valida-

инструмента визуализации

Facets Overview

предостав­

ляет высокоуровневый взгляд на распределение значений по различным признакам
и может раскрывать несколько обычных и необычных проблем, таких как неожи­
данные значения признаков, пропущенные значения признаков и асимметрия меж­

ду тренировкой и обслуживанием.

Оценивание интервала перетренировки
Полезная и относительно дешевая тактика, позволяющая понять характер влияния
дрейфа данных и дрейфа концепции на модель, заключается в тренировке модели
на устаревших данных и оценивании результативности этой модели на более све­
жих данных (рис.

5 .8).

Таким образом можно сымитировать непрерывный процесс

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

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

мени и частоты перетренировки, которая может потребоваться.

17

См. https://oreil.ly/RP2e9.

18

См. https://oreil.ly/NE-SQ.

270

Глава

5
Сравнить метр~ки оценивания
г---------------J----------------1
1
1

i
Оценивание

Оценивание

на устаревших данных

на текущих данных

Модель, натренированная

Модель, натренированная

на устаревших данных

на устаревших данных

Устаревшие данные

Текущие данные

-6 месяцев
Рис.

5.8.

Тренировка модели на устаревших данных и оценивание на текущих данных

имитируют непрерывный процесс оценивания модели в офлайновой среде

ПАТТЕРН

19. Двухфазные

Патrерн "Двухфазные предсказания"
к

решению задачи

поддержания

предсказания

(Two-Phase Predictions)

обеспечивает подход

результативности крупных сложных моделей

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

Постановка задачи
При развертывании моделей машинного обучения мы не всегда можем полагаться

на конечных пользователей в том, что у них будут надежные интернет-соединения.
В таких ситуациях модели развертываются на периферии, т. е. скачиваются на уст­
ройство пользователя и не требуют подключения к Интернету для генерирования
предсказаний. Если учитывать технические пределы устройств, следует отметить,

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

Существуют разнообразные сценарии, по которым можно развертывать свои моде­
ли на периферийном устройстве. Один из примеров

-

устройство контроля физи­

ческой подготовки, в котором модель дает рекомендации пользователям на основе
их активности, отслеживаемой с помощью акселерометра и гироскопа. Вполне ве­

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

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

Паттерны для отказоустойчивой обработки

271

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

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

риферийных устройствах, модели часто проходят процесс, именуемый квантизаци­
ей, при котором усвоенные модельные веса представляются меньшим числом бай­

тов . В

TensorF\ow,

рования19

например, используется формат

сохраненных

моделей

в

меньший

TensorFlow Lite

формат,

для конверти­

оптимизированный

под

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

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

Квантизация и другие методы , используемые в

TF Lite,

значительно уменьшают

размер и задержку предсказания результирующих МL-моделей, но вместе с этим
может снижать и точность модели . Кроме того, поскольку мы не можем неизменно

опираться на периферийные устройства, имеющие возможность подключения, так­
же представляет проблему и своевременное развертывание новых версий моделей
на этих устройствах .

Как компромиссы достигаются на практике, можно увидеть, взглянув на варианты

тренировки периферийных моделей в службе

Cloud AutoML Vision 20

на рис.

5.9.

Optimize model for
Goal
О Higher

Package slze

Accuracy

La1ency for Google Plxel 2

бМВ

Hlgher

ЗбОms

3.2 МВ

Medium

150 ms

О . б МВ

Lower

5бms

accuracy

(i Best tradeoff
О

Faster
predictions

Please note that prediction latency estimates are for guidance only. Actual latency will
depend оп your network connectlvity.

CONTINUE

Рис.

5.9.

Поиск компромиссов между модельной точностью, размером и задержкой для моделей,
развернутых на периферии в службе

Cloud AutoML Visioп

В целях учета этих компромиссов нам нужно техническое решение, которое урав­

новешивает уменьшенный размер и задержку периферийных моделей с добавлен­
ной усложненностью и точностью облачных моделей.

19См .
20

https://oreil.lyf1.JaMq7.

См. https://oreil.ly/МWsQH .

272

Глава

5

Решение
С помощью паттерна "Двухфазные предсказания" мы подразделяем нашу задачу на
две части. Мы начинаем с меньшей, более дешевой модели, которую можно раз­

вернуть на периферийном устройстве. Поскольку эта модель обычно имеет более
простую задачу, она способна выполнять эту задачу на периферийном устройстве
с относительно высокой точностью. За ней следует вторая, более сложная модель,
развернутая в облаке и запускаемая только при необходимости. Разумеется, ука­
занный паттерн требует, чтобы у вас была задача, которую можно подразделить на
две части с разными уровнями сложности. Одним из примеров такой задачи явля­

ются умные устройства, такие как

Google Home 21 ,

которые активируются сигналом

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

занные с настройкой будильника, чтением новостей и взаимодействием со встроен­

ными устройствами, такими как лампы и термостаты.
тивируется словами "ОК

Google"

или "Неу

Google".

Google

Ноте, например, ак­

После того как устройство рас­

познает слово пробуждения, пользователи могут задавать более сложные вопросы,
такие как: "Сможешь назначить встречу с Сарой на



часов утра?"

Эту задачу можно разбить на две отличимые части: первоначальную модель, кото­

рая прослушивает слово пробуждения, и более сложную модель, которая способна
понимать и отвечать на любой другой запрос пользователя. Обе модели будут вы­
полнять распознавание звука. Первая модель, однако, должна будет выполнять
только двоичное классифицирование: соответствует ли звук, который она только
что услышала, слову пробуждения или нет? Хотя эта модель по сложности проще,
она должна работать постоянно, что будет обходиться дорого, если ее развернуть
в облаке. Вторая модель потребует распознавания звука и понимания естественного

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

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

-

в облаке.

В дополнение к этому варианту использования умного устройства паттерн "Двух­
фазные предсказания" может задействоваться в целом ряде других ситуаций. До­
пустим, вы являетесь сотрудником завода, где в определенный момент времени ра­

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

разному. В идеале вы можете построить модель, которая будет помечать проблем­
ные шумы и выявлять смысл, который они означают. С помощью паттерна "Двух­

фазные предсказания" можно было бы построить первую, офлайновую, модель для
обнаружения аномальных звуков. Затем задействовать вторую, облачную, модель,
чтобы выявлять, не является ли обычный звук признаком какого-то неисправного
состояния.

21

См. https://oгeil.ly/ЗROKg.

Паттерны для отказоустойчивой обработки

273

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

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

животного на фото.
В целях иллюстрации патгерна "Двухфазные предсказания" давайте воспользуемся

общецелевым набором данных распознавания звука из
данных содержит около

9 тыс.

Kaggle 22 •

Указанный набор

звуковых семплов знакомых звуков с

41

категорией

меток, включая "виолончель", "стук", "телефон", "труба" и многие другие. Первой

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

инструмент из общего числа

18

возможных вариантов. На рис.

5 .1 О

показан двух­

фазный процесс для данного примера.

Аудиоклиn

Двоичная классификационная модель
на периферийном устройстве
Рис.

5.10.

TF Lite

Действий не требуется

Использование паттерна "Двухфазные предсказания"

для идентифицирования звуков музыкальных инструментов

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

Это позволит нам использовать архитектуры распространенных снимковых мо­
делей наряду с патгерном "Трансферное обучение" для решения этой задачи. На
рис.

5.11

приведена спектрограмма аудиофрагмента звучания саксофона из нашего

набора данных.

22

См. https://oreil.ly/189Pr.

274

Глава

1

5

Рис.

5.11.

Снимок (спектрограмма) аудиофрагмента звучания саксофона

из нашего тренировочного набора данных. Исходный код для конвертирования WАV-файлов
в спектрограммы можно найти в репозитории 23 на GitHub

Фаза

1:

построение офлайновой модели

Первая модель в нашем техническом решении на основе паттерна "Двухфазные

предсказания" должна быть достаточно малой, чтобы ее можно было загружать на
мобильное устройство для быстрого предсказательного вывода, не полагаясь на
интернет-соединение. Опалкиваясь от приведенного выше примера с музыкаль­
ным инструментом, мы приведем пример первой фазы предсказания, построив дво­

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

41

метку для разных типов аудиокли­

пов. Наша первая модель будет иметь только две метки: "инструмент" или "не ин­
струмент". Мы построим нашу модель, используя архитектуру модели
натренированную на наборе данных
венно в

Keras

ImageNet. MobileNetV2

Mobi\eNetV224,

доступна непосредст­

и представляет собой архитектуру, оптимизированную под обработку

запросов на периферийном устройстве. В случае нашей модели мы заморозим веса
MoЬileNetV2 и загрузим ее без верхней части, вследствие чего сможем добавить
наш собственный выходной слой двоичного классифицирования:

mobilenet = tf.keras.applications.MobileNetV2(
input_shape= ((l28,128,3)),
include_top=False,
weights='imagenet'
mobilenet.trainaЫe

= False

Если мы организуем наши изображения спектрограмм в каталоги с соответствую­
щим именем метки, то сможем использовать класс

Keras для

ImageDataGenerator фреймворка

создания тренировочного и валидационного наборов данных:

23 См. https://github.com/GoogleCloudPlatform/ml-design-patterns/ЬloЫmaster/OS_resilience/audio_to_
spectro.ipynb.
24

См. https://oreil.ly/zvbzR.

Паттерны для отказоустойчивой обработки

275

train_data_gen = image_generator.flow_from_directory(
directory=data_dir,
batch_size=32,
shuffle=True,
target_size=(l28,128),
classes = ['not_instrument', 'instrument'],
class_mode='binary')
Когда тренировочный и валидационный наборы данных будут готовы, мы сможем
натренировать модель так, как это делается обычно. Типичным подходом к экспор­

тированию натренированных моделей для обработки запросов является использо­
вание TensorFlow-мeтoдa

model. save (). Вместе с тем следует помнить, что эта мо­

дель будет обслуживать запросы на периферийном устройстве, и следовательно,
она должна быть как можно меньше. Для создания модели, которая вписывается

в эти требования, мы будем использовать библиотеку

TensorFlow Lite25 ,

оптимизи­

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

В

TF Lite

есть несколько встроенных утилит для квантизации моделей как во время

тренировки, так и после нее.

В целях подготовки натренированной модели для периферийной обработки запро­
сов мы используем

TF Lite для

ее экспортирования в оптимизированный формат:

converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_model = converter.convert()
open('converted_model.tflite', 'wb') .write(tflite_model)
Этот подход к квантизированию модели после ее тренировки является самым быст­
рым. Используя настройки оптимизации, принятые в

TF Lite

по умолчанию, ука­

занный подход будет сводить веса модели к их 8-битному представлению. Он
также будет квантизировать входные данные во время предсказательного вывода,
когда мы делаем предсказания на нашей модели. Выполнив приведенный выше ис­

ходный код, результирующая экспортированная модель

TF Lite

будет иметь размер

в одну четвертую размера, который был бы, если бы мы экспортировали ее без
квантизации.

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

На момент написания этой книги оптимизир~емая квантизацией тренировка моде­

лей TensoгFlow 2 числится в дорожной карте
Для генерирования предсказания на модели

TF Lite Interpreter,

6.

TF Lite

мы используем интерпретатор

который оптимизирован под низкую задержку. Скорее всего, вы

захотите загрузить свою модель на устройство

25

См. https://oreil.ly/dyx93.

26

См. https://oreil.ly/RuONn.

Android

или

iOS

и генерировать

Глава

276

5

предсказания непосредственно из кода приложения. Для обеих платформ имеются
свои

API, но здесь мы покажем исходный код генерирования предсказаний на язы­
Python, чтобы можно было запускать его из того же блокнота, в котором вы соз­
дали свою модель. Сначала мы создаем экземпляр интерпретатора TF Lite и полу­
ке

чаем подробную информацию о входном и выходном форматах, которые он ожи­
дает:

interpreter = tf. lite. Interpreter (model _path="converted_model. tflite")
interpreter.allocate_tensors()
input_details = interpreter.get input_details()
output_details = interpreter.get_output_details()
Для двоичной классификационной модели MoЬileNetV2, которую мы натренирова­
ли

выше,

переменная

input _ details

с деталями выходных данных

выглядит сле­

дующим образом:

[{ 'dtype': numpy.float32,
'index': О,
'name': 'mobilenetv2 1.00 128_input',
'quantization': (О.О, 0),
'quantization_parameters': { 'quantized_dimension': О,
'scales': array([], dtype=float32),
'zero_points': array([], dtype=int32) },
'shape': array([ 1, 128, 128, 3], dtype=int32),
'shape_signature': array([ 1, 128, 128, 3], dtype=int32),
'sparsity_parameters': {}}]
Затем мы передадим первый снимок из нашего валидационного пакета в загружен­

ную модель

TF Lite для

предсказания, вызовем интерпретатор и получим результат:

input_data = np.array([image_batch[21]], dtype=np.float32)
interpreter.set_tensor(input_details[O] ['index'], input_data)
interpreter.invoke()
output_data = interpreter.get tensor (output_details [0] [ 'index'])
print(output_data)
На выходе мы получим сигмоидный массив с одним-единственным значением
в промежутке [О;

1],

указывающим на то, является ли поступивший на вход звук

звуком музыкального инструмента.

В зависимости от того, насколько дорого обходится вызов облачной модели, може­
те также

изменить метрику,

под которую вы оптимизируете

модель,

когда трени­

руете ее для периферийного устройства. Например, если вы больше всего стреми­
тесь избегать ложных утверждений (ложноположительных результатов), можете
оптимизировать не под полноту, а под прецизионность.

Теперь, когда модель работает на устройстве, мы можем получать быстрые пред­

сказания без необходимости полагаться на интернет-соединение. Если модель уве­
рена в том, что данный звук не является звуком музыкального инструмента, мы

Паттерны для отказоустойчивой обработки

277

можем на этом остановиться. Если же модель предсказывает "инструмент", то са­
мое время перейти к отправке аудиоклипа в более сложную облачную модель.

Какие модели подходят для периферии?
Как определить, что модель подходит для работы на периферии? На этот счет есть
несколько соображений, связанных с размером модели, ее сложностью и имею­
щимся аппаратным обеспечением. Как правило, малые, менее сложные модели оп­

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

с более простой задачей предсказания и архитектурой подходят для периферийных
устройств лучше всего. Под "проще" мы подразумеваем такие компромиссы, как

предпочтение двоичной классификации перед многоклассовой или выбор менее
сложной архитектуры модели (например, модели, основанной на дереве решений,

или линейно-регрессионной модели), когда это возможно.
Когда вам приходится разворачивать модели на периферии, при этом все-таки при­
держиваясь некоторых пределов по размеру модели и ее сложности, стоит взгля­

нуть на периферийное аппаратное обеспечение, специально разработанное с учетом

предсказательного вывода

ML. Например, плата Coral Edge TPU 27 обеспечивает
ASIC, оптимизированную под высокопроизводительный
офлайновый предсказательный вывод ML на моделях TensorFlow Lite. Подобным
же образом, компания NVIDIA предлагает набор инструментов Jetson Nano 28 для
оптимизированного под периферию маломощного предсказательного вывода ML.
Аппаратная поддержка предсказательного вывода ML быстро эволюционирует по
мере того, как встроенное периферийное ML становится все более распространен­
прикладную микросхему

ным.

Фаза

2:

построение облачной модели

Поскольку наша облачная модель не нуждается в оптимизации под предсказатель­

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

мости от вашего варианта использования на основе паттерна "Двухфазные предска­
зания" эта вторая модель может принимать множество разных форм. В примере
с

Google

Ноте фаза

2

могла бы включать в себя несколько моделей: одну, которая

на входе конвертирует речь говорящего пользователя в текст,

и вторую, которая

выполняет естественно-языковую обработку, чтобы понять текст и маршрутизиро­
вать запрос пользователя. Если пользователь просит что-то более сложное, можно
предусмотреть и третью модель, которая могла бы предоставлять рекомендацию на
основе предпочтений пользователя или прошлой активности.

27

См. https://oreil.ly/N2NOs.

28

См. https://oreil.ly/GUOQc.

278

Глава

5

В нашем примере с музыкальным инструментом второй фазой решения будет
мультиклассовая модель, которая классифицирует звуки в одну из 18 возможных
категорий музыкальных инструментов. Поскольку эта модель не нуждается в раз­
вертывании на периферийном устройстве, в качестве отправной точки можно ис­
пользовать более крупную модельную архитектуру, такую как VGG, а затем следо­
вать паттерну "Трансферное обучение", описанному в главе 4.
Мы загрузим

VGG,

натренированную на наборе данных

наших спектрограмм в параметре

input_shape

ImageNet,

зададим размер

и заморозим модельные веса перед

добавлением нашего собственного классификационного выходного слоя с функци­
ей мягкого максимума:

vgg_model = tf.keras.applications.VGG19(
include_top=False,
weights='imagenet',
input_shape=((l28,128,3))
vgg_model.trainaЫe

= False

На выходе получим 18-элементный массив sоftmах-вероятностей:

prediction_layer = tf.keras.layers.Dense(l8, activation='softmax')
Мы ограничим наш набор данных только аудиоклипами музыкальных инструмен­
тов, а затем преобразуем метки инструментов в 18-элементные векторы, кодиро­
ванные с одним активным состоянием. Дr~я подачи снимков в модель и ее трени­
ровки мы можем использовать такой же подход, как в вышеприведенном генерато­

ре image_generator. Вместо того чтобы экспортировать нашу модель как модель TF
Lite, мы можем применить model. save (), чтобы экспортировать ее для обработки
запросов.

В целях демонстрации развертывания модели фазы

2 в облаке мы будем использо­
Cloud AI Platfonn Prediction29 • Нужно закачать сохраненные активы
модели в корзину хранилища Cloud Storage, а затем развернуть модель, указав
фреймворк и направив службу AI Platfonn Prediction в нашу корзину хранения.
вать службу

Для второй фазы паттерна "Двухфазные предсказания" можно использовать лю­
бой другой облачный инструмент развертывания моделей. Помимо службы AI
Platform Predictioп облачного инструментария Google Cloud, инфраструктуры AWS
SageMaker30 и Azure Machiпe Learпiпg 31 предлагают службы для развертывания
моделей.

Когда мы экспортируем модель в формате

SavedModel

фреймворка

TensorFlow,

мы

можем передавать URL-aдpec корзины хранилища непосредственно в метод сохра­
нения модели

save ():

model.save('gs://your_storag e_bucket/path')

29

См. https://oreil.ly/P5Cn9.

30

См. https://oreil.Iy/zlHey.

31

См. https://oreil.Iy/dCxHE.

Паттерны для отказоустойчивой обработки

Приведенная выше инструкция экспортирует модель в формате
и закачивает ее в корзину хранилища
На платформе А1

Platform

279

1

TF SavedModel

Cloud Storage.

ресурс модели содержит разные версии вашей модели.

Каждая модель может иметь сотни версий. Сначала мы создадим ресурс модели

с помощью интерфейса командной строки

gcloud

инфраструктуры

Google Cloud:

gcloud ai-platform models create instrument_classification
Существует несколько подходов к развертыванию модели. Мы воспользуемся

интерфейсом

gcloud

и направим платформу

AI Platform

в подкаталог хранилища,

содержащий наши сохраненные модели:

gcloud ai-platform versions create vl \
--model instrument classif ication \
--origin 'gs://your_storage_bucket/path/model_timestamp' \
--runtime-version=2.l \
--framework='tensorflow' \
--python-version=З.7

Теперь мы можем отправлять предсказательные запросы в нашу модель через

службы

AI Platform Prediction,

API

который поддерживает онлайновое и пакетное пред­

сказание. Онлайновое предсказание позволяет получать предсказания почти в ре­
жиме реального времени сразу на нескольких примерах. Если у нас сотни или ты­
сячи примеров, которые мы хотим отправить для предсказания, мы можем создать

пакетное предсказательное задание, которое будет работать асинхронно в фоновом

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

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

Компромиссы и альтернативы
Хотя паттерн "Двухфазные предсказания" хорошо работает во многих случаях,
следует учитывать ситуации, когда у ваших конечных пользователей интернет­

соединение очень слабое, и поэтому шансы на вызов модели, размещенной в обла­
ке, весьма невелики. В этом разделе мы обсудим две исключительно офлайновые
альтернативы

-

сценарий, в котором клиент должен делать много предсказатель­

ных запросов за один раз, и рекомендации в отношении того, как выполнять непре­

рывное оценивание для офлайновых моделей.

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

способ доступа к вашему приложению. В этом случае вместо того, чтобы полагать-

Глава

280

5

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

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

ровки, так и после нее. Этот технический прием называется тренировкой с учетом

квантuзацuu

(quantization aware training)32 •

Одним из примеров приложения, которое предоставляет более простую офлайно­

вую модель, является

Google

Переводчик33 • Это надежная служба онлайнового пе­

ревода с сотен языков. Однако во многих сценариях вы будете нуждаться в исполь­
зовании службы перевода без интернет-доступа. В таких ситуациях
водчик позволяет скачивать офлайновые переводы на более чем

Эти офлайновые модели невелики, около

50

Goog\e

Пере­

разных языков.

40-50 Мбайт, и близки по точности
5.12 показано сравнение качества

к более сложным онлайновым версиям. На рис.
периферийной и онлайновой моделей перевода.

On- device РВМТ
rrench ...

On-device NMT

Online NMT
Engll.sh.

Engli$/l •

Frcnch ."

Engl1Sh•

Un sourire colite moins cher que
l'electricite. mais donne autant
de lumiere

х

Un sourire coute moins cher que
l'electricite. mals donne autant
de lumiere

х

Un sourire coute moins cher que
l'electricite, mais donne autant
delumiere

А sm1le costs less expens1ve than
electnc1ty, but g1ves as many l1ght

*

А sm1le costs cheaper than
electric1ty, but g1ves as much ltght

*

А sm1le costs less than electr1c1ty,

0

;



Рис.

5.12.

~1ro:

Offiщe

~~

f{j

х

'!':!

but g1ves as much l1ght

•• ro : .

Сравнение периферийной фразовой и (более новой) нейронной моделей машинного перевода

и онлайнового нейронного машинного перевода (источник: The Keywoгd 34 )

Еще одним примером автономной однофазной модели является

Google Bolo35 -

речевое приложение для изучения языка, предназначенное для детей. Приложение
работает полностью в офлайновом режиме и было разработано с намерением по­
мочь населению там, где надежный доступ в Интернет не всегда имеется .

32

См. https://oreil.ly/ABd8r.

33

См. https://oreil.ly/uEWAM.

34

См. https://oreil.ly/S_woM.

35

См. https://oreil.ly/zTy79.

Паттерны для отказоустойчивой обработки

281

Офлайновая подцержка
для специфических вариантов использования
Еще одно техническое решение, которое позволяет вашему приложению работать
для пользователей с минимальным интернет-соединением, состоит в том, чтобы

делать доступными в офлайновом режиме только некоторые части вашего прило­
жения. Сюда может входить предоставление нескольких общих признаков в оф­
лайновом режиме или кэширование результатов предсказания МL-модели для по­
следующего использования в офлайновом режиме. С этой альтернативой мы по­

прежнему задействуем две фазы предсказания, но ограничиваемся вариантами ис­
пользования, охватываемыми

приложение работает в

нашей офлайновой моделью. При таком подходе

офлайновом режиме, но обеспечивает полную функцио­

нальность, когда восстанавливает соединение.

Например,

Goog\e Maps

позволяет заранее скачивать карты и маршруты движения.

В целях экономии места на мобильном устройстве за счет ограничения числа хра­

нимых направлений движения в офлайновом режиме могут быть доступны только
направления движения на автомобиле (не ходьба или езда на велосипеде). Еще

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

-

это проверка количества пройденных шагов за

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

пользователя по

Bluetooth,

там самым обеспечивая возможность проверять состоя­

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

запросы

пользователя,

пока его устройство

находится в офлайновом

режиме,

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

базовую рекомендательную модель, функционирующую в офлайновом режиме,
с намерением дополнять его улучшенными результатами,

когда приложение в со­

стоянии отправлять запросы пользователя в облачную модель. При таком техниче­
ском решении пользователь по-прежнему получает некоторую функциональность,
даже если интернет-соединение отсутствует. Когда он вернется в сеть, то сможет
воспользоваться полнофункциональным приложением и надежной МL-моделью.

Манипулирование многочисленными предсказаниями
почти в режиме реального времени

Бывает, что надежное интернет-соединение все-таки имеется у конечных пользова­

телей вашей МL-модели, но им может потребоваться делать сотни или даже тысячи
предсказательных запросов к вашей модели одномоментно. Если у вас есть лишь

облачная модель и каждое предсказание требует АРI-вызова внешней службы, то

282

1

Глава

5

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

Давайте предположим, что у нас есть встроенные устройства, и они развернуты

в различных местах по всему дому пользователя. Эти устройства собирают данные
о температуре, давлении и качестве воздуха. Наша модель развернута в облаке для

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

внимание показания датчиков со всех мест. Этот подход является вариацией опи­

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

Непрерывное оценивание для офлайновь1х моделей
Как обеспечить актуальность и независимость от дрейфа данных наших моделей на
периферийных устройствах? Существует несколько вариантов выполнения непре­
рывного оценивания на моделях, не имеющих сетевого соединения. Прежде всего,

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

стве не будут переходить на облачную модель второй фазы. Еще один вариант

-

создавать реплику нашей модели на периферийном устройстве для выполнения
в онлайновом режиме только для целей непрерывного оценивания. Это техниче­

ское решение более предпочтительно, если офлайновая и облачная модели выпол­
няют похожие задачи предсказания,

как в упомянутом ранее случае естественно­

языкового перевода.

ПАТТЕРН

20.

Предсказания по ключу

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

паттерном "Предсказания по ключу"
димым условием для
в этой главе паттернов.

(Keyed Predictions),

и ключ является необхо­

масштабируемой реализации нескольких рассмотренных

Паттерны для отказоустойчивой обработки

283

Постановка задачи
Если ваша модель развернута как сервис и на входе принимает всего одну пере­

менную, то совершенно ясно, что выходная пере~енная соответствует входной пе­

ременной. Но что делать, если ваша модель на входе принимает файл с миллионом
переменных и отправляет на выход файл с миллионом предсказаний?
Вы, возможно, подумаете, что первый выходной экземпляр, очевидно, соответству­
ет первому входному экземпляру, второй выходной экземпляр

му экземпляру и т. д. Однако при соотношении

1: 1

-

второму входно­

каждый узел сервера должен

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

чается

в том,

что

выходные данные будут перемешаны.

Требование,

чтобы

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

Эта же проблема возникает, если ваша система обработки запросов принимает мас­
сив экземпляров, как описано в паттерне "Функция обслуживания без поддержки
состояния". Проблема в том, что обработка большого числа экземпляров локально
приведет к "горячим" точкам. Серверные узлы, получающие лишь несколько за­

просов, смогут поспевать, но любой серверный узел, получающий особо большой
массив, начнет отставать. Эти "горячие" точки обяжут вас делать серверные маши­

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

ограничение

на

число

экземпляров,

которые

могут

отправляться

в одном запросе. Если такого ограничения нет либо модель настолько затратна
в вычислительном отношении, что запросы с меньшим числом экземпляров, чем

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

Решение
Решение заключается в использовании сквозных ключей. Попросите клиента пре­
доставить ключ, связанный с каждой входной переменной. Например, предполо­

жим, что ваша модель тренируется с использованием трех переменных (А, В, С) на
входе (рис.

5.13,

слева), чтобы на выходе получать результат

D.

Тогда надо лишь

дать вашим клиентам возможность поставлять в модель (К, А, В, С), где К -

это

ключ с уникальным идентификатором. Ключ может быть чем-то простым, вроде

нумерации входных экземпляров
(К,

D),

1, 2, 3, ...

Ваша модель тогда будет возвращать

и клиент сможет выяснять, какой экземпляр на выходе соответствует своему

экземпляру на входе.

284

Глава

5
А

в

5.13.

D

К1



IQ

IQ

К3

К9

К4

К7

~ СохраненнаяJ:>

кs

Рис.

с

модель

К1

Кб

К4

К7

К5

К8

К8

К9

К3

Клиент предоставляет на входе уникальный ключ для каждого экземпляра.

Система обработки запросов присоединяет указанные ключи к соответствующему предсказанию .

Это позволяет клиенту получать правильное предсказание для каждой переменной на входе,
даже если результаты на выходе не упорядочены

Как проносить сквозные ключи в
Для того чтобы ваша модель

Keras

Keras

проносила сквозные ключи, во время экспорти­

рования модели следует предоставлять сигнатуру модельного обслуживания.

Например, ниже приведен фрагмент исходного кода, вызывающий модель, которая
в противном случае принимала бы четыре входные переменные (is_ma l e, mother_age,
plurality и gestation_weeks), и дающий ей возможность брать ключ, который она
будет проносить через всю обработку вместе с изначальным результатом работы
модели (babyweight):

# Функция обслуживания, ко торая проносит сквозные ключи
@tf.function(input signature= [{
'is_male': tf.TensorSpec([None, ] , dtype=tf.string, name='is_male ' ) ,
'mother_age': tf.TensorSpec([None,], dtype=tf.float32, name='mother_age'),
'plurality': tf.TensorSpec([None ,], dtype=tf.str i ng, name='plurality'),
'gestation_weeks': tf.TensorSpec( [None,], dtype=t f.float3 2,
name=' ge sta t i on_weeks ' ) ,
'key' : t f. TensorSpec ( [None ,], dtype=tf . string , name= ' key' )
}] )

def keyed_prediction(inputs):

feats = inputs. copy()
key = feats.pop ( 'key') #взять ключ из входной
output = model (feats) #вызва ть модель
return { 'key ' : key, ' babywe i ght' : output }

переменной

Паттерны для отказоустойчивой обработки

285

Затем эта модель сохраняется, как описано в паттерне "Функции обслуживания без
поддержки состояния":

model.save(EXPORT_PATH,
signatures={'serving default': keyed_prediction})
Добавление возможности предсказания по ключу
в существующую модель

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

tf. saved_ model. l oad (} , прикрепить

функцию обслуживания и применить приведенный выше фрагмент исходного кода
(рис.

5.14).
Ключ ,

Признаки

Ключ ,

Выход

выход

Рис.

5.14. Загрузить модель, сохраненную в формате SavedModel,

прикрепить не заданную по умолчанию функцию обслуживания и сохранить модель

При этом предпочтительно предоставить функцию обслуживания, которая воспро­

изводит старое поведение без ключа:

#

Функция обслуживания,

которая не требует ключа

@tf.function{input_signature=[{
'is_male': tf.TensorSpec([None,J, dtype=tf.string, name='is_male' ) ,
'mot her_age ': tf.TensorSpec([None, ], dtype=tf.float32, name= 'mother_age') ,
'plurality': tf . TensorSpec ([None, ), dtype=tf . stri ng, name='plurality'),
'gestation_weeks': tf.TensorSpec( [None,], dtype=tf.float32,
name='gestation_weeks')
}] )

def nokey_prediction(inputs):

output = model(inputs) #вызвать
return { 'babywe ight': output )

модель

Приведенное выше поведение следует использовать по умолчанию и добавлять

keyed prediction в качестве новой функции обслуживания:
model.save(EXPORT_PATH,
signatures={'serving_default': nokey_predi ction,
'keyed_pred ict ion': keyed_prediction
))

286

1

Глава

5

Компромиссы и альтернативы
Почему сервер не может просто назначать ключи данным, которые он получает на

входе? При онлайновом предсказании серверы могут назначать уникальные иден­

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

ID

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

перед отправкой результатов. Проблема заключается в том, что упорядочение вы­
числений в распределенной обработке данных обходится очень дорого.
Вдобавок, есть несколько других ситуаций, когда поставляемые клиентом ключи

полезны: это асинхронное обслуживание и оценивание. Учитывая обе ситуации,
предпочтительно, чтобы ключ был уникальным для варианта использования и под­

давался идентификации. Поэтому обращение к клиентам с просьбой предоставить
ключ упрощает решение.

Асинхронное обслуживание
В наши дни многие промышленные МL-модели являются нейронными сетями,

а нейронные сети предусматривают наличие матричных умножений. Матричное
умножение на таких аппаратных средствах, как графические процессоры

и тензорные процессоры

(TPU),

(GPU)

выполняется эффективнее, если вы можете обес­

печивать, чтобы матрицы находились в определенных диапазонах размеров и/или
были кратны определенному числу. Поэтому полезно накапливать запросы (разу­
меется, вплоть до максимальной задержки) и обрабатывать входящие запросы по
частям. Поскольку блоки будут состоять из чередующихся запросов от многочис­

ленных клиентов, ключ в этом случае тоже должен обладать каким-то идентифика­
тором клиента.

Непрерывное оценивание
Если вы выполняете непрерывное оценивание, то полезно регистрировать метадан­

ные о предсказательных запросах, чтобы осуществлять мониторинг случаев, когда
результативность падает по всем направлениям или только в определенных ситуа­

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

нить паттерн "Призма объективности"

(Faimess Lens;

см. главу 7) с целью обеспе­

чения объективной результативности модели для разных клиентских сегментов

(например, по возрасту клиента и/или расе клиента). Модель не будет использовать
клиентский сегмент на входе, но нам нужно оценивать результативность модели,

нарезанной по клиентскому сегменту. В таких случаях наличие встроенного в ключ

клиентского сегмента (например, ключ может быть 35-Темнокожий-Мужчина-

34324323)

облегчает нарезку.

Паттерны для отказоустойчивой обработки

1

287

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

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

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

-

просить клиентов предоставлять ключи с каждым предсказанием и

указывать ключи, которые не станут причиной коллизии с другими клиентами.

Резюме
В этой главе мы рассмотрели технические приемы операционализации моделей

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

ML.

Мы начали эту главу с рассмотрения подходов к инкапсулированию вашей натре­

нированной МL-модели в качестве функции без поддержки состояния с использо­

ванием паттерна "Функция обслуживания без поддержки состояния"

Serving Function).

(Stateless

Функция обслуживания устраняет сцепленность среды трениров­

ки со средой развертывания модели, определяя функцию, которая выполняет пред­
сказательный вывод на экспортированной версии модели, и развертывается в виде

RЕSТ-сервиса. Не все промышленные модели требуют немедленных результатов
предсказания, т. к. существуют ситуации, когда необходимо отправить крупный
пакет данных в модель для предсказания, но нет надобности получать результаты

сразу. Мы ознакомились с тем, как паттерн "Пакетное обслуживание"

Serving)

(Batch

решает эту задачу, используя инфраструктуру распределенной обработки

данных, предназначенную для асинхронного выполнения многочисленных запро­

сов на модельное предсказание в качестве фонового задания, при котором резуль­
тат пишется в указанное место.

Затем на основе паттерна "Непрерывное оценивание модели"

Evaluation)

(Continued Model

мы рассмотрели подход к верификации развернутой модели в той части,

которая касается того, что она по-прежнему показывает хорошую результативность

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

необходимости в перетренировке. В паттерне "Двухфазные предсказания"

Phase Predictions)

(Two-

мы нашли техническое решение для специфических вариантов

использования, когда существует потребность в развертывании модели на перифе-

288

Глава

5

рии. Когда можно подразделить задачу на две логические части, этот паттерн сна­

чала создает более простую модель, которую можно развертнуть на периферийном

устройстве. Такая периферийная модель соединена с более сложной моделью, раз­
мещенной

в

облаке.

Наконец,

в

паттерне

"Предсказания

по

ключу"

Predictions)

мы обсудили вопрос, почему при исполнении предсказательных запро­

(Keyed

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

В следующей главе мы рассмотрим паттерны обеспечения воспроизводимости.
Указанные технические приемы решают проблемы, связанные с врожденной слу­
чайностью, присутствующей во многих аспектах машинного обучения, и фоку­
сируются на обеспечении надежных и согласованных результатов при каждом

выполнении рабочего потока машинного обучения.

ГЛАВА

6

Паттерны

обеспечения воспроизводимости

Лучшие практические приемы разработки программного обеспечения, такие как
модульное тестирование, базируются на том, что при выполнении нами фрагмента
кода он будет выдавать детерминированный результат:

def sigmoid(x):
return 1.0 / (1 +

пр.ехр(-х))

class TestSigmoid(unittest.TestCase):
def test zero(self):
self.assertAlmostEqual(sigmoid(O), 0.5)
def test_neginf(self):
self.assertAlmostEqual(sigmoid(float("-inf") ), 0)
def test_inf(self):
self.assertAlmostEqual(sigmoid(float("inf")), 1)
В машинном обучении такого рода воспроизводимость затруднена. Во время тре­
нировки МL-модели инициализируются случайными значениями, а затем коррек­
тируются на основе тренировочных данных. Простой алгоритм
реализован в библиотеке

scikit-leam,

требует задания

k

средних, который

переменной random_state

(случайное состояние) для того, чтобы алгоритм всякий раз возвращал одни и те же
результаты:

def cluster_ kmeans (Х) :
from sklearn i.шport cluster
k_means = cluster.КМeans(n_clusters=lO, random_state=lO)
labels = k_means.fit(X).labels_[::]
return labels
Помимо случайного начального числа существует ряд других артефактов, которые
нужно урегулировать в целях обеспечения воспроизводимости во время трениров­
ки. Вдобавок машинное обучение состоит из разных этапов, таких как тренировка,
развертывание и перетренировка. Нередко бывает важно, чтобы некоторые компо­
ненты оставались воспроизводимыми и на этих этапах.

В данной главе мы рассмотрим паттерны, которые затрагивают разные аспекты

обеспечения воспроизводимости. Паттерн "Преобразователь"

(Transforrn)

захваты-

Глава

290

6

вает зависимости процесса подготовки данных из конвейера тренировки модели,

чтобы воспроизводить их во время модельного обслуживания запросов. Паттерн
"Повторяемая разбивка" (RepeataЬ\e

Splitting)

фиксирует подход, на основе которо­

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

использовался для

оценивания

набора данных. Паттерн "Мостовая схема"

или тестирования даже по

(Bridged Schema)

роста

мере

обращается к задаче

обеспечения воспроизводимости, когда тренировочный набор данных является
гибридом, соответствуя разным схемам данных. Паттерн "Конвейер рабочего пото­
ка"

(Worktlow Pipeline)

охватывает все этапы рабочего потока машинного обуче­

ния, чтобы при повторной тренировке модели части конвейера могли использо­

ваться многоразово. Паттерн "Хранилище признаков"

(Feature Store)

обращается

к вопросу обеспечения воспроизводимости и неоднократного использования при­
знаков в разных заданиях по машинному обучению. Паттерн "Оконный предсказа­

тельный вывод"

обеспечивает, чтобы признаки, рассчитанные

(Windowed Inference)

динамическим, зависящим от времени путем, могли повторяться правильно между

тренировкой и обслуживанием. Паттерн "Управление версиями"

(Versioning)

связан

с контролем версий данных и моделей и является необходимым условием для ма­
нипулирования многими описанными в этой главе паттернами.

ПАТТЕРН

21.

Преобразователь

Паттерн "Преобразователь"

(Transform)

значительно облегчает перенесение МL-мо­

дели в промышленную среду, держа входные данные, признаки и преобразования

тщательным образом отделенными друг от друга.

Постановка задачи
Проблема заключается в том, что переменные, поступающие на вход в МL-модель,
не являются признаками, которые МL-модель использует в своих вычислениях.

Например, в модели классифицирования текста на вход подаются сырые текстовые
документы,

а

признаками

являются

числовые

представления

этого текста в

виде

векторных вложений. Когда мы тренируем МL-модель, то делаем это при помощи
признаков, которые извлекаются из сырых данных. Возьмем приведенную ниже
модель,

которая

натренирована

прогулок по Лондону, используя
СRЕАТЕ

предсказывать

продолжительность

BigQuery ML:

OR REPIACE MODEL ch09eu.bicycle_model

OPТIONS(input_label_cols=['duration'],

model_type='linear_reg')
AS

SELECT
duration
, start_station name
, CAST(EXТRACT(dayofweek from start_date) AS

SТRING)

велосипедных

Паттерны обеспечения воспроизводимости
аз

,

dayofweek

CAST(EX'l'RACТ(hour

аз

291

from start_date) AS

SТRING)

hourofday

~

'bigquery-puЫic-data.london_bicycles.cycle_hire ·

Указанная модель имеет три признака (start_station_name, dayofweek и hourofday),
из

вычисляемых

(рис.

двух

входных

переменных

-

start_station_name

и

start date

6.1).
Название станции

Название станции

"r
День начала

.

"r
День недели

Преобразователь
Час дня

6.1. Модель

Продолжительность"

.

МL-модель

"r

Признаки

Входы
Рис.

."

Выходы

имеет три признака, вычисляемых из двух входных переменных

Приведенный выше SQL-кoд смешивает входные переменные и признаки и не от­
слеживает выполненные преобразования. Это вернется бумерангом, когда мы по­
пытаемся с помощью данной модели делать предсказания. Поскольку модель была
натренирована на трех признаках, сигнатура предсказания должна выглядеть имен­
но так, как показано ниже:

SELECT * ~ ML.PREDICT(MODEL ch09eu.bicycle_model, (
'Kings Cross' AS start_station_name
, '3' аз dayofweek
, '18' аз hourofday
))

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

"3"

нам нужно отправлять для dayofweek. Так, а эта тройка". она означает втор­

ник или среду? Все зависит от того, какая библиотека использовалась в модели, или
от того, что мы считаем началом недели!

Асимметрия между тренировкой и обслуживанием, вызванная различиями в любом

из этих факторов между средами тренировки модели и обслуживания запросов,

-

одна из ключевых причин, по которым продукционализация МL-моделей является
столь сложной.

Решение
Решение состоит в том, чтобы в явной форме захватывать преобразования, приме­
няемые для конвертирования входных модельных данных в признаки. В

BigQuery ML

это делается с помощью спецификатора инструкции TRANSFORМ, который обеспечи-

292

Глава

6

вает, чтобы эти преобразования автоматически применялись во время выполнения
инструкции

ML. PREDICT.

С учетом поддержки инструкции TRANSFORМ приведенную выше модель нужно пере­

писать следующим образом:
СRЕАТЕ

OR REPLACE MODEL ch09eu.bicycle_model

OPТIONS(input_label_cols=['duration'],

model_type='linear_reg')
TRANSFORМ(

SELECT * EXCEPТ(start date)
, CAST(EXТRACT(dayofweek from start date) AS SТRING)
as dayofweek -- featurel
, CAST(EXТRACT(hour from start_date) AS SТRING)
as hourofday -- feature2
AS
SELECT
duration, start_station_name, start_date -- inputs
FRGf
'bigquery-puЫic-data.london_bicycles.cycle

hire'

Обратите внимание, как мы четко отделили входные переменные (в инструкции
SELEcт) от признаков (в инструкции TRANSFORМ). Теперь предсказывать стало гораздо
проще. Мы можем отправлять в модель просто название станции и метку времени

(входные данные):

SELECT * FRGf ML.PREDICT(MODEL ch09eu.bicycle_model, (
'Kings Cross' AS start_station_name
, CURRENT_TIMESTAМP() as start_date
))

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

ные данные и помещаем всю последующую обработку входных данных в инструк­

цию TRANSFORМ,

BigQuery ML

будет применять эти преобразования автоматически во

время предсказания.

Компромиссы и альтернативы
Описанное выше решение работает, потому что

BigQuery ML

отслеживает преоб­

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

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

Паттерны обеспечения воспроизводимости

модели или создав хранилище преобразованных признаков (см. разд. "Паттерн

293

26.

ХранW1uще признаков").

Преобразования в

TensorFlow

Допустим, что мы тренируем модель

и

Keras

ML

для оценивания стоимости поездки (fare)

в нью-йоркском такси и имеем шесть входных переменных (широту места посадки

(pickup_latitude), долготу места посадки (pickup_longitude), широту места высадки
(dropoff_latitude), долготу места высадки (drop off_longitude), количество пасса­
жиров (passanger_count) и время посадки (pickup_datetime)).

TensorF\ow

поддержи­

вает концепцию признаковых столбцов, которые сохраняются в модельном графе.
Однако

API

разработан исходя из того, что сырые входные данные будут такими

же, что и признаки.

Предположим, что мы хотим пронормализовать широты и долготы (подробности
см. в разд. "Простые представления данных" главы

2),

создать преобразованный

признак, а именно евклидово расстояние (euclidean), и извлечь час дня 1 из метки
времени (hourofday). Нам придется старательно проработать дизайн модельного
графа (рис.

6.2),

твердо помня о концепции паттерна "Преобразователь". Просмат­

ривая приведенный ниже фрагмент исходного кода, обратите внимание на то, как
мы четко расположили три отдельных слоя в модели

Keras -

слой входов Input,

слой преобразования Transform и слой плотных признаков DenseFeatures.
Во-первых, каждая переменная на входе в модель

ный исходный код находится на

Keras

делается слоем Input (пол­

GitHub 2):

inputs = {
colname : tf.keras.layers.Input(
name=colname, shape=(), dtype='float32')
for colname in ['pickup_longitude', 'pickup_latitude',
'dropoff_longitude', 'dropoff_latitude']

На рис.

6.2

эти прямоугольники помечены как dropoff _ latitude (широта высадки),

dropoff longitude (долгота высадки) и т. д.
Во-вторых, поддерживается словарь преобразованных признаков и каждое преоб­
разование делается либо слоем Preprocessing, либо слоем LamЬda. Здесь мы нормали­
зуем входные переменные с помощью слоев LamЬda:

transformed = {}
for lon col in ['pickup_longitude', 'dropoff_longitude']:
transformed[lon_col] = tf .keras.layers.LamЬda(
lamЬda х: (х+78) /8.0,
name='scale_{}' .format(lon_col)
) (inputs [lon_col])

1 Для

2

пояснения: hourofday (datetime (2015-12-14 18: 54) ) == 18.

См. https://github.com/GoogleCloudPlatform/training-data-analyst/ЫoЬ/master/quests/serverlessml/

06_ feateng_ keras/solution/taxifare_fc.ipyn Ь.

Глава б

294

for lat col in ['pickup_latitude', 'dropoff_latitude' ] :
transformed[lat_co l] = tf.keras.layers.LamЬda(
lamЬda х:

(х-37)/8.0,

name=' scale_ {}'. format (lat_col)
) (inputs [lat_col])

Scale dropoff latitude:
- Lambda
Oropoff_latitude:
lnputlayer

Scale_dropoff_longitude:
Lambda

Oropoff_longitude:
lnputlayer

Pickup_latitude:
lnputlayer

Pickup_longitude:
lnputlayer

Pickup_datetime:
lnputlayer

Euclidean:
Lambda

Scale_pickup latitude:
Lamьaa

Oense_featuresJ:
OenseFeatures

hl: Oense

Passanger_count:
lnputlayer

Scale_pickup_longitude:
Lambda

Fare: Dense

Hourofday:
Lambda
Рис.

6.2.

Модельный граф

Keras для

задачи оценивания стоимости проезда в такси

На рис.

6.2 эти прямоугольники помечены как scale_dropoff_latit ude (нормализо­
ванная широта высадки), scale_drop off_longitude (нормализованная долгота вы­
садки) и т. д.

У нас также будет один слой LamЬda для евклидова расстояния (eucl idean), который

вычисляется из четырех слоев Input (рис.

6.2):

def euclidean(params):

lonl, latl, l on2 , lat2
params
londiff = lon2 - lonl
latdiff = lat2 - latl
return tf.sqrt(londiff*lon diff + latdiff *l atdi ff )

Паттерны обеспечения воспроизводимости

295

transformed['euclidean'] = tf.keras.layers.LamЬda(euclidean, name='euclidean') ([
inputs['pickup_longitude'],
inputs['pickup_latitude'],
inputs['dropoff_longitude'J,
inputs['dropoff_latitude')
))

Аналогично столбец для создания часа дня из метки времени (hourofday) является
слоем LamЬda:

transformed['hourofday') =
lamЬda х:

tf.keras.layers.LamЬda(

11, 2),
out_type=tf .dtypes.int32),

tf.strings.to_numЬer(tf.strings.substr(x,

name='hourofday'
) (inputs['pickup_datetime'])
В-третьих, все эти преобразованные слои будут объединены в слой DenseFeatures:

dnn_inputs = tf.keras.layers.DenseFeatures(feature_columns.values()) (transformed)
Поскольку конструктор для слоя DenseFeatures требует набора признаковых столб­

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

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

feature columns = (
colname: tf.feature column.numeric column(colname)
for colname in ['pickup_longitude', 'pickup_latitude',
'dropoff longitude', 'dropoff_latitude']
feature_columns['euclidean'J = \
tf.feature column.numeric column('euclidean')
Имея входной слой

Keras,

DenseFeatures, мы можем построить остальную часть модели

как обычно:

hl = tf.keras.layers.Dense(32, activation='relu', name='hl') (dnn_inputs)
h2 = tf.keras.layers.Dense(B, activation='relu', name='h2')(hl)
output = tf.keras.layers.Dense(l, name='fare') (h2)
model = tf.keras.models.Model(inputs, output)
model.compile(optimizer='adam', loss='mse', metrics=['mse'])
Полный пример 3 находится в репозитории на

GitHub.

Обратите внимание на то, как мы организовали слои модели
был Inputs, второй СЛОЙ

-

Transform И третий СЛОЙ -

Keras:

первым слоем

DenseFeatures, КОТОрЫЙ ИХ

объединил. После этой последовательности слоев начинается обычная архитектура

3

См. https://github.com/GoogleCloudPlatform/training-data-analyst/ЫoЬ/master/quests/serverlessml/

06_feateng_ keras/solution/taxifare_fc.ipyn Ь.

Глава б

296

модели. Поскольку слой тransfonn является частью модельного графа, обычные
технические решения на основе паттернов "Функция обслуживания без поддержки

состояния" и "Пакетное обслуживание" (см. главу

5)

будут работать как есть.

Эффективные преобразования
с помощью библиотеки

tf.transform

Один из недостатков приведенного выше подхода заключается в том, что преобра­

зования будут выполняться во время каждой итерации тренировки. Это не так уж и
важно, если мы лишь нормализуем на известные константы. А если наши преобра­

зования окажутся более дорогими с точки зрения вычислений? Или если мы хотим
нормализовать, используя среднее значение и дисперсию, и в этом случае нам нуж­

но прокручивать все данные, чтобы вычислять эти переменные? Что делать тогда?
Полезно различать преобразования уровня экземпляра, которые могут быть непо­
средственно частью модели (где единственный недостаток

-

это их применение

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

набора данных не могут быть частью модели и должны применяться в качестве

масштабируемого шага предобработки, который производит преобразование, за­
хватывающее логику и артефакты (среднее значение, дисперсию, словарь и т. д.),
подлежащие прикреплению к модели. Для преобразования уровня набора данных
следует использовать библотеку tf.tгaпsfoгm.

Библиотека

tf.transform

(входящая в состав

TensorFlow Extended 4 )

обеспечивает эф­

фективный подход к выполнению преобразований в ходе предобрабатывающего
прохода по данным и сохранению результирующих признаков и артефактов преоб­
разования, чтобы эти преобразования могли применяться системой

Serving

TensorFlow

во время предсказания.

Первый шаг

-

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

пронормализовать все входные данные, сведя их среднее к нулю, а дисперсию

-

к единице, и сгруппировать их в корзины, мы создадим следующую функцию пред­

обработки (полный исходный код 5 см. в репозитории на

GitHub):

def preprocessing_fn(inputs):

outputs = { 1
for key in ... :
outputs[key + '_z'] = tft.scale_to_z_score(inputs[key])
outputs[key + '_bkt'] = tft.bucketize(inputs[key], 5)
return outputs
Перед тренировкой сырые данные читаются и преобразуются с помощью предва­

рительной функции в

4

Apache Beam:

См. https://oreil.ly/Ozn13.

См. https://githu b.com/tensorflow/tfx/ЫoЬ/master/tfx/examples/chicago_ taxi_pipeline/
taxi_utils_native_keras.py.
5

Паттерны обеспечения воспроизводимости

297

transformed_dataset, transform_fn = (raw dataset
beam_impl.AnalyzeAndTransformDataset(preprocessing_fn))
transformed_data, transformed_metadata = transformed_dataset
1

Преобразованные данные затем записываются в формат, подходящий для чтения
тренировочным конвейером:

transformed_data

1

tfrecordio.WriteToTFRecord(

PATH_TO_TFТ_ARTIFACTS,

coder=example_proto_coder.ExampleProtoCoder(
transformed_metadata.schema))
Конвейер

Beam

также сохраняет подлежащую выполнению функцию предобработ­

ки вместе с любыми артефактами, необходимыми этой функции, в артефакт в фор­
мате графа

TensorF\ow.

В приведенном выше случае, например, этот артефакт

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

преобразованные данные, и, следовательно, не приходится повторять преобразова­
ния внутри цикла тренировки.

Функция

обслуживания

должна

загружать

эти

артефакты

и

создавать

слой

Transform:
tf transform_output = tft.TFТransformOutput(PATH_TO_TFТ_ARTIFACTS)
tf_transform_layer = tf_transform_output.transform_features_layer()
Затем функция обслуживания может применять слой Transform к разобранным
входным признакам и вызывать модель с преобразованными данными для вычис­
ления результата:

@tf.function
def serve_tf_examples fn(serialized_tf_examples):

feature_spec = tf_transform_output.raw_feature_spec()
feature_spec.pop(_IAВEL_KEY)

parsed_features = tf.io.parse_example(serialized_tf_examples, feature_spec)
transformed_features = tf_transform_layer(parsed_features)
return model(transformed features)
При таком подходе мы обеспечиваем вставку преобразований в граф модели для
обработки запросов. В то же время, поскольку тренировка модели происходит на

преобразованных данных, циклу тренировки не приходится выполнять эти преоб­
разования в течение каждой эпохи.

Преобразования текста и снимков
В текстовых моделях принято предварительно обрабатывать входной текст (напри­
мер, удалять знаки препинания, стоп-слова, заглавные буквы, выделять основы
слов и т. д.) перед тем, как передавать очищенный текст в модель в качестве при­
знака. Другие распространенные приемы инженерии признаков на текстовых дан­
ных включают лексемизацию (токенизацию) и сопоставление с регулярными вы­

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

Глава б

298

Необходимость захвата преобразований важна даже в том случае, если нет явного
генерирования признаков, как при использовании глубокого обучения со снимками.
Снимковые модели обычно имеют входной слой, который принимает снимки кон­
кретного размера.

Входные снимковые данные другого размера перед подачей

в модель должны быть обрезаны, дополнены или передискретизированы до этого

фиксированного размера. Другие распространенные преобразования в снимковых
моделях включают манипуляции с цветом (гамма-коррекцию, преобразование от­

тенков серого и т. д.) и коррекцию ориентации. Важно, чтобы такие преобразова­
ния были идентичными для тренировочного набора данных и предсказательного
вывода.

Паттерн

"Преобразователь"

позволяет обеспечивать эту воспроизводи­

мость.

В снимковых моделях есть некоторые преобразования (например, аугментация
данных путем случайной обрезки и масштабирования), которые применяются толь­
ко во время тренировки. Эти трансформации не нужно захватывать во время пред­
сказательного вывода. Такие преобразования не будут частью паттерна "Преобра­
зователь".

Альтернативные подходы
Альтернативным подходом к решению проблемы асимметрии между тренировкой

и

обслуживанием

(Feature Store).

является

использование

паттерна

"Хранилище

признаков"

Хранилище признаков содержит скоординированный вычислитель­

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

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

Java, операции предобработки можно выполнять
Java, в то время как саму модель можно написать с использованием библиотеки
PyTorch языка Python. Недостатком хранилища признаков является то, что оно де­
на

лает модель зависимой от хранилища признаков и значительно усложняет инфра­

структуру обработки запросов.
Еще один подход к отделению языка программирования и фреймворка, предназна­
ченных для преобразования признаков, от языка, применяемого для написания мо­
дели, состоит в выполнении предобработки в контейнерах и использовании этих
контейнеров

в рамках тренировки и обслуживания.

в разд. "Паттерн

25.

практике в инструментарии

ПАТТЕРН

22.

Этот подход обсуждается

Конвейер рабочего потока" далее в этой главе и внедрен на

Kubetlow Serving.

Повторяемая разбивка

В целях обеспечения повторимости и воспроизводимости выборок данных необхо­

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

Паттерны обеспечения воспроизводимости

нированную хеш-функцию. Паттерн "Повторяемая разбивка" (RepeataЫe

299

Splitting)

предлагает легковесную, повторимую разбивку данных.

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

зованием исходного кода, подобного приведенному ниже:

df = pd.DataFrame( ... )
rnd = np.random.rand (len (df))
train
df[ rnd < 0.8 ]
valid
df[ rnd >= 0.8 & rnd <
test
df[ rnd >= 0.9

о.

9 ]

К сожалению, во многих практических ситуациях этот подход не работает. Причи­
на в том, что строки данных редко бывают независимыми. Например, если мы тре­

нируем модель предсказывать задержки рейсов, то задержки прибытия рейсов
в один и тот же день будут сильно коррелировать друг с другом. Это приводит

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

-

распространенная проблема, и мы должны ее избегать

при выполнении машинного обучения.
Кроме того, функция rand упорядочивает данные при каждом ее выполнении по­

разному, поэтому, если мы выполним программу снова, то получим разные

80%

строк. Это может привнести хаос, в случае если мы экспериментируем с разными

моделями машинного обучения с целью выбора лучшей из них

-

нам необходимо

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

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

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

в один и тот же срез данных. Например, мы не хотим, чтобы рейсы

2

января

2019

го­

да включались в тестовый набор данных, если рейсы в тот день находятся в трени­
ровочном наборе данных.

Решение
Сначала мы выявляем столбец, который улавливает корреляционную связь между

строками. В наборе данных о задержке рейсов это столбец даты (date). Затем мы

Глава

300

6

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

ния

Fann Fingerprint

на столбце date, чтобы разбить имеющиеся данные на трени­

ровочный, валидационный и тестовый наборы данных.
Дополнительные сведения об алгоритме цифрового отпечатка Faгm Fingeгpгint,
поддержке им других каркасов и языков, а также о взаимосвязи между хеширова­

нием и криптографией см. в разд. "Паттерн

1. Хешированный признак" главы 2.
В частности, существуют обертки алгоритма Faгm Hash6 с открытым исходным ко­
дом на нескольких языках (включая Python\ и поэтому указанный паперн может
применяться, даже если данные не находятся на складе данных, поддерживающем

повторимый хеш прямо из коробки.

Вот как можно разбить набор данных на хеше столбца date:

SELECT
airline,
departure airport,
departure_schedule,
arrival_airport,
arrival_delay
FR(I.{

'bigquery-samples' .airline ontime_data.flights
WНERE

АВS(М:Ю(FАRМ

FINGERPRINT(date), 10)) < 8 -- 80%

для

ТРЕНИРОВКИ

В целях разбивки по столбцу date мы вычисляем его хеш с помощью функции
FARМ FINGERPRINT, а затем используем функцию деления по модулю для отыскания
произвольного 80%-ного подмножества строк. Теперь этот срез повторяем

-

по­

скольку функция FARМ_ FINGERPRINT возвращает одно и то же значение всякий раз,
когда она вызывается на конкретной дате, мы можем быть уверены в том, что вся­
кий раз будем получать одни и те же

80% данных.

Как следствие, все рейсы на лю­

бую заданную дату будут принадлежать одному и тому же срезу данных

-

трени­

ровочному, валидационному или тестовому. Этот результат повторим независимо
от случайного начального числа.

Если мы хотим разбить данные по аэропорту прибытия arrival_airport (чтобы

80%

аэропортов находились в тренировочном наборе данных, возможно, потому, что мы
пытаемся что-то предсказать об удобствах аэропорта), то будем вычислять хеш не
по дате, а по аэропорту прибытия.
Также не представляет труда получить валидационные данные: в приведенном
выше запросе надо лишь поменять

<

в на =В, а для тестовых данных заменить это

на =9. При таком подходе мы получаем

10%

в тестовый.

6

См. https://github.com/goog\e/farmhash.

7

См. https://oreil.ly/526Dc.

10%

образцов в валидационный набор и

Паттерны обеспечения воспроизводимости

301

Какие соображения следует учитывать при выборе столбца, по которому следует

проводить разбивку? Столбец даты date должен обладать несколькими характери­
стиками, чтобы иметь возможность его использовать в качестве столбца разбивки
на части.

+

Строки с одной и той же датой имеют тенденцию коррелировать. Это ключевая
причина, обязывающая нас обеспечивать нахождение всех строк с одной и той
же датой в одном и том жесрезе.

+

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

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

80%

20%

воз­

данных используется на­

ми для тренировки.

+

В столбце date должно быть достаточно значений. Поскольку мы вычисляем
хеш и находим значение по модулю



1О,

нам нужно иметь по крайней мере

уникальных хеш-значений. Чем больше у нас уникальных значений, тем

лучше. Для надежности эмпирическое правило нацеливает на 3-5-кратное пре­
вышение знаменателя

мы хотим

+

40

операции деления

по

модулю,

поэтому в данном

случае

уникальных дат или около того.

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

1 января,

и не было никаких задержек до конца года, то это

не сработает, т. к. разбитые на срезы наборы данных будут искажены. Для на­

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

следует посмотреть на граф и обеспечить, чтобы распределение метки по отно­
шению к задержке отправления и другим входным переменным было одинако­
вым во всех трех наборах данных.
Проверка на одинаковость распределения меток в трех наборах данных может
Смирнова: надо лишь
быть автоматизирована с помощью теста Коломогорова построить график кумулятивных функций распределения меток в трех наборах
данных и найти максимальное расстояние между каждой парой. Чем меньше мак­
симальное расстояние, тем лучше срез.

Компромиссы и альтернативы
Давайте рассмотрим несколько вариантов в отношении того, как мы могли бы осу­
ществлять повторяемую разбивку, и обсудим достоинства и недостатки каждого из

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

Единый запрос
Для генерирования тренировочного, валидационного и тестового срезов нам не
нужны три отдельных запроса. Мы можем это сделать в одном-единственном за­

просе следующим образом:

302

Глава

6

OR REPLACE ТАВLЕ mydataset.mytaЬle AS
SELECT
airline,
departure_airport,
departure_schedule,
arrival_airport,
arri val _ delay,
CASE(AВS(м::>D(FARМ FINGERPRINT(date), 10) ))
WНEN 9 ТНЕN 'test'
WНEN 8 ТНЕN 'validation'
ELSE 'training' END AS split col

СRЕАТЕ

FRCМ

'bigquery-samples' .airline_ontime_data.flights
Затем мы можем использовать столбец split_col, чтобы решать, в какой из трех
наборов данных будет попадать отдельно взятая строка данных, Использование
единого запроса сокращает вычислительное время, но требует создания новой таб­

лицы или модифицирования исходной таблицы путем внесения дополнительного
столбца split _ col.

Случайная разбивка
Что делать, если строки не коррелированы? В этом случае мы хотим иметь случай­
ный, повторяющийся срез, но не имеем естественного столбца, по которому следу­

ет проводить разбивку. Мы можем хешировать всю строку данных, конвертировав
ее в значение типа

String

и хешировав это строковое значение:

SELECT
airline,
departure_airport,
departure_schedule,
arrival_airport,
arrival_delay
FRCМ

'bigquery-samples' .airline_ontime_data.flights f
WНERE

AВS(м:>D(FARМ_FINGERPRINT(ТO_JSON_SТRING(f),

10)) < 8

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

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

ID

SELECT,

Разбивка по нескольким столбцам
Мы говорили об одном столбце, который улавливает корреляцию между строками.
Что делать, если корреляция между двумя строками улавливается комбинацией

столбцов? В таких случаях следует просто проконкатенировать поля (мы получаем

Паттерны обеспечения воспроизводимости

303

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

SELECT
airline,
departure airport,
departure_schedule,
arrival_airport,
arrival_delay
FRCМ

'bigquery-samples' .airline ontime_data.flights
WНERE

AВS(}ol)[)(FARМ_FINGERPRINT(CONCAT(date,

arrival_ai:i:port)), 10)) < 8

Если мы выполняем разбивку по гибриду из нескольких столбцов, то в качестве
одной из переменных на входе в модель на самом деле можно использовать аэро­

порт прибытия (arrival_airport), поскольку примеры любого конкретного аэропор­
та будут присутствовать как в тренировочном, так и в тестовом наборах. С другой

стороны, если мы выполним разбивку только по аэропорту прибытия, то трениро­
вочный и тестовый наборы будут иметь взаимоисключающий набор аэропортов
прибытия, и, следовательно, arrival_airport не может быть входной переменной
для модели.

Повторяемая разбивка
Базового решения будет вполне достаточно, если мы хотим, чтобы

80%

всего набо­

ра данных было тренировочным. Но что делать, если мы хотим оперировать мень­

шим набором данных, чем тот, который у нас есть в

терен для локальной разработки. Набор данных

BigQuery? Этот случай харак­
flights состоит из 70 млн строк дан­

ных, и, возможно, нам нужен меньший набор данных из миллиона рейсов. Как бы
мы выбрали по

1 из

каждых

70

рейсов, а затем

80%

ных?
Нельзя сделать что-то вроде этого:

SELECT
date,
airline,
departure airport,
departure_schedule,
arrival_airport,
arrival_delay
FRCМ

'bigquery-samples' .airline_ontime_data.flights
WНERE

AВS(}ol)[)(FARМ_FINGERPRINT(date),

AND

70))

AВS(}ol)[)(FARМ_FINGERPRINT(date),



10)) < 8

из них в качестве тренировоч­

Глава

304

6

Мы не можем выбирать по

дых

1О.

1

из каждых

70

строк, а затем выбирать по

Если мы выбираем числа, которые делятся на

делиться и на

10!

70,

8

из каж­

то они, конечно же, будут

Эта вторая операция деления по модулю бесполезна.

Вот более подходящее решение:

SELECT
date,
airline,
departure airport,
departure_schedule,
arrival_airport,
arrival_delay
FRG!
'Ыgquery-samples·

.airline_ontime_data.flights

WНERE

AВS(М::Ю(FARМ_FINGERPRINT(date),

AND

В этом запросе

700

дулю выбирает по
по

70)) = О
700)) < 560

AВS(м::>D(FARМ_FINGERPRINT(date),

8 из

каждых



равно 70х 1О и

1 из

каждых

560

70

равно 70х8. Первая операция деления по мо­

строк, а вторая операция деления по модулю

-

этих строк.

Для валидационных данных вы бы заменили < 560 диапазоном:
AВS(М::Ю(FARМ_FINGERPRINT(date),

AND

70))

AВS(М::Ю(FARМ_FINGERPRINT(date),



700))

ВЕТWЕЕN

560 AND 629

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

-

например, мы можем моделировать полный спектр рейсов в любой кон­

кретный день, экспериментируя с меньшим набором данных. Однако, если мы хо­
тим получить 1/70-ю часть рейсов в любой конкретный день, то нам придется ис­
пользовать RAND ( J и сохранить результат в виде новой таблицы для обеспечения

повторяемости. Из этой меньшей таблицы мы можем отобрать

80%

дат с помощью

функции FARМ_FINGERPRINT () . Поскольку эта новая таблица содержит только

1 млн

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

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

45

тренировки

модели

прогнозирования

спроса

на основе данных

дней с целью предсказания спроса в течение следующих

14

за последние

дней (полный ис­

ходный код см. в репозитории по ссылке 8 ) мы извлекаем необходимые данные:

См. https://github.com/GoogleCloudPlatform/Ьigquery-oreilly-book/ЫoЬ/master/blogs/bqml_arima/
bqml_arima.ipynb.

8

Паттерны обеспечения воспроизводимости

305

OR REPLACE MODEL ch09eu.numrentals forecast

СRЕАТЕ

OPТICNS(model_type='ARIМA',

time_series_data_col='numrentals',
time_series timestamp_col='date') AS
SELECT
from start date) AS
AS numrentals

CAST(EXТRACT(date

,

COUNТ(*)

ТIМЕSТАМР)

AS date

FRCМ

'bigquery-puЫic-data'

GROUP

.london_bicycles.cycle_hire

date
date BETWEEN

ВУ

НAVING

DAТE_SUB(CURRENТ_DAТE(),

INTERVAL 45 DAY) AND

CURRENТ_DAТE()

Такая последовательная разбивка данных также необходима в быстро меняющихся
средах, даже если не преследуется цель предсказания будущего значения времен­

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

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

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

ло правильно оценивать. Например (полный исходный код см. в репозитории 9 ):
def read_dataset(client, row_restriction, batch size=2048):

bqsession = client.read_session(
row- restriction=row- restriction)
dataset = bqsession.parallel_read_rows()
return (dataset.prefetch(l) .map(features and labels)
.shuffle(batch_size*lO) .batch(batch_size))
client = BigQueryClient()
train df = read_dataset(client, 'Ti.me 144803', 2048)
Еще один пример, где требуется последовательная разбивка данных,

-

это высо­

кие корреляции между интервалами времени, которые следуют друг за другом. На­
пример, в метеопрогнозировании погода в последовательные дни сильно коррели­

рует. Поэтому нецелесообразно помещать
ных, а

9

13

12

октября в тренировочный набор дан­

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

См. https://github.com/GoogleCloudPlatform/training-data-analyst/bloЬ/master/blogs/

Ьigquery _ datascience/Ьigquery_ tensorflow.ipynb.

306

1

Глава

6

(представьте, например, что

12

октября был ураган). Кроме того, погода сильно

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

ной разбивки, но при учете сезонности, используя первые
в тренировочном наборе данных, следующие
и последние

5 дней

5 дней

20

дней каждого месяца

в проверочном наборе данных

в тестовом наборе данных.

Во всех этих случаях повторяемая разбивка требует только того, чтобы мы помес­
тили

логику,

используемую

для

создания

среза,

в

систему

управления

версиями

и обеспечили, чтобы версия модели обновлялась всякий раз, когда эта логика меня­
ется.

Стратифицированная разбивка
Приведенный выше пример в отношении того, как погодные закономерности раз­
личаются в разные времена года, является примером ситуации, когда разбивка

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

5

20

дней каждого месяца в тренировочном наборе данных,

дней в проверочном наборе данных и последние

5

дней в тестовом

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

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

признаков будут хорошо распределены между всеми срезами. Поэтому в крупно­
масштабном машинном обучении необходимость стратификации возникает до­
вольно часто только в случае асимметричных наборов данных. Например, в наборе

данных

flights

менее

1%

рейсов вылетают до

6

часов утра, и поэтому число рейсов,

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

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

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

требность стратифицировать набор данных по метке и разбить каждую стратифи­
кацию равномерно. Это также важно, если мы имеем мультиметочную задачу
и некоторые метки встречаются реже, чем другие. Указанные задачи обсуждаются

в разд. "Паттерн

10.

Перебалансировка" главы

3.

Неструктурированные данные
Хотя в этом разделе мы сосредоточились на структурированных данных, те же
принципы применимы и к неструктурированным данным, таким как снимки, видео,

Паттерны обеспечения воспроизводимости

307

аудио или текст произвольной формы. Дrlя их разбивки просто следует воспользо­
ваться метаданными. Например, если видео, снятые в один и тот же день, коррели­

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

же

человека

Farm Fingerprint

тяготеют

к

коррелированию,

следует

использовать

отпечаток

идентификатора user_ id рецензента для многократной разбивки

отзывов между наборами данных. Если метаданные недоступны или нет корреля­
ции между экземплярами, нужно закодировать снимок или видео с помощью алго­

ритма

Base64

и вычислить цифровой отпечаток кодировки.

Естественным подходом к разбивке текстовых наборов данных может быть исполь­
зование хеша самого текста. Однако этот подход подобен случайной разбивке и не
решает проблему корреляции между отзывами. Например, если человек часто ис­
пользует слово "потрясающий" в своих негативных отзывах или оценивает все

фильмы "Звездных войн" как плохие, то его отзывы коррелируют. Аналогично ес­
тественным подходом к разбивке наборов фото- или аудиоданных может быть ис­

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

ходе к разбивке набора данных. По нашему опыту, многие проблемы с низкой ре­
зультативностью

ML

можно решить путем надлежащей разбивки (и сбора) данных

с учетом потенциальных корреляций.

Во время вычисления векторных вложений или предварительной тренировки авто­
кодировщиков мы должны сначала разбивать данные и выполнять эти предвари­

тельные вычисления только на тренировочном наборе данных. По этой причине
разбивка не должна выполняться на векторных вложениях снимков, видео или тек­

ста, если только эти вложения не были созданы на совершенно отдельном наборе
данных.

ПАТТЕРН

23.

Мостовая схема

Паттерн "Мостовая схема"

(Bridged Schema)

предоставляет подходы к адаптирова­

нию данных, используемых для тренировки модели, путем наведения моста из ста­

рой изначальной схемы в новые и более совершенные данные. Польза от этого пат­

терна обусловлена тем, что, когда поставщик входных данных вносит улучшения

в свой поток данных, часто требуется время для сбора достаточного объема данных
улучшенной схемы, чтобы можно было адекватно натренировать заменяющую мо­

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

Постановка задачи
Рассмотрим

приложение кассового терминала,

которое предсказывает, сколько

чаевых нужно дать курьеру. Приложение может использовать МL-модель, которая
предсказывает оплату с учетом суммы заказа, времени доставки, расстояния дос-

308

Глава

6

тавки и т. д. Такая модель будет тренироваться на фактических оплатах, добавлен­
ных клиентами.

Предположим, что одной из пременных оплат на входе в модель является тип пла­
тежа. В исторических данных это было записано как "наличные" либо "карта". Од­
нако предположим, что платежная система была обновлена и теперь предлагает

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

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

Мы не можем тренировать новую модель исключительно на новых данных, потому
что их объем будет довольно малым, ограниченным тем, что есть, т. е. транзакция­
ми после обновления платежной системы. Поскольку качество МL-модели сильно
зависит от объема данных, используемых для ее тренировки, вполне вероятно, что
модель, натренированная только с новыми данными, будет демонстрировать сла­

бые результаты.

Решение
Решение состоит в том, чтобы навести мост из схемы старых данных, чтобы те со­
ответствовали новым данным. Затем следует тренировать модель, используя столь­
ко новых данных, сколько имеется, и дополнить ее старыми данными. При этом

возникают два вопроса. Во-первых, как мы будем соотносить тот факт, что в ста­
рых данных присутствует только две

категории типа

платежа, тогда

как в новых

данных их четыре? Во-вторых, как будет осуществляться дополнение данными для

создания тренировочного, валидационного и тестового наборов данных?

Схема с наведенным мостом
Рассмотрим случай, когда старые данные имеют две категории (наличные и карта).

В новой схеме категория карт теперь детализированнее (подарочная карта, дебето­
вая карта, кредитная карта). Мы знаем лишь то, что транзакция, кодированная как
"карта" в старых данных, была бы одним из этих типов, но фактически этот тип не
был зафиксирован. Навести мост из схемы можно вероятностно либо статически.
Мы рекомендуем статический метод, но его легче понять, если мы сначала обсудим
вероятностный метод.

Вероятностный метод. Допустим, глядя на новые тренировочные данные, мы оце­
ниваем, что из карточных транзакций
товые карты и

60% -

10% -

это подарочные карты,

30% -

дебе­

кредитные карты. Всякий раз, когда старый тренировочный

пример загружается в программу-тренер, мы могли бы выбирать тип карты, гене­
рируя равномерно распределенное случайное число в диапазоне [О;
подарочную карту, когда случайное число меньше

10,

100)

и выбирая

дебетовую карту, если она

Паттерны обеспечения воспроизводимости

находится в интервале

[ 1О; 40),

309

и кредитную карту в противном случае. При усло­

вии, что мы тренируем модель в течение достаточного числа эпох, любой трениро­
вочный пример будет представлен как все три категории, но пропорционально фак­
тической частоте встречаемости. Новые тренировочные примеры, конечно же, все­

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

в

каждую

эпоху

В этой симуляции мы ожидаем, что в

мы

внедряем

10% случаев

один

из

этих

экземпляров.

использования карты транзакция

происходила с подарочной картой. Вот почему мы выбираем "подарочную карту"
для значения категориальной входной переменной в

10%

случаев. Это, конечно же,

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

10% случаев
10% случаев

для какой-либо конкретной транзакции. Вообще-то может оказаться, что таксомо­
торные

компании запрещают использование

подарочных карт в

поездках в

аэро­

порт (и обратно), и поэтому для некоторых исторических примеров подарочная

карта даже не имеет юридической ценности. Однако в отсутствие какой-либо до­
полнительной информации будем считать, что распределение частот является оди­
наковым для всех исторических примеров.

Статический метод. Категориальные переменные обычно кодируются с одним
активным состоянием. Если мы будем следовать описанному выше вероятностному
подходу и тренировать достаточно долго, то кодированное с одним активным со­

стоянием среднее значение, поданное в тренирующую программу "карты" в старых
данных, будет равно [О; О, 1;

0,3; 0,6]. Первое число, О, соответствует категории на­
личных. Второе число равно О, 1, потому что в 10% случаев в карточных операциях
это число будет равно 1, а во всех остальных случаях - нулю. Подобным же обра­
зом у нас будет 0,3 для дебетовых карт и 0,6 для кредитных карт.
В целях наведения моста из старых данных в новую схему мы можем преобразо­
вать старые категориальные данные в это представление, в котором мы вставляем

априорную вероятность новых классов, оцененную по тренировочным данным. Но­
вые данные будут иметь [О, О,

1,

О] для транзакции, о которой известно, что она бы­

ла оплачена дебетовой картой.
Мы рекомендуем использовать статический метод, а не вероятностный, потому что

они практически эквиваленты, если вероятностный метод работает достаточно
долго. К тому же он намного проще реализуется, т. к. каждый платеж по карте из

старых данных будет иметь точно такое же значение (массив из

0,3; 0,6]).

4 элементов

[О; О, 1;

Вместо того чтобы писать сценарий для генерирования случайных чисел,

как в вероятностном методе, мы можем обновлять старые данные в одной строке
кода. Кроме того, статический метод вычислительно намного дешевле.

Аугментированные данные
Для того чтобы максимизировать использование новых данных, следует иметь

только два среза данных, которые обсуждаются в разд. "Паттерн

12.

Контрольные

Глава

310

точки" главы

5000

6

4.

Предположим, что у нас

1 млн

примеров в старой схеме, но только

примеров в новой схеме. Как в этом случае создать тренировочный и оценоч­

ный наборы данных?
Давайте сначала возьмем оценочный набор данных. Важно понимать, что цель тре­
нировки МL-модели

-

делать предсказания на ранее не встречавшихся данных.

Невстречавшиеся данные в нашем случае будут исключительно теми данными, ко­
торые соответствуют новой схеме. Следовательно, нам нужно выделить достаточ­

ное число примеров из новых данных, чтобы адекватно оценивать результатив­

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

2000

примеров в оценочном наборе данных. Оценочный набор данных не будет со­

держать никаких старых примеров, которые были соединены мостом, чтобы соот­
ветствовать новой схеме.

Как узнать, сколько нам нужно примеров в оценочном наборе данных:

1ООО

или

2000?

Для получения этого количества следует вычислить метрику оценивания в текущей

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

Вычислить метрику оценивания на разных подмножествах можно следующим

образом (как обычно, полный исходный код 10 находится на

GitHub

в репозитории

исходного кода этой книги):

for subset_size in range(lOO, 5000, 100):
sizes.append(subset_size)
#
#

Вычислять изменчивость метрики оценивания

в этом размере подмножества на протяжении 25 испытаний
scores = []
for х in range(l, 25):
indices = np.random.choice(N_eval,
size=subset size, replace=False)
scores.append(
model.score(df_eval[indices],
df_old.loc[N_train+indices, 'tip'])

score_mean.append(np.mean(scores))
score_stddev.append(np.std(scores))
В приведенном выше фрагменте кода мы пробуем размеры
ждом размере подмножества мы оцениваем модель

25

100, 200, ... , 5000.

В ка­

раз, всякий раз на другом,

случайно отбираемом подмножестве полного оценочного набора. Поскольку мы
имеем дело с оценочным набором текущей производственной модели (которую
мы смогли натренировать миллионом примеров), оценочный набор данных здесь
может содержать сотни тысяч примеров. Затем мы можем вычислить стандартное

10

См. https://github.com/GoogleCloudPlatfoгm/ml-design-patteгns/ЫoЬ/masteг/06_гepгoducibllity/

bгidging_schema.ipynb.

Паттерны обеспечения воспроизводимости

отклонение метрики оценивания над

25

З 11

подмножествами, повторить это на разных

размерах оценивания и построить график этого стандартного отклонения относи­
тельно размера оценивания. Результирующий график будет выглядеть примерно
так, как показано на рис.

6.3.
-

st:ddev

oos

0.04

0.03

002

0.01

1000

2000

4000

3000

5000

eval_s1ze

Рис.

6.3.

Определить число необходимых оценочных примеров путем оценивания

производственной модели на подмножествах разных размеров и отслеживания изменчивости метрики

оценивания по размеру подмножества. Здесь стандартное отклонение начинает достигать плато
примерно на

Из рис.

примерах

видно, что число оценочных примеров должно быть не менее

6.3

а в идеале

2000

-

3000

2000,

и более. Для остальной части обсуждения этой темы давайте

предположим, что мы решили оценивать на

2500 примерах.

Тренировочный набор будет содержать оставшиеся

новых данных, оставшихся после удержания

2500

2500

новых примеров (объем

для оценивания), дополненных

некоторым числом старых примеров, которые были соединены мостом, чтобы со­
ответствовать новой схеме. Оrкуда мы узнаем, сколько старых примеров нам нуж­

но? А мы и не узнаем. Это гиперпараметр, который нам придется настраивать. На­
пример, в задаче с оплатой за услуги (чаевыми), используя поиск о сетке, мы видим

из рис.

6.4

(блокнот 11 в репозитории на

метрика оценивания резко падает до

GitHub содержит полную информацию), что
20 ООО примеров, а затем начинает достигать

плато.

11

См. https://github.com/GoogleCloudPlatfoгm/ml-design-patteгns/ЬloЬ/masteг/06_гepгoducibllity/

bгidging_schema.ipynb.

312

Глава

6
-

evl!ll_metrк

09688

09686

09684

0.9682

0.9680

20000

40000

60000

80000

100000

Г acceptaЫe_deviation
Это работает на исторических (тренировочных) данных, потому что весь кадр дан­
ных находится под рукой. Разумеется, при выполнении предсказательного вывода

на нашей модели у нас не будет всего кадра данных целиком. В промышленной

Паттерны обеспечения воспроизводимости

1

317

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

2010-02-03 08:45:00,19.0
Видно, что приведенный выше рейс (в

08:45 3

февраля) опаздывает на

19

минут, но

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

06:45

и

DFW

между

08:45:

2010-02-03 06:45:00,?
2010-02-03 06:?:00,?
2010-02-03 08:45:00,19.0
Выполнять предсказательный вывод по одному рейсу за раз не получится. Нам

нужно каким-то образом предоставлять модели информацию обо всех предыдущих
рейсах.

Как выполнять предсказательный вывод, если модель требует не одного экземпля­
ра, а последовательности экземпляров?

Решение
Решение состоит в том, чтобы осуществлять потоковую передачу с поддержкой
состояния, т. е. потоковую передачу, в которой отслеживается состояние модели во
времени.

+

К данным о прибытии рейса применяется скользящее окно. Его необходимо
будет рассчитывать над двухчасовым промежутком, но оно может закрываться
чаще, например каждые



будут рассчитываться каждые

+

минут. В этом случае агрегированные значения



минут в течение предыдущих

2 часов.

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

+ Всякий

раз, когда окно закрывается (в нашем примере каждые

10

минут), по­

строенная на временном ряде МL-модель тренируется на двухчасовом списке

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

+

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

сионное интегрированное скользящее среднее (autoregressive integrated moving
average, ARIMA) или долгая краткосрочная память (long short-term memory,
LSTM), и в этом случае параметры модели были бы коэффициентами модели
ARIMA или весами модели LSTM. Для того чтобы не усложнять исходный код,

мы будем использовать нуль-порядковую регрессионную модель 1 4, и поэтому

14

Другими словами, мы вычисляем среднее.

Глава б

318

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

+

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

нет необходимости иметь полный список рейсов за последние

-

2 часа.

Для потоковой передачи конвейеров можно задействовать набор инструменталь­
ных средств

Apache Beam,

потому что тогда один и тот же исходный код будет ра­

ботать и на исторических, и на вновь поступающих данных. В

Apache Beam

сколь­

зящее окно настраивается следующим образом (полный исходный код 15 находится
в репозитории на

GitHub ):

windowed = (data
'window' >> beam.Windowlnto(
beam.window.SlidingWindows(2 * 60 * 60, 10*60))
Модель обновляется путем совмещения всех рейсовых данных, собранных за по­
следние

2 часа,

и передачи их в функцию ModelFn:

model_state = (windowed
'model' >> beam.transfonns.ComЬineGlobally(ModelFn()))
1

Функция ModelFn обновляет внутреннее состояние модели рейсовой информацией.
Здесь внутреннее состояние модели будет содержать кадр данных

pandas,

который

обновляется вместе с рейсами в окне:

class

ModelFn(beam.ComЬineFn):

def create accumulator(self):

return pd.DataFrame()
def add_input(self, df, window):

return df.append(window, ignore_index=True)
Всякий раз, когда окно закрывается, извлекается результат, который в нашем слу­
чае (мы называем его экстернализованным состоянием модели) состоит из модель­
ных параметров:

def extract_output(self, df):

if len(df) < 1:
return {)

orig = df['delay') .values
xarr = np.delete(orig, [np.argmin(orig), np.argmax(orig) ))
return {

'prediction': np.mean(xarr),
4 * np.std(xarr)

'acceptaЬle_deviation':

15

См. https://github.com/GoogleCloudPlatform/ml-design-patterns/ЫoЬ/master/06_reproducibllity/

find_anomalies_model.py.

Паттерны обеспечения воспроизводимости

Экстернализованное состояние модели обновляется каждые
двухчасового скользящего окна (табл.
Таблица

6.1.



319

минут на основе

6.1 ).

Фрагмент обновляемых данных

Время закрытия окна

prediction

acceptaЬle_deviation

2010-05-10Т06:35:00

-2.8421052631578947

10.48412597725367

2010-05-10Т06:45:00

-2.6818181818181817

12.083729926046008

2010-05-10Т06:55:00

-2.9615384615384617

11.765962341537781

Показанный выше исходный код извлечения параметров модели аналогичен исход­
ному коду для случая с использованием

Beam.

pandas,

но он выполняется в конвейере

За счет этого обеспечивается возможность работы исходного кода в потоко­

вом режиме, но состояние модели доступно только в контексте скользящего окна.

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

модельные веса в файл в паттерне "Функции обслуживания без поддержки состоя­
ния", чтобы отцепить его от контекста программы тренировки, в которой эти веса
вычисляются):

model_external = beam.pvalue.AsSingleton(model state)
Указанное экстернализованное состояние можно использовать для обнаружения
аномальности данного рейса:

def is_anomaly(flight, model_external state):

result = flight.copy()
error = flight [ 'delay'] - model _ external _ state ( 'prediction' ]
tolerance = model_external_state['acceptaЫe_deviation']
result('is_anomaly'] = np.abs(error) > tolerance
return result
Затем функция is_anomaly применяется к каждому элементу в последней секции
скользящего окна:

anomalies = (windowed
'latest slice' >> beam.FlatMap(is_latest_slice)
'find_anomaly' >> beam.Map(is_anomaly, model_external))

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

улучшено, если параметры МL-модели способны обновляться в онлайновом режи­
ме. Этот паттерн также применим к МL-моделям с поддержкой состояния, таким

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

320

Глава б

Сокращение вычислительных затрат
В разд. "Постановка задачи" мы использовали следующий код библиотеки

pandas:

dfw['delay'] .rolling('2h') .apply(is_anomaly, raw=False);
тогда как в разд. "Решение" исходный код библиотеки

Beam

был следующим:

windowed = (data
1 'window' >> beam.Windowinto(
beam.window.SlidingWindows(2 * 60 * 60, 10*60))
model state = (windowed
1 'model' >> beam.transforms.ComЬineGlobally(ModelFn()))
Между скользящим окном в

pandas

и скользящим окном в

Apache Beam

существу­

ют значимые различия в том, как часто вызывается функция is _anomaly и как часто
необходимо вычислять модельные параметры (среднее значение и стандартное от­

клонение). Обсудим это.

Поэлементно либо за интервал времени. В коде

pandas

функция is _anomaly вызы­

вается на каждом экземпляре набора данных. Исходный код обнаружения анома­
лии

вычисляет параметры

модели

менту в окне. В конвейере

и

Beam

немедленно применяет их

к последнему эле­

состояние модели тоже создается на каждом

скользящем окне, но скользящее окно в этом случае основано на времени. Поэтому
параметры модели вычисляются только один раз в



минут.

Само обнаружение аномалии осуществляется на каждом экземпляре:

anomalies = (windowed
'latest slice' >> beam.FlatMap(is_latest_slice)
'find_anomaly' >> beam.Map(is_anomaly, model_external))
Обратите внимание, что за счет этого вычислительно дорогостоящая тренировка
старательно

отделяется

от

вычислительно

дешевого

предсказательного

Вычислительно дорогостоящая часть выполняется только один раз в

10

вывода.

минут, по­

зволяя классифицировать каждый экземпляр как аномалию или норму.

Высокая пропускная способность потоков данных. Объемы данных продолжают
расти, и большая часть этого процесса происходит за счет реально-временнЬ1х дан­
ных. Следовательно, этот паттерн нужно применять к потокам данных высокой
пропускной способности

-

потокам, в которых число элементов может превышать

тысячи элементов в секунду. Подумайте, например, о потоках щелчков мышью

с веб-сайтов или потоках машинной активности от компьютеров, носимых уст­

ройств или автомобилей.
Предлагаемое техническое решение с использованием потокового конвейера вы­

годно тем, что позволяет избегать перетренировки модели на каждом экземпляре,

т. е. того, что делает исходный код
возвращает эти

преимущества,

записей. Если мы получаем

кадр данных за



pandas

создавая

5000

в разд. "Постановка задачи". Однако оно
в

памяти

кадр данных

всех полученных

элементов в секунду, то размещенный в памяти

минут будет содержать

3

млн записей. Поскольку в любой мо-

Паттерны обеспечения воспроизводимости

мент времени необходимо поддерживать
каждое за

2

12

скользящих окон

( 1О-минутные

321
окна,

часа), требования к памяти могут стать значительными.

Хранение всех полученных записей (для вычисления модельных параметров в кон­
це окна) может вылиться в проблему. Когда поток данных имеет высокую про­

пускную способность, важной становится возможность обновлять параметры моде­

ли с каждым элементом. Это можно сделать путем изменения функции ModelFn сле­
дующим образом (полный исходный код 16 находится на

class

GitHub):

OnlineМodelFn(beam.ComЬineFn):

def add_input(self, inmem_state, input_dict):

(sum, sumsq, count) = inmem_state
input = input _ dict [ 'delay']
return (sum + input, sumsq + input*input, count + 1)
def extract output(self, inmem state):

(sum, sumsq, count) = inmem_state
mean = sum / count
variance = (sumsq / count) - mean*mean
stddev = np.sqrt(variance) if variance
return {
'prediction' : mean,
'acceptaЫe_deviation': 4 * stddev



else

О

Ключевое отличие заключается в том, что в памяти хранится не весь кадр данных
полученных экземпляров, а только три числа с плавающей точкой (sum, sum2, count),

необходимые для извлечения выходного состояния модели. Обновление парамет­
ров модели по одному экземпляру за раз называется онлайновым обновлением и

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

среднего второй обход данных не требуется.

Потоковый

SQL

Если наша инфраструктура состоит из высокопроизводительной базы данных

SQL,

способной обрабатывать потоковые данные, то можно реализовать паттерн "Окон­
ный предсказательный вывод" альтернативным способом, используя окно агрега­

ции (полный исходный код 17 находится на

16

GitHub).

См. https://github.com/GoogleCloudPlatform/ml-design-patterns/ЫoЬ/master/06_reproducibllity/

find_anomalies_model.py.
17

См. https://github.com/GoogleCloudPlatform/ml-design-patterns/ЫoЬ/master/06_reproducibllity/

find_anomalies_model.py.

Глава

322

6

Мы вытаскиваем рейсовые данные из

BigQuery:

data AS (
SELECT
PARSE_DATETIME ( '%Y-%m-%d-%H%M',
CONCAT(CAST(date AS STRING),
'-' FORМAT('%04d', arrival schedule))
) AS scheduled_arrival_time,
arrival_delay
~ 'bigquery-samples.airline_ontime_data.flights'
'2010-05'
WНERE arrival_airport = 'DFW' AND SUBSTR(date, О, 7)

WIТН

)

'

Затем создаем состояние модели model_state, вычисляя параметры модели в тече­

ние временного окна, заданного как предшествующие

2

часа и предшествующая

1 секунда (RANGE BETWEEN 7200 PRECEDING AND 1 PRECEDING):
model_state AS (
SELECT
scheduled arrival_time,
arrival_delay,
AVG(arrival_delay) OVER (time_window) AS prediction,
4*STDDEV(arrival_delay) OVER (time_window) AS ассерtаЫе deviation
~ data
WINDCМ time window AS
(ORDER ВУ UNIX_SECONDS(TIМESTAМP(scheduled_arrival_time))
RANGE ВЕТWЕЕN 7200 PRECEDING AND 1 PRECEDING)
Наконец, применяем алгоритм обнаружения аномалий к каждому экземпляру:

SELECT

*'

(AВS(arrival_delay

FR~

- prediction) >

acceptaЫe_deviation)

AS

is_anomaly

model state

Результат выглядит так, как представлено в табл.

6.2,

в которой 54-минутная за­

держка прибытия отмечена как аномалия, учитывая, что все предыдущие рейсы

прибыли рано.
Таблица

6.2.

Результат запроса

BigQuery,

определяющего аномальность входящих рейсовых данных

scheduled_arrival_time

arrival_delay

prediction

acceptaЫe_deviation

is_anomaly

2010-05-01ТО5:45:00

-18.0

-8.25

62.51399843235114

false

2010-05-01Т06:00:00

-13.0

-10.2

56.878818553131005

false

2010-05-01Т06:35:00

-1.0

-10.666

51.0790237442599

false

2010-05-01Т06:45:00

-9.0

-9.28576

48.86521793473886

false

2010-05-01Т07:00:00

54.0

-9.25

45.24220532707422

true

Паттерны обеспечения воспроизводимости

В отличие от решения на основе

SQL

Apache Beam,

323

эффективность распределенного

позволит нам рассчитывать двухчасовое временное окно, центрируемое на

каждом экземпляре (а не с разрешающей способностью 10-минутных окон). Однако

недостатком является тяготение

BigQuery

к относительно высокой задержке (по­

рядка секунд), и поэтому его нельзя использовать для приложений управления
в режиме реального времени.

Модели на основе последовательностей
Паттерн "Оконный предсказательный вывод" передачи скользящего окна, состоя­
щего из предыдущих экземпляров, в функцию предсказательного вывода полезен за

пределами обнаружения аномалий или даже моделей на основе временНI;IХ рядов.
В частности, он полезен в любом классе моделей, таких как модели на основе по­
следовательностей, т. е. моделей, которые требуют исторического состояния. На­
пример, прежде чем модель машинного перевода сможет выполнить перевод, она
должна увидеть ряд из нескольких последовательных слов для учета контекста сло­

ва в переводе. Ведь перевод слов
Ьу

ний

road"

"1 left Chicago
Road" (поверните налево

left, Chicago

и

road

варьируется среди предложе­

(я уехал из Чикаго по дороге) и

"Tum left

оп

Chicago

на Чикагской дороге).

По соображениям производительности модель машинного перевода будет настрое­

на как не поддерживащая состояние и требовать от пользователя предоставления
контекста. Например, если модель не поддерживает состояние, то экземпляры

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

перевод знаменитого монолога из "Гамлета" Шекспира на немецкий язык могбы
следовать

этим

шагам,

выхватывая

из

шрифтом слово подлежит переводу (табл.
Таблица
Вход

(9 слов,

по

6.3.

середины

там,

где

выделенное

жирным

6.3).

Перевод отдельных слов
Выход

4 по обе стороны)

The undiscovered country, from whose bourn No traveller returns

dessen

undiscovered country, from whose bourп No traveller returns, puules

Bourn

country, from whose bourn No traveller returns, puules the

Kein

from whose bourn No traveller returns, puules the will,

Reisender

Следовательно, клиенту потребуется потоковый конвейер. Конвейер мог бы при­
нимать входной английский текст, лексемизировать его, посылать по

9

лексем за

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

и абзацы.
Большинство моделей на основе последовательностей, таких как рекуррентные

нейронные сети и

LSTM,

требуют потоковых конвейеров в целях обеспечения

высокопроизводительного предсказательного вывода.

Глава б

324

Признаки с подцержкой состояния
Патгерн "Оконный предсказательный вывод" может быть полезен, если подавае­
мый в модель признак требует состояния, даже если сама модель не поддерживает
состояние. Например, предположим, что мы тренируем модель предсказывать за­
держки прибытия, и одной из входных модельных переменных является ·задержка
вылета. У нас вполне может возникнуть потребность включить среднюю задержку
вылета рейсов из этого аэропорта за последние

2

часа в качестве входной перемен­

ной модели.

Во время тренировки мы можем создать набор данных с помощью оконной функ­
ции

SQL:

da ta AS (
SELECT
SAFE. PARSE DATETIME ( '%Y-%m-%d-%H%M',
CONCAT(CAST(date AS STRING), '-',
FORМAT ( '%04d', departure _ schedule))
) AS scheduled_depart_time,
arri val _ delay,
departure_delay,
departure_airport
~ 'bigquery-samples.airline ontime_data.flights'
WНERE arrival_airport = 'DFW'

WIТН

)

,
SELECT
* EXCEPТ(scheduled_depart time),
EXТRACT(hour from scheduled_depart time) AS hour_of_day,
AVG(departure_delay) OVER (depart_time_window) AS avg_depart_delay
FRCМ data
WINDOW depart_time_window AS
(PARTITION ВУ departure_airport ORDER ВУ
UNIX_SECONDS(TIМESTAМP(scheduled_depart time))
RANGE ВЕТWЕЕN 7200 PRECEDING AND 1 PRECEDING)

Тренировочный набор данных теперь включает среднюю задержку в качестве еще
одного признака (табл.

6.4).

Таблица

6.4. Тренировочный набор данных
departure_airport

hour_of_day

avg_depart_delay

-7.0

LFT

8

-4.0

56. о

50.0

LFT

8

41.0

3

-14.0

-9.0

LFT

8

5.0

4

-3.0

о.о

LFT

8

-2.0

Строка

arrival_delay

1

-3.0

2

departure_delay

Правда, во время предсказательного вывода нам понадобится потоковый конвейер,

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

Паттерны обеспечения воспроизводимости

325

вать ее в модель. В целях ограничения асимметрии между тренировкой и обслужи­

ванием предпочтительнее использовать тот же самый

Python

или

функции окна­

в

SQL

перевертыша18 в потоковом конвейере, а не пытаться переводить

SQL

на язык

Scala,

Java.

Упаковь1вание предсказательных запросов
Еще один сценарий, в котором мы могли бы использовать паттерн "Оконный пред­
сказательный вывод", даже если модель не поддерживает состояния,

это случай,

-

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

предсказательных запросов друг за другом в развернутую в облаке модель может
привести к переполнению. В этой ситуации можно применить паттерн "Двухфаз­
ные предсказания" из главы

5,

где в первой фазе используется конвейер по сбору

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

Если мы собираем входные экземпляры в течение

5

минут, клиент должен терпимо

относиться к пятиминутной задержке в получении предсказаний .

ПАТТЕРН

25.

Конвейер рабочего потока

В паттерне "Конвейер рабочего потока"

(Workflow Pipeline)

мы решаем задачу соз­

дания сквозного воспроизводимого конвейера путем контейнеризации и оркестри­

рования шагов в нашем рабочем потоке процессов машинного обучения. Контей­
неризация может выполняться в явной форме либо с использованием каркаса,
который упрощает выполнение этой работы.

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

6.6)

в рамках од­

ного скрипта или блокнота. Однако по мере того, как каждый шаг в рабочем потоке
процессов

ML

становится все сложнее, и все больше людей в организации хотят

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

о~е~~о-~о----е·~-е
Сбор

Валидация

Предобработка

Строительство

Тренировка

Развертывание

данных

данных

данных

модели

и оценивание модели

модели

Рис.

6.6.

Шаги типичного сквозного рабочего потока процессов

ML.

Показанное не означает, что поток является всеобъемлющим, однако он охватывает

наиболее распространенные шаги в ходе разработки модели

18 Оконо-перевертыш (tumЫing window),

или переворачивающееся окно, -

вающийся интервал, смежный с предыдущим и последующим интервалами.

ML

это фиксированный, неперекры­
- Прим. перев.

326

Глава

6

В традиционном программировании в монолитных приложениях вся логика обра­

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

ком. То же самое относится и к развертыванию или отладке монолитных приложе­

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

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

архитектуре отдельные части бизнес-логики строятся и развертываются в виде
изолированных (микро) пакетов кода. С помощью микросервисов большое прило­
жение разбивается на меньшие, более управляемые части, благодаря чему разра­

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

Тема "монолит против микросервиса"

рабочего потока процессов
того, что шаги

ML

ML,

аналогична обсуждению масштабирования

обеспечения возможности совместной работы и

должны быть воспроизводимыми и готовыми к многоразовому

использованию в разных рабочих потоках. Когда кто-то строит МL-модель само­
стоятельно, вполне возможно, что итеративное применение "монолитного" подхода

будет быстрее. Данный подход нередко работает также и потому, что в разработку
и техническое сопровождение каждого шага: сбор и предобработка данных, разра­

ботка, тренировка и развертывание модели,

-

активно вовлечен только один чело­

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

рабочего потока процессов

ML

нам нужен подход, с помощью которого коллектив

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

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

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

ные и выполнять трассировку ошибок на отдельных шагах.

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

Паттерны обеспечения воспроизводимости

327

1

руют, что мы сможем выполнять один и тот же исходный код в разных средах,

и между этими выполнениями мы увидим согласованное поведение. Такие отдель­
ные контейнеризированные шаги позднее все вместе выстраиваются в цепочку,

создавая конвейер, который может выполняться с помощью вызова

REST API.

По­

скольку шаги конвейера выполняются в контейнерах, мы можем запускать их на

ноутбуке разработчика с помошью локально установленной инфраструктуры либо
посредством внешней облачной службы. Указанный конвейерный рабочий поток
позволяет членам команды выстраивать шаги конвейера самостоятельно. Контей­
неры также обеспечивают воспроизводимый способ запуска всего конвейера цели­
ком, от начала до конца, поскольку они гарантируют согласованность между вер­

сиями библиотек, от которых зависит его работа, и средами выполнения. Кроме
того, поскольку шаги контейнеризированного конвейера допускают разделение

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

Для создания конвейеров существует масса инструментов как с вариантом локаль­

ной установки, так и с вариантом размещения в облаке, включая платформы Cloud
AI Platfonn Pipelines 19 , TensorFlow Extended 20 (TFX), Kubeflow Pipelines21 (KFP),
MLflow22 и Apache Airflow23 • В целях демонстрации паттерна "Конвейер рабочего
потока" здесь мы определим конвейер с помощью платформы TFX и запустим его
во внешней службе Cloud AI Platfonn Pipelines для выполнения конвейеров ML
в облачной инфраструктуре Google Cloud с использованием вычислительного ме­
ханизма Google Kubernetes Engine (GKE) в качестве инфраструктуры контейнеров.
Шаги в конвейерах

TFX

называются компонентами, они бывают двух видов: пред­

варительно построенные и индивидуально настраиваемые. Как правило, первым
в конвейере

TFX

является компонент, который принимает данные из внешнего ис­

точника. Он называется

ExampleGen,

где слово

example

в названии относится

к терминологии машинного обучения и обозначает помеченый экземпляр, исполь­

зуемый для тренировки. Составляющие компонент

ExampleGen 24

варианты позво­

ляют получать данные из источников, таких как СSV-файлы, файлы
просы

BigQuery или
BigQueryExampleGen

TFRecord,

за­

из реального прикладного источника. Например, компонент

позволяет

подключать

данные,

хранящиеся

в

BigQuery,

к конвейеру с помощью запроса, который будет извлекать эти данные. Затем он

сохраняет эти данные в виде файла

Storage (GCS),

TFRecord

в корзине хранилища

Google Cloud

чтобы следующий компонент смог их использовать. Это как раз тот

компонент, который мы будем настраивать, передавая ему запрос. Указанные вари­
анты компонента
на рис.

ExampleGen относятся к
6.6 рабочего потока процессов ML.

19

См. https://oreil.ly/nJolp.

20

См. https://oreil.ly/Oznl3.

21

См. https://oreil.ly/ВoegQ.

22

См. https://mlflow.org/.

23

См. https://oreil.ly/63_GG.

24

См. https://oreil.ly/Sjx9F.

фазе сбора данных в рамках описанного

Глава б

328

Следующий шаг указанного рабочего потока

-

это валидация данных. После того

как мы получим и импортируем данные, мы сможем передать их другим компонен­

там

для

преобразования

StatisticsGen25

или

анализа

перед тренировкой

статистику по предоставленным данным.

ExampleGen, и
SchemaGen выводит

из импортированных данных. Задействуя результаты работы
нент

модели.

берет данные, принятые на шаге

ExampleValidator2

7

Компонент

генерирует сводную
вычисленную схему

SchemaGen26 ,

компо­

обнаруживает аномалии на наборе данных и проверяет

данные на наличие дрейфа данных или потенциальной асимметрии между трени­

ровкой и обслуживанием 28 • Компонент
нента

SchemaGen,

Transform 29

также берет результат компо­

и здесь мы выполняем инженерию признаков для преобразова­

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

После того как данные будут готовы к подаче в модель, мы можем передать их

в компонент тренировки

TFX Trainer3°.

Настраивая компонент

Trainer,

мы указыва­

ем на функцию, которая определяет наш исходный код модели. Мы также можем
отметить место, где мы хотели бы тренировать модель. Здесь мы покажем принцип

использования тренировки в службе
та. Наконец, компонент

Pusher3'

Cloud AI Platform Training

из этого компонен­

занимается развертыванием модели.

гает много других уже построенных компонентов 32

-

TFX

предла­

мы включили сюда лишь не­

сколько из них и только те, которые будем использовать в примере конвейера.

В этом примере мы будем использовать набор данных

BigQuery,

NOAA

об ураганах из

чтобы построить модель, которая выполняет предсказательный вывод,

продуцируя код

SSHS 33

урагана. Мы будем поддерживать список признаков, ком­

понентов и объем модельного кода относительно короткими, чтобы сосредоточить­
ся на инструментах конвейера. Шаги нашего конвейера описаны ниже и примерно
соответствуют рабочему потоку, представленному на рис.

6.6.

1.

Сбор данных: выполнить запрос на получение данных об ураганах из

2.

Валидация данных: применить компонент

ExampleValidator

BigQuery.

для выявления ано­

малий и проверки на дрейф данных.

25

См. https://oreil.ly/kXI QY.

26

См. https://oreil.ly/QpBlu.

27

См. https://oreil.ly/UD7Uh.

28

Дополнительные сведения о валидации данных см. в разд. "Паттерн 30. Призма объективности" ?Jювы 7.

29

См. https://oreil.ly/xsJYТ.

30

См. https://oreil.ly/XFtR_.

31

См. https://oreil.ly/qPSGU.

32

См. https://oreil.ly/gHv_z.

33

SSHS расшифровывается как шкала ураганов Саффира - Симпсона (https://oreil.ly/62kf3) и представляет
1 до 5, используемую для измерения силы и серьезности урагана. Обратите внимание, что

собой шкалу от

МL-модель не предсказывает степень серьезности урагана в более позднее время. Вместо этого она просто

усваивает пороговые значения скорости ветра, используемые в шкале Саффира

-

Симпсона.

Паттерны обеспечения воспроизводимости

329

Анализ и пред обработка данных: сгенерировать немного статистики на данных

3.

и определить схему.

Тренировка модели: натренировать модель

4.

tf.keras

на платформе

AI Platform.

Развертывание модели: развернуть натренированную модель в службе

5.

AI Plat-

form Prediction34 •
Когда наш конвейер будет завершен, мы сможем вызывать весь описанный выше

рабочий поток целиком с помощью одного-единственного вызова

API.

Начнем

с обсуждения вопросов сооружения строительных лесов для типичного конвейера

TFX

и процесса его выполнения на платформе

Разработка конвейера

AI Platform.

TFX

Для создания и вызова конвейера будем использовать инструменты командной
строки

tfx.

Новые вызовы конвейера называются исполнениями и отличаются от

обновлений, вносимых нами в сам конвейер, например добавления нового компо­
нента. И то и другое можно делать с помощью интерфейса командной строки

( command line interface, CLI)

платформы

TFX.

Мы можем определять базовые эле­

менты для конвейера в одном-единственном скрипте

Python,

который состоит из

двух ключевых частей:

+

экземпляра

tfx.orchestration.pipeline35 ,

в котором мы определяем сам конвейер и

компоненты, которые он содержит;

+ экземпляра

из библиотеки tfx. 37 • Мы будем использовать
его для создания и исполнения конвейера. В дополнение к Kubeflow runner су­

kubeflow_dag_runner3 6

ществует также

Beam 38 ,

API

для исполнения конвейеров

с инструментарием

TFX

Apache

который мы могли бы использовать для исполнения конвейера локально.

Наш конвейер (полный исходный код 39 см. на

GitHub)

будет иметь пять перечис­

ленных выше шагов или компонентов, и мы можем определить наш конвейер сле­
дующим образом:

pipeline.Pipeline(
pipeline_narne='huricane prediction',
pipeline_root='path/to/pipeline/code',
cornponents=[
bigquery_gen, statistics_gen, scherna_gen, train, rnodel_pusher

34

Хотя в примере конвейера развертывание является последним шагом, производственные конвейеры часто

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

CI/CD

и тестирование.

35

См. https://oreil.ly/62kf3.

36

См. https://oreil.ly/62kf3.

37

См. https://oreil.ly/62kf3.

38

См. https://oreil.ly/hnOvF.

39

См. https://github.com/GoogleCloudPlatform/ml-design-patterns/tree/master/06_reproducibllity/

workЛow _pipeline.

Глава б

330
В

целях

использования

поставляемого

платформой

компонента

TFX

мы отправляем запрос, который принесет наши данные. Этот

BigQueryExampleGen

компонент можно определить в одной строке кода, где query- это SQL-зaпpoc

к

BigQuery в

виде следующей инструкции:

bigquery_gen = BigQueryExampleGen(query=query)
Еще одним преимуществом использования конвейеров является то, что они предос­
тавляют инструменты для отслеживания входных переменных, выходных артефак­
тов

и

журналов

для

каждого

компонента.

Результатом

работы

компонента

statistics_gen, например, является сводка о наборе данных, которую мы видим на
6.7. statistics_gen40 - это предварительно построенный компонент платфор­

рис.
мы

TFX,

в котором используется компонент валидации данных

TF Data Va\idation

для генерирования сводной статистики на нашем наборе данных.

Chart to show

Numerlc Features (2)

Standard
count

missing

mеа п

std dev

zeros

2.13

1.24

0%

min

median

max

2

5

О log O expand

usa_sshs
Э.796

0%

40)

1_5

usa...wind
Э.796

0%

87. Э

22.91

0%

65

87

165

•СО

70

Рис.

6.7.

Выходной артефакт из компонента

TFX

можно исполнять в службе

25

~А.)

• _, ~

:35

4.5

1

110

131)

150

statis t ics_gen в конвейере TFX

Исполнение конвейера на платформе
Конвейер

-

I_ JI
1 •

Cloud AI Platform

Cloud AI Platform Pipelines,

которая бу­

дет управлять низкоуровневыми деталями инфраструктуры за нас. В целях развер­
тывания конвейера на платформе

AI Platform мы упакуем конвейерный код в кон­
Docker41 и разместим его в реестре контейнеров GCR (Google Cloud
Container Registry )42 • 43 • После перенесения контейнеризированного кода в реестр
GCR создадим конвейер, используя интерфейс CLI платформы TFX:

тейнер

tfx pipeline create \
--pipeline-path=kubeflow_dag_runner. py \
--endpoint='your-pipelines-dashboard-url' \
--build-target-image='gcr.io/your-pipeline-container-url'

40

См. https://oreil.ly/wvq9n.

41

См. https://oreil.ly/rdXeb.

42

См. https://oreil.ly/mSwqD.

Обратите внимание, что для запуска конвейеров TFX на платформе AI Platfoпn в настоящее время вам
GCR, и вы не можете использовать друтую службу реестра контейне­
ров, такую как DockerHub.

43

необходимо разместить свой код на

Паттерны обеспечения воспроизводимости

331

В приведенной выше команде адрес сервиса соответствует URL-aдpecy нашей па­
нели мониторинга в службе

AI Platfonn Pipelines.

Когда она завершится, на панели

мониторинга конвейеров мы увидим только что созданный конвейер. Команда

create создает ресурс конвейера, который мы можем вызывать, инициировав ис­
полнение (run create):

tfx run create --pipeline-name=' your-pipeline-name' --endpoint=' pipeline-1Jrl'
После выполнения этой команды мы сможем увидеть график, который обновляется
в режиме реального времени по мере прохождения нашего конвейера через каждый

шаг. На панели мониторинга службы

Pipelines

мы можем дополнительно проин­

спектировать отдельные шаги и увидеть любые дефекты, которые они генерируют,
метаданные и многое другое. Пример результата для отдельного шага показан на

рис.

6.8.
Artlfacts

lnput/Output

ML Metadata

Volumes

Statlc HTML

Manlfest

Logs

Pod

Events

0

Туре

Presence

Valency

'usa_sshs'

INТ

required

single

usa_wfnd

INТ

required

single

Domain

Feature name

1

1

Рис.

6.8.

Результат работы компонента

schema gen для

конвейера

ML.

В верхнем горизонтальном меню отображаются данные по КЗждому отдельному шагу конвейера
Мы могли бы натренировать модель непосредственно в контейнерезированном

конвейере в вычислительном механизме

GKE, но платформа TFX предоставляет
AI Platfonn Training в рамках нашего

утилиту для использования облачной службы
процесса.

TFX также имеет расширение для развертывания натренированной моде­
AI Platfonn Prediction. В нашем конвейере мы будем использовать обе
интеграции. Служба AI Platform Training позволяет экономически эффективно

ли в службе

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

нировки и минимизирует затраты на нее. Индивидуальные тренировочные задания

и их результаты можно отслеживать в консоли платформы

AI Platform.

Одним

из преимуществ создания конвейера с помощью платформ TFX или
является то, что мы не заперты в инфраструктуре Google Cloud. Мы мо­
жем выполнять приведенный здесь исходный код, используя службы GooJJle AI

Kubeflow

Platform Pipeliпes в Azure ML Pipelines44 , на платформе Amazon SageMaker4 либо

локально.

44

См. https://oгeil.ly/ASRxe.

45

См. https://oгeil.ly/H3p3Y.

332

Глава б

В целях реализации тренировочного шага в

Trainer

TFX

будем применять компонент

и передавать ему информацию о тренировочных данных для использования

на входе в модель вместе с исходным кодом тренировки модели.
ет расширение,

которое

предназначено для

TFX

предоставля­

выполнения тренировочного

шага на

платформе

AI Platform. Его можно задействовать, импортировав tfx.extensions.
google_ cloud_ ai_platform.trainer и предоставив подробную информацию о конфигу­
рации тренировки, настроенной в платформе AI Platform. Указанная информация
включает название проекта, регион и местоположение контейнера в реестре кон­

тейнеров

Google Cloud (GCR)

Кроме того,

с тренировочным кодом.

имеет компонент

AI Platform Pusher46 , который предназначен для
развертывания натренированных моделей в службе AI Platform Prediction. Для того
чтобы воспользоваться компонентом Pusher с платформой AI Platform, мы предос­
TFX

тавляем подробную информацию о названии и версии нашей модели, а также
функцию обслуживания, сообщающую платформе

AI Platform

формат входных

данных, которые та ожидает для нашей модели. С учетом всего этого мы получаем
полный конвейер, который принимает данные, анализирует их, выполняет их пре­

образование и, наконец, тренирует и развертывает модель с помощью платформы

AI Platform.
Почему это работает
Без выполнения нашего кода

ML

в качестве конвейера другим людям было бы

трудно надежно воспроизводить нашу работу. Им бы приходилось брать наш ис­

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

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

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

ML

от начала до конца как

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

воспроизводить как среду,

которую

мы

использовали для

его строительства, так и весь рабочий поток целиком, зафиксированный в конвейе­
ре. Она также дает нам возможность потенциального воспроизведения окружаю­

щей среды позже при необходимости для поддержания нормативных потребностей.
Кроме того, с конвейерами

TFX

и

AI Platform Pipelines

панель мониторинга предла­

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

46

См. https://oгeil.ly/bJavO.

Паттерны обеспечения воспроизводимости

333

ра. Это позволяет ускорять разработку и минимизировать риски, связанные с более
монолитным рабочим потоком процессов

ML,

в котором шаги неразрывно связаны

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

ными каркасами, такими как

TFX,

паттерн "Конвейер рабочего потока" дает нам

преимущества, которые приходят вместе с ориентированным ациклическим графом

(directed acyclic graph, DAG).

Поскольку конвейер представляет собой ориентиро­

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

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

готовые к использованию шаги для распространенных компонен­

тов рабочего потока, включая тренировку, оценивание и предсказательный вывод.
Эти компоненты работают как отдельные контейнеры везде, где мы решим испол­
нить наш конвейер.

Компромиссы и альтернативы
Главной альтернативой использованию конвейерного каркаса является выполнение

шагов рабочего потока процессов

ML

с помощью паллиативного подхода через от­

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

ML

в организованный конвейер связаны накладные расходы. В этом разделе мы рас­
смотрим некоторые вариации и расширения паттерна "Конвейер рабочего потока":
создание контейнеров вручную, автоматизацию конвейера с помощью инструмен­

тов

непрерывной

интеграции

и

непрерывной доставки

(continuous integration/

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

continuous delivery, CI/CD),

пользования конвейеров для отслеживания метаданных.

Разработка компонентов
Вместо использования уже разработанных и настроенных компонентов

TFX

для

строительства конвейера мы можем определять наши собственные контейнеры,

которые будут выступать в качестве компонентов либо использовать функцию на
языке

Python

как компонент.

В целях использования контейнерно-ориентированных компонентов 47 , предлагае­
мых платформой

47

TFX,

См. https://oreil.ly/SгyEn.

мы применяем метод create _ container_ component, передавая

Глава

334

6

ему входные и выходные параметры нашего компонента и базовый образ

Docker

вместе с любыми относящимися к контейнеру командами точки входа. Например,
следующий ниже контейнерно-ориентированный компонент вызывает инструмент

командной строки

bq для

скачивания набора данных

BigQuery:

component = create_container_component(
name='DownloadBQData',
parameters={
'dataset_name': string,
'storage_location': string
)

,

image='google/cloud-sdk:278.0.0',
command=[
'bq', 'extract', '--compression=csv', '--field_delimiter=, ',
InputValuePlaceholder('dataset_name'),
InputValuePlaceholder('storage_location'),

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

Google Cloud SDK,
bq.

который имеет

Помимо этого, с помощью декоратора @component можно конвертировать функцию

Python

в компонент

TFX.

В целях демонстрации предположим, что у нас есть шаг

для подготовки ресурсов, используемых во всем конвейере, в котором мы создаем

корзину облачного хранилища

Google Cloud Storage.

Этот шаг можно определить,

используя следующий фрагмент исходного кода:

fran google.cloud import storage
client = storage.Client(project="your-cloud-project")
@component
def CreateBucketComponent(

bucket_name: Parameter[string] = 'your-bucket-name',
) -> OutputDict(bucket_info=string):
client.create_bucket('gs://' + bucket_name)
bucket info = storage_client.get_bucket('gs://' + bucket_name)
return {
'bucket info': bucket info
Затем мы можем добавить этот компонент в определение конвейера:

create_bucket = CreateBucketComponent(
bucket_name='my-bucket')

Паттерны обеспечения воспроизводимости

Интеграция

Cl/CD

335

с конвейерами

В дополнение к вызову конвейеров через панель мониторинга или программно че­
рез интерфейс командной строки

или

(CLI)

API,

скорее всего, по мере того как мы

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

вариант

-

у нас может возникнуть потребность исполнять конвейер, когда его ис­

ходный код изменяется. Добавление

CI/CD

в конвейер рабочего потока помогает

соединять триггерные события с исполнениями конвейера .
Существует масса управляемых служб по настройке триггеров, которые исполняют
конвейер при возникновении потребности в перетренировывании модели на новых

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

ную событийно-управляемую платформу, такую как

Cloud Functions48 ,

для вызова

конвейера при добавлении новых данных в хранилище. В нашей функции мы мо­
жем указать условия

-

например, порог количества новых добавленных данных,

обусловливающий необходимость перетренировки,

-

для инициирования нового

исполнения конвейера. Как только у нас появилось достаточно новых тренировоч­
ных данных, мы можем пересоздать конвейер для перетренировки и переразверты­
вания модели (рис.

6.9).

Новые данные .

Перетренировать

Если новых данных достаточно,

добавленные =ну_х_р_ан-ил_и_щ_а_ _ _то...'""0в-е-йе_р---• · -и_п_е_ре_р_аз_ве_р_нут_ь_мо_д_ел_ь_.
Инфраструктура облачного хранения

Инструмент

Инструмент

Cloud Strorage

Cloud Functions

AI Platform Pipelines

!

о

Вычислительный механизм KuЬemetes

Рис.

6.9.

Рабочий поток процессов

Cl/CD

с использованием инструмента

Cloud

Fuпctioпs

для вызова конвейера при наличии достаточного количества новых данных в хранилище

Если мы хотим исполнять конвейер, основываясь на изменениях в исходном коде,

нам поможет инструмент

CVCD,

такой как

Cloud Build.

Когда

Cloud Build49

испол­

няет исходный код, он отрабатывает его в виде серии контейнеризированных ша­
гов. Этот подход хорошо вписывается в контекст конвейеров. Мы можем присое­

динить службу

Cloud Build

48

См. https://oreil.ly/rVyzX.

49

См. https://oreil.ly/kz8Aa.

50

См. https://oreil.ly/G2Xwv.

51

См. https://oreil.ly/m_dYr.

к действиям

GitHub 50

или триггерам

GitLab 51

в репози-

Глава

336

6

тории, где находится конвейерный код. Когда код будет зафиксирован в репозито­
рии, служба

C\oud Build,

основываясь на новом коде, построит контейнеры, кото­

рые ассоциированы с нашим конвейером, и инициирует его исполнение.

Платформы

Apache Airflow

В дополнение к

TFX

и

Kubeflow Pipelines

альтернативными платформами для реализации паттерна

"Конвейер рабочего потока" являются платформы

Pipelines53 •

Как и

TFX,

платформы

Airflow

и

KFP

Apache Airflow52

и

Kubeflow

рассматривают конвейеры как

ориентированный ациклический граф, в котором рабочий поток для каждого шага
определяется в скрипте

Python.

Затем они берут этот скрипт и предоставляют АРl­

интерфейсы для манипуляций с запуском по расписанию и оркестрированием гра­

фа в указанной инфраструктуре. И

Airflow,

и

KFP

имеют открытый исходный код и

поэтому могут работать локально либо в облаке.
Обычно

Apache Airflow

используется для инженерии данных, поэтому его следует

рассматривать для задач извлечения, преобразования и загрузки

ных данных. Однако, хотя

Google Kubernetes
eng1ne (GKE)

Airflow

(ETL)

корпоратив­

и обеспечивает надежный инструментарий для

Другие облака.
локально установленные
инструменты

Рис.

6.10. Взаимосвязь между платформами TFX, Kubeflow Pipelines, Kubeflow и инфраструктурой.
Платформа TFX работает на самом высоком уровне поверх платформы Kubeflow Pipeliпes,
с предварительно построенными компонентами, предлагающими те или иные подходы

к распространенным шагам рабочего потока . Платформа Kubeflow Pipeliпes предлагает API
для определения и организации конвейера ML, обеспечивая б6льшую гибкость в реализации каждого
шага. И TFX, и KFP работают на Kubeflow - платформе для выполнения контейнерно-ориентированных
рабочих нагрузок ML в Kubeгпetes. Все инструменты на этой диаграмме имеют открытый исходный код,
поэтому инфраструктура, в которой работают конвейеры , зависит от пользователя некоторые варианты включают GKE, Anthos, Azuгe, AWS либо локально установленную инфраструктуру

52

См . https://oгeil.ly/rQlqК..

53

См. https://oгeil.ly/e_7z.J.

Паттерны обеспечения воспроизводимости

337

1

выполнения текущих заданий, она была построена как общецелевое техническое

решение и не была рассчитана на рабочие нагрузки
стороны, была создана специально для

ML

ML.

обеспечивая большую гибкость в том, как определяются шаги конвейера. В то

TFX,

время как

TFX

реализует собственный подход к оркестровке, КFР позволяет нам

выбирать способ оркестровки конвейеров через свой

KFP

Платформа КFР, с другой

и работает на более низком уровне, чем

и

Kubeflow

представлена на рис.

API.

Взаимосвязь между

TFX,

6.1 О.

Конвейер разработки и промышленный конвейер
Принцип вызова конвейера часто меняется по мере перехода от разработки к про­
мышленному использованию. Скорее всего, мы захотим строить и прототипировать

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

расписанию и облегчим другим сотрудникам нашей организации вызов конвейера
воспроизводимым способом. Одним из инструментов для создания таких конвейе­

ров является Ка\е 54 , который берет код блокнота
в скрипт, используя

API

платформы

Jupyter
Kubeflow Pipelines.

и конвертирует его

Промышленный конвейер также допускает оркестровку рабочего потока процессов

ML.

Под оркестровкой мы подразумеваем добавление в конвейер логики, которая

определяет типы исполняемых шагов и результатов этих шагов. Например, мы

могли бы принять решение развертывать только те модели, которые имеют точ­
ность

95%

или выше. Когда свежие данные запустят конвейер на исполнение и

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

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

Airflow

и

Kubeflow Pipelines предоставляют API

для оркестровки конвейеров.

Отслеживание линии преемственности в конвейерах

ML

Еще одной особенностью конвейеров является их использование для отслеживания
модельных метаданных и артефактов. Такое отслеживание называется отслежива­
нием линии преемственности

(lineage ).

Всякий раз при вызове конвейера генериру­

ется ряд артефактов. Они могут включать сводки о наборах данных, экспортиро­
ванные

модели,

результаты

модельного оценивания,

метаданные

о тех или иных

вызовах конвейера и многое другое. Отслеживание линии преемственности позво­
ляет нам визуализировать историю версий модели вместе с другими ассоциирован­

ным модельными артефактами. Например, в платформе

AI Platform Pipelines

мы

можем использовать панель мониторинга конвейеров, чтобы знакомиться с данны-

54

См. https://github.com/kubeflow-kale/kale.

Глава б

338

ми, разбитыми по схеме данных и по дате, на которых та или иная версия модели
была натренирована. На рис.

6.11

показана панель мониторинга проводника по ли­

нии преемственности для конвейера

TFX,

работающего на платформе

AI Platfonn.

Она позволяет нам отслеживать входные данные и выходные артефакты, ассоции­
рованные с той или иной моделью.

lnputA.rШact

Terget

Output Artifact

lr•мfonned_n:•m~"

Ы•••ln&

мra}a°CJ,pip...м

$W8)1Xl_p.pell'l8

/

Рис.

6.11.

Секция

Lineage Explorer в

панели мониторинга платформы

для конвейера



waiu•t.lon



pudtod_model
-•_tui_p~



AI Platfonn Pipelines

TFX

Одним из преимуществ отслеживания линии преемственности для управления

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

ML,

важным аспектом обеспечения

воспроизводимости

поскольку оно позволяет сравнивать метаданные и артефакты из

разных исполнений конвейера.

ПАТТЕРН

26.

Хранилище признаков

Паттерн "Хранилище признаков"

(Feature Store)

упрощает управление признаками

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

процессом создания признаков и разработкой моделей, в которых эти признаки
используются.

Постановка задачи
Хорошая инженерия признаков имеет решающее значение для успеха многих тех­

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

Паттерны обеспечения воспроизводимости

некоторых признаков требуются значительные знания предметной области

339

-

из­

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

комендуется, чтобы эти признаки находились под контролем экспертов предметной

области, а не инженеров

ML.

Некоторые входные поля вполне могут допускать

разные варианты представления данных (см. главу

2),

делая их более удобными для

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

ML

или исследователь данных

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

ML

данные не берутся из одного источника. Од­

ни данные могут поступать со склада данных, другие могут находиться в корзине

хранилища в виде неструктурированных данных, а третьи же могут собираться
в реальном времени посредством потоковой передачи. Структура данных также

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

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

Нерегламентированный подход, при котором признаки создаются в проектах

ML

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

+

Нерегламентированные признаки нелегкоиспользовать многократно. Признаки
создаются снова и снова, отдельными пользователями или внутри коллективов,

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

процессов, таких как

предварительно

натрениро­

ванные векторные вложения пользователей или позиций каталога. В других слу­

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

тации рынка. Еще один источник сложности кроется в том, что признаки более
высокого уровня, такие как число заказов клиента за последний месяц, преду­
сматривают агрегирование во времени. Усилия и время тратятся впустую, соз­
давая одни и те же признаки с нуля для каждого нового проекта.

+

Руководство данными усложняется, если каждый МL-проект вычисляет призна­
ки из чувствительных данных по-разному.

+

Нерегламентированные признаки непросто использовать совместно в разных
командах или проектах. Во многих организациях одни и те же сырые данные
используются несколькими командами, но команды могут определять признаки

по-своему, при этом нелегко получить доступ к документации признаков. Всё

340

Глава

6

это также препятствует эффективному взаимному сотрудничеству, приводит
к разрозненной работе и ненужному дублированию усилий.

+

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

ме. Однако обработка запросов моделью, как правило, осуществляется в онлай­
новом режиме. Если признаковый конвейер для модельной тренировки вообще

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

+ Производство

признаков затруднено. При переходе к промышленному исполь­

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

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

разработку модели и приводит к дублированию усилий и неэффективности рабоче­
го потока. Более того, процессы создания признаков несовместимы между трени­
ровкой и предсказательным выводом, что приводит к риску асимметрии между

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

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

данных выступает в качестве интерфейса между конвейерами создания признаков

(компетенция инженера данных) и рабочих потоков разработки моделей с исполь­
зованием этих признаков (компетенция исследователя данных) (рис.

6.12).

При та­

ком подходе существует центральное хранилище для размещения предварительно

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

знакам базовые принципы инженерии программного обеспечения

-

управление

версиями, документирование и контроль доступа.

Типичное хранилище признаков строится с двумя ключевыми характеристиками их

дизайна: инструментарием для быстрой обработки крупных наборов признаковых
данных и методикой хранения признаков, которая поддерживает как доступ с низ­

кой задержкой (для предсказательного вывода), так и крупнопакетный доступ (для

Паттерны обеспечения воспроизводимости

341

тренировки модели). Существует также слой метаданных, который упрощает доку­

ментирование и управление версиями разных наборов признаков, а также

API,

ко­

торый управляет загрузкой и извлечением признаковых данных.
Сырые данные

Офnlйновь• модепм

Хранилище признаков

(тренировка)
Набор nризнаков А

Набор nризнаков В

Набор nризнаков С

Набор nризнаков О

Набор nризнаков Е

Рис.

6.12.

Хранилище признаков обеспечивает мост между источниками сырых данных

и модельной тренировкой и обслуживанием запросов

Типичный рабочий поток исследователя данных или инженера

ML

состоит в чте­

нии сырых данных (структурированных или потоковых) из источника данных,

применении различных преобразований на данных посредством любимого фрейм­
ворка и сохранении преобразованного признака внутри хранилища признаков.

Вместо того чтобы создавать признаковые конвейеры для подцержания одной­
единственной модели МL, паттерн "Хранилище признаков", наоборот, устраняет

сцепленность между генерированием признаков и разработкой модели. В частно­
сти, такие инструменты, как

Apache Beam, Flink

или

Spark,

часто используются при

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

метрии между тренировкой и обработкой, т. к. признаковые данные заполняются
одинаковыми конвейерами создания признаков.

После создания признаки помещаются в хранилище данных, откуда они извлека­

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

торая поддерживает какое-либо онлайновое приложение, возможно, должна будет
выдавать

предсказания

в

режиме

реального

времени

в

пределах

миллисекунд,

а

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

тренировки крупными пакетами. Хранилище признаков обращается к обоим этим
вариантам, используя разные хранилища данных для доступа к онлайновым и
офлайновым

признакам.

Например, хранилище признаков может использовать

Cassandra или Redis как хранилища данных для онлайнового извлечения
а Hive или BigQuery-для доставки исторических наборов признаков.

признаков,

342

Глава б

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

ния наборов признаков и обеспечения реестра с целью легкого обнаружения при­
знаков и перекрестного сотрудничества между коллективами.

Хранилище

Feast

В качестве примера этого паттерна в действии рассмотрим хранилище данных

с открытым исходным кодом для машинного обучения под названием

Feast55 , раз­
Google Cloud и Gojek56 • Оно построено вокруг облачных служб Google
Cloud57, использующих BigQuery для офлайновой тренировки моделей и Redis для
обработки запросов с низкой задержкой (рис. 6.13). Набор инструментальных
средств Apache Beam применяется для создания признаков, что позволяет создавать
работанное в

согласованные конвейеры данных как для пакетной, так и для потоковой передачи.

Источник

Задание

Источник

no

nриемке данных

Источник

Задание

no

nриемке данных

"""""""""""""""""""""""""""""" "

" " " " " " " "" " " " " . " " " " " " " " " " "" " " " " "

Историческое
хранилище

Обработка заnросов

хранилищем

Feast (онлайново)

Feast (исторически)

Реально-временные nризнаки

Модельное
обслуживание
заnросов

Рис.

6.13.

См. https://github.com/feast-dev.

56

См. https://oreil.ly/Pszln.

57

См . https://oreil.ly/ecJou.

Исторические nризнаки

Модельная
трениров ка

Высокоуровневая архитектура хранилища признаков

Она строится вокруг

55

Обработка заnросов

хранилищем

Google BigQuery, Redis

и

Feast.
Apache Beam

Паттерны обеспечения воспроизводимости

343

В целях ознакомления с тем, как это хранилище работает на практике, мы восполь­

зуемся публичным набором данных

BigQuery,

содержащим информацию о поезд­

ках в нью-йоркском такси 58 • Каждая строка таблицы содержит метку времени по­
садки, широту и долготу места посадки, широту и долготу места высадки, число

пассажиров и стоимость проезда в такси. Целью МL-модели будет предсказание
стоимости проезда в такси, обозначаемой fare _arnount, с использованием этих ха­
рактеристик.

Указанная модель пользуется преимуществом генерирования дополнительных при­
знаков из сырых данных. Например, поскольку поездки в такси основаны на рас­
стоянии

и продолжительности

поездки,

предварительно

вычисленное расстояние

между местом посадки и высадки является полезным признаком. После того как

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

Feast.

Данные хранятся в

Feast,

используя специальный для наборов признаков класс Featuresets. Это класс содер­
жит схему данных и информацию об источнике данных независимо от того, откуда
она поступает: из кадра данных
лищу

Feast

pandas

или же из темы

Katka.

Он позволяет храни­

знать о том, из каких источников выбирать необходимые для признака

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

вместе, а наборы признаков обеспечивают эффективное хранение и логически ор­

ганизованную разбивку данных на пространства имен внутри этих хранилищ.
После регистрации нашего набора признаков хранилище

Apache Beam

Feast

запустит задание

для заполнения хранилища признаков данными из источника. Набор

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

модели и обрабатывать запросы на модельное предсказание с помощью одних и тех
же данных.

Feast

обеспечивает, чтобы данные из источников соответствовали ожи­

даемой схеме набора признаков.

Как показано на рис.

6.14,

приемка признаковых данных в хранилище

Feast состоит

из четырех шагов.

Эти четыре шага заключаются в следующем.

1.

Создать экземпляр FeatureSet. Набор признаков содержит сущности, признаки и
источник.

2.

Добавить сущности и признаки в экземпляр Featureset.

3.

Зарегистрировать экземпляр FeatureSet. В результате будет создан именованный
набор признаков внутри хранилища

Feast.

Набор признаков не содержит призна­

ковых данных.

4.

58

Загрузить признаковые данные в экземпляр FeatureSet.

Данные доступны в таблице BigQuery: Ьigquery-puЬlic-data.new__york_taxi_trips.tlc__yellow_trips_2016.

Глава

344

6

18
Хранилище признаков

г+

.infer_from_df()

taxi._ ri.des:
....___
· enti.t1.es
-features
-source (e.g. Kafka top1.c)

.applyO

.injestO

.addO

--------

: taxi._гi.des:
1 • enti.ti.es
- features
: -source (e . g

~---------

18

•lr

Хранилище признаков

---------,

taxi._гi.de s :

. ,,

1
1
1
1

1

_к~~k~ _t~~t~~ J

2

1

'

2010-0S-3111:29:48" 40.787403

-7J.9SS848 40.723042

uтс

2011-04-0614:30:00

40.645343

71776698 40.71489

40.650105

-73.785373 40.6J88S8

uтс

3

2010-04-2413:11:06
uтс

4

-1010-02-20 09:07:00 40.761365
UTC

- 7З.91S7ЗJ

40.740118

Рис. 6.14. Приемка признаковых данных в хранилище Feast состоит из четырех шагов:
создать набор признаков, добавить сущности и признаки, зарегистрировать экземпляр FeatuгeSet
и импортировать признаковые данные в FeatureSet

Блокнот с полным исходным кодом 59 этого примера можно найти в репозитории,
прилагаемом к этой книге.
Создание экземпляра Featureset. Мы подключаемся к развернутому хранилищу

Feast,
froш

#

настраивая клиента с помощью

f eas t

iшport

SDK

на языке

Python:

Client, FeatureSe t , Enti t y, Va lueType

Подключить ся к существук:щему развернутому хранvtлищу

Fea st

client = Clie nt (core url='localhost: 6565 ' )
Мы можем проверить подключение клиента, распечатав существующие наборы

признаков с помощью команды c lient. li s t _ fea t ure _ sets () . Если выполняется новое
развертывание, она вернет пустой список. В целях создания нового набора призна­
ков следует вызвать класс Featureset и указать имя набора признаков :

#

Создать набор признаков

taxi_fs = FeatureSet ("taxi_rides" )
Добавление сущностей и признаков в экземпляр Featureset. В контексте храни­
лища

Feast

класс Featu rese t s состоит из сущностей и признаков. Сущности исполь­

зуются в качестве ключей для поиска значений признаков и для соединения при­

знаков между разными наборами признаков при создании наборов данных для тре­

нировки модели или обработки запросов. Сущность служит идентификатором для
любой релевантной характеристики, которая у вас есть в наборе данных. Он пред-

59 См. https://github.com/GoogleCloudPlatform/ml-design-patterns/ЫoЬ/master/06_reproducibllity/
feature_store.ipynb.

Паттерны обеспечения воспроизводимости

345

ставляет собой объект, который можно моделировать и куда можно сохранять

информацию. В контексте службы найма автомобиля с водителем или доставки
релевантной сущностью может быть customer_id, order_id, driver_id или
restaurant_ id. В контексте модели оттока клиентов сущностью может быть
customer _ id или segment _ id. В нашем случае сущностью является taxi _ id, уникаль­

еды

ный идентификатор поставщика такси для каждой поездки.
На этом этапе созданный нами набор признаков под названием taxi_rides (поездки
в такси) не содержит никаких сущностей или признаков. Мы можем использовать

ядерного клиента

Feast,

чтобы указать их из кадра данных

жит сырые входные данные и сущности (табл.
Таблица

6.5.

Набор данных

taxi_ride,

pandas,

который содер­

6.5).

содержащий информацию о поездках

в нью-йоркском такси. Сущностью является

taxi id,

уникальный идетификатор

поставщика такси для каждой поездки

numpass

taxi_id

fare_amt

-73. 993106

2

о

15.3

40.645343 -73. 776698 40. 71489

-73.987242

2

о

45.0

2020-04-24
13: 11 : о 6 uтс

40.650105 - 73. 785373 40.638858

-73.9678

2

2

32.1

2020-02-20
09:07:00 UTC

40.762365 -73.925733 40. 740118 -73.986487

2

1

21.3

Строка

pickup_datetime

pickup_lat

1

2020-05-31
11:29:48 UTC

40.787403 -73.955848 40. 723042

2

2011-04-06
14:30:00 UTC

3

4

pickup_lon

dropoff_lat

dropoff_lon

Определение источников потоковых данных
при создании экземпляра

FeatureSet

При создании набора признаков пользователи могут определять источники потоко­
вых данных. После того как набор признаков будет зарегистрирован с источником,
хранилище

Feast

автоматически начнет заполнять свои хранилища данными из это­

го источника. Ниже приведен пример набора признаков с предоставленным пользо­

вателем источником, который извлекает потоковые данные из темы

feature set = FeatureSet(
name="stream_feature",
entities=[
Entity("taxi_id", ValueType.INT64)
]

'

features=[
Feature("traffic last_Smin", ValueType.INT64)
)

'

source=KafkaSource(
brokers="mybroker:9092",
topic="my_feature_topic"

Kafka:

Глава б

346

Здесь важна метка времени pickup_ datetime, т. к. она необходима для извлечения

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

тельного признака, такого как евклидово расстояние, следует загрузить набор дан­
ных в кадр данных

#

pandas

и вычислить этот признак:

Заrрузить кадр данных

taxi_df = pd.read_csv("taxi-train.csv")
#

Сконструировать признак,

евклидово расстояние

taxi_df['euclid_dist'] = taxi_df.apply(compute_dist, axis=l)
Мы можем добавлять сущности и признаки в набор признаков с помощью функции

. add ( ... ) . С другой стороны, метод . infer_ fields _ from_ df ( ... ) создаст сущности и
признаки для нашего экземпляра FeatureSet непосредственно из фрейма данных

pandas.
и

Мы просто указываем имя столбца, который представляет сущность. Схема

типы

данных

для

признаков

экземпляра

FeatureSet

позднее

вычисляются

из

фрейма данных:

pandas
taxi_fs.infer_fields_from_df(taxi_df,
entities=[Entity(name='taxi_id', dtype=ValueType.INT64)],
replace_existing_features=True)
#

Вычислить признаки из кадра данных

Регистрация экземпляра Featureset. После того как набор признаков будет соз­
дан,

мы

можем зарегистрировать его

в хранилище

Feast

с

помощью метода

cl ien t. appl у (taxi _ f s) . В целях подтверждения правильности регистрации набора
признаков или инспектирования содержимого еще одного набора признаков мы
можем извлечь его с помощью метода

. get_ feature _ set ( ... ) :

print (client .get_feature_set ( "taxi_rides"))
Приведенная выше инструкция возвращает объект
ных для набора признаков taxi _rides:

"spec": {
"name": "taxi _ rides",

"entities":
"name":

11

key",

"valueТype":

]

"INT64"

,

"features":
"name": "dropoff_lon",
"valueТype":

},

"DOUBLE"

JSON,

содержащий схему дан­

Паттерны обеспечения воспроизводимости

347

"name": "pickup_lon",
"valueТype":

"DOUBLE"

},

]

,

Внесение признаковых данных в экземпляр FeatureSet. Убедившись в правиль­
ности нашей схемы, мы можем направить признаковые данные кадра данных
в хранилище

Feast для

их приемки, используя метод

. ingest ( ... } .

Здесь мы укажем

экземпляр FeatureSet под названием taxi _ fs и кадр данных taxi _ df, из которого бу­
дут заполняться признаковые данные.

# Загрузить признаковые данные
client.ingest(taxi fs, taxi_df}

в

Feast

для этого конкретного набора признаков

На этом шаге приемки на экран выводится индикатор хода выполнения, показывая,
что мы внесли
ща

28 247

строк данных в набор признаков taxi_rides внутри хранили­

Feast:

100% ,• • • • 128247 /28247 [00: 02IC)

.,.,..,,(...,

egeney.eode..Fld8ral~

O

~,.c:odl_N8tion81Credit

о

Unюn ~(NCUA)

+

t~

·-·-

Colono

ь,1n•" ,.,. ~

е1

Рис.

7.13.

'.t>.ol

Редактор точек данных инструмента What-lf для двоичной классификационной модели .
Ось у- это результат предсказания модели для каждой точки данных
в диапазоне от О (отклонено) до

1

(одобрено)

32 На этом наборе данных можно было бы выnолн1пь еще м1ю1·0 других пр~дтренировочных оптимизаций.
Мы выбрали только одну ю них в качестве демонстрации того, что возможно.

Глава

400

7

Вкладка Performance & Fairness (Результативность и объективность) инструмента
What-lf позволяет оценивать объективность модели по разным срезам данных. Вы­
брав один из признаков модели для Slice Ьу (Нарезать по), мы можем сравнить
результаты работы модели для различных значений этого признака. На рис. 7.14
показано, что мы нарезали набор данных по признаку agency_ code _ HUD значению, указывающему на факт гарантирования заявки агентством
кредитов не под надзором

~

""'

--__

....."_,..""'
-----"~.... _"
,__ "_

HUD, 1 для

кредитов под надзором

булеву

HUD

(О для

HUD).

Custom thr~holds kx 2 va~s of agency_code_Depor~t of Нousrng and 1.kЬм ~ {HUD) 0

St3

-TIStмf ...110>

___.

."

,"

"

05

--"-~
PA-~OЬIJQ

6R

/

/

-12~

(З13J

u_n.

(3SJ 71 .7'.

(368)

(1tO}

/
l.Wyanopllmtlttlori•tr1t~
ktlкt•1IПICl!gylOM-ic:'8!fJ"'~llVeМolch,Ьasedon

ll\tмtQISlnltiohid.ta--~.-lly.ь..w,i~OI
c:Nl\orl!QCO.lnll10Wll-...,мrt11010·cuяom~

00

05

@) Cи"""\tlr»l1Q/dtQ
QS