Здесь единицей является отдельная картинка. Видео рассматривается как набор картинок.
Датасет рукописных цифр
Перед дата-сайентистами часто встает вопрос: где взять данные?
Студентам проще: у некоторых обширных библиотек вроде Scikit-learn встречаются собственные встроенные датасеты, прекрасно подходящие для обучения:
from sklearn.datasets import load_digits
digits = load_digits()
Помимо таких встроенных коллекций, данные предоставляют бесплатно еще и ресурсы вроде kaggle.com.
А вот на рабочей ниве требования к информации куда специфичнее. Порой проще и лучше собрать свой набор, и в таком случае мы обращаемся к инструментам ETL.
(extract, transform, load – извлечь, преобразовать и загрузить) группа процессов, происходящих при переносе данных из нескольких систем в одно хранилище.
Если у вас есть данные из нескольких источников, вам необходимо:
• Извлекать данные из исходного источника
• Преобразовывать информацию путем очистки, объединения и других способов подготовки
• Загружать результат в целевое хранилище
Как правило, один инструмент ETL выполняет все три шага. Пожалуй, самый популярный сегодня представитель такого программного обеспечения – это Hadoop.
ETL уходит своими корнями в 1970-е годы к появлению централизованных хранилищ данных. Но только в конце 1980-х и начале 1990-х годов, когда они заняли центральное место, мир ощутил потребность в специализированных загрузочных инструментах. Первым пользователям нужен был способ извлекать информацию из разрозненных систем, преобразовывать ее в целевой формат и загружать в конечное место хранения. Первые инструменты ETL были примитивными, и объем данных, которые они обрабатывали, был скромным по сегодняшним меркам.
По мере роста объема данных росли и хранилища данных, а программные инструменты ETL множились и становились все более сложными. Но до конца 20-го века хранение и преобразование данных осуществлялось в основном в локальных хранилищах. Однако произошло нечто, навсегда изменившее наш взгляд на хранение и обработку.
Объем данных, которые мы генерируем и собираем, продолжает расти с экспоненциальной скоростью. У нас есть все более сложные инструменты, которые позволяют нам использовать все наши данные для получения представления о исследуемом предмете в режиме онлайн.
Традиционная инфраструктура не может масштабироваться для хранения и обработки большого объема данных. Это неэффективно с точки зрения затрат. Если мы хотим выполнять высокоскоростную, сложную аналитику и строить подобные модели, облако – оптимальное решение.
Облачные хранилища могут бесконечно масштабироваться для размещения практически любого объема данных. Облачное хранилище также позволяет координировать огромные рабочие нагрузки между группами вычисляющих серверов.
Преобразования и моделирование данных часто выполняются с помощью SQL – языка запросов к базе данных.
Конечная точка ETL – хранилище данных (DWH).
(data warehouse – хранилище данных) предназначено исключительно для выполнения запросов и часто содержит большие объемы исторических данных. Данные в хранилище обычно поступают из широкого круга источников, таких как:
• Логи приложений
• Сведения, собираемые с форм на сайте
• Записи различных устройств, вроде видеокамер и датчиков температуры
Хранилище объединяет большие объемы данных из нескольких источников. Это позволяет генерировать ценные инсайты2 и улучшать процесс принятия решений. С ростом объема и качества DWH становится бесценным объектом для бизнес-аналитики. Типичное хранилище данных часто включает следующие элементы:
• Реляционная база данных
• ПО для ETL
• Инструменты анализа и визуализации
• Модели машинного обучения
К популярным хранилищам можно отнести Amazon Redshift, Google BigQuery и Greenplum.
Стоит отличать DWH от так называемого озера данных (data lake). Хранилище содержит очищенные и структурированные данные, готовые к анализу на основе предопределенных потребностей бизнеса. В озере же все содержится в необработанном, неструктурированном виде.
Когда команда ML получает доступ к такому хранилищу, то предваряет моделирование целой серией действий – разведочным анализом данных (EDA).
(exploratory data analysis – разведочный анализ данных) предварительное исследование датасета с целью определения его основных характеристик, взаимосвязей между признаками, а также сужения набора методов, используемых для создания модели.
Давайте рассмотрим, на какие этапы разбивают EDA. Для этого мы используем данные3 банка, который продает кредитные продукты своим клиентам. Возьмет ли клиент кредит или нет?
Мы располагаем обширным набором переменных (столбцов):
Это не сам датасет, а только описание столбцов
Столбец Y назван так неслучайно: это общепринятое обозначение целевой переменной (target variable). Изучив 40 тысяч записей о клиентах, модель автоматически сможет предсказывать, возьмет новый клиент кредит или не возьмет.
Довольно увесистый датасет: записей в нем более 40 тысяч. Для начала4 импортируем датасет и посмотрим на "шапку". С помощью метода head() мы отобразим шапку датафрейма и первые пять записей:
df = pd.read_csv('https://www.dropbox.com/s/62xm9ymoaunnfg6/bank-full.csv?dl=1', sep=';')
df.head()
Параметр sep используется, чтобы задать нестандартный разделитель данных по столбцам, в данном случае – точку с запятой.
Все столбцы мы отображать здесь, конечно, не будем
(duplicates removing) Повторяющиеся записи искажают статистические показатели. Всего несколько повторов – и среднее значение столбца сместится в их пользу. Дубликаты также снижают качество обучения модели. Для начала уточним, сколько у нас строк с помощью df.shape. Затем удалим повторы с помощью drop_duplicates() и обновим данные о размере данных:
print(df.shape)
df.drop_duplicates(inplace=True)
print(df.shape)
Библиотека pandas вообще сопровождает любителей и профессионалов на каждом шагу, так что у некоторых ее компонентов параметры одинаковые. Чтобы удалить повторы “на месте”, без излишнего перекопирования датафрейма, дополняем drop_duplicates() параметром inplace, равным True.
Ячейка выдает, что удалила 41188 – 41176 = 12 дубликатов:
(41188, 21)
(41176, 21)
Хоть число и небольшое, все же качество набора мы повысили.
(omission handling) Если пропусков у признака-столбца слишком много (более 70%), такой признак удаляют. Проверим, насколько разрежены наши признаки:
df.isnull().mean() * 100
Метод isnull() пройдется по каждой ячейке каждого столбца и определит, кто пуст, а кто нет. Метод mean() определит концентрацию пропусков в каждом столбце. На 100 мы умножаем, чтобы получить значение в процентах:
Возраст 0.000000
Работа 0.801438
Семейный статус 0.194288
Образование 4.201477
Кредитный дефолт 0.000000
Ипотека 0.000000
Займ 0.000000
Контакт 0.000000
Месяц 0.000000
День недели 0.000000
Длительность 0.000000
Кампания 0.000000
День 96.320672
Предыдущий контакт 0.000000
Доходность 0.000000
Колебание уровня безработицы 0.000000
Индекс потребительских цен 0.000000
Индекс потребительской уверенности 0.000000
Европейская межбанковская ставка 0.000000
Количество сотрудников в компании 0.000000
y 0.000000
Среди всех признаков слишком много пропусков оказалось у фактора “День” (более 96%). Он подлежит удалению с помощью drop():
df = df.drop(columns=['День'])
Разберемся для начала с категориальными переменными, объединив их в один вектор. Метод pandas.unique() выделит уникальные значения из всего перечня столбцов column_values. pandas принято сокращать псевдонимом до pd.
column_values = df[['Работа', 'Семейный статус', 'Образование', 'Контакт', 'Месяц', 'День недели', 'Доходность']].values.ravel()
unique_values = pd.unique(column_values)
print(unique_values)
Список получится совсем уж нелогичный, но это здесь не столь важно. Мы лишь ищем способы обозначения пропусков. Они обозначаются словом "Неизвестно":
['Самозанятый', 'Не женат / не замужем', 'Университетская степень', 'Городской телефон', 'Октябрь', 'Пятница', 'Отсутствует', 'Предприниматель', 'Женат / замужем', 'Голубой воротничок', 'Базовое (9 классов)', 'Менеджер',
'Высшая школа', 'Базовое (4 класса)', 'Техник', 'Профессиональный курс', 'Разведен(-а)', 'Неизвестно', 'Сотовый телефон', 'Август', 'Понедельник', 'Студент', 'Домохозяйка', 'Обслуживающий персонал', 'Базовое (6 классов)',
'Пенсионер', 'Четверг', 'Вторник', 'Не присутствует', 'Июль', 'Среда', 'Июнь',
'Неграмотный', 'Май', 'Ноябрь', 'Присутствует', 'Cамозанятый', 'Декабрь', 'Март', 'Апрель', 'Сентябрь']
Процесс обработки пропусков можно сократить с помощью sklearn.impute.SimpleImputer. Мы выбираем все категориальные переменные и применяем стратегию "вставить вместо пропуска самое распространенное значение":
imputer = SimpleImputer(missing_values = np.nan, strategy = 'most_frequent')
categorical_columns = ["Работа", "Семейный статус", "Образование", "Месяц", "День недели", "Доходность"]
df[categorical_columns] = imputer.fit_transform(df[categorical_columns].values)
Признаки, принадлежащие к булевому типу данных, обрабатываются алгоритмом тем же образом:
imputer = SimpleImputer(missing_values = np.nan, strategy = 'most_frequent')
boolean_columns = ["Кредитный дефолт", "Ипотека", "Займ"]
df[boolean_columns] = imputer.fit_transform(df[boolean_columns].values)
Целевую переменную y мы не обрабатываем (если в этом столбце есть пропуски, их стоит удалить).
Подобным образом заполняются пустоты в числовых переменных, только стратегия теперь – "вставить среднее значение":
imputer = SimpleImputer(missing_values = np.nan, strategy = 'mean')
numeric_columns = ["Возраст", "Длительность", "Кампания", 'Предыдущий контакт', "Колебание уровня безработицы", "Индекс потребительских цен", "Индекс потребительской уверенности", "Европейская межбанковская ставка", "Количество сотрудников в компании"]