programing

스파이피를 사용하여 2차원 보간을 수행하려면 어떻게 해야 합니까?

padding 2023. 8. 31. 23:41
반응형

스파이피를 사용하여 2차원 보간을 수행하려면 어떻게 해야 합니까?

이 Q&A는 스파이피를 사용한 2차원(및 다차원) 보간에 관한 표준(-ish)으로 의도되었습니다.다양한 다차원 보간 방법의 기본 구문과 관련하여 종종 질문이 있는데, 저도 이를 바로잡고 싶습니다.

저는 분산된 2차원 데이터 포인트 세트를 가지고 있습니다. 그리고 저는 그것들을 멋진 표면으로 플롯하고 싶습니다. 가급적이면 다음과 같은 것을 사용합니다.contourf또는plot_surfacematplotlib.pyplot스파이피를 사용하여 2차원 또는 다차원 데이터를 메시에 보간하려면 어떻게 해야 합니까?

scipy.interpolate▁using다,를 사용하면 오류가 발생합니다. 하지만 사용할 때 오류가 계속 발생합니다.interp2d또는bisplrep또는griddata또는RBFInterpolator 더 (또는이전버전버)전▁(Rbf이 방법들의 적절한 구문은 무엇입니까?

例고:는 대부분 에 두고을 쓰고 저는 주로 구문적인 고려와 일반적인 행동을 염두에 두고 이 게시물을 쓰고 있습니다.저는 설명된 방법의 메모리 및 CPU 측면에 대해 잘 알지 못하며, 보간의 품질이 고려해야 할 주요 측면이 될 수 있도록 데이터 집합이 상당히 작은 사람들을 대상으로 이 답변을 목표로 합니다. 큰 할 때 더발휘하는 (즉, 큰데즉세작때할방성더법나능의은업터이로트매우즉▁(방,▁i▁sets의법(성▁when능,▁thename▁with,griddata그리고.RBFInterpolatorneighbors키워드 인수)를 사용할 수 없습니다.

이 답변은 1.7.0에 도입된 새로운 클래스를 사용합니다.레거시 클래스에 대해서는 이 답변의 이전 버전을 참조하십시오.

세 가지 다차원 보간 방법(/interp2dspline, 및 )을 비교해 보겠습니다.저는 그들에게 두 가지 종류의 보간 작업과 두 가지 종류의 기본 기능(보간될 지점)을 적용할 것입니다.구체적인 예는 2차원 보간을 보여주겠지만 실행 가능한 방법은 임의의 차원에서 적용할 수 있습니다.각 방법은 다양한 종류의 보간을 제공합니다. 모든 경우에 저는 입방 보간(또는 비슷한 것)을1 사용할 것입니다.보간법을 사용할 때마다 원시 데이터와 비교하여 편향이 발생하며, 사용되는 특정 방법이 최종적으로 사용될 아티팩트에 영향을 미친다는 점에 유의해야 합니다.항상 이 점에 유의하고 책임감 있게 인터폴하십시오.

두 개의 보간 작업은 다음과 같습니다.

  1. 업샘플링(입력 데이터는 직사각형 그리드에, 출력 데이터는 더 밀도가 높은 그리드에 있음)
  2. 분산된 데이터를 정규 그리드에 보간

의 함수 ( ()는[x, y] in [-1, 1]x[-1, 1]) 될 것입니다.

  1. 기능: 부럽고친한기능근드기::cos(pi*x)*sin(pi*y)의 범위에 있는.[-1, 1]
  2. 특히,인) 함수: 사한특함(수히, ) 악연:x*y / (x^2 + y^2)에서 0으로, 는 점 근 에 서 처 0.5의 로 으 범 위 값 :[-0.5, 0.5]

그들의 모습은 다음과 같습니다.

fig1: test functions

먼저 이 네 가지 테스트에서 세 가지 방법이 어떻게 작동하는지 시연한 다음 세 가지 모두의 구문을 자세히 설명하겠습니다., 데 을 낭비하고 않을 수도 .interp2d).

테스트 데이터

명시적으로, 여기 제가 입력 데이터를 생성한 코드가 있습니다.이 특정한 경우에는 데이터의 기초가 되는 함수를 분명히 알고 있지만, 보간 방법에 대한 입력을 생성하는 데만 사용할 것입니다.편의상 numpy를 사용하지만(대부분 데이터 생성에 사용) scipy만으로도 충분합니다.

import numpy as np
import scipy.interpolate as interp

# auxiliary function for mesh generation
def gimme_mesh(n):
    minval = -1
    maxval =  1
    # produce an asymmetric shape in order to catch issues with transpositions
    return np.meshgrid(np.linspace(minval, maxval, n),
                       np.linspace(minval, maxval, n + 1))

# set up underlying test functions, vectorized
def fun_smooth(x, y):
    return np.cos(np.pi*x) * np.sin(np.pi*y)

def fun_evil(x, y):
    # watch out for singular origin; function has no unique limit there
    return np.where(x**2 + y**2 > 1e-10, x*y/(x**2+y**2), 0.5)

# sparse input mesh, 6x7 in shape
N_sparse = 6
x_sparse, y_sparse = gimme_mesh(N_sparse)
z_sparse_smooth = fun_smooth(x_sparse, y_sparse)
z_sparse_evil = fun_evil(x_sparse, y_sparse)

# scattered input points, 10^2 altogether (shape (100,))
N_scattered = 10
rng = np.random.default_rng()
x_scattered, y_scattered = rng.random((2, N_scattered**2))*2 - 1
z_scattered_smooth = fun_smooth(x_scattered, y_scattered)
z_scattered_evil = fun_evil(x_scattered, y_scattered)

# dense output mesh, 20x21 in shape
N_dense = 20
x_dense, y_dense = gimme_mesh(N_dense)

원활한 기능 및 업샘플링

가장 쉬운 작업부터 시작하겠습니다.[6, 7]의 하나까지[20, 21]매끄러운 테스트 기능에 대해 설명합니다.

fig2: smooth upsampling

이것은 간단한 작업이지만 출력 간에는 이미 미묘한 차이가 있습니다.언뜻 보기에 세 가지 출력은 모두 합리적입니다.기본 기능에 대한 사전 지식을 바탕으로 주의해야 할 두 가지 기능이 있습니다. 바로 다음과 같은 경우입니다.griddata데이터를 가장 많이 왜곡합니다.에 하십시오.y == -1nearest그아경계쪽림(래의아▁the)))xlabel 이후). 함수는 엄격하게 0이어야 합니다(이후y == -1매끄러운 함수를 위한 노달 라인)이지만, 이는 에 해당되지 않습니다.griddata 한참고에 하십시오.x == -1 뒤): 함수는 근처의 를 나타냄): 기그경국최값(0도 기울기를 나타냄)에서.[-1, -0.5]도 런도데그.griddata출력은 이 영역에서 0이 아닌 기울기를 분명히 보여줍니다.효과는 미묘하지만, 그럼에도 불구하고 편견입니다.

