Русский
Русский
English
Статистика
Реклама

CatBoost и ML-конкурсы

Анализ данных и базоваямодель

Вступление

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

Информация для конкурса была получена Министерством водных ресурсов Танзании с использованием платформы с открытым исходным кодом под названием Taarifa. Танзаниясамая большая страна в Восточной Африке с населением около 60 миллионов человек. Половина населения не имеет доступа к чистой воде, а 2/3 населения страдает от плохой санитарии. В бедных домах семьям часто приходится тратить несколько часов пешком, чтобы набрать воду из водяных насосов.

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

Данные

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

Пункты водоснабжения разделены на исправные, нефункциональные и исправные, но нуждающиеся в ремонте. Цель конкурсапостроить модель, прогнозирующую функциональность точек водоснабжения.
Данные содержат 59400 строк и 40 столбцов. Целевая метка содержится в отдельном файле.
Показатель, используемый для этого соревнования,это classification rate, который вычисляет процент строк, в которых прогнозируемый класс совпадает с фактическим классом в тестовом наборе. Максимальное значение равно 1, а минимальное0. Цель состоит в том, чтобы максимизировать classification rate.

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

Описания полей в таблице с данными:

  • amount_tshобщий статический напор (количество воды, доступное для точки водоснабжения)

  • date_recordedдата сбора данных

  • funderкто спонсировал постройку колодца

  • gps_heightвысота на которой находится колодец

  • installerорганизация построившая колодец

  • longitudeGPS координаты (долгота)

  • latitudeGPS координаты (широта)

  • wpt_nameназвание, если оно есть

  • num_privateнет информации

  • basinгеографический водный бассейн

  • subvillageгеографическая локация

  • regionгеографическая локация

  • region_codeгеографическая локация (код)

  • district_code географическая локация (код)

  • lgaгеографическая локация

  • ward географическая локация

  • populationколичество населения около колодца

  • public_meetingда/нет

  • recorded_by кто собрал данные

  • scheme_managementкто управляет колодцем

  • scheme_nameкто управляет колодцем

  • permitтребуется ли разрешение на доступ

  • construction_yearгод постройки

  • extraction_typeтип колодца

  • extraction_type_groupгруппа типа колодца

  • extraction_type_classкласс типа колодца

  • managementкак управляется колодец

  • management_groupгруппа управления колодца

  • paymentстоимость воды

  • payment_typeтип стоимости воды

  • water_qualityкачество воды

  • quality_groupгруппа качества воды

  • quantityколичество воды

  • quantity_groupгруппа количества воды

  • sourceисточник воды

  • source_typeтип источника воды

  • source_classкласс источника воды

  • waterpoint_typeтип колодца

  • waterpoint_type_groupгруппа типа колодца

    Прежде всего, давайте посмотрим на целевую меткуклассы не имеют равномерного распределения:

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

    • уменьшать количество примеров у преобладающих классов(under-sampling)

    • дублировать строки с метками, которых мало(over-sampling)

    • генерировать синтетические выборкиэто случайная выборка атрибутов из экземпляров в классе меньшинства (SMOTE)

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

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

    Посмотрим, как водяные насосы распределяются по территории страны.

    Некоторые данные содержат пустые значения.

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

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

    Давайте посмотрим на общую картину взаимоотношений на дендрограмме.

    В характеристиках водяных насосов есть та, которая показывает количество воды. Мы можем проверить, как количество воды связано с состоянием насосов (quantity_group).

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

    Влияет ли качество воды на состояние водяных насосов? Мы можем посмотреть на данные, сгруппированные по quality_group.

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

    Большинство колодцев с неизвестным качеством из quality_group не работают.

    Есть еще одна интересная характеристика водных точеких тип (waterpoint_type_group).

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

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

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

    Danidaсовместная организация Танзании и Дании по финансированию скважин, и хотя у них много работающих водозаборов, процент неисправных очень высок. Похожая ситуация с RWSSP (программа сельского водоснабжения и канализации), Dhv и некоторыми другими. Следует отметить, что большинство скважин, профинансированных Германией и частными лицами, находятся в рабочем состоянии. Напротив, большое количество скважин, которые финансируются государством, не функционируют. Большинство пунктов водоснабжения, установленных центральным правительством и районным советом, также не работают.

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

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

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

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

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

    Часть данных была заполнена значением 0 вместо реальных данных. Мы также можем видеть, что amount_tsh выше у исправных колодцев (label = 0). Также следует обратить внимание на выбросы в функции amount_tsh. В качестве особенности можно отметить перепад высот и тот факт, что значительная часть населения проживает на высоте 500 метров над средним уровнем моря.

