Минимизация многомерного решения по набору данных

У меня есть прямоугольник в двухмерном пространстве и набор точек внутри прямоугольника. Прямоугольник перемещается следующим образом: центр перемещается на значение u по оси X, v по оси Y, и все масштабируется с коэффициентом sx и sy соответственно. Я получаю расположение точек только после движения. Моя цель — оценить вектор (u, v, sx, sy).

У меня есть следующие данные во время выполнения:

  • px — ndarray со значениями x точек до движения
  • py — ndarray со значениями y точек перед движением
  • cx — ndarray со значениями x точек после движения
  • cy — ndarray со значениями y точек после движения
  • x0 — значение x местоположения центра прямоугольника в предыдущем кадре.
  • y0 — значение y местоположения центра прямоугольника в предыдущем кадре.

Уравнение для расчета положения точки в текущем кадре с учетом вектора (u, v, sx, sy) имеет вид:

x_currentFrameCalaulated = sx * px + u + x0 * (1 - sx)
y_currentFrameCalaulated = sy * py + v + y0 * (1 - sy)

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

def estimateCurr(vec, previous, current, center):
    return np.abs(current - (vec[1]* previous + vec[0]+ center * (1 - vec[1])))

Здесь vec[0] представляет движение относительно оси, а vec[1] представляет масштаб. Я устанавливаю границу в соответствии с моей проблемой следующим образом:

h = 270
w = 480
boundsX = Bounds([-w, -1], [w, w - 1])
boundsY = Bounds([-h, -1], [h, h - 1])

Инициализация предположения для [0, 0]:

init = np.zeros((2 , ))

Я возобновляю попытку найти оптимальное решение:

res = minimize(estimateCurr, x0 = init, args=(px, cx, centerX), method='trust-constr',  bounds=boundsX, options = {'verbose': 1})
print(res)
res = minimize(estimateCurr, x0 = init, args=(py, cy, centerY), method='trust-constr',  bounds=boundsY, options = {'verbose': 1})
print(res)

Я получаю:

ValueError: все входные массивы должны иметь одинаковое количество измерений, но массив с индексом 0 имеет 2 измерения, а массив с индексом 1 имеет 1 измерение(я)

Это очевидно, так как у меня 17 точек, а размеры печати: печать(px.shape) печать (cx.shape) печать (centerX.shape) печать (init.shape)

(17,) (17,) (17,) (2,)

Однако я не уверен, как установить правильные размеры для задачи и даже использую ли я правильный решатель. Я попытался умножить (u, v, sx, sy), чтобы подогнать размер данных, чтобы не было зла. Как мне подойти к этой проблеме?

Мой формальный вопрос: с учетом набора измеренных точек данных, как мне подобрать многомерное решение, которое минимизирует ошибку с помощью Python?


Добавляем фиктивный пример запроса комментариев. Я сократил набор данных до 6 пунктов:

from scipy.optimize import Bounds
from scipy.optimize import minimize
import numpy as np

def estimateCurr(vec, previous, current, center):
    # np.full(())
    return np.abs(current - (vec[1] * previous + vec[0] + center * (1 - vec[1])))


h = 270
w = 480
x0 = 90.8021
y0 = -20.8282

px = np.array([86.7581, 74.5433, 85.0012, 84.348, 83.704, 91.6176])
py = np.array([-19.5163, -17.3714, -3.39899, -4.83069, -1.97073, -2.20099])
cx = np.array([89.7436, 75.8955, 87.5827, 87.1492, 86.0817, 92.6683])
cy = np.array([-19.2132, -16.3913, -2.9177, -4.81898, -1.49321, -2.43572])

numPoints = px.shape[0]

boundsX = Bounds([-w, -1], [w, w - 1])
boundsY = Bounds([-h, -1], [h, h - 1])
centerX = np.full((numPoints,), x0)
centerY = np.full((numPoints,), y0)
init = np.zeros((2 ,))
print(px.shape)
print(cx.shape)
print(centerX.shape)
print(init.shape)
res = minimize(estimateCurr, x0 = init, args=(px, cx, centerX), method='trust-constr',  bounds=boundsX, options = {'verbose': 1})
print(res)
res = minimize(estimateCurr, x0 = init, args=(py, cy, centerY), method='trust-constr',  bounds=boundsY, options = {'verbose': 1})
print(res)