불량 기능 및 업샘플링

조금 더 어려운 작업은 악의적인 기능에 대한 업샘플링을 수행하는 것입니다.

fig3: evil upsampling

세 가지 방법 사이에 분명한 차이가 나타나기 시작했습니다.표면도를 보면, 다음의 출력에 명백한 가상 극단이 나타납니다.interp2d(표시된 표면의 오른쪽에 있는 두 개의 험프를 참고하십시오.)하는 동안에griddata그리고.RBFInterpolator언뜻 보기에 유사한 결과를 생성하는 것처럼 보이며, 근처의 국소 최소치를 생성합니다.[0.4, -0.4]기본 함수에 없는 경우.

하지만, 한 가지 중요한 측면이 있습니다.RBFInterpolator훨씬 우수합니다. 기본 함수의 대칭을 존중합니다(물론 샘플 메시의 대칭으로도 가능합니다).의 입니다.griddata평활한 경우 이미 약하게 보이는 표본 점의 대칭이 깨집니다.

원활한 기능 및 분산된 데이터

대부분 분산된 데이터에 대해 보간을 수행하려고 합니다.이러한 이유로 저는 이 시험들이 더 중요할 것으로 기대합니다.위에 표시된 것처럼, 관심 영역에서 표본 점이 유사 균일하게 선택되었습니다.실제 시나리오에서는 각 측정값에 추가 노이즈가 있을 수 있으므로 원시 데이터를 보간하는 것이 타당한지 여부를 고려해야 합니다.

평활 기능에 대한 출력:

fig4: smooth scattered interpolation

이제 이미 약간의 공포 쇼가 진행 중입니다.는 에서출을잘다니습냈라물에서 을 잘라냈습니다.interp2d[-1, 1]최소한의 정보를 보존하기 위해 오로지 플롯을 위한 것입니다.기본적인 형태가 일부 존재하지만, 방법이 완전히 고장나는 거대한 소음 영역이 있다는 것은 분명합니다. 경째우의 두 번째 griddata모양을 상당히 잘 재현하지만 등고선도의 경계에 있는 흰색 영역을 확인합니다.이는 다음과 같은 사실 때문입니다.griddata입력 데이터 포인트의 볼록한 선체 내부에서만 작동합니다(즉, 외삽은 수행하지 않습니다).볼록한 2선체 외부에 있는 출력점의 기본 NaN 값을 유지했습니다.이러한 특징들을 고려하면,RBFInterpolator가장 잘 하는 것 같습니다.

