Подбор функций косинуса (синуса) с машинным обучением в Python

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

Авторы: Кармен Мартинес-Барбоса и Хосе Селис-Хиль

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

где a₀, a₁, ⍵, ϕ - смещение, амплитуда, частота и фаза сигнала. На следующем рисунке мы можем увидеть график этой функции и роль, которую каждый из этих компонентов играет в сигнале:

Получив письмо от нашего коллеги, мы подумали, что эту проблему легко решить с помощью существующих библиотек Python, таких как Scipy. В этом пакете Python есть метод под названием optimize.curve_fit,, который использует нелинейные методы наименьших квадратов для подгонки функции f к некоторым входным данным (пример с подгонкой функции Sine может можно найти здесь). Функция, предоставляемая Scipy, довольно быстрая; однако после некоторых испытаний мы заметили, что пользователь должен иметь представление о значениях каждого параметра, чтобы код мог дать хорошую оценку. Мы исследовали другие альтернативы, такие как байесовская оптимизация или регрессия, и они оказались очень хорошими альтернативами для согласования данных с гармоническими сигналами.

В этом блоге мы исследуем, как можно использовать Scipy и Hyperopt для подбора гармонического сигнала. Мы также представляем пакет Python HOBIT (Harmonic Oscillator hyBrid fIT): гибридный метод, сочетающий байесовскую оптимизацию с линейной регрессией для эффективного соответствия функциям косинуса (синуса). В этом блоге мы рассмотрим преимущества и недостатки каждого из этих методов.

Весь код этого блога доступен в этом репозитории GitHub.

Начнем с игрушечного набора данных из n = 100 наблюдений, который ведет себя согласно f (x):

Мы используем функцию np.random.normal (size = n) для добавления шума в сигнал, чтобы сделать его более похожим на реальные измерения.

Мы разделяем данные на обучение и тестирование, так что 80% наблюдений используются для обучения, а остальные используются для проверки соответствия (т.е. мы выполняем однократную проверку соответствия):

Установка с помощью Scipy optimize

Функция optimize. curve_fit в Scipy использует нелинейный алгоритм наименьших квадратов для нахождения оптимальных параметров f (x). Эта функция предлагает различные методы оптимизации: алгоритм Левенберга-Марквардта (lm); Алгоритм отражения доверительной области (trf) и алгоритм изгиба (собачка). Мы не будем объяснять эти методы, для получения дополнительной информации вы можете посетить документацию Scipy, которая объясняет реализацию алгоритма наименьших квадратов.

Реализация optimize.curve_fit в Python показана ниже:

pₒ - это необязательный ввод функции optimize.curve_fit, и это первоначальное предположение о параметрах f (x),, заданных пользователем .

Выполнение этого кода приводит к следующему результату:

Обратите внимание, что a₁ и ϕ далеки от исходных параметров. Это можно объяснить тем, что f (x) имеет периодическое поведение, а функция потерь, которая в нашем случае является среднеквадратичной ошибкой (MSE), имеет множество локальных минимумов. Это может привести к неправильной подгонке параметров независимо от метода оптимизации . Другими словами: p₀ должен быть очень близок к реальным параметрам функции, что противоречит подгонке функция с неизвестными параметрами.

Еще одним следствием периодического поведения f (x) является то, что Scipy может обеспечить разумное соответствие, хотя параметры далеки от реальных, см. Рисунок ниже:

Несмотря на ограничения Scipy для соответствия периодическим функциям, одним из самых больших преимуществ optimize.curve_fit является его скорость, очень высокая скорость и отображение результатов через 0,016 секунды. Если есть известная оценка области параметров, мы рекомендуем установить «method = 'trf'» или «method = 'dogbox'» в optimize.curve_fit и установить диапазоны с помощью option bounds, чтобы пользователь по-прежнему мог воспользоваться скоростью этого пакета.

Примерка с использованием Hyperopt

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

  1. Целевая функция: это функция, которую мы хотим минимизировать. В нашем случае это MSE.
  2. Домен параметров: диапазон, в котором мы знаем или думаем, что параметры могут находиться.
  3. Алгоритм оптимизации: это метод, используемый для создания вероятностной модели целевой функции, из которой на каждой итерации выбираются новые параметры a₀, a₁, ω и ϕ. Вероятностная модель также называется суррогатной поверхностью.

В этом посте мы не собираемся подробно объяснять, как работает Hyperopt. Для отличного введения в эту тему вы можете перейти в этот блог.

Мы определяем функцию target, как показано ниже:

Из-за реализации Hyperopt нам необходимо определить вспомогательную функцию с именем objective2, которая добавляет более одного параметра к оптимизации.

Реализация Hyperopt следующая:

Переменная пробел определяет область параметров. tpe_algo - это один из алгоритмов оптимизации, используемых Hyperopt, который представляет собой Подход к оценке парзена с древовидной структурой (TPE). fmin - это функция Hyperopt, которая минимизирует целевую функцию в определенном пространстве в соответствии с tpe_algo до определенного количества оценок. Переменная rstate настроена для получения воспроизводимых результатов.

После выполнения fmin для 500 итераций лучшие параметры f (x) сохраняются в переменной tpe_best. Результаты следующие:

