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

Каждая строка данных, предоставленных корпорацией Майкрософт, соответствует уникальной машине, идентифицируемой ее MachineID в данных. Данные содержат 8 921 483 записи в обучающем наборе train.csv, и мы должны использовать эти данные, чтобы предсказать, найдем ли мы вредоносное ПО в 7 853 253 записях в тестовом наборе test.csv, представленном полем HasDetections в данных.

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

Извлечение соответствующих функций

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

Как только данные оказались в памяти, я уменьшил количество функций, представленных в данных, оставив только столбцы с менее чем 50% отсутствующих значений и столбцы, в которых наиболее распространенное значение встречается менее чем в 95% случаев. Этот процесс фильтрации сократил данные с 83 столбцов до 60 столбцов.

Очистка и обработка оставшихся функций

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

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

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

  1. Преобразование значений в нижний регистр.
  2. Объедините значения разных вариантов написания.
  3. Установите значения NA на «неизвестно».
  4. Объедините или установите необычные значения как «неизвестные».

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

Кодирование данных

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

Модели машинного обучения

Теперь, когда все функции очищены и закодированы как целые числа, модель, наконец, готова к работе с данными. Обучение моделей со всеми 17 миллионами строк данных и итерация различных типов моделей заняли бы слишком много времени, учитывая временные рамки проекта, поэтому я решил взять 5% случайную выборку данных и обучить на ней свои модели, сократив обучение должно быть установлено только на ~ 450 000 строк.

Из этих 450 000 строк я разделил их на 80% обучающих и 20% проверочных наборов, чтобы определить базовую производительность моделей. Честно говоря, я не тратил слишком много времени на повторение различных моделей, чтобы найти наилучшую производительность, так как у меня было мало времени для завершения проекта, но обе модели работают лучше, чем исходное предположение с точностью 50%.

Первой моделью, которую я выбрал для тестирования, был классификатор Random Forest. Точность проверки для этой модели составила 62,73%. Второй моделью, которую я выбрал, была логистическая регрессия, точность которой была несколько ниже — 60,11%. Поскольку случайный лес имел более высокую точность проверки, я использовал эту модель для прогнозирования всего набора тестов.

Используя только 5% доступных обучающих данных, я смог достичь точности теста 59,22% с гиперпараметрами по умолчанию. Пока этот результат далеко не лучший (лучшие игроки в этом испытании достигли точности теста не менее 69,8%). Для таких задач могут быть предпочтительны более сложные древовидные модели, такие как XGBoost, которые обеспечивают более высокую точность тестирования, но я буду изучать это при улучшении этой работы в будущем.

Пояснения к модели

Я выбрал две визуализации, чтобы помочь объяснить выбор случайного леса.

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

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

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

Вторая визуализация представляет собой график силы объяснения SHAP (SHapley Additive exPlanations) для первой записи в тестовом наборе.

Используя график силы объяснения SHAP, мы можем увидеть функции, которые больше всего повлияли на прогнозируемую моделью вероятность для каждой записи в данных. Здесь мы видим, что SmartScreen = 3 дает самый высокий положительный эффект, а AVProductsInstalled = 1 дает самый высокий отрицательный эффект на прогнозирование того, будет ли эта конкретная машина заражена вредоносным ПО или нет. Числовые и двоичные признаки легко считываются с этого графика, но закодированные категориальные данные необходимо восстановить из словаря кодирования, чтобы расшифровать, что представляет каждое значение.

Хотя эта модель далека от совершенства (а модели никогда не бывают таковыми), она все же помогает получить полезную информацию о том, как защитить миллиарды машин Microsoft от злоумышленников.

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