악의적인 기능과 분산된 데이터

그리고 우리 모두가 기다려온 순간:

fig5: evil scattered interpolation

그것은 별로 놀라운 일이 아닙니다.interp2d단니다합념. 사실와의 통화 에, 통중에.interp2d 당신은합다의니대해야기을친근함간약합니다.RuntimeWarning스플라인 건설이 불가능하다는 불평다른 두 가지 방법에 대해서는,RBFInterpolator결과가 추정되는 영역의 경계 근처에서도 최고의 결과를 산출하는 것처럼 보입니다.


따라서 세 가지 방법에 대해 선호도가 낮은 순서로 몇 마디 하겠습니다(최악의 경우 누구도 읽을 가능성이 가장 낮습니다).

scipy.interpolate.RBFInterpolator

RBF의 으로 된 .RBFInterpolator클래스는 "기본 함수"를 나타냅니다.솔직히 말해서, 저는 이 게시물에 대한 연구를 시작하기 전까지는 이 접근법을 고려해 본 적이 없지만, 저는 미래에 이것들을 사용할 것이라고 꽤 확신합니다.

스플라인 기반 방법(나중에 참조)과 마찬가지로 사용은 두 단계로 이루어집니다. 첫 번째 단계는 호출 가능한 방법을 만듭니다.RBFInterpolator입력 데이터를 기반으로 한 클래스 인스턴스를 호출한 다음 주어진 출력 메시에 대해 이 개체를 호출하여 보간된 결과를 얻습니다.평활 업샘플링 테스트의 예:

import scipy.interpolate as interp

sparse_points = np.stack([x_sparse.ravel(), y_sparse.ravel()], -1)  # shape (N, 2) in 2d
dense_points = np.stack([x_dense.ravel(), y_dense.ravel()], -1)  # shape (N, 2) in 2d

zfun_smooth_rbf = interp.RBFInterpolator(sparse_points, z_sparse_smooth.ravel(),
                                         smoothing=0, kernel='cubic')  # explicit default smoothing=0 for interpolation
z_dense_smooth_rbf = zfun_smooth_rbf(dense_points).reshape(x_dense.shape)  # not really a function, but a callable class instance

zfun_evil_rbf = interp.RBFInterpolator(sparse_points, z_sparse_evil.ravel(),
                                       smoothing=0, kernel='cubic')  # explicit default smoothing=0 for interpolation
z_dense_evil_rbf = zfun_evil_rbf(dense_points).reshape(x_dense.shape)  # not really a function, but a callable class instance

참고로 우리는 API를 만들기 위해 어레이 구축 체조를 해야 했습니다.RBFInterpolator에 2d 포인트는 형체 배열로 통과해야 합니다. 2D 포인트는 형체 배열로.(N, 2)입력 그리드를 평평하게 하고 두 개의 평평한 배열을 쌓아야 합니다.형식의 하며, 이 될 입니다.(N,)2D 그리드에 맞게 다시 모양을 바꿔야 합니다. 때부터RBFInterpolator는 입력점의 치수 수에 대해 가정하지 않으며 보간을 위해 임의 치수를 지원합니다.

그렇게,scipy.interpolate.RBFInterpolator

  • 비정상적인 입력 데이터에 대해서도 잘 조정된 출력을 생성합니다.
  • 고차원에서 보간을 지원합니다.
  • 입력점의 볼록한 선체 외부에서 외삽합니다(물론 외삽은 항상 도박이며, 일반적으로 전혀 의존해서는 안 됩니다).
  • 첫 번째 단계로 보간기를 생성하므로 다양한 출력 지점에서 보간기를 평가하는 것이 추가적인 노력을 덜합니다.
  • 임의의 모양의 출력 점 배열을 가질 수 있습니다(장방형 메시로 제한되는 것과 반대로, 나중에 참조).
  • 입력 데이터의 대칭성을 유지할 가능성이 더 높습니다.
  • 키드에대한여러종방기지능원사형류의에 대해 여러 합니다.kernel:multiquadric,inverse_multiquadric,inverse_quadratic,gaussian,linear,cubic,quintic,thin_plate_spline 1로 인해 하지 않지만, 될 가능성이 .SciPy 1.7.0 기준으로 이 클래스는 기술적인 이유로 인해 사용자 지정 호출을 전달하는 것을 허용하지 않지만, 이는 향후 버전에서 추가될 가능성이 높습니다.
  • 는 정하지 ▁the▁incre다▁can를 증가시켜 할 수 있습니다.smoothing