Добавление полной трассировки:

--------------------------------------------------------------------------- ValueError                                Traceback (most recent call last) /tmp/ipykernel_6249/3484902536.py in <module>
     25 print(centerX.shape)
     26 print(init.shape)
---> 27 res = minimize(estimateCurr, x0 = init, args=(px, cx, centerX), method='trust-constr',  bounds=boundsX, options = {'verbose': 1})
     28 print(res)
     29 res = minimize(estimateCurr, x0 = init, args=(py, cy, centerY), method='trust-constr',  bounds=boundsY, options = {'verbose': 1})

~/.conda/envs/oxip-new6/lib/python3.7/site-packages/scipy/optimize/_minimize.py in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)
    634         return _minimize_trustregion_constr(fun, x0, args, jac, hess, hessp,
    635                                             bounds, constraints,
--> 636                                             callback=callback, **options)
    637     elif meth == 'dogleg':
    638         return _minimize_dogleg(fun, x0, args, jac, hess,

~/.conda/envs/oxip-new6/lib/python3.7/site-packages/scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py in _minimize_trustregion_constr(fun, x0, args, grad, hess, hessp, bounds, constraints, xtol, gtol, barrier_tol, sparse_jacobian, callback, maxiter, verbose, finite_diff_rel_step, initial_constr_penalty, initial_tr_radius, initial_barrier_parameter, initial_barrier_tolerance, factorization_method, disp)
    518             initial_barrier_tolerance,
    519             initial_constr_penalty, initial_tr_radius,
--> 520             factorization_method)
    521 
    522     # Status 3 occurs when the callback function requests termination,

~/.conda/envs/oxip-new6/lib/python3.7/site-packages/scipy/optimize/_trustregion_constr/tr_interior_point.py in tr_interior_point(fun, grad, lagr_hess, n_vars, n_ineq, n_eq, constr, jac, x0, fun0, grad0, constr_ineq0, jac_ineq0, constr_eq0, jac_eq0, stop_criteria, enforce_feasibility, xtol, state, initial_barrier_parameter, initial_tolerance, initial_penalty, initial_trust_radius, factorization_method)
    306         barrier_parameter, tolerance, enforce_feasibility, ...
    347 

<__array_function__ internals> in concatenate(*args, **kwargs)

ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 2 dimension(s) and the array at index 1 has 1 dimension(s)

Можете ли вы опубликовать полную обратную трассировку, включая ту часть, которая показывает, какая строка вызвала ошибку?

Nick ODell 11.08.2024 19:52

Стоит отметить, что эта проблема является линейной, поэтому вы можете использовать линейную регрессию для ее решения, если minimize() и ее нелинейные решатели вам не подходят.

Nick ODell 11.08.2024 19:53

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

Nick ODell 11.08.2024 20:47

Что дает тестовый вызовestimateCurr(init, *args)? Это должно быть одно значение, которое необходимо минимизировать. Я предполагаю, что вместо этого будет массив (17).

hpaulj 12.08.2024 05:36

Пожалуйста, найдите время, чтобы написать минимально воспроизводимый пример, невозможно воспроизвести вашу проблему просто потому, что отсутствует часть кода и данных. В это время NameError: name 'Bounds' is not defined.

jlandercy 12.08.2024 09:59

@jlandercy Bound — это импорт from scipy.optimize import Bounds. Обычно импорт не включается в минимальные примеры AFAIK. Я добавлю их в любом случае.

havakok 12.08.2024 10:07

Минимально воспроизводимый пример включает в себя все необходимое для воспроизведения проблемы. Включите импорт, данные и т. д. Пожалуйста, прочитайте ссылку.

MatBailie 12.08.2024 10:12
Почему в 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
7
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Целевая функция должна быть скалярной функцией. В вашем определении функция возвращает массив. Поэтому вам нужно как-то агрегировать это. Наиболее очевидным выбором обычно является сумма.

Например, следующая целевая функция работает и сходится:

def estimateCurr(vec, previous, current, center):
    return np.sum(np.power(current - (vec[1] * previous + vec[0] + center * (1 - vec[1])), 2))

#     message: `xtol` termination condition is satisfied.
#     success: True
#      status: 2
#         fun: 3.1694871819514345
#           x: [ 2.274e+00  1.013e+00]
# ...

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