Очевидно, что Hyperopt дает результаты, близкие к реальным значениям по сравнению с optimize.curve_fit Scipy, даже несмотря на то, что MSE больше (см. Рисунок ниже). Однако обратите внимание, что пользователю необходимо заранее знать область параметров, хотя диапазон может быть шире, чем в подходе Scipy.

Для 500 итераций Hyperopt требуется 4,88 секунды, чтобы найти оптимальные параметры f (x). Если у пользователя нет никаких предыдущих знаний о a₀, a₁, ω и ϕ, необходимо определить более широкий диапазон параметров, но для этого потребуется больше итераций для поиска оптимального решения. С другой стороны, если реальные значения a₀, a₁, ω и ϕ не находятся в пределах определенной области параметров, результаты будут отключены.

Монтаж гибридным методом: HOBIT

Мы разработали библиотеку Python под названием Harmonic Oscillator hyBrid fIT (HOBIT). Эта библиотека сочетает в себе мощь Hyperopt с гибкостью S cikit learn для точной подгонки гармонических сигналов. HOBIT предназначен для работы с сигналами синусоидальной (косинусной) формы. Пользователь может определить область значений ω и ϕ, но HOBIT по умолчанию использует следующие диапазоны:

которые характерны для гармонических осцилляторов.

Нет необходимости иметь предварительные знания о a₀ и a₁, поскольку они определены HOBIT.

Реализация HOBIT очень проста:

Класс RegressionForTrigonometric имеет 2 метода подгонки: fit_sin для соответствия функциям синуса и fit_cos для соответствия функциям косинуса. В любом из этих методов вам необходимо указать набор поездов (X_train, y_train) и количество итераций, на которых вы хотите запустить оптимизацию (заданное параметром max_evals). Также можно включить другие аргументы Hyperopt, например, если вы хотите сделать результаты воспроизводимыми, установите случайное начальное число в переменной rstate. HOBIT сохраняет полученные параметры в переменной best_parameters.

Выполнение приведенного выше кода дает следующие результаты:

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

Подгонка f (x) данных выглядит так:

Для 500 итераций HOBIT требуется 3,05 секунды, чтобы найти оптимальные параметры f (x), что почти на две секунды быстрее, чем Hyperopt! Для того же количества итераций соответствие HOBIT имеет более низкую MSE.

Как работает HOBIT?

Цель HOBIT - предоставить параметры a₀, a₁, ω и ϕ, которые наилучшим образом соответствуют входным данным, таким же образом, как при использовании одного из классификаторов Scikit. учиться. HOBIT делает первую оценку a₀ и a₁ на основе наблюдений. Исходные допущения для этих параметров:

Мы вводим эти начальные значения и диапазоны значений по умолчанию для ω и ϕ в Hyperopt. После итераций, указанных в функции подбора, мы получаем подогнанные ω и ϕ с помощью tpe_algorithm.

Мы используем подобранные ω и ϕ, чтобы сделать преобразование, которое позволяет нам выполнять полиномиальную регрессию. Мы используем Scikit модель линейной регрессии для этого преобразования, чтобы получить окончательные значения a₀ и a₁. (Для получения дополнительной информации о полиномиальной регрессии с использованием Scikit learn вы можете перейти в этот блог). Используя этот гибридный подход, HOBIT подбирает данные быстрее, чем Hyperopt, поскольку он должен находить только ω и ϕ, в ​​то время как a₀ и a₁ получаются с помощью регрессионной модели.

Как только параметры найдены, пользователь может использовать функцию прогнозирования, чтобы применить модель к другим невидимым данным. Использование HOBIT простое и интуитивно понятное, особенно если вы используете Scikit learn. Мы рекомендуем заранее просмотреть данные, чтобы дать реалистичное определение области ω.

Вы можете найти здесь блокноты с примерами, которые помогут более подробно изучить HOBIT.

Выводы

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

Мы исследуем три инструмента: optimize.curve_fit из Scipy, Hyperopt и HOBIT. Мы подбираем набор данных, который ведет себя в соответствии с функцией косинуса. У каждого пакета есть свои преимущества. Вот наши рекомендации по использованию каждого из них: Если у пользователя есть предыдущие подробные сведения о диапазонах, в которых могут быть найдены оптимальные параметры, то лучшим выбором будет использование optimize.curve_fit от Scipy. однако, если у пользователя нет этих знаний, результаты могут быть неверными. В случаях, когда пользователь имеет очень ограниченные знания о функции, Hyperopt может быть полезен, основная проблема заключается в том, что потребуется установить большой домен для каждого параметра, что делает обязательным использование большего количества итераций. чтобы сделать то, что нужно. Наконец, HOBIT - это новый инструмент, который сочетает в себе лучшее из обоих миров, упрощая и ускоряя подбор сигналов синусоидальной (косинусной) формы, предоставляя пользователю возможность устанавливать диапазоны и итерации. Как и в случае с Hyperopt, если пользователь не имеет никаких предварительных знаний о параметрах, можно определить более широкие диапазоны, но это потребует дополнительных итераций для поиска оптимального решения. Несмотря на это, HOBIT будет быстрее, чем использование только Hyperopt, учитывая, что будет изменяться только область двух параметров.

Спасибо за прочтение!

Вы можете связаться с нами через LinkedIn по адресу: