3

leastsqScipy を使用して、2 次元の測定点座標のセットに最適な「正方形」グリッドを見つけようとしています (実験点はほぼ正方形グリッド上にあります) 。

グリッドのパラメータは、ピッチ (x と y に等しい)、中心位置 (center_xcenter_y)、およびrotation(度) です。

ポイントの各ペア(実験グリッドと理想グリッド)のユークリッド距離を計算し、平均を取る誤差関数を定義しました。この機能を最小限に抑えたいのです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

ここで何が問題なのかわかりません:(

4

3 に答える 3

1

leastsq 関数は err_function が残差ドキュメントの配列を返すと想定しているため、この方法で err_function を記述するのは少し難しいので、別の scipy の関数を使用しないでください -最小化。次に、メトリックを追加します。これは、既に持っているエラー関数であり、機能します。ただし、get_spot_grid 関数 (y_spots と y_spads) にはもう 1 つタイプミスがあると思います。完全なコード:

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))
于 2014-02-06T08:24:39.057 に答える
0

leastsq に渡される関数 (err_func など) は、xeand と同じ形状の値の配列を返す必要があります。つまり、 andyeの各値に対して 1 つの残差が返されます。xeye

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)

mean()inの呼び出しget_mean_distanceは、戻り値を 1 つのスカラーに減らしています。xeと にye渡されるのerr_funcは、スカラーではなく配列であることに注意してください。

エラーメッセージ

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

は、パラメータの数 4 が によって返される残差の数 1 を超えてはならないことを示していますerr_func


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)

私はあなたのコードがどれであるべきかを知るのに十分なほどよく理解していません. しかし、アイデアは、 と の各「ポイント」に 1 つの値が存在する必要があるということxeですye

于 2014-02-06T01:45:38.943 に答える