Решение нелинейных уравнений в python

У меня есть 4 нелинейных уравнения с тремя неизвестными X , Y и Z , для которых я хочу решить. Уравнения имеют вид:

 F(m) = X^2 + a(m)Y^2 + b(m)XYcosZ + c(m)XYsinZ 

… где a , b и c – константы, зависящие от каждого значения F в четырех уравнениях.

Каков наилучший способ решить это?

2 Solutions collect form web for “Решение нелинейных уравнений в python”

Есть два способа сделать это.

  1. Использовать нелинейный решатель
  2. Линеаризовать проблему и решить ее в смысле наименьших квадратов

Настроить

Итак, насколько я понимаю ваш вопрос, вы знаете F, a, b и c в 4 разных точках и хотите инвертировать параметры модели X, Y и Z. У нас есть 3 неизвестных и 4 наблюдаемых точки данных, поэтому проблема переопределена. Поэтому мы будем решать в смысле наименьших квадратов.

В этом случае чаще используется противоположная терминология, поэтому давайте перевернем ваше уравнение. Вместо:

 F_i = X^2 + a_i Y^2 + b_i XY cosZ + c_i XY sinZ 

Давай напишем:

 F_i = a^2 + X_i b^2 + Y_i ab cos(c) + Z_i ab sin(c) 

Где мы знаем F , X , Y и Z в 4 разных точках (например, F_0, F_1, ... F_i ).

Мы просто меняем имена переменных, а не само уравнение. (Это больше для моей легкости мышления, чем для чего-либо еще.)

Линейное решение

На самом деле можно линеаризовать это уравнение. Вы легко можете решить для a^2 , b^2 , ab cos(c) и ab sin(c) . Чтобы сделать это немного легче, давайте еще раз повторим:

 d = a^2 e = b^2 f = ab cos(c) g = ab sin(c) 

Теперь уравнение намного проще: F_i = d + e X_i + f Y_i + g Z_i . Легко сделать линейную инверсию наименьших квадратов для d , e , f и g . Затем мы можем получить a , b и c из:

 a = sqrt(d) b = sqrt(e) c = arctan(g/f) 

Хорошо, давайте напишем это в матричной форме. Мы собираемся перевести 4 наблюдения (код, который мы напишем, будет принимать любое количество наблюдений, но давайте укажем его конкретное на данный момент):

 F_i = d + e X_i + f Y_i + g Z_i 

В:

 |F_0| |1, X_0, Y_0, Z_0| |d| |F_1| = |1, X_1, Y_1, Z_1| * |e| |F_2| |1, X_2, Y_2, Z_2| |f| |F_3| |1, X_3, Y_3, Z_3| |g| 

Или: F = G * m (я геофизик, поэтому мы используем G для «функций Грина» и m для «параметров модели». Обычно мы использовали d для «данных» вместо F )

В python это будет означать:

 def invert(f, x, y, z): G = np.vstack([np.ones_like(x), x, y, z]).T m, _, _, _ = np.linalg.lstsq(G, f) d, e, f, g = m a = np.sqrt(d) b = np.sqrt(e) c = np.arctan2(g, f) # Note that `c` will be in radians, not degrees return a, b, c 

Нелинейное решение

Вы также можете решить это, используя scipy.optimize , как предлагал @Joe. Наиболее доступной функцией в scipy.optimize является scipy.optimize.curve_fit которая по умолчанию использует метод scipy.optimize.curve_fit -Marquardt.

Levenberg-Marquardt – это алгоритм «восхождения на холм» (ну, в данном случае он идет вниз, но этот термин используется в любом случае). В некотором смысле вы делаете первоначальное предположение о параметрах модели (все они по умолчанию в scipy.optimize ) и следуют по склону observed - predicted в вашем пространстве параметров вниз по низу.

Предостережение: выбор правильного метода нелинейной инверсии, первоначальная догадка и настройка параметров метода – это очень «темное искусство». Вы только учитесь этому, делая это, и есть много ситуаций, когда вещи не будут работать должным образом. Levenberg-Marquardt – хороший общий метод, если пространство параметров довольно гладкое (это должно быть). Есть много других (включая генетические алгоритмы, нейронные сети и т. Д. В дополнение к более распространенным методам, таким как имитированный отжиг), которые лучше в других ситуациях. Я не собираюсь вникать в эту часть здесь.

Существует одна общая информация о том, что некоторые инструменты оптимизации пытаются исправить для этого scipy.optimize не пытается обрабатывать. Если ваши параметры модели имеют разные величины (например, a=1, b=1000, c=1e-8 ), вам нужно будет перемасштабировать вещи так, чтобы они были одинаковыми по величине. В противном случае scipy.optimize «восхождение по холму» (например, LM) не будут точно рассчитать оценку локального градиента и дадут дико неточные результаты. На данный момент я предполагаю, что a , b и c имеют относительно близкие значения. Кроме того, имейте в виду, что по существу все нелинейные методы требуют от вас первоначального предположения и чувствительны к этой догадки. Я оставляю его ниже (просто передайте его как p0 kwarg в curve_fit ), потому что по умолчанию a, b, c = 1, 1, 1 является довольно точным предположением для a, b, c = 3, 2, 1 ,

