В соответствии с вопросом, два столбца x
и y
являются двумя временными сериями, то есть x(t)
и y(t)
. Параметр t
представлен индексом
Во-первых, давайте загрузим данные:
import io
import requests
import numpy as np
import scipy as sp
import matplotlib as mpl
import scipy.interpolate
import scipy.ndimage
import matplotlib.pyplot as plt
file_id = '1q4zY7B-BwG8bmbQJT3QvRt6B2MD4k0a0'
url = requests.get('https://drive.google.com/uc?export=download&id=' + file_id)
csv_file = io.StringIO(url.text)
data = np.loadtxt(csv_file, delimiter=',')
x = data[:, 0]
y = data[:, 1]
t = np.arange(len(x))
Теперь, y(x)
, как правило, не может быть четко определен. Более полезное представление данных получается путем построения x(t)
и y(t)
(возможно, вдоль y(x)
):
fig, ax = plt.subplots(1, 3, figsize=(15, 4), squeeze=False)
ax[0, 0].scatter(t, x, color='k', s=8.0)
ax[0, 1].scatter(t, y, color='k', s=8.0)
ax[0, 2].scatter(x, y, color='k', s=8.0)
ax[0, 0].plot(t, x, color='b')
ax[0, 1].plot(t, y, color='b')
ax[0, 2].plot(x, y, color='b')
![vis](https://i.stack.imgur.com/aYomV.png)
Обратите внимание, что в то время как визуализация y(x)
получает две кластеризации, то есть растянутую спираль и прямую линию, без дополнительной информации, это наблюдение не следует переоценивать.
Теперь, без подходящей модели то, что мы могли бы сделать, это иметь интерполяционную числовую функцию для x(t)
и y(t)
. Если x(t)
и y(t)
предполагаются бесшумными, то простой 1D-интерполятор, как предусмотрено scipy.interpolate.interp1d()
:
func_x_t = sp.interpolate.interp1d(t, x, kind='cubic', assume_sorted=True)
func_y_t = sp.interpolate.interp1d(t, y, kind='cubic', assume_sorted=True)
x_interp = func_x_t(t)
y_interp = func_y_t(t)
fig, ax = plt.subplots(1, 3, figsize=(15, 4), squeeze=False)
ax[0, 0].scatter(t, x, color='k', s=8.0)
ax[0, 1].scatter(t, y, color='k', s=8.0)
ax[0, 2].scatter(x, y, color='k', s=8.0)
ax[0, 0].plot(t, x_interp, color='r')
ax[0, 1].plot(t, y_interp, color='r')
ax[0, 2].plot(x_interp, y_interp, color='r')
![interp](https://i.stack.imgur.com/VRb9t.png)
Обратите внимание, что красная линия теперь генерируется интерполятором. SciPy предлагает множество различных интерполяторов, которые, возможно, стоит изучить.
Если x(t)
и y(t)
являются измерениями с шумом, можно получить более полезный интерполятор, как указано выше, но с использованием шумоподавляющего шума. x(t)
и y(t)
. Здесь я предполагаю, что наблюдаемые высокочастотные колебания вызваны шумом (как в x(t)
, так и в y(t)
), и простым, но эффективным подходом по снижению шума будет фильтрация Гаусса (как предусмотрено * 1054). *:
smooth_x = sp.ndimage.gaussian_filter1d(x, 12.0, mode='nearest')
smooth_y = sp.ndimage.gaussian_filter1d(y, 12.0, mode='nearest')
func_x_t = sp.interpolate.interp1d(t, smooth_x, kind='cubic', assume_sorted=True)
func_y_t = sp.interpolate.interp1d(t, smooth_y, kind='cubic', assume_sorted=True)
x_smooth_interp = func_x_t(t)
y_smooth_interp = func_y_t(t)
fig, ax = plt.subplots(1, 3, figsize=(15, 4), squeeze=False)
ax[0, 0].scatter(t, x, color='k', s=8.0)
ax[0, 1].scatter(t, y, color='k', s=8.0)
ax[0, 2].scatter(x, y, color='k', s=8.0)
ax[0, 0].plot(t, smooth_x, color='g')
ax[0, 1].plot(t, smooth_y, color='g')
ax[0, 2].plot(smooth_x, smooth_y, color='g')
ax[0, 0].plot(t, x_smooth_interp, color='r')
ax[0, 1].plot(t, y_smooth_interp, color='r')
ax[0, 2].plot(x_smooth_interp, y_smooth_interp, color='r')
![smooth_interp](https://i.stack.imgur.com/0lJqT.png)
Обратите внимание, что *_smooth
и *_smooth_interp
получают графики друг над другом.
Другим подходом будет использование искусственной нейронной сети, например, из scikit-learn:
import sklearn as skl
import sklearn.neural_network as skl_nn
import sklearn.preprocessing
x_train = t.reshape(-1, 1)
y_train = data
reg = skl_nn.MLPRegressor(
solver='adam', hidden_layer_sizes=(24, 8), activation='tanh',
learning_rate='adaptive', max_iter=1024)
reg.fit(x_train, y_train)
y_predict = reg.predict(x_train)
x_ann = y_predict[:, 0]
y_ann = y_predict[:, 1]
fig, ax = plt.subplots(1, 3, figsize=(15, 4), squeeze=False)
ax[0, 0].scatter(t, x, color='k', s=8.0)
ax[0, 1].scatter(t, y, color='k', s=8.0)
ax[0, 2].scatter(x, y, color='k', s=8.0)
ax[0, 0].plot(t, x, color='b')
ax[0, 1].plot(t, y, color='b')
ax[0, 2].plot(x, y, color='b')
ax[0, 0].plot(t, x_ann, color='r')
ax[0, 1].plot(t, y_ann, color='r')
ax[0, 2].plot(x_ann, y_ann, color='r')
![iterp_ann](https://i.stack.imgur.com/XMfTj.png)
Это поможет вам Интерполятор без необходимости явно подавлять шум на вашем целевом сигнале, который может быть более или менее желательным, в зависимости от приложения.
Повторная параметризация x(t')
и y(t')
с t'(t)
(переупорядочение)
Если мы ослабим требование, что x(t)
и y(t)
относятся к временной серии, мы могли бы исследовать x(t')
и y(t')
для данного t'(t)
преобразования.
Возможное преобразование, которое приводит к несколько интересному результату, получается путем сортировки данных CSV по y
(временные ряды отсортированы по x
):
data = data[data[:, 1].argsort()]
x = data[:, 0]
y = data[:, 1]
![vis_t'](https://i.stack.imgur.com/aPYjl.png)
с этим преобразованием мы получаем следующий интерполятор для ANN подход:
![ann_t'](https://i.stack.imgur.com/79Cs0.png)
и это для сглаженных x(t')
и y(t')
:
![interp_smooth_t'](https://i.stack.imgur.com/GjNh8.png)
Возможно, существуют более эффективные переупорядочения, но их может быть непросто сформулировать. Относительно простая формулировка может включать кластеризацию, но я считаю, что этот ответ уже довольно длинный.
(полный код доступен здесь )