의 한 보의간한가단보이간법점은지법ating▁rb▁interpol▁one▁that이▁of법f를 보간한다는 것입니다.N데이터 점은 반전을 포함합니다.N x N포인트에 날려버립니다.이러한 2차 복잡성은 많은 데이터 포인트에 대한 메모리 요구를 매우 빠르게 증가시킵니다. 그나러운, 로새운.RBFInterpolator 클스는니다지합원을 합니다.neighbors을 각방형기로 매개변수k가장 가까운 이웃에 위치하여 메모리 필요성을 줄입니다.

scipy.interpolate.griddata

내가 예전에 가장 좋아하던griddata임의의 차원에서의 보간을 위한 일반적인 작업용 말입니다.노달점의 볼록한 선체 밖에 있는 점에 대해 하나의 미리 설정된 값을 설정하는 것 이상으로 외삽을 수행하지는 않지만 외삽은 매우 변덕스럽고 위험한 것이므로 반드시 사기라고 할 수는 없습니다. 예 예용 사:

sparse_points = np.stack([x_sparse.ravel(), y_sparse.ravel()], -1)  # shape (N, 2) in 2d
z_dense_smooth_griddata = interp.griddata(sparse_points, z_sparse_smooth.ravel(),
                                          (x_dense, y_dense), method='cubic')  # default method is linear

입력 어레이의 경우와 동일한 어레이 변환이 필요했습니다.RBFInterpolator은 모양 .[N, D]D치수 또는 1d 어레이의 튜플로:

z_dense_smooth_griddata = interp.griddata((x_sparse.ravel(), y_sparse.ravel()),
                                          z_sparse_smooth.ravel(), (x_dense, y_dense), method='cubic')

출력 지점 배열은 (위의 두 스니펫에서와 같이) 임의 차원 배열의 튜플로 지정할 수 있으므로 유연성이 향상됩니다.

