Сплайн-интерполяция в 3D на питоне

Я ищу эквивалентную команду Matlab

Vq = interp3(X,Y,Z,V,Xq,Yq,Zq)

в Питоне. В Matlab я могу использовать метод интерполяции «сплайн», который я не могу найти в python для 3D-данных. Существует scipy.interpolate.griddata, но у него нет опции сплайна для 3D-данных.

Данные, которые я хочу интерполировать, представляют собой трехмерную матрицу (51x51x51), которая регулярно распределяется по трехмерной сетке.

scipy.interpolate.Rbf может быть вариантом, но у меня он не работает:

xi = yi = zi = np.linspace(1, 132651, 132651) interp = scipy.interpolate.Rbf(xi, yi, zi, data, function='cubic')

приводит к ошибке памяти.

Изменить: минимальный пример того, что я хочу (без интерполяции): код Matlab

v=rand([51,51,51]);
isosurface (v, 0.3);

Для простоты в этом примере я использую случайные данные. Я хочу сделать графики изоповерхностей (в частности, графики поверхности Ферми). Поскольку некоторые структуры очень маленькие, необходимо высокое разрешение сетки 51x51x51.

Еще один комментарий: набор данных в матрице не зависит друг от друга, z (или 3-й компонент) НЕ является функцией x и y.


person cerv21    schedule 04.09.2017    source источник
comment
Ошибка памяти может быть связана с размером ваших данных. Почему вы используете interpolate.Rbf? scipy эквивалентно interp3, скорее всего, будет griddata, docs.scipy.org/doc/scipy-0.14.0/reference/generated/.   -  person atru    schedule 04.09.2017
comment
griddata поддерживает (кубические) сплайны только в 2D (см. вашу ссылку). docs.scipy.org/doc/scipy/reference/ сгенерированный/, интерполяция. Rbf, похоже, не имеет этого ограничения.   -  person cerv21    schedule 04.09.2017
comment
Правда куб не проверял. Но Rbf, кажется, работает — так как вы получили ошибку памяти, пробовали ли вы меньшие наборы данных?   -  person atru    schedule 05.09.2017
comment
Я не могу использовать scipy.interpolate.Rbf, потому что у меня более 5000 точек данных. согласно stackoverflow.com/questions/39880747/ . Так как у меня 132000 баллов, то это не вариант. А в Matlab сплайн-интерполяция работает с гораздо более высокими наборами данных. Возможно, ndimage.map_coordinates является опцией ( docs.scipy.org/doc/scipy/reference/generated/ ), но я еще этого не понял.   -  person cerv21    schedule 05.09.2017


Ответы (1)


Сплайн-интерполяция для 3+ измерений может быть выполнена с использованием scipy.interpolate.Rbf, как вы описали. Для целей построения графика вы можете использовать меньшее разрешение (1000 точек — хорошее эмпирическое правило), а когда вы хотите оценить свой сплайн, вы можете без проблем интерполировать гораздо больше, чем 132000 точек (см. пример ниже).

Можете ли вы добавить минимальный, полный и проверяемый пример того, что вы пытаетесь сделать в Matlab? Это объяснит, почему вам нужно создать пространство сетки с разрешением 132000 точек. Также, обратите внимание, существует проклятие размерности. Matlab использует кубический сплайн или кусочный полином, которые могут быть опасны из-за переобучения. Я рекомендую вам использовать более разумный метод для обучения на 51 точке данных и применения к более чем 132000 точкам данных. Это отличный пример подбора полиномиальной кривой и выбора модели.

Пример:

Сгенерировать данные:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d

%matplotlib inline
import random
# set seed to reproducible
random.seed(1)
data_size = 51
max_value_range = 132651
x = np.array([random.random()*max_value_range for p in range(0,data_size)])
y = np.array([random.random()*max_value_range for p in range(0,data_size)])
z = 2*x*x*x + np.sqrt(y)*y + random.random()
fig = plt.figure(figsize=(10,6))
ax = axes3d.Axes3D(fig)
ax.scatter3D(x,y,z, c='r')

введите описание изображения здесь

Подгонка сплайна и интерполяция

x_grid = np.linspace(0, 132651, 1000*len(x))
y_grid = np.linspace(0, 132651, 1000*len(y))
B1, B2 = np.meshgrid(x_grid, y_grid, indexing='xy')
Z = np.zeros((x.size, z.size))

import scipy as sp
import scipy.interpolate
spline = sp.interpolate.Rbf(x,y,z,function='thin_plate',smooth=5, episilon=5)

Z = spline(B1,B2)
fig = plt.figure(figsize=(10,6))
ax = axes3d.Axes3D(fig)
ax.plot_wireframe(B1, B2, Z)
ax.plot_surface(B1, B2, Z,alpha=0.2)
ax.scatter3D(x,y,z, c='r')

введите описание изображения здесь

Подгонка сплайна к большим данным

predict_data_size = 132000
x_predict = np.array([random.random()*max_value_range for p in range(0,predict_data_size)])
y_predict = np.array([random.random()*max_value_range for p in range(0,predict_data_size)])
z_predict = spline(x_predict, y_predict)
fig = plt.figure(figsize=(10,6))
ax = axes3d.Axes3D(fig)
ax.plot_wireframe(B1, B2, Z)
ax.plot_surface(B1, B2, Z,alpha=0.2)
ax.scatter3D(x_predict,y_predict,z_predict, c='r')

введите описание изображения здесь

person mrandrewandrade    schedule 26.11.2017
comment
Большое спасибо за ваш комментарий и извините за мой поздний ответ. Я изменил свой вопрос, чтобы сделать его, надеюсь, более ясным. Подводя итог, я хочу сделать изоповерхностные графики. Могу ли я сделать это с вашим ответом? Думаю, если z_predict = spline(x_predict, y_predict) не верно, как у меня, то ваш подход не работает, или я ошибся? - person cerv21; 09.12.2017
comment
Эти сплайны ужасно медленные! - person duhaime; 01.05.2019
comment
Моих 8Gb RAM недостаточно. Я мог бы запустить его с max_value_range = 13265 (на десять меньше), x_grid = np.linspace(0, max_value_range, 1000*len(x)) (на сто меньше - то же самое для y_grid) - person lalebarde; 29.03.2020
comment
Если вы не запускаете его с Jupyter, удалите строку %matplotlib inline и добавьте plt.show() в конце каждой ячейки. - person lalebarde; 29.03.2020