С предостережениями в сторону curve_fit ожидает, что будет передана функция, набор точек, где были сделаны наблюдения (как один ndim x npoints ) и наблюдаемые значения.

Итак, если мы напишем функцию следующим образом:

 def func(x, y, z, a, b, c): f = (a**2 + x * b**2 + y * a * b * np.cos(c) + z * a * b * np.sin(c)) return f 

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

В двух словах:

 def nonlinear_invert(f, x, y, z): def wrapped_func(observation_points, a, b, c): x, y, z = observation_points return func(x, y, z, a, b, c) xdata = np.vstack([x, y, z]) model, cov = opt.curve_fit(wrapped_func, xdata, f) return model 

Автономный Пример двух методов:

Чтобы дать вам полную реализацию, вот пример того, что

  1. генерирует случайно распределенные точки для оценки функции on,
  2. оценивает функцию на этих точках (используя параметры модели набора),
  3. добавляет шум к результатам,
  4. а затем инвертирует параметры модели с использованием как линейных, так и нелинейных методов, описанных выше.

 import numpy as np import scipy.optimize as opt def main(): nobservations = 4 a, b, c = 3.0, 2.0, 1.0 f, x, y, z = generate_data(nobservations, a, b, c) print 'Linear results (should be {}, {}, {}):'.format(a, b, c) print linear_invert(f, x, y, z) print 'Non-linear results (should be {}, {}, {}):'.format(a, b, c) print nonlinear_invert(f, x, y, z) def generate_data(nobservations, a, b, c, noise_level=0.01): x, y, z = np.random.random((3, nobservations)) noise = noise_level * np.random.normal(0, noise_level, nobservations) f = func(x, y, z, a, b, c) + noise return f, x, y, z def func(x, y, z, a, b, c): f = (a**2 + x * b**2 + y * a * b * np.cos(c) + z * a * b * np.sin(c)) return f def linear_invert(f, x, y, z): G = np.vstack([np.ones_like(x), x, y, z]).T m, _, _, _ = np.linalg.lstsq(G, f) d, e, f, g = m a = np.sqrt(d) b = np.sqrt(e) c = np.arctan2(g, f) # Note that `c` will be in radians, not degrees return a, b, c def nonlinear_invert(f, x, y, z): # "curve_fit" expects the function to take a slightly different form... def wrapped_func(observation_points, a, b, c): x, y, z = observation_points return func(x, y, z, a, b, c) xdata = np.vstack([x, y, z]) model, cov = opt.curve_fit(wrapped_func, xdata, f) return model main() 

Вероятно, вы хотите использовать нелинейные решатели Scipy, они очень легкие: http://docs.scipy.org/doc/scipy/reference/optimize.nonlin.html

  • Линейная регрессия с использованием scipy.ODR не выполняется (не полный ранг в решении)
  • Результаты SciPy interp1d отличаются от MatLab interp1
  • Что такое тензор в анано?
  • проблема с иерархической кластеризацией в Python
  • Python Scipy: scipy.stats.spearmanr возвращает nans
  • Интеграция функций, возвращающих массив в Python
  • Установка NumPy и SciPy на 64-битной Windows (с помощью Pip)
  • Есть ли эффективный способ конкатенации матриц scipy.sparse?
  • Как установить SciPy на 64-битную Windows?
  • Эмуляция функции сплайна Excel «разброс с плавной кривой» в Matplotlib для 3 точек
  • scipy.optimize.curve_fit не может соответствовать сдвинутой перекошенной гауссовой кривой
  •  
    Interesting Posts for Van-Lav

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

    Приложение Python ничего не делает

    Как поместить текст внутри коробки на участок в matplotlib

    Создавайте и передавайте большой архив, не сохраняя его в памяти или на диске.

    Есть ли модуль python для решения линейных уравнений?

    Как вызвать средство настройки свойств из __init__

    Python эквивалентен Java JNLP Web Start?

    Не удается записать window.inch (y, x) вывод в файл в python

    При каких обстоятельствах __rmul__ называется?

    Как получить временную метку unix из numpy.datetime64

    Pygame: графический ввод + ввод текста

    Может ли сельдерей, сельдерей и джанго-сельдерей-бить динамически добавлять / удалять задачи во время выполнения без перезапуска celerybeat?

    Как проверить, был ли импортирован модуль python?

    Какой лучший способ расширить анонимный пользователь в Django?

    Несколько текстовых узлов в ElementTree Python? Генерация HTML

    Python - лучший язык программирования в мире.