Введение в "Большие надежды"

Что такое большие надежды?

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

Цитата из команды Большие надежды:

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

Мы должны использовать «Большие надежды», потому что мы можем:

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

Ускорьте ETL и нормализацию данных.

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

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

Упростите отладочные конвейеры данных, если (когда) они сломаются.

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

В Spike мы используем Большие надежды, потому что:

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

Применение больших ожиданий к набору данных.

Получить данные

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

Набор данных выглядит так:

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

import pandas as pd
from sklearn.model_selection import train_test_split
data = pd.read_csv("../data/insurance.csv")
train, test = train_test_split(data, test_size=0.3, random_state=0)

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

Мы собираемся сохранить данные о поездах и тестах в файлы csv.

train.to_csv("../data/train.csv", index=False)
test.to_csv("../data/test.csv", index=False)

Формирование ожиданий с помощью GE

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

  1. Проверка наличия некоторых столбцов.
  2. Проверка типа данных каждого столбца.
  3. Проверьте правильность формата даты и времени (например, %Y-%m-%d).

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

Вы можете установить great_expectations, используя:

pip install great_expectations

Теперь импортируйте great_expectations и загрузите данные:

import great_expectations as ge
data = ge.read_csv("../data/train.csv")

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

data.expect_column_values_to_be_in_set("sex",['female','male'])
data.expect_column_values_to_be_in_set("region",['northeast', 'southwest', 'southeast', 'northwest'])
data.expect_column_values_to_be_in_set("smoker",['no','yes'])

Использование expect_column_values_to_be_in_set позволяет проверить, содержит ли этот столбец только указанные значения. Например, если мы загружаем новые данные и столбец sexсодержит что-то отличное от femaleили male, наш тест завершится неудачно.

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

data.expect_column_values_to_be_of_type("age","int")
data.expect_column_values_to_be_of_type("sex","string")
...
data.expect_column_values_to_be_of_type("charges","float")

Еще одно основное ожидание - проверка существования некоторых столбцов:

data.expect_column_to_exist("age")
data.expect_column_to_exist("sex")
...
data.expect_column_to_exist("charges")

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

age_partition = ge.dataset.util.continuous_partition_data(data['age'],)
data.expect_column_bootstrapped_ks_test_p_value_to_be_greater_than('age', age_partition)
charges_partition = ge.dataset.util.continuous_partition_data(data['charges'])
data.expect_column_bootstrapped_ks_test_p_value_to_be_greater_than('charges', charges_partition)

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

data.save_expectations_config("expectations.json")

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

WARNING: get_expectations_config discarded
0 failing expectations
17 result_format kwargs
0 include_configs kwargs
0 catch_exceptions kwargs

Примените ожидания к новым данным

Выполнить ожидания для новых данных довольно просто, нам нужно только загрузить данные и выходной jsonfile из предыдущего шага, а затем запустить тест:

test = ge.read_csv("../data/test.csv")
import json
with open("expectations.json") as file:
    saved_expectations = json.load(file)
test.validate(expectations_config=saved_expectations, result_format='BOOLEAN_ONLY')

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

{'results': [{'success': True,
'exception_info': {'raised_exception': False,
'exception_message': None,
'exception_traceback': None},
'expectation_config': {'expectation_type': 'expect_column_values_to_be_in_set',
'kwargs': {'column': 'sex',
'value_set': ['female', 'male'],
'result_format': 'BOOLEAN_ONLY'}}},
{'success': True,
'exception_info': {'raised_exception': False,
'exception_message': None,
'exception_traceback': None},
'expectation_config': {'expectation_type': 'expect_column_values_to_be_in_set',
'kwargs': {'column': 'region',
'value_set': ['northeast', 'southwest', 'southeast', 'northwest'],
'result_format': 'BOOLEAN_ONLY'}}},
... A lot of stuff here...
'success': True,
'statistics': {'evaluated_expectations': 17,
'successful_expectations': 17,
'unsuccessful_expectations': 0,
'success_percent': 100.0}}

Если все в порядке, то success_percent должно быть 100.0.

Что произойдет, если изменится распределение данных?

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

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

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

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

fail_data = {
    "age":0,
    "sex":"other",
    "bmi":3,
    "children":0,
    "smoker":"other",
    "region":"other",
    "charges":0
}
test = test.append(pd.DataFrame([fail_data]),ignore_index=True, sort=True)
test.validate(expectations_config=saved_expectations, result_format='BOOLEAN_ONLY')

После применения нашего теста мы можем получить результаты:

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

Выводы

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