Algorithm 薄板样条插值实现的结果取决于自变量
我实现了该算法(另请参见),以便使用Python对分散的数据进行插值 当初始散乱数据的边界框的纵横比接近1时,我的算法似乎工作正常。但是,缩放其中一个数据点坐标会更改插值结果。我创建了一个最小的工作示例,它代表了我正在努力实现的目标。下面是显示50个随机点插值结果的两个图 首先,在域Algorithm 薄板样条插值实现的结果取决于自变量,algorithm,python-3.x,interpolation,Algorithm,Python 3.x,Interpolation,我实现了该算法(另请参见),以便使用Python对分散的数据进行插值 当初始散乱数据的边界框的纵横比接近1时,我的算法似乎工作正常。但是,缩放其中一个数据点坐标会更改插值结果。我创建了一个最小的工作示例,它代表了我正在努力实现的目标。下面是显示50个随机点插值结果的两个图 首先,在域x=[0,3],y=[0120]上插入z=x^2: 如您所见,插值失败。现在,执行相同的过程,但将x值缩放40倍后,我得到: 这一次,结果看起来更好。选择稍有不同的比例因子将导致稍有不同的插值。这表明我的算法有问
x=[0,3],y=[0120]
上插入z=x^2
:
如您所见,插值失败。现在,执行相同的过程,但将x
值缩放40倍后,我得到:
这一次,结果看起来更好。选择稍有不同的比例因子将导致稍有不同的插值。这表明我的算法有问题,但我找不到确切的原因。以下是算法:
import numpy as np
import numba as nb
# pts1 = Mx2 matrix (original coordinates)
# z1 = Mx1 column vector (original values)
# pts2 = Nx2 matrix (interpolation coordinates)
def gen_K(n, pts1):
K = np.zeros((n,n))
for i in range(0,n):
for j in range(0,n):
if i != j:
r = ( (pts1[i,0] - pts1[j,0])**2.0 + (pts1[i,1] - pts1[j,1])**2.0 )**0.5
K[i,j] = r**2.0*np.log(r)
return K
def compute_z2(m, n, pts1, pts2, coeffs):
z2 = np.zeros((m,1))
x_min = np.min(pts1[:,0])
x_max = np.max(pts1[:,0])
y_min = np.min(pts1[:,1])
y_max = np.max(pts1[:,1])
for k in range(0,m):
pt = pts2[k,:]
# If point is located inside bounding box of pts1
if (pt[0] >= x_min and pt[0] <= x_max and pt[1] >= y_min and pt[1] <= y_max):
z2[k,0] = coeffs[-3,0] + coeffs[-2,0]*pts2[k,0] + coeffs[-1,0]*pts2[k,1]
for i in range(0,n):
r2 = ( (pts1[i,0] - pts2[k,0])**2.0 + (pts1[i,1] - pts2[k,1])**2.0 )**0.5
if r2 != 0:
z2[k,0] += coeffs[i,0]*( r2**2.0*np.log(r2) )
else:
z2[k,0] = np.nan
return z2
gen_K_nb = nb.jit(nb.float64[:,:](nb.int64, nb.float64[:,:]), nopython = True)(gen_K)
compute_z2_nb = nb.jit(nb.float64[:,:](nb.int64, nb.int64, nb.float64[:,:], nb.float64[:,:], nb.float64[:,:]), nopython = True)(compute_z2)
def TPS(pts1, z1, pts2, factor):
n, m = pts1.shape[0], pts2.shape[0]
P = np.hstack((np.ones((n,1)),pts1))
Y = np.vstack((z1, np.zeros((3,1))))
K = gen_K_nb(n, pts1)
K += factor*np.identity(n)
L = np.zeros((n+3,n+3))
L[0:n, 0:n] = K
L[0:n, n:n+3] = P
L[n:n+3, 0:n] = P.T
L_inv = np.linalg.inv(L)
coeffs = L_inv.dot(Y)
return compute_z2_nb(m, n, pts1, pts2, coeffs)
薄板样条曲线是标量不变的,这意味着如果用相同的因子缩放x和y,结果应该是相同的。但是,如果缩放x和y的方式不同,则结果将不同。这是径向基函数的共同特征。有些径向基函数甚至不是标量不变的 当你说它“失败”时,你是什么意思?最大的问题是,它是否仍然精确地在构造点处插值?假设您的代码是正确的,并且您没有病态,那么它应该不会失败 我认为正在发生的是,添加比例使
x
方向上的行为更具主导性,因此您不会看到插值自然产生的摆动
另外,通过矢量化,您可以大大加快代码的速度,而无需使用Numba
import scipy.spatial.distance
import scipy.special
def gen_K(n,pts1):
# No need for n but kept to maintain compatability
pts1 = np.atleast_2d(pts1)
r = scipy.spatial.distance.cdist(pts1,pts1)
return scipy.special.xlogy(r**2,r)
import scipy.spatial.distance
import scipy.special
def gen_K(n,pts1):
# No need for n but kept to maintain compatability
pts1 = np.atleast_2d(pts1)
r = scipy.spatial.distance.cdist(pts1,pts1)
return scipy.special.xlogy(r**2,r)