Несколько дней назад я работал с критически важными данными клиентов, и моя модель машинного обучения работала, как и ожидалось, но окончательные результаты были действительно неверными. Я проверил баллы перекрестной проверки, чтобы увидеть, не является ли это случаем переобучения, я запустил свою модель на случайной выборке, чтобы убедиться, что распределение данных остается неизменным, я просмотрел все параметры оценки модели, проверил все корреляции функций, пошел через раунды настройки гиперпараметров, анализ ошибок; Я проверил все, что знал, но проблемы не нашел. Затем я обнаружил чудовищную ошибку, которая спокойно спит за маской функции-обертки.

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

Как оно возникло?

Почему я не поймал это раньше?

Что я мог сделать, чтобы этого избежать?

Каков был жизненный цикл ошибки?

Каков жизненный цикл ошибки?

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

Возвращаясь к своему мыслительному процессу, я разделил анализ на две части:

  1. Каковы потенциальные источники появления ошибок? Особенно в проекте машинного обучения.
  2. Как избежать ошибок в проектах машинного обучения?

Возможные источники появления ошибок в проектах машинного обучения

  • Унаследованная кодовая база: «Я не знаю, как воспроизвести нашу текущую модель, человека, который работал над ней, больше нет, но он работает, и я не хочу тыкать медведь ». Я слышал это много раз, и виноват, что повторял это много раз. Иногда у нас нет знаний предметной области, или мы упускаем важные детали во время передачи знаний, или мы не знаем предположений, сделанных в коде, или мы боимся вносить изменения. Такая кодовая база - питательная среда для ошибок. Возможно, вы не используете входные данные, как предполагалось, или просто не обрабатываете тестовые данные, что может незаметно испортить ваши результаты.
  • Отсутствие модульности. Большинство проектов машинного обучения представляют собой смесь экспериментального и производственного кода. Поэкспериментировав, мы получим запутанные записные книжки Jupyter / Colab. Я люблю блокнот Jupyter, но он может превратить жизнь в ад, если будет слишком длинным. Ноутбук, который работает нормально, может ужасно выйти из строя при изменении порядка выполнения. Следовательно, код становится монолитом и подвержен ошибкам.
  • Пакеты. Благодаря множеству доступных пакетов машинного обучения цикл экспериментов стал очень быстрым. Но мы должны делать предположения относительно API, управления версиями и совместимости, лицензионных соглашений и т. Д. Эти предположения могут быть очень опасными, потому что это может незаметно нарушить работу вашего кода, например, просто при обновлении пакета.
  • Недетерминированные результаты: при создании любой модели машинного обучения мы имеем дело с двумя аспектами: детерминированными системами с интенсивным пользовательским интерфейсом, в которых мы знаем, как должны выглядеть наши обучающие данные, как должны кодироваться метки, как сохранить нашу модель, каким должен быть формат данных прогноза и т. д. Это те места, где мы можем избежать ошибок, написав более жесткий тест. Проблема возникает, когда ошибка вводится в недетерминированной части модели машинного обучения, интенсивно использующей алгоритм, например, некоторая проблема модели в настройке иерархического классификатора, когда у вас есть несколько моделей, где одна модель работает нормально, а другая модель не дает желаемых результатов на определенных данных. Такие ошибки, зависящие от данных и моделей, очень сложно отловить.
  • Отсутствие определений типов. Мы склонны пропускать написание определений типов при создании прототипа, и, как всегда, этот прототип превращается в нечто реальное, но наш бестиповый код постепенно внедряется в производство. Это приводит к исключениям nullpointer, плохой обработке крайних случаев, ошибкам сериализации и десериализации, и это лишь некоторые из них.

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

  • Организуйте свой код. Как бы вы ни торопились, всегда упорядочивайте свой код. Напишите более мелкие многоразовые вспомогательные функции с соответствующей документацией. Если ваш сценарий содержит более 100 строк, подумайте о том, чтобы разбить его на несколько сценариев. Подумайте о создании общего места для хранения всех ваших служебных программ и кода предварительной обработки. Всегда старайтесь добавлять проверки к старым кодам и перенесенным примерам.
  • Тестовые среды для выполнения как системного тестирования, связанного с интерфейсом, так и тестирования, зависящего от данных. Это действительно важный шаг для написания эффективных модулей машинного обучения. Модульное тестирование / Nosetests могут помочь с системными тестами, связанными с интерфейсом, а использование простой выборки данных для проверки качества модели может помочь выявить системы, интенсивно использующие алгоритмы. Подумайте о написании тестового примера, который будет применим для различного масштаба данных и обработки крайних случаев вашего сложного модуля.
  • Посмертный анализ ошибок: Посмертный анализ / ретроспектива ошибок не только полезны для понимания характеристик уже существующих ошибок, но и дают возможность изучить более сложные шаблоны кодирования. Он может предоставить информацию для руководства проектированием средств обнаружения ошибок, сортировки отчетов об ошибках, определения вероятного местоположения ошибок, предложения возможных исправлений, измерения затрат на тестирование и отладку, измерения качества программного обеспечения, а также помогает контролировать процессы разработки и управлять ими.
  • Подробно изучите пакеты, используемые в вашем модуле: очень важно знать подробную информацию об используемых пакетах. Сосредоточьтесь на библиотеках, которые вы используете, их нюансах, совместимости кода, ограничениях пакетов, управлении версиями и т. Д. Потратьте некоторое время на создание собственной мини-библиотеки утилит ML. Иногда бывает удобно написать собственные средства доступа и библиотеку примеров, которые могут использовать примитивные структуры данных, что обеспечивает большую прозрачность кода.
  • Пишите лучше журналы и документы: я не могу особо выделить этот момент. Журнал исследований со всеми подробностями экспериментов с журналами и документацией не только помогает в ретроспективе, но и структурирует вашу базу кода. Управлять модулем машинного обучения само по себе достаточно сложно, но отсутствие слоя описания делает его еще более запутанным. Ведение всех записей экспериментов может помочь понять общий характер ваших данных, может дать отправные точки для будущих экспериментов, помочь в формулировании соответствующей гипотезы и стратегии отладки.
  • Увеличьте прозрачность вашей модели: Я твердо верю в технику обучения Фейнмана. Если мы не можем объяснить какую-либо концепцию простыми словами, то, вероятно, мы сами не поняли эту концепцию должным образом. Попробуйте проверить больше гипотез вашей модели. Задокументируйте ваше обоснование сделанных предположений. Напишите лучший пример ожидаемых данных и последующих результатов. Уделите время лучшим визуализациям. Такие инструменты, как Matplotlib, Seaborn, Highcharts, qgrid могут помочь в этом процессе.
  • Приложите немного усилий к использованию инструментов управления экспериментами с машинным обучением, таких как SageMaker: здесь есть отличная статья, описывающая полный цикл эксперимента с машинным обучением и его управление.

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

Ниже я прикрепил несколько замечательных статей по этой теме.

Несколько хороших ссылок для чтения: