Я использую функцию наименьший квадрат из scipy.optimize, чтобы подогнать координаты сферы и радиус из 3D-координат.
Итак, мой код выглядит так:
def distance(pc,point):
xc,yc,zc,rd = pc
x ,y ,z = point
return np.sqrt((xc-x)**2+(yc-y)**2+(zc-z)**2)
def sphere_params(coords):
from scipy import optimize
err = lambda pc,point : distance(pc,point) - pc[3]
pc = [0, 0, 0, 1]
pc, success = optimize.leastsq(err, pc[:], args=(coords,))
return pc
(Построено благодаря: как мне подгонять 3D-данные.)
Я начал работать с переменными координатами в виде списка кортежей (каждый кортеж представляет собой координату x, y, z):
>> coords
>> [(0,0,0),(0,0,1),(-1,0,0),(0.57,0.57,0.57),...,(1,0,0),(0,1,0)]
Что привело меня к ошибке:
>> pc = sphere_params(coords)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/michel/anaconda/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 374, in leastsq
raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m))
TypeError: Improper input: N=4 must not exceed M=3
Где N — количество параметров, хранящихся в компьютере, а M — количество точек данных. Это выглядит так, как будто я не дал достаточно точек данных, в то время как мои координаты списка фактически перегруппировывают 351 кортеж против 4 параметров в pc!
Из того, что я прочитал в мини-пакете, фактическим виновником кажется эта строка (из _check_func()):
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
Если я не ошибаюсь, в моем случае это означает
res = atleast_1d(distance(*(pc[:len(pc)],) + args)
Но мне ужасно трудно понять, что это значит вместе с остальной частью функции _check_func().
В итоге я изменил координаты в массив, прежде чем передать его в качестве аргумента sphere_param()
: coords = np.asarray(coords).T
, и он начал работать нормально. Я действительно хотел бы понять, почему формат данных доставлял мне проблемы!
Заранее большое спасибо за ваши ответы!
РЕДАКТИРОВАТЬ: я заметил, что мое использование координат для функций «расстояние» и «ошибка» было действительно неразумным и вводящим в заблуждение, этого не было в моем исходном коде, поэтому это не было ядром проблемы. Теперь побольше смысла.
x, y, z = [(x0, y0, z0), (x1, y1, z1), (x2, y2, z2), (x3, y3, z3), etc]
, что переводит первый элемент списка вx
, второй вy
и третий вz
, но ваш список на самом деле намного длиннее этого. То есть он попытается установитьx
в(x0, y0, z0)
. Что вам нужно, так этоx, y, z = zip(coords)
, который будет делать то же самое, что и транспонирование. Я не знаю, почему вы не получилиValueError: too many values to unpack
- person askewchan   schedule 27.08.2015distance
: вxc,yx,zx,rd = pc
я думаю, чтоyx
иzx
должны бытьyc
иzc
. - person askewchan   schedule 27.08.2015args
, который представляет собой кортеж вокругcoords
целиком, поэтому он передаетargs = (coords,)
какerr(pc, *args)
, что эквивалентноerr(pc, args[0], ...)
, что, в свою очередь, равноerr(pc, coords)
, посколькуlen(args)
равно1
. - person askewchan   schedule 27.08.2015