3D-экстраполяция в Python (в основном, scipy.griddata расширена для экстраполяции)

Я использую функцию griddata в scipy для интерполяции 3 и 4-мерных данных. Он работает как чемпион, за исключением того, что он возвращает кучу NaN, потому что некоторые из точек, которые мне нужны, находятся вне диапазона входных данных. Учитывая, что данные Nd в любом случае работают только с интерполяцией в "линейном" режиме, очень просто сделать так, чтобы griddata выполняла экстраполяцию, а не просто возвращала NaN. Кто-нибудь сделал это или нашел обходной путь? Чтобы уточнить: у меня есть неструктурированные данные, поэтому я не могу использовать ни одну из функций, которые требуют регулярной сетки. Спасибо! Alex

1 ответ

Одна из возможностей интерполировать и экстраполировать данные с 3, 4 или фактически любыми измерениями - это scipy.interpolate.Rbf

В get_data() функция и plot_3d() функции прикреплены к концу для удобства.

Пример данных

Данные примера выглядят следующим образом (четвертое измерение, w, показано цветом). Данные расположены неравномерно и не привязаны к сетке.

       x, y, z, w = get_data(N=200)
plot_3d(x, y, z, w)

Интерполяция и экстраполяция в 3D

Во-первых, давайте установим новые координаты x и y. Чтобы сделать это более интересным, давайте экстраполируем в направлении минус x и минус y. Это формирует новый интересующий диапазон x и y.

       xs = np.linspace(-10, 20) # some extrapolation to negative numbers
ys = np.linspace(-10, 20) # some extrapolation to negative numbers
xnew, ynew = np.meshgrid(xs, ys)
xnew = xnew.flatten()
ynew = ynew.flatten()

Интерполяция с помощью scipy.interpolate.Rbf. В настоящее время,

       from scipy.interpolate import Rbf
rbf3 = Rbf(x, y, z, function="multiquadric", smooth=5)
znew = rbf3(xnew, ynew)

plot_3d(xnew, ynew, znew)
  • Может быть сколько угодно переменных / размеров. Первые аргументы (x, y) рассматриваются как координаты узлов. Последний аргумент перед function аргумент - это "значения", которые должны быть интерполированы (сейчас: z).
  • В functionаргумент может быть использован для управления как для значения интерполяции. Это повлияет на результаты, так что поиграйте со своими данными. .
  • В smoothПараметр можно использовать для сглаживания некоторого шума в данных. Если smoothравен нулю, результат интерполируется; он пройдёт через все ваши точки данных. Если это положительное значение, данные будут более плавными. Это повлияет на результаты, так что поиграйте со своими данными. .
  • Ниже приведены результаты, и экстраполяция, конечно, неудачна. Это просто чтобы продемонстрировать, что экстраполяция возможна. Возможно, вы захотите точную настройку function и smoothдля желаемых результатов. Обычно данные не следует экстраполировать "сильно" (как в этом примере).

Добавление четвертого измерения

Также возможно интерполировать и экстраполировать до четвертого измерения. Вот как:

       rbf4 = Rbf(x, y, z, w, function="thin_plate", smooth=5)
wnew = rbf4(xnew, ynew, znew)
plot_3d(xnew, ynew, znew, wnew)
  • Я создал другой Rbf пример для четвертого измерения, и я использовал znew рассчитывается с rbf3 (интерполяция в 3d).
  • Я изменил function к "thin_plate"поскольку казалось, что с этим набором данных визуально он работает лучше.
  • Вот как выглядят результаты:

Приложение: get_data и plot_3d

В целях тестирования:

       import numpy as np

def get_data():
    np.random.seed(100)
    N = 200
    maxval = 20
    x = np.random.random(N) * maxval
    y = np.random.random(N) * maxval
    z = x ** 2 + np.sqrt(y) * y - y ** 3 + np.random.random(N) + 18 * y ** 2 * 2
    w = x ** 2 - np.log(y + (x * y) ** 2)
    return x, y, z, w


def plot_3d(x, y, z, w=None, show=True):
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import axes3d

    fig = plt.figure(figsize=(10, 6))
    ax = axes3d.Axes3D(fig)
    ax.scatter3D(x, y, z, c=w if not w is None else "b")
    plt.show()

Не совсем уверен, что это сработает для вас и пока недоступно, но в версии numpy для разработки есть функция массива 'pad'...

https://github.com/numpy/numpy/blob/master/numpy/lib/arraypad.py

Одним из параметров является 'linear_ramp', который экстраполирует (дополняет) наружу, начиная с граничного значения, и линейно увеличивает / уменьшает до заданного конечного значения.

Это чисто функция Python, так что вы можете просто скопировать ее в свой путь и импортировать (хотя я не проверял)

Другие вопросы по тегам