2017-02-23 23 views
2

私はthin plate splineアルゴリズム(this descriptionも参照)を実装して、Pythonを使って分散データを補間しました。私の薄板スプライン補間の実装の結果は、独立変数に依存します

初期散乱データのバウンディングボックスのアスペクト比が1に近い場合、アルゴリズムが正しく動作しているように見えますが、データポイント座標の1つをスケーリングすると補間結果が変わります。私は達成しようとしているものを代表する最小の実例を作成しました。以下は、50のランダムな点の補間の結果を示す2つのプロットです。

まず、ドメインx = [0, 3], y = [0, 120]z = x^2の補間:

failed interpolation

あなたが見ることができるように、補間は失敗します。さて、同じプロセスを実行するが、40倍にx値をスケーリングした後、私が手:

successful interpolation

この時間は、結果が良く見えます。わずかに異なるスケーリング係数を選択すると、わずかに異なる補間が行われます。これは私のアルゴリズムで何かが間違っていることを示していますが、正確に何かを見つけることはできません。ここではアルゴリズムです:最後に

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) 

、ここで私は2つのプロットを作成するために使用されるコードスニペットは、次のとおりです。

import matplotlib.pyplot as plt 
import numpy as np 

N = 50 # Number of random points 

pts = np.random.rand(N,2) 
pts[:,0] *= 3.0 # initial x values 
pts[:,1] *= 120.0 # initial y values 

z1 = (pts[:,0])**2.0 

for scale in [1.0, 40.0]: 

    pts1 = pts.copy() 
    pts1[:,0] *= scale 

    x2 = np.linspace(np.min(pts1[:,0]), np.max(pts1[:,0]), 40) 
    y2 = np.linspace(np.min(pts1[:,1]), np.max(pts1[:,1]), 40) 
    x2, y2 = np.meshgrid(x2, y2) 

    pts2 = np.vstack((x2.flatten(), y2.flatten())).T 
    z2 = TPS(pts1, z1.reshape(z1.shape[0], 1), pts2, 0.0) 

    # Display 
    fig = plt.figure(figsize=(4,3)) 
    ax = fig.add_subplot(111) 
    C = ax.contourf(x2, y2, z2.reshape(x2.shape), np.linspace(0,9,10), extend='both') 
    ax.plot(pts1[:,0], pts1[:,1], 'ok') 
    ax.set_xlabel('x') 
    ax.set_ylabel('y') 
    plt.colorbar(C, extendfrac=0) 
    plt.tight_layout() 

plt.show() 

答えて

0

薄板スプラインは、あなたがでxとyをスケーリングする場合を意味し、不変スカラーであります同じ要因、結果は同じでなければなりません。しかし、xとyのスケールを違うと、結果は異なります。これはラジアル基底関数の共通特性です。ラジアル基底関数の中には、スカラ不変でないものもあります。

関連する問題