Подготовка данных

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

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

  • После очистки мы заменяем все элементы, которые встречаются менее 71 раз (0,95 квантиля), на other.

  • Повторяем по аналогии с фичей funder. Порог отсечки98.

  • Данные содержат фичи с очень похожими категориями. Выберем только по одной из них. Поскольку в датасете не так много данных, мы оставляем функцию с наименьшим набором категорий. Удаляем следующие фичи: scheme_management, quantity_group, water_quality, payment_type, extraction_type, waterpoint_type_group, region_code.

  • Заменим latitude и longitude значения у выбросов медианным значением для соответсвующего региона из region_code.

  • Аналогично повторям для пропущенных значений для subvillage и scheme_name.

  • Пропущенные значения в public_meeting и permit заменяем медианным значением.

  • Для subvillage, public_meeting, scheme_name, permit, создаем дополнительные категориальные бинарные фичи, которы будут отмечать данные с пропущенными значениями. Так как мы заменяем их на медианные, то для модели оставим информацию, что пропуски были.

  • Фичи scheme_management, quantity_group, water_quality, region_code, payment_type, extraction_type, waterpoint_type_group, date_recorded, и recorded_by можно удалить, так как там повторяются данные из других фичей, для модели они будут бесполезны.

Модель

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

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

def fit_model(train_pool, test_pool, **kwargs):    model = CatBoostClassifier(        max_ctr_complexity=5,        task_type='CPU',        iterations=10000,        eval_metric='AUC',        od_type='Iter',        od_wait=500,        **kwargs    )return model.fit(        train_pool,        eval_set=test_pool,        verbose=1000,        plot=False,        use_best_model=True)

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

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

def classification_rate(y, y_pred):    return np.sum(y==y_pred)/len(y)

Поскольку данных мало, разбивать полную выборку на обучающую и проверочную частине лучший вариант. В этом случае лучше использовать методику OOF (Out-of-Fold). Мы не будем использовать сторонние библиотеки; давайте попробуем написать простую функцию. Обратите внимание, что разбиение набора данных на фолды необходимо стратифицировать.

def get_oof(n_folds, x_train, y, x_test, cat_features, seeds):    ntrain = x_train.shape[0]    ntest = x_test.shape[0]              oof_train = np.zeros((len(seeds), ntrain, 3))    oof_test = np.zeros((ntest, 3))    oof_test_skf = np.empty((len(seeds), n_folds, ntest, 3))    test_pool = Pool(data=x_test, cat_features=cat_features)     models = {}    for iseed, seed in enumerate(seeds):        kf = StratifiedKFold(            n_splits=n_folds,            shuffle=True,            random_state=seed)                  for i, (train_index, test_index) in enumerate(kf.split(x_train, y)):            print(f'\nSeed {seed}, Fold {i}')            x_tr = x_train.iloc[train_index, :]            y_tr = y[train_index]            x_te = x_train.iloc[test_index, :]            y_te = y[test_index]            train_pool = Pool(data=x_tr, label=y_tr, cat_features=cat_features)            valid_pool = Pool(data=x_te, label=y_te, cat_features=cat_features)model = fit_model(                train_pool, valid_pool,                loss_function='MultiClass',                random_seed=seed            )            oof_train[iseed, test_index, :] = model.predict_proba(x_te)            oof_test_skf[iseed, i, :, :] = model.predict_proba(x_test)            models[(seed, i)] = modeloof_test[:, :] = oof_test_skf.mean(axis=1).mean(axis=0)    oof_train = oof_train.mean(axis=0)    return oof_train, oof_test, models

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

Кривая обучения одного изфолдовКривая обучения одного изфолдов

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

Посмотрев на важность фичей в модели, мы можем убедиться в отсутствии явной утечки информации (лика).

После усреднения прогнозов:

balanced accuracy: 0.6703822994494413classification rate: 0.8198316498316498

Попробуем загрузить результаты на сайт с конкурсом и посмотрим на результат.

Учитывая, что на момент написания этой статьи результат топ-5 был только на 0,005 лучше, мы можем сказать, что базовая модель получилась хорошей.

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

balanced accuracy: 0.6549535670689709classification rate: 0.8108249158249158

Результат заметно хуже.

Итоги

В статье:

  • познакомились с данными и поискали идеи для модели;

  • очистили и подготовили данные для модели;

  • приняли решение использовать CatBoost, так как основная масса фичей категориальные;

  • написали функцию для OOF-предсказания;

  • получили отличный результат для базовой модели.

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

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

Код из статьи можно посмотреть здесь.

Источник: habr.com
К списку статей
Опубликовано: 15.05.2021 14:20:40
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Python

Программирование

Визуализация данных

Машинное обучение

Машинное+обучение

Catboost

Eda

Analysis

Ml

Соревнование

Kaggle

Классификация

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru