Решение нелинейной системы сильно зависит от начального предположения

У меня есть система нелинейных уравнений

  1. xF - xA * exp(-(wAA * xA + wBB * xB)) = 0
  2. xF - xB * exp(-(wBB * xB + wAB * xA)) = 0
  3. хА + хВ + хF -1 = 0

где переменные — это xA, xB и xF, а wAA, wBB и wAB — заданные параметры. Переменные неотрицательны и находятся в интервале [0,1] Вот минимальный пример кода

import math
from scipy.optimize import least_squares

coupleInteractions = [10000., 10., 0.]

def equations(p):
    xA, xB, xF = p
    wAA, wBB, wAB = coupleInteractions

    eq1 = xF - xA * math.exp(-(wAA * xA + wBB * xB))
    eq2 = xF - xB * math.exp(-(wBB * xB + wAB * xA))
    eq3 = xA + xB + xF -1

    return (eq1, eq2, eq3)

guess = [0., 1., 0.]
bounds = ([0., 0., 0.], [1., 1., 1.])
root = least_squares(equations, x0=guess, bounds=bounds, xtol=1.e-15, gtol = 1.e-15, ftol = 1.e-15, loss = "cauchy")

print(root)
print(root.x)

Я хочу протестировать код в некоторых предельных случаях. Например, если все параметры равны нулю, wAA = wAB = wBB = 0, у меня есть простая линейная система с xA = xB = xF = 1,/3. В этом случае код отлично работает вне зависимости от догадок.

Я хочу проверить, как в опубликованном коде, случай wAA >> wBB и wAA >> wAB. С математической точки зрения я получаю xA = 1, xB = 0 и xF = 0. Но с функцией least_square я получаю неправильный ответ. Я намеренно использую "неправильную" догадку для проверки метода, потому что в промежуточных случаях не хочу, чтобы результаты сильно зависели от первоначального выбора. Есть ли ошибка в моем коде?

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

def scalarEquations(p):
    xA, xB, xF = p
    wAA, wBB, wAB = coupleInteractions

    eq1 = xF - xA * math.exp(-(wAA * xA + wBB * xB))
    eq2 = xF - xB * math.exp(-(wBB * xB + wAB * xA))
    eq3 = xA + xB + xF -1

    return (eq1**2 + eq2**2 + eq3 **2)

Он возвращает сумму квадратов для 3 уравнений. Затем я выполнил подход грубой силы.

from scipy.optimize import brute
rranges = (slice(0,1, 0.05), slice(0,1, 0.005), slice(0,1, 0.005))
t = brute(scalarEquations, rranges)
print(t)

Я получаю такое же «неправильное» решение. Я знаю, что глобальный оптимизатор должен найти абсолютный минимум. Я не понимаю.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
69
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ваш код выглядит нормально. Похоже, что существует локальный минимум около [0,1,0] для wAA big и wBB больше e, и оптимизация сходится к нему.

Как этого избежать?

Jonny_92 19.03.2022 13:30

вы, вероятно, не можете. Если есть локальный минимум, вы можете ожидать, что любой оптимизатор сойдется к нему, когда он будет запущен достаточно близко. (И «близко» может быть довольно далеко)

William 19.03.2022 17:20

Хорошо спасибо. Мне интересно, могу ли я использовать глобальный оптимизатор.

Jonny_92 19.03.2022 22:26

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

def scalarEquations(p):
    xA, xB, xF = p
    wAA, wBB, wAB = coupleInteractions

    eq1 = math.log(xF) - math.log(xA * math.exp(-(wAA * xA + wAB * xB)))
    eq2 = math.log(xF) - math.log(xB * math.exp(-(wBB * xB + wAB * xA)))
    eq3 = math.log(xA + xB + xF) -math.log(1.)

    return (eq1**2 + eq2**2 + eq3 **2)

rranges = ((1.e-15, 1.), (1.e-15, 1.), (1.e-15, 1.) )
t = brute(scalarEquations, rranges, Ns = 100)
print(t)

Другие вопросы по теме