Интерполяция Python - PullRequest
       18

Интерполяция Python

0 голосов
/ 08 мая 2019

Моя проблема довольно проста, однако я не могу найти быстрое решение.

Я хотел бы интерполировать массив y_model, который определен как x_model координаты

x_model = np. array([ 400.,  425.,  450.,  475.,  500.,  525.,  550.,  575.,  600.,
    625.,  650.,  675.,  700.])
y_model = np.array([  3.30395705e-03,   3.07586379e-03,   2.90207925e-03,
     2.81385536e-03,   2.78152394e-03,   2.14072505e-03,
     1.64075861e-03,   9.81255709e-04,   3.61950352e-04,
     2.15834081e-04,   1.35457654e-04,   8.22104550e-05,
     5.84126935e-05])

до нового, x_data координаты:

x_data = np.array([412., 443., 490., 510., 555., 670.])

Итак, я должен получить простой одномерный массив y-data с 6 элементами.

Я думал о чем-то подобном, каково ваше мнение?

from scipy import interpolate

f                  = interpolate.interp1d(x_model, y_model, kind = 'linear')
y_data             = f(x_data)

Изначально было найдено решение, основанное на поднятой проблеме, ограничивающее вопрос линейной интерполяцией. Однако в ходе обсуждения некоторые авторы справедливо отметили, что для такой задачи линейное приближение будет недостаточным.

Должно ли подгонка нелинейной кривой быть более подходящей?

Ответы [ 4 ]

2 голосов
/ 08 мая 2019

Наиболее простыми методами было бы подгонка линейной функции с использованием метода наименьших квадратов. Простая реализация в numpy это numpy.linalg.lstsq.

Затем можно использовать функцию lambda x: m*x+c с вычисленным наклоном m и смещением c, чтобы получить значение y в строке для любого x.

Примерная документация содержит пример, который выглядит почти как пример в вашем вопросе.


Мой ответ выше для случая линейной интерполяции.

Относительно вашего редактирования от линейной до общей интерполяции: вам нужно знать, какую функцию вы хотите подогнать. Вы предполагаете, что ваши данные линейны?

Вы можете установить линейную функцию для каждого набора точек, но результат может быть плохим, либо потому, что нет линейных отношений, либо потому, что это шумные данные. Не имея представления о том, какая функция может быть подходящей или насколько велик уровень шума, вы не сможете легко подобрать функцию.

То же самое верно для многочленов более высокого порядка, за исключением того, что вы можете изменить rror с недостаточного подбора (линейная регрессия для функции, которая не является линейной) на переобучение (имеющего слишком сложную функцию, которая соответствует заданным точкам, но не подходит для интерполяция).

2 голосов
/ 08 мая 2019

Numpy имеет функцию interp, которая может сделать это для вас.Вы можете просто позвонить:

y_data = np.interp(x_data,x_model,y_model)

Документацию для numpy.interp () вы можете найти здесь: https://docs.scipy.org/doc/numpy/reference/generated/numpy.interp.html

1 голос
/ 08 мая 2019

«Научный» способ сделать это - подогнать линейную функцию к существующим точкам данных и затем вычислить функцию по новым значениям x_values. Это имеет множество преимуществ, включая возможное использование неопределенностей для каждого элемента данных, а также возможность распространения ошибок для интерполированных значений. (например, в сочетании с очень хорошим пакетом «неопределенностей») Вы также можете легко изменить функцию модели, и она не обязательно должна быть линейной, но может быть любой функцией ...

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit


x_model = np. array([ 400.,  425.,  450.,  475.,  500.,  525.,  550.,  575.,  600., 625.,  650.,  675.,  700.])
y_model = np.array([  3.30395705e-03,   3.07586379e-03,   2.90207925e-03,
     2.81385536e-03,   2.78152394e-03,   2.14072505e-03,
     1.64075861e-03,   9.81255709e-04,   3.61950352e-04,
     2.15834081e-04,   1.35457654e-04,   8.22104550e-05,
     5.84126935e-05])

x_data = np.array([412., 443., 490., 510., 555., 670.])


def linFunc(x, k, d):
    return k*x+d


cop, cov = curve_fit(linFunc, x_model, y_model)


xplot = np.linspace(min(x_model), max(x_model), 10**4)

plt.figure()
plt.plot(x_model, y_model, 'ro', label = 'original data')
plt.plot(xplot, linFunc(xplot, *cop), 'r--', label = "fittet function")
plt.plot(x_data, linFunc(x_data, *cop), 'bo', label = "interpolated values")

print(linFunc(x_data, *cop))
1 голос
/ 08 мая 2019

Если вы хотите иметь возможность проверить свою линейную регрессию и немного ее настроить, я бы порекомендовал использовать линейную регрессию scikit-learn. Код будет следующим:

import numpy as np
from sklearn.linear_model import LinearRegression

x_model = np. array([ 400.,  425.,  450.,  475.,  500.,  525.,  550.,  575.,  600.,
    625.,  650.,  675.,  700.])
y_model = np.array([  3.30395705e-03,   3.07586379e-03,   2.90207925e-03,
     2.81385536e-03,   2.78152394e-03,   2.14072505e-03,
     1.64075861e-03,   9.81255709e-04,   3.61950352e-04,
     2.15834081e-04,   1.35457654e-04,   8.22104550e-05,
     5.84126935e-05])

lr = LinearRegression()
lr.fit(x_model[:, None], y_model)

x_data = np.array([412., 443., 490., 510., 555., 670.])
y_data = lr.predict(x_data[:, None])
print(y_data)

Обратите внимание, что мне нужно добавить измерение к x при подгонке или прогнозировании, потому что линейная регрессия ожидает двумерный массив.

...