Найпростіший підхід - зробити якусь інтерполяцію сплайну, як пропонує Джим Клей (лінійний чи інший). Однак якщо у вас розкіш пакетної обробки, і особливо якщо у вас завищений набір неоднорідних зразків, існує надзвичайно елегантний алгоритм "ідеального відновлення". З чисельних причин це може бути не практично у всіх випадках, але про нього, принаймні, варто знати концептуально. Я вперше про це прочитав у цій статті .
Хитрість полягає в тому, щоб вважати ваш набір неоднорідних зразків таким, що вже був реконструйований з рівномірних зразків за рахунок синпокальної інтерполяції . Дотримуючись позначень у статті:
у( t ) = ∑k = 1Nу( k T) гріх( π( т - к Т) / Т)π( т - к Т) / Т= ∑k = 1Nу( k T) s i n c ( t - k TТ) .
Зауважимо, що це надає набір лінійних рівнянь, по одному для кожного неоднорідного зразка , де невідомі є рівномірно розташованими зразками , наприклад:y ( k T )у( t )у( k T)
⎡⎣⎢⎢⎢⎢у( т. зв0)у( т. зв1)⋯у( т. звм)⎤⎦⎥⎥⎥⎥= ⎡⎣⎢⎢⎢⎢⎢⎢s i n c ( t0- ТТ)s i n c ( t1- ТТ)⋯s i n c ( tм- ТТ)s i n c ( t0- 2 ТТ)s i n c ( t1- 2 ТТ)⋯s i n c ( tм- 2 ТТ)⋯⋯⋯⋯s i n c ( t0- п. ТТ)s i n c ( t1- п. ТТ)⋯s i n c ( tм- п. ТТ)⎤⎦⎥⎥⎥⎥⎥⎥⎡⎣⎢⎢⎢⎢у( Т)у( 2 Т)⋯у( н Т)⎤⎦⎥⎥⎥⎥.
У наведеному рівнянні - кількість невідомих рівномірних зразків, - обернена рівномірна швидкість вибірки, - кількість неоднорідних зразків (яка може бути більше ). Обчислюючи рішення найменших квадратів цієї системи, рівномірні зразки можна реконструювати. Технічно потрібні лише неоднорідних зразків, але залежно від того, наскільки вони "розкидані" в часі, інтерполяційна матриця може бути жахливо обумовлена . У такому випадку зазвичай допомагає використання більше неоднорідних зразків.T m n nнТмнн
Як приклад іграшки, ось порівняння (з використанням numpy ) між вищевказаним методом та інтерполяцією кубічної сплайну на м'яко тремтілій сітці:
(Код для відтворення вищевказаного сюжету міститься в кінці цієї відповіді)
Все, що було сказано, для якісних, надійних методів, починаючи з чогось в одному з наступних робіт, мабуть, буде більш доречним:
А. Олдрубі та Карлхенц Грохеніг, Неоднорідне відбір проб та реконструкція в інваріантних просторах зсуву , SIAM Rev., 2001, вип . 4, 585–620. ( посилання у форматі PDF ).
К. Гроченіг та Х. Шваб, Швидкі локальні методи реконструкції для неоднорідного відбору проб у просторах , що інвартують зсув , SIAM J. Matrix Anal. Appl., 24 (2003), 899-913.
-
import numpy as np
import pylab as py
import scipy.interpolate as spi
import numpy.random as npr
import numpy.linalg as npl
npr.seed(0)
class Signal(object):
def __init__(self, x, y):
self.x = x
self.y = y
def plot(self, title):
self._plot(title)
py.plot(self.x, self.y ,'bo-')
py.ylim([-1.8,1.8])
py.plot(hires.x,hires.y, 'k-', alpha=.5)
def _plot(self, title):
py.grid()
py.title(title)
py.xlim([0.0,1.0])
def sinc_resample(self, xnew):
m,n = (len(self.x), len(xnew))
T = 1./n
A = np.zeros((m,n))
for i in range(0,m):
A[i,:] = np.sinc((self.x[i] - xnew)/T)
return Signal(xnew, npl.lstsq(A,self.y)[0])
def spline_resample(self, xnew):
s = spi.splrep(self.x, self.y)
return Signal(xnew, spi.splev(xnew, s))
class Error(Signal):
def __init__(self, a, b):
self.x = a.x
self.y = np.abs(a.y - b.y)
def plot(self, title):
self._plot(title)
py.plot(self.x, self.y, 'bo-')
py.ylim([0.0,.5])
def grid(n): return np.linspace(0.0,1.0,n)
def sample(f, x): return Signal(x, f(x))
def random_offsets(n, amt=.5):
return (amt/n) * (npr.random(n) - .5)
def jittered_grid(n, amt=.5):
return np.sort(grid(n) + random_offsets(n,amt))
def f(x):
t = np.pi * 2.0 * x
return np.sin(t) + .5 * np.sin(14.0*t)
n = 30
m = n + 1
# Signals
even = sample(f, np.r_[1:n+1] / float(n))
uneven = sample(f, jittered_grid(m))
hires = sample(f, grid(10*n))
sinc = uneven.sinc_resample(even.x)
spline = uneven.spline_resample(even.x)
sinc_err = Error(sinc, even)
spline_err = Error(spline, even)
# Plot Labels
sn = lambda x,n: "%sly Sampled (%s points)" % (x,n)
r = lambda x: "%s Reconstruction" % x
re = lambda x: "%s Error" % r(x)
plots = [
[even, sn("Even", n)],
[uneven, sn("Uneven", m)],
[sinc, r("Sinc")],
[sinc_err, re("Sinc")],
[spline, r("Cubic Spline")],
[spline_err, re("Cubic Spline")]
]
for i in range(0,len(plots)):
py.subplot(3, 2, i+1)
p = plots[i]
p[0].plot(p[1])
py.show()