Экспериментирование является неотъемлемой частью любого сложного процесса; включен процесс построения моделей машинного обучения. Построение «успешной» модели машинного обучения означает оптимизацию на нескольких уровнях, эти уровни (не в порядке важности):

  1. тип модели,
  2. гиперпараметры модели,
  3. особенности данных и
  4. наборы данных, используемые для обучения и тестирования.

Причину этой оптимизации легко понять для первых двух:

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

Однако пайплайны оптимизации для первых двух пунктов также стали проще. У многих облачных провайдеров есть службы AutoML для сравнения и настройки моделей, например. AWS SageMaker AutoPilot и Google Vertex AI. Это освобождает специалистов по данным от ручных экспериментов, которые могут занимать много времени. Тем не менее, уровни оптимизации 3 и 4 могут быть довольно сложными.

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

Кроме того, крайне важно убедиться, что набор обучающих данных имеет адекватные выборки во всем «пространстве признаков», т. е. обучающие данные должны напоминать (насколько это возможно) данные, которые модель увидит «в дикой природе», во всех формах и формы. В противном случае мы можем получить неожиданные прогнозы, когда модель столкнется с данными за пределами своего периода обучения, что может иметь катастрофические последствия в зависимости от приложения. Это опять-таки то, что нельзя сделать автоматически (пока?), и используемый набор данных, скорее всего, со временем будет улучшаться итеративно.

Однако при проведении большого количества экспериментов может быть сложно отслеживать (какие данные использовались для какого запуска? где хранились артефакты эксперимента? как лучше всего собирать результаты экспериментов?). Вот где на помощь приходят такие инструменты, как Neptune.ai.

Что такое Neptune.ai?

Вкратце, Neptune.ai — это инструмент для:

Регистрируйте, систематизируйте, сравнивайте, регистрируйте и делитесь всеми метаданными вашей модели машинного обучения в одном месте.

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

Задание

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

Однако, как упоминалось ранее, каждая точка данных, составляющая сигналы, представляет собой «отдельную функцию», поэтому традиционные методы AutoML для проектирования и выбора функций могут быть не такими полезными. Вместо этого мы используем наши знания предметной области, чтобы выбирать из ряда производных функций:

  1. Амплитуда сигнала
  2. Энергия волны
  3. PCA осциллограммы
  4. PCA автокорреляции сигналов
  5. PCA кросс-корреляции сигналов с шаблонами
  6. PCA спектральной плотности мощности сигнала

Но возникает вопрос: если мы знаем все функции, которые МОЖЕМ использовать, то почему бы просто не использовать их все? Это не особенно большое количество функций, поэтому на производительность нашей модели не должна влиять разница между 5–15 функциями (при условии, что мы возьмем 3–4 ПК для функций 3–6). Однако важно иметь в виду, что расчет этих функций, особенно функций 3–6, требует затрат. качественное вычисление автокорреляции сигналов занимает больше времени, чем вычисление признаков 1–3 вместе взятых. Следовательно, если мы хотим включить функции в наш конвейер, мы хотим убедиться, что они того стоят, в чем нам могут помочь систематические эксперименты.

Проведение экспериментов с использованием Neptune.ai

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

  1. Точность модели (на тестовом наборе)
  2. Матрица путаницы (набор тестов)
  3. Время обучения
  4. Время предсказания

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

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

Ниже приведен код для записи этих данных. Как упоминалось выше, здесь я использую Neptune.ai только для записи нужных мне деталей (я запускаю прогон → регистрирую все → останавливаю прогон), но если вы запустите прогон до обучения своей модели, Neptune.ai также может запись сведений о производительности системы.

После инициализации run (обработчик для регистрации сведений об этом эксперименте) я разбил ведение журнала на:

  1. Подробная информация о данных (отслеживание файла HDF5, содержащего данные и связанные файлы CSV метаданных)
  2. Точность модели регистрации и матрица путаницы
  3. Детали модели (оптимизированные гиперпараметры, тип модели, порог титрования для желаемого отзыва и т. д.)
  4. Загружать артефакты конвейера (конвейер функций и обученный классификатор) и
  5. Цифры для анализа Shap

