Scipy lesssq: установка квадратной сетки в экспериментальные точки в 2D

Я пытаюсь использовать Scipy leastsq для поиска наилучшего соответствия «квадратной» сетки для набора координат измеренных точек в 2-D (экспериментальные точки примерно равны квадратной сетке).

Параметры сетки – это шаг (равный для x и y), центральное положение ( center_x и center_y ) и rotationcenter_y ).

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

Вот определения функций:

 import numpy as np from scipy.optimize import leastsq def get_spot_grid(shape, pitch, center_x, center_y, rotation=0): x_spots, y_spots = np.meshgrid( (np.arange(shape[1]) - (shape[1]-1)/2.)*pitch, (np.arange(shape[0]) - (shape[0]-1)/2.)*pitch) theta = rotation/180.*np.pi x_spots = x_spots*np.cos(theta) - y_spots*np.sin(theta) + center_x y_spads = x_spots*np.sin(theta) + y_spots*np.cos(theta) + center_y return x_spots, y_spots def get_mean_distance(x1, y1, x2, y2): return np.sqrt((x1 - x2)**2 + (y1 - y2)**2).mean() def err_func(params, xe, ye): pitch, center_x, center_y, rotation = params x_grid, y_grid = get_spot_grid(xe.shape, pitch, center_x, center_y, rotation) return get_mean_distance(x_grid, y_grid, xe, ye) 

Это экспериментальные координаты:

 xe = np.array([ -23.31, -4.01, 15.44, 34.71, -23.39, -4.10, 15.28, 34.60, -23.75, -4.38, 15.07, 34.34, -23.91, -4.53, 14.82, 34.15]).reshape(4, 4) ye = np.array([-16.00, -15.81, -15.72, -15.49, 3.29, 3.51, 3.90, 4.02, 22.75, 22.93, 23.18, 23.43, 42.19, 42.35, 42.69, 42.87]).reshape(4, 4) 

Я пытаюсь использовать leastsq таким образом:

 leastsq(err_func, x0=(19, 12, 5, 0), args=(xe, ye)) 

но я получаю следующую ошибку:

 --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-19-ee91cf6ce7d6> in <module>() ----> 1 leastsq(err_func, x0=(19, 12, 5, 0), args=(xe, ye)) C:\Anaconda\lib\site-packages\scipy\optimize\minpack.pyc in leastsq(func, x0, args, Dfun, full_output, col_deriv, ftol, xtol, gtol, maxfev, epsfcn, factor, diag) 369 m = shape[0] 370 if n > m: --> 371 raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m)) 372 if epsfcn is None: 373 epsfcn = finfo(dtype).eps TypeError: Improper input: N=4 must not exceed M=1 

Я не могу понять, в чем проблема 🙁

Так как функция lesssq предполагает, что err_function возвращает массив остатков docs, и поэтому трудно написать err_function таким образом, почему бы не использовать другую функцию scipy – свести к минимуму . Затем вы добавляете свой показатель – функцию ошибки, которую вы уже имеете, и она работает. Тем не менее, я думаю, что есть еще одна опечатка в функции get_spot_grid (y_spots vs y_spads). Полный код:

 import numpy as np from scipy.optimize import leastsq, minimize def get_spot_grid(shape, pitch, center_x, center_y, rotation=0): x_spots, y_spots = np.meshgrid( (np.arange(shape[1]) - (shape[1]-1)/2.)*pitch, (np.arange(shape[0]) - (shape[0]-1)/2.)*pitch) theta = rotation/180.*np.pi x_spots = x_spots*np.cos(theta) - y_spots*np.sin(theta) + center_x y_spots = x_spots*np.sin(theta) + y_spots*np.cos(theta) + center_y return x_spots, y_spots def get_mean_distance(x1, y1, x2, y2): return np.sqrt((x1 - x2)**2 + (y1 - y2)**2).mean() def err_func(params, xe, ye): pitch, center_x, center_y, rotation = params x_grid, y_grid = get_spot_grid(xe.shape, pitch, center_x, center_y, rotation) return get_mean_distance(x_grid, y_grid, xe, ye) xe = np.array([-23.31, -4.01, 15.44, 34.71, -23.39, -4.10, 15.28, 34.60, -23.75, -4.38, 15.07, 34.34, -23.91, -4.53, 14.82, 34.15]).reshape(4, 4) ye = np.array([-16.00, -15.81, -15.72, -15.49, 3.29, 3.51, 3.90, 4.02, 22.75, 22.93, 23.18, 23.43, 42.19, 42.35, 42.69, 42.87]).reshape(4, 4) # leastsq(err_func, x0=(19, 12, 5, 0), args=(xe, ye)) minimize(err_func, x0=(19, 12, 5, 0), args=(xe, ye)) 

Функция, переданная в lesssq (например, err_func), должна возвращать массив значений той же формы, что и xe и ye т. Е. Один остаточный для каждого значения xe и ye .

 def err_func(params, xe, ye): pitch, center_x, center_y, rotation = params x_grid, y_grid = get_spot_grid(xe.shape, pitch, center_x, center_y, rotation) return get_mean_distance(x_grid, y_grid, xe, ye) 

Вызов to mean() в get_mean_distance уменьшает возвращаемое значение до одного скаляра. Имейте в виду, что xe и ye переданы err_func – это массивы, а не скаляры.

Сообщение об ошибке

 TypeError: Improper input: N=4 must not exceed M=1 

говорит, что число параметров 4 не должно превышать число остатков, возвращаемых err_func , 1.


Программу можно сделать выполнимой, изменив вызов на mean() на mean(axis=0) (т. Е. Возьмем среднее значение для каждого столбца) или mean(axis=1) (т. Е. Возьмем среднее значение для каждой строки):

 def get_mean_distance(x1, y1, x2, y2): return np.sqrt((x1 - x2)**2 + (y1 - y2)**2).mean(axis=1) 

Я не очень хорошо понимаю ваш код, чтобы знать, что это должно быть. Но идея состоит в том, что должно быть одно значение для каждой «точки» в xe и ye .