말하면, 히말해서단간,서▁in해말히간,scipy.interpolate.griddata

  • 비정상적인 입력 데이터에 대해서도 잘 조정된 출력을 생성합니다.
  • 고차원에서 보간을 지원합니다.
  • 을 수행하지 을 설정할 수 (참조: 외법수행않으입, 껍볼외출있수다설니습값대할정단참조을일질력부해록에의며삽의력점을지하see있(참▁does▁can조▁be다니습▁of▁(▁value▁a▁outside▁for▁the▁set▁single).fill_value)
  • 단일 호출에서 보간된 값을 계산하므로 여러 출력 지점 세트의 프로빙이 처음부터 시작됩니다.
  • 임의의 모양의 출력 점을 가질 수 있습니다.
  • 1d 및 2d 단위의 입방체 임의 치수에서 가장 가까운 제곱 및 선형 보간을 지원합니다. 가까운 및 은 가장가이및선보사간을 사용합니다.NearestNDInterpolator그리고.LinearNDInterpolator각각후 아있습니. 1d 하고, 1d 입방 보간은 1d 입방 보간을 사용합니다.CloughTocher2DInterpolator연속적으로 미분 가능한 조각별 보간기를 구성합니다.
  • 입력 데이터의 대칭을 위반할 수 있음

scipy.interpolate.interp2d/scipy.interpolate.bisplrep

는 ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠinterp2d그리고 그것의 친척들은 그것이 기만적인 이름을 가지고 있고, 사람들이 그것을 사용하려고 할 것이라는 것입니다.스포일러 경고: 사용하지 마십시오. SciPy 버전 1.10에서는 더 이상 사용되지 않으며 SciPy 1.12에서는 제거될 예정입니다.자세한 내용은 이 메일 목록 토론을 참조하십시오.또한 2차원 보간에 특별히 사용된다는 점에서 이전의 대상자들보다 더 특별하지만, 이것이 다변량 보간에 가장 일반적인 경우라고 생각합니다.

구론에관한한문한,,interp2d는 와유다사 니합다니.RBFInterpolator먼저 실제 보간 값을 제공하기 위해 호출될 수 있는 보간 인스턴스를 구성해야 한다는 점에서.그리드에 . 출력 지점은 직사각형 메시에 위치해야 하므로 보간기 호출로 들어가는 입력은 출력 그리드에 걸쳐 있는 1d 벡터여야 합니다.numpy.meshgrid:

# reminder: x_sparse and y_sparse are of shape [6, 7] from numpy.meshgrid
zfun_smooth_interp2d = interp.interp2d(x_sparse, y_sparse, z_sparse_smooth, kind='cubic')   # default kind is 'linear'
# reminder: x_dense and y_dense are of shape (20, 21) from numpy.meshgrid
xvec = x_dense[0,:] # 1d array of unique x values, 20 elements
yvec = y_dense[:,0] # 1d array of unique y values, 21 elements
z_dense_smooth_interp2d = zfun_smooth_interp2d(xvec, yvec)   # output is (20, 21)-shaped array

▁when하나를 사용할 때 발생하는 실수 중 입니다.interp2d당신의 완전한 2D 메시를 인터폴 호출에 넣는 것이고, 그것은 폭발적인 메모리 소비로 이어지고, 바라건대 서둘러야 합니다.MemoryError.

자의 큰 , 장큰문는제가▁now.interp2d그것은 종종 작동하지 않는다는 것입니다.이것을 이해하기 위해서, 우리는 후드 아래를 살펴봐야 합니다.알고 보니interp2d는 하위 레벨 함수 +에 대한 래퍼로, FITPACK 루틴(포트란으로 작성됨)에 대한 래퍼입니다.앞의 예에 해당하는 호출은 다음과 같습니다.

kind = 'cubic'
if kind == 'linear':
    kx = ky = 1
elif kind == 'cubic':
    kx = ky = 3
elif kind == 'quintic':
    kx = ky = 5
# bisplrep constructs a spline representation, bisplev evaluates the spline at given points
bisp_smooth = interp.bisplrep(x_sparse.ravel(), y_sparse.ravel(),
                              z_sparse_smooth.ravel(), kx=kx, ky=ky, s=0)
z_dense_smooth_bisplrep = interp.bisplev(xvec, yvec, bisp_smooth).T  # note the transpose

자, 여기에 대한 것이 있습니다.interp2d(스파이 버전 1.7.0)에 대한 좋은 의견이 있습니다.interp2d:

if not rectangular_grid:
    # TODO: surfit is really not meant for interpolation!
    self.tck = fitpack.bisplrep(x, y, z, kx=kx, ky=ky, s=0.0)

로 고정말로리그로.interpolate/fitpack.pybisplrep이 있고 궁극적으로 " ▁there로으궁적극"

tx, ty, c, o = _fitpack._surfit(x, y, z, w, xb, xe, yb, ye, kx, ky,
                                task, s, eps, tx, ty, nxest, nyest,
                                wrk, lwrk1, lwrk2)                 

그리고 이것이 마지막입니다.▁under의 기본이 되는 .interp2d보간을 수행하기 위한 것이 아닙니다.이러한 데이터는 충분히 잘 작동하는 데이터로 충분할 수도 있지만, 현실적인 상황에서는 다른 데이터를 사용하는 것이 좋습니다.

부터 말하자면, 결부터말면자하론,면,interpolate.interp2d

  • 효율적인 데이터를 사용하더라도 아티팩트가 발생할 수 있습니다.
  • 이변량 문제에 대한 것입니다().interpn그리드에 정의된 입력 지점의 경우)
  • 외삽법을 수행합니다.
  • 첫 번째 단계로 보간기를 생성하므로 다양한 출력 지점에서 보간기를 평가하는 것이 추가적인 노력을 덜합니다.
  • 직사각형 그리드를 통해서만 출력을 생성할 수 있습니다. 산란 출력의 경우 루프에서 보간기를 호출해야 합니다.
  • 선형, 입방 및 5중 보간 지원
  • 입력 데이터의 대칭을 위반할 수 있음

1저는 꽤 확신합니다.cubic그리고.linear 의일종능의 기본 .RBFInterpolator동일한 이름의 다른 인터폴레이터와 정확히 일치하지 않습니다.
2이러한 NaN은 표면도가 매우 이상하게 보이는 이유이기도 합니다. matplotlib은 역사적으로 적절한 깊이 정보로 복잡한 3D 객체를 그리는 데 어려움이 있습니다.데이터의 NaN 값은 렌더러를 혼동하므로 뒤에 있어야 하는 표면 부분이 앞에 표시됩니다.이것은 시각화의 문제이지 보간의 문제가 아닙니다.

언급URL : https://stackoverflow.com/questions/37872171/how-can-i-perform-two-dimensional-interpolation-using-scipy

반응형