如何使用 numpy 创建一个 returns 来自数据数组的二维值的函数?
How can I use numpy to create a function that returns two-dimensional values from arrays of data?
这道题是关于推导一个数学函数,该函数 returns 基于数据数组的值对 - 来自二维值的二维值。
我创建了a Python library that drives a pen-plotter using cheap servo motors。
从笔的 x/y 位置,我获得了所需的电机角度,以及需要馈送到它们的脉冲宽度。
这些廉价电机当然是非线性的,整个机械系统表现出滞后和扭曲行为。
库可以用不同的方式计算所需的脉冲宽度值。一种方法是为每个伺服确定一些实际的 pulse-width/angle 测量值,如下所示:
servo_angle_pws = [
# angle, pulse-width
[ 45, 1000],
[ 60, 1200],
[ 90, 1500],
[120, 1800],
[135, 2000],
]
然后 use numpy to create a function that fits the curve 由这些值描述:
servo_2_array = numpy.array(servo_2_angle_pws)
self.angles_to_pw = numpy.poly1d(numpy.polyfit(servo_2_array[:, 0], servo_2_array[:, 1], 3))
看起来像这样:
现在我想采取另一个步骤,以类似的方式找到一个函数,它给我 x/y 位置和脉冲宽度之间的关系,而不是角度(这将提供更高的准确性,因为它将考虑系统中更多现实世界的缺陷)。不过在这种情况下,我将有两对值,如下所示:
# x/y positions, servo pulse-widths
((-8.0, 8.0), (1900, 1413)),
((-8.0, 4.0), (2208, 1605)),
(( 8.0, 4.0), ( 977, 1622)),
((-0.0, 4.0), (1759, 1999)),
(( 6.0, 13.0), (1065, 1121)),
我的问题是:我需要做什么才能得到一个函数(我当然需要其中两个),returns 所需的一对 x/y 脉冲宽度值职位?例如:
pw1 = xy_to_pulsewidths1(x=-4, y=6.3)
pw2 = xy_to_pulsewidths2(x=-4, y=6.3)
我相信我需要做一个“多元回归”——但我不是数学家所以我不知道这是否正确,即使是这样,我在 numpy 的研究中还没有发现任何东西scipy 表示我在代码中实际需要做什么。
如果我没理解错的话,你要进行多元回归,相当于求解一个多元least-squares问题。假设您的函数是二维多项式,您可以使用 polyval2d
and scipy.optimize.least_squares
:
的组合
import numpy as np
from numpy.polynomial.polynomial import polyval2d
from scipy.optimize import least_squares
x = np.array((-8.0,-8.0, 8.0, -0.0, 6.0))
y = np.array((8.0, 4.0, 4.0, 4.0, 13.0))
pulse_widths = np.array(((1900, 1413),(2208, 1605),(977, 1622),(1759, 1999),(1065, 1121)))
# we want to minimize the sum of the squares of the residuals
def residuals(coeffs, x, y, widths, poly_degree):
return polyval2d(x, y, coeffs.reshape(-1, poly_degree+1)) - widths
# polynomial degree
degree = 3
# initial guess for the polynomial coefficients
x0 = np.ones((degree+1)**2)
# res1.x and res2.x contain your coefficients
res1 = least_squares(lambda coeffs: residuals(coeffs, x, y, pulse_widths[:, 0], degree), x0=x0)
res2 = least_squares(lambda coeffs: residuals(coeffs, x, y, pulse_widths[:, 1], degree), x0=x0)
# Evaluate the 2d Polynomial at (x,y)
def xy_to_pulswidth(x, y, coeffs):
num_coeffs = int(np.sqrt(coeffs.size))
return polyval2d(x, y, coeffs.reshape(-1, num_coeffs))
# Evaluate the function
pw1 = xy_to_pulswidth(-4, 6.3, res1.x)
pw2 = xy_to_pulswidth(-4, 6.3, res2.x)
这道题是关于推导一个数学函数,该函数 returns 基于数据数组的值对 - 来自二维值的二维值。
我创建了a Python library that drives a pen-plotter using cheap servo motors。
从笔的 x/y 位置,我获得了所需的电机角度,以及需要馈送到它们的脉冲宽度。
这些廉价电机当然是非线性的,整个机械系统表现出滞后和扭曲行为。
库可以用不同的方式计算所需的脉冲宽度值。一种方法是为每个伺服确定一些实际的 pulse-width/angle 测量值,如下所示:
servo_angle_pws = [
# angle, pulse-width
[ 45, 1000],
[ 60, 1200],
[ 90, 1500],
[120, 1800],
[135, 2000],
]
然后 use numpy to create a function that fits the curve 由这些值描述:
servo_2_array = numpy.array(servo_2_angle_pws)
self.angles_to_pw = numpy.poly1d(numpy.polyfit(servo_2_array[:, 0], servo_2_array[:, 1], 3))
看起来像这样:
现在我想采取另一个步骤,以类似的方式找到一个函数,它给我 x/y 位置和脉冲宽度之间的关系,而不是角度(这将提供更高的准确性,因为它将考虑系统中更多现实世界的缺陷)。不过在这种情况下,我将有两对值,如下所示:
# x/y positions, servo pulse-widths
((-8.0, 8.0), (1900, 1413)),
((-8.0, 4.0), (2208, 1605)),
(( 8.0, 4.0), ( 977, 1622)),
((-0.0, 4.0), (1759, 1999)),
(( 6.0, 13.0), (1065, 1121)),
我的问题是:我需要做什么才能得到一个函数(我当然需要其中两个),returns 所需的一对 x/y 脉冲宽度值职位?例如:
pw1 = xy_to_pulsewidths1(x=-4, y=6.3)
pw2 = xy_to_pulsewidths2(x=-4, y=6.3)
我相信我需要做一个“多元回归”——但我不是数学家所以我不知道这是否正确,即使是这样,我在 numpy 的研究中还没有发现任何东西scipy 表示我在代码中实际需要做什么。
如果我没理解错的话,你要进行多元回归,相当于求解一个多元least-squares问题。假设您的函数是二维多项式,您可以使用 polyval2d
and scipy.optimize.least_squares
:
import numpy as np
from numpy.polynomial.polynomial import polyval2d
from scipy.optimize import least_squares
x = np.array((-8.0,-8.0, 8.0, -0.0, 6.0))
y = np.array((8.0, 4.0, 4.0, 4.0, 13.0))
pulse_widths = np.array(((1900, 1413),(2208, 1605),(977, 1622),(1759, 1999),(1065, 1121)))
# we want to minimize the sum of the squares of the residuals
def residuals(coeffs, x, y, widths, poly_degree):
return polyval2d(x, y, coeffs.reshape(-1, poly_degree+1)) - widths
# polynomial degree
degree = 3
# initial guess for the polynomial coefficients
x0 = np.ones((degree+1)**2)
# res1.x and res2.x contain your coefficients
res1 = least_squares(lambda coeffs: residuals(coeffs, x, y, pulse_widths[:, 0], degree), x0=x0)
res2 = least_squares(lambda coeffs: residuals(coeffs, x, y, pulse_widths[:, 1], degree), x0=x0)
# Evaluate the 2d Polynomial at (x,y)
def xy_to_pulswidth(x, y, coeffs):
num_coeffs = int(np.sqrt(coeffs.size))
return polyval2d(x, y, coeffs.reshape(-1, num_coeffs))
# Evaluate the function
pw1 = xy_to_pulswidth(-4, 6.3, res1.x)
pw2 = xy_to_pulswidth(-4, 6.3, res2.x)