[Python, Программирование, Визуализация данных, Машинное обучение] CatBoost и ML-конкурсы

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
15-Май-2021 16:33

Анализ данных и базовая модельВступлениеЭта статья основана на данных конкурса, который компания Driven Data опубликовала для решения проблем с источниками воды в Танзании. Информация для конкурса была получена Министерством водных ресурсов Танзании с использованием платформы с открытым исходным кодом под названием Taarifa. Танзания — самая большая страна в Восточной Африке с населением около 60 миллионов человек. Половина населения не имеет доступа к чистой воде, а 2/3 населения страдает от плохой санитарии. В бедных домах семьям часто приходится тратить несколько часов пешком, чтобы набрать воду из водяных насосов. Для решения проблемы с пресной воды Танзании предоставляются миллиарды долларов иностранной помощи. Однако правительство Танзании не может разрешить эту проблему по сей день. Значительная часть водяных насосов полностью вышла из строя или практически не работает, а остальные требуют капитального ремонта. Министерство водных ресурсов Танзании согласилось с Taarifa, и они запустили конкурс в надежде получить подсказки от сообщества для выполнения стоящих перед ними задач.ДанныеВ данных много характеристик(фичей), связанных с водяными насосами, имеется информация относящаяся к географическим местоположениям точек с водой, организациям, которые их построили и управляют ими, а также некоторые данные о регионах, территориях местного самоуправления. Также есть информация о типах и количестве платежей. Пункты водоснабжения разделены на исправные, нефункциональные и исправные, но нуждающиеся в ремонте. Цель конкурса — построить модель, прогнозирующую функциональность точек водоснабжения.
Данные содержат 59400 строк и 40 столбцов. Целевая метка содержится в отдельном файле.
Показатель, используемый для этого соревнования, — это classification rate, который вычисляет процент строк, в которых прогнозируемый класс совпадает с фактическим классом в тестовом наборе. Максимальное значение равно 1, а минимальное — 0. Цель состоит в том, чтобы максимизировать classification rate.Анализ данныхОписания полей в таблице с данными:
  • amount_tsh — общий статический напор (количество воды, доступное для точки водоснабжения)
  • date_recorded — дата сбора данных
  • funder — кто спонсировал постройку колодца
  • gps_height — высота на которой находится колодец
  • installer — организация построившая колодец
  • longitude — GPS координаты (долгота)
  • latitude — GPS координаты (широта)
  • 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.6703822994494413
classification rate: 0.8198316498316498
Попробуем загрузить результаты на сайт с конкурсом и посмотрим на результат.
Учитывая, что на момент написания этой статьи результат топ-5 был только на 0,005 лучше, мы можем сказать, что базовая модель получилась хорошей.
Проверим, что работы по анализу и очистке данных делались не зря —  построим модель исключительно на основе исходных данных. Единственное, что мы сделаем, это заполним пропущенные значения нулями.
balanced accuracy: 0.6549535670689709
classification rate: 0.8108249158249158

Результат заметно хуже.ИтогиВ статье:
  • познакомились с данными и поискали идеи для модели;
  • очистили и подготовили данные для модели;
  • приняли решение использовать CatBoost, так как основная масса фичей категориальные;
  • написали функцию для OOF-предсказания;
  • получили отличный результат для базовой модели.
Правильный подход к подготовке данных и выбору правильных инструментов для создания модели может дать отличные результаты даже без дополнительной фиче-генерации.В качестве домашнего задания я предлагаю добавить новые фичи, выбрать оптимальные параметры модели, использовать другие библиотеки для повышения градиента и построить ансамбли из полученных моделей.Код из статьи можно посмотреть здесь.
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_python, #_programmirovanie (Программирование), #_vizualizatsija_dannyh (Визуализация данных), #_mashinnoe_obuchenie (Машинное обучение), #_mashinnoe+obuchenie (машинное+обучение), #_catboost, #_python, #_eda, #_analysis, #_ml, #_sorevnovanie (соревнование), #_kaggle, #_klassifikatsija (классификация), #_python, #_programmirovanie (
Программирование
)
, #_vizualizatsija_dannyh (
Визуализация данных
)
, #_mashinnoe_obuchenie (
Машинное обучение
)
Профиль  ЛС 
Показать сообщения:     

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

Текущее время: 22-Ноя 08:16
Часовой пояс: UTC + 5