Когда эксперименты выполняются, мы можем настроить нашу панель инструментов для просмотра наиболее важных для нас результатов. Ниже приведен пример этого для моих экспериментов для текущей задачи (отсортировано по accuracy ). Мы можем ясно видеть, что модель с наибольшим количеством функций (отметьте train_set_size ) работает лучше всего, но на самом деле между моделями нет большой разницы (после того, как мы пройдем нижние три), т.е. WAV-25 является вполне приемлемой моделью с меньшим количеством функций. чем остальные модели и разница в точности ‹1% по сравнению с топовой моделью. Было бы полезно записывать время, затрачиваемое на преобразование признаков, чтобы также количественно оценить это, но, как я упоминал ранее, вычисление auto_corr и cross_corr — это трудоемкие процессы, которых мы хотим избежать, если можем, и, безусловно, кажется, что можем.

Но хотя очень полезно отображать точность и значения из матрицы путаницы, как это помогает нам понять, какие функции важны? Ну, как показано в коде выше, Neptune.ai также отслеживает результаты нашего анализа Shap. Используя вкладку Compare Runs, мы можем сравнивать различные объекты (метрики, изображения, артефакты) между выбранными запусками.

Увеличив масштаб (ниже), мы видим, что energy и amplitude более важны, чем большинство основных компонентов сигнала, и намного важнее, чем auto_corr и template_corr (взаимная корреляция шаблона). Это объясняет, почему различия в производительности модели становятся минимальными, как только мы добавляем первые 3 ПК, энергию и амплитуду.

Реестр моделей с Neptune.ai

Как только мы закончим конкретный эксперимент, мы можем добавить нужную модель в реестр моделей (вместе со всеми нужными нам метаданными и артефактами). Кроме того, мы можем установить промежуточные флаги и теги для нашей модели. Эта настройка позволяет нам загружать артефакты моделей и метаданные для готовых к производству моделей, используя эти флаги программным способом (документы здесь) для использования на последующих этапах нашего конвейера (развертывание, A/B-тестирование).

Эксперимент удался?

Итак, после экспериментов и регистрации нашей модели, что мы сделали? Ниже приведены некоторые графики из примера прогнозирования. Из примерно 250 000 сигналов классификатор предсказал, что ~ 14 000 будут положительными. Нижняя часть графика показывает, что фактические сгруппированные сигналы идентифицированы пользователем. Следует отметить 2 важные вещи:

  1. Прогнозируемое количество больше, чем фактическое количество. Это сделано намеренно, поскольку во время наших экспериментов мы отрегулировали наш порог предсказания, чтобы иметь 99% отзыва на тестовом наборе.
  2. Можно увидеть, что предсказанные формы волны содержат 2 кластера, о чем свидетельствует неравномерная плотность при отклонении желоба.

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

Из 32 наборов данных среднее количество выборок составило около 200 000. Из них примерно 10% точек данных были положительными. Классификатор в среднем давал 12–14% положительных результатов, но, что важно, эта разница всегда была положительной, т. е. классификатор всегда был более либерален в подсчете положительных результатов (опять же, по замыслу). Учитывая, что после этой классификации все еще есть этап ручной проверки (см. предыдущий пост), это очень хорошо. Наш этап классификации удаляет ~85% данных (~95% истинно отрицательных результатов) и, следовательно, служит отличным этапом очистки данных.

Кроме того, этот дополнительный шаг ничего нам не стоит, а скорее экономит время вычислений. Первоначально (т. е. без классификации) сигналы были сгруппированы неконтролируемым образом с использованием модели смеси Гаусса, из которой кластеры выбирались пользователем вручную. Для приведенных выше наборов данных исходный clustering занял всего 6 минут 33 секунды, тогда как classification + clustering занял 5 минут 44 секунды. Вероятно, это связано с тем, что кластеризация выполнялась намного быстрее при значительно меньшем количестве сигналов в миксе.

Заключение

Учитывая итеративный характер разработки конвейеров машинного обучения в сочетании с доступностью многих типов моделей и методом проб и ошибок, необходимым для разработки функций, экспериментирование является неотъемлемой частью создания эффективного конвейера. Здесь я изучил инструмент, призванный упростить и организовать эти эксперименты. В то время как служебный пояс MLOps все еще находится в стадии быстрой разработки, Neptune.ai представляет собой очень полезный гаджет для повседневных операций.

Этот этап предварительной обработки является частью конвейера сортировки пиков Katz Lab (Github). Код для создания модели и экспериментов доступен здесь.

Благодарности

Моя искренняя благодарность Нишаат Мукадам, Цзянь-Ю Лин и Ханне Жермен за их полезные комментарии к этой истории.

Рекомендации

  1. https://neptune.ai/home
  2. https://shap.readthedocs.io/en/latest/
  3. https://medium.com/@abuzar_mahmood/weeding-out-noise-with-ml-258bcd87783f
  4. https://github.com/abuzarmahmood/neuRecommend