Всегда знайте, чего ожидать от ваших данных

Эта статья была впервые опубликована в Блоге Neptune AI.

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

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

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

Что такое трубопроводный долг?

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

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

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

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

Фотографии выше уже должны были насторожить — они показывают накопление задолженности по трубопроводу.

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

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

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

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

  • Во-первых, хотя у вас есть полный контроль над своим кодом и вы можете изменить его, когда он не работает, вы не всегда можете изменить свои данные; во многих случаях вы просто наблюдатель, наблюдающий за поступающими данными, генерируемыми каким-то реальным процессом.
  • Во-вторых, программный код всегда бывает правильным или неправильным: либо он делает то, для чего предназначен, либо нет. Данные никогда не бывают правильными или неправильными. Он может быть только подходящим или не подходящим для определенной цели. Вот почему автоматизированное тестирование требует особого подхода, когда речь идет о данных.

Автоматизированное тестирование: надежды на помощь

Автоматизированное тестирование, адаптированное для конвейеров данных, является предпосылкой Great Expectations, широко используемого пакета Python с открытым исходным кодом для проверки данных.

Разработанная компанией Superconductive и впервые опубликованная в 2018 году книга «Большие надежды» имеет слоган «Всегда знай, чего ожидать от своих данных», и это именно то, что она предлагает.

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

Например, чтобы утверждать, что значения столбца «num_complaints» в некоторой таблице находятся в диапазоне от одного до пяти, вы можете написать:

expect_column_values_to_be_between(
    column="num_complaints",
    min_value=1,
    max_value=5,
)

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

Ожидание можно рассматривать как модульный тест для данных.

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

expect_column_values_to_be_between(
    column="num_complaints",
    min_value=1,
    max_value=5,
    mostly=0.95,
)

Приведенный выше оператор вернет успех, если по крайней мере 95% значений «num_complaints» находятся в диапазоне от одного до пяти.

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

expect_column_values_to_be_between(
    column="num_complaints",
    min_value=1,
    max_value=5,
    mostly=0.95,
    meta={
        “created_by”: “Michal”,
        “craeted_on”: “28.03.2022”,
        “notes”: “number of client complaints; more than 5 is unusual and likely means something broke”,
    }
)

Эти примечания к метаданным также лягут в основу документации данных, которую «Большие надежды» могут просто сгенерировать из воздуха — но об этом позже!

Пакет содержит несколько десятков ожиданий, которые можно использовать «из коробки», все они имеют многословные, понятные человеку имена, такие как «expect_column_distinct_values_to_be_in_set», «expect_column_sum_to_be_between» или «expect_column_kl_divergence_to_be_less_than». Этот синтаксис позволяет четко указать, что ожидается от данных и почему.

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

Great Expectations работает со многими различными бэкендами. Вы можете оценить свои ожидания локально во фрейме данных Pandas так же легко, как в базе данных SQL (через SQLAlchemy) или в кластере Apache Spark.

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

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

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

Начало работы с большими надеждами

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

Постановка проблемы

Мы будем рассматривать набор данных Поездки на такси по городу Чикаго. Данные содержат информацию о каждой поездке такси, сообщаемую городским властям, такую ​​как время начала и окончания поездки, идентификатор такси, расстояние поездки, стоимость проезда, места посадки и высадки и многое другое. Исходные данные огромны (обновляются ежемесячно с 2013 года по настоящее время), поэтому для целей этой демонстрации мы ограничим их двумя днями: 27 февраля и 28 февраля 2022 года. Это составляет более 13 000 поездок.

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

Настройка больших ожиданий

Начнем с установки пакета. Для Great Expectations требуется Python 3, и вы можете установить его с помощью pip.

pip install great_expectations

Приведенная выше команда устанавливает не только сам пакет Python, но и сопутствующий CLI (интерфейс командной строки), который предлагает удобные утилиты, доступные из терминала. Теперь мы воспользуемся одним из них, командой init, для настройки проекта «Большие надежды».

great_expectations init

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

Введите Enter, чтобы продолжить, и в каталоге вашего проекта появится каталог с именем «great_expectations» со всем содержимым, как показано на снимке экрана выше.

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

Подключение данных

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

great_expectations datasource new

Это сгенерирует три подсказки. Во-первых, нас спрашивают, хотим ли мы подключиться к файловой системе или базе данных. Поскольку у нас есть данные о поездках на такси локально в виде CSV-файлов, мы выбираем первое. Второй вопрос касается механизма обработки, который мы хотели бы использовать: pandas или spark. Мы идем за пандами. Наконец, нас просят указать путь к нашим файлам данных, который нам нужно ввести.

Предоставление всех необходимых входных данных приводит к открытию Jupyter Notebook. Записная книжка под названием «datasource_new» содержит шаблонный код Python для настройки нашего источника данных. Настройки по умолчанию подходят для использования, поэтому нам не нужно ничего менять, может быть, кроме имени источника данных во второй ячейке кода. Я назвал свои поездки «путешествиями».

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

С настроенным пакетом и подключенными данными мы можем углубиться в ключевые функции Great Expectations!

Ключевые особенности «Больших надежд»

Great Expectations предлагает три очень полезных функции:

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

Давайте пройдемся по ним один за другим.

Автоматическое профилирование данных

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

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

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

great_expectations suite new

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

Затем GE спрашивает, какие данные нужно профилировать. Он обнаружил файлы CSV, доступные в нашем контексте данных. Как объяснялось ранее, для профилирования мы выбираем данные от 27 февраля.

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

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

Затем нам просто нужно запустить всю записную книжку, чтобы создать набор ожиданий. Наш набор ожиданий был сохранен внутри нашего контекста данных, в каталоге ожиданий, в виде файла JSON. Хотя мы могли просматривать этот довольно читаемый файл JSON, гораздо удобнее просматривать документы Data Docs, которые должны были открываться в браузере, когда мы запускали блокнот. Это подводит нас ко второй замечательной особенности книги «Большие надежды».

Документация данных

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

Документы данных содержат сводную статистику данных и ожидания, которые были созданы на их основе. Желтая кнопка на панели «Действие» с левой стороны помогает нам отредактировать ожидания, чтобы мы могли исправить те, которые могли быть сгенерированы неправильно, или добавить совершенно новые. Не стесняйтесь нажимать и исследовать эту страну чудес! Как только вы вернетесь, мы перейдем к проверке новых данных.

Проверка новых данных

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

Контрольная точка запускает набор ожиданий для пакета данных. Мы можем создать его экземпляр, передав ключевые слова «checkpoint new» в great_expectations, за которыми следует выбранное имя контрольной точки. Здесь я назвал свой «feb_28_checkpoint».

great_expectations checkpoint new feb_28_checkpoint

Откроется еще один блокнот конфигурации. Единственная важная для нас ячейка — это вторая ячейка кода, определяющая переменную «yaml_config». Там мы можем выбрать, какой набор данных должен быть проверен («data_asset_name») и по какому набору ожиданий его следует оценивать («expectation_suite_name»). На этот раз мы можем оставить все значения по умолчанию такими, какие они есть — GE пришла к выводу, что, поскольку у нас есть только два файла данных, и один из них использовался для профилирования, мы, вероятно, захотим проверить другой.

Чтобы запустить нашу контрольную точку, то есть оценить наши ожидания от новых данных, нам просто нужно раскомментировать последние две строки кода в последней части блокнота «Выполнить контрольную точку» и запустить ее. Это снова открывает Data Docs, на этот раз показывая нам результаты проверки.

Что касается наших данных о поездках на такси, многие ожидания не оправдались. Некоторые из этих сбоев можно было ожидать: например, на основе данных за 27 февраля мы создали ожидание о том, что медиана тарифа должна быть больше или равна 21, а для данных на 28 февраля медиана тарифа равна 15. Неудивительно, что средняя стоимость проезда различается в разные дни.

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

Работа с ожиданиями вручную

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

Как упоминалось ранее, набор ожиданий — это просто файл JSON, содержащий ожидания в формате, который мы видели в начале этой статьи, например:

{
      "expectation_type": "expect_column_values_to_not_be_null",
      "kwargs": {
        "column": "Trip Seconds",
        "mostly": 0.99
      },
      "meta": {}
    },

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

Варианты использования для больших ожиданий

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

  • Мы используем автоматизированный профилировщик данных для создания пакета ожиданий на основе наших существующих данных.
  • Мы тщательно анализируем ожидания, исправляя и добавляя больше по мере необходимости (на самом деле мы не делали этого в этом руководстве, так как это очень специфичный для данных и предметной области процесс, но на практике это важный шаг!). На этом этапе мы можем обнаружить некоторые интересные или опасные свойства в наших данных. Это подходящее время, чтобы прояснить их.
  • Мы запускаем каждый новый входящий пакет данных в соответствии с нашим набором ожиданий и пропускаем его дальше в наши конвейеры данных только в том случае, если он проходит проверку. Если это не удается, мы пытаемся понять, почему и являются ли искаженными новые данные, или, возможно, наши ожидания не оправдали какой-то крайний случай.

Теперь, когда мы знаем, как работать с «Большими ожиданиями» для проверки данных, давайте обсудим пару конкретных случаев использования, в которых время, потраченное на GE, окупается с лихвой.

Обнаружение дрейфа данных

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

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

Входит проверка данных.

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

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

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

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

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

Предотвращение выхода из строя трубопроводов

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

Если это приводит к сбою кода, это не обязательно плохо. Но часто этого не происходит: работа завершается успешно, сообщая нижестоящим системам о том, что в предыдущий день на ваш сайт было 0 посещений. Эти точки данных затем отображаются на информационных панелях KPI или, что еще хуже, передаются в модели, которые автоматически переобучаются. Как предотвратить такой сценарий?

С ожиданиями, конечно. Просто ожидайте, что последние данные — например, с достаточно свежей отметкой времени — будут там.

Обнаружение вредных предубеждений

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

Хотя они ни в коем случае не дают окончательного ответа, «Большие надежды» могут, по крайней мере, помочь нам обнаружить опасные предубеждения. Справедливость в машинном обучении — обширная и сложная тема, поэтому давайте сосредоточимся на двух небольших частях общей картины: обучающих данных, которые поступают в модель, и прогнозах, полученных ею для различных тестовых входных данных.

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

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

Улучшение командной коммуникации и понимания данных

И последнее, но не менее важное: позвольте мне привести пример очень творческого использования Больших надежд, о котором я слышал от Джеймса Кэмпбелла, одного из авторов пакета, у него брали интервью в подкасте Data Engineering.

А именно, вы можете начать с создания пустого набора ожиданий, то есть: перечислить все столбцы, но пока не налагать никаких проверок на их значения. Затем соберите вместе людей, вовлеченных в данные или бизнес-процессы, и спросите их: какова максимальная месячная скорость оттока, которая вызывает беспокойство? Насколько низко должна упасть липкость веб-сайта, чтобы сработало оповещение? Такие разговоры могут улучшить связь между командами, связанную с данными, и понимание самих данных в компании.

Дополнительные ресурсы

Чтобы узнать больше о пакете Great Expectations, в том числе о том, как его использовать с Apache Spark или реляционными базами данных, или о том, как писать собственные ожидания, ознакомьтесь с официальной документацией пакета. Написано действительно хорошо и приятно читать. Вам также может быть интересно послушать уже упомянутое интервью с одним из авторов GE, а если вы ищете более короткий ресурс, ознакомьтесь с этой презентацией руководителя отдела продуктов компании Superconductive, стоящей за Большими надеждами. Наконец, я желаю вам всегда знать, чего ожидать от ваших данных!

Спасибо за прочтение!

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

Хотите всегда держать руку на пульсе стремительно развивающейся области машинного обучения и искусственного интеллекта? Ознакомьтесь с моим новым информационным бюллетенем AI Pulse. Нужна консультация? Вы можете спросить меня о чем угодно или заказать 1:1 здесь.

Вы также можете попробовать одну из других моих статей. Не можете выбрать? Выберите один из них: