Рассмотрим следующую примерную проблему:
# dummy data for a SO question
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')
from keras.models import Model
from keras.layers import Input, Conv1D, Dense
from keras.optimizers import Adam, SGD
time = np.array(range(100))
brk = np.array((time>40) & (time < 60)).reshape(100,1)
B = np.array([5, -5]).reshape(1,2)
np.dot(brk, B)
y = np.c_[np.sin(time), np.sin(time)] + np.random.normal(scale = .2, size=(100,2))+ np.dot(brk, B)
plt.clf()
plt.plot(time, y[:,0])
plt.plot(time, y[:,1])
У вас есть N
временной ряд, и у них есть один компонент, который следует за общим процессом, и другой компонент, который уникален для самого ряда. Предположим для простоты, что вы a priori знаете, что выпуклость составляет от 40 до 60, и вы хотите смоделировать его одновременно с синусоидальным компонентом.
TCN хорошо справляется с общим компонентом, но не может получить уникальный для серии компонент:
# time series model
n_filters = 10
filter_width = 3
dilation_rates = [2**i for i in range(7)]
inp = Input(shape=(None, 1))
x = inp
for dilation_rate in dilation_rates:
x = Conv1D(filters=n_filters,
kernel_size=filter_width,
padding='causal',
activation = "relu",
dilation_rate=dilation_rate)(x)
x = Dense(1)(x)
model = Model(inputs = inp, outputs = x)
model.compile(optimizer = Adam(), loss='mean_squared_error')
model.summary()
X_train = np.transpose(np.c_[time, time]).reshape(2,100,1)
y_train = np.transpose(y).reshape(2,100,1)
history = model.fit(X_train, y_train,
batch_size=2,
epochs=1000,
verbose = 0)
yhat = model.predict(X_train)
plt.clf()
plt.plot(time, y[:,0])
plt.plot(time, y[:,1])
plt.plot(time, yhat[0,:,:])
plt.plot(time, yhat[1,:,:])
С другой стороны, базовая линейная регрессия с N выходами (здесь реализовано в Keras) идеально подходит для уникального компонента:
inp1 = Input((1,))
x1 = inp1
x1 = Dense(2)(x1)
model1 = Model(inputs = inp1, outputs = x1)
model1.compile(optimizer = Adam(), loss='mean_squared_error')
model1.summary()
brk_train = brk
y_train = y
history = model1.fit(brk_train, y_train,
batch_size=100,
epochs=6000, verbose = 0)
yhat1 = model1.predict(brk_train)
plt.clf()
plt.plot(time, y[:,0])
plt.plot(time, y[:,1])
plt.plot(time, yhat1[:,0])
plt.plot(time, yhat1[:,1])
Я хочу использовать керасы для совместной оценки компонента временного ряда и своеобразного компонента. Основная проблема заключается в том, что сети прямой связи (частная регрессия которых является частным случаем) принимают форму batch_size x dims
в то время как сети временных рядов принимают размерность batch_size x time_steps x dims
.
Поскольку я хочу совместно оценить уникальную часть модели (часть линейной регрессии) вместе с частью временного ряда, я только собираюсь делать выборку целых временных рядов. Вот почему я указал batch_size = time_steps
для модели 1.
Но в статической модели я действительно моделирую свои данные как time_steps x dims
.
Я пытался повторно привести модель прямой связи как модель временного ряда, но безуспешно. Вот нерабочий подход:
inp3 = Input(shape = (None, 1))
x3 = inp3
x3 = Dense(2)(x3)
model3 = Model(inputs = inp3, outputs = x3)
model3.compile(optimizer = Adam(), loss='mean_squared_error')
model3.summary()
brk_train = brk.reshape(1, 100, 1)
y_train = np.transpose(y).reshape(2,100,1)
history = model3.fit(brk_train, y_train,
batch_size=1,
epochs=1000, verbose = 1)
ValueError: Error when checking target: expected dense_40 to have shape (None, 2) but got array with shape (100, 1)
Я пытаюсь установить ту же модель, что и модель1, но другой формы, чтобы она была совместима с моделью TCN, и, что важно, чтобы она имела такую же структуру дозирования.
Выход в конечном итоге должен иметь форму (2, 100, 1)
в этом примере. В основном я хочу, чтобы модель делала следующий алгоритм:
- глотание
X
формы (N, time_steps, dims)
- Потерять первое измерение, потому что матрица дизайна будет идентична для каждой серии, давая
X1
формы (time_steps, dims)
- Шаг вперед:
np.dot(X1, W)
, где W
имеет размерность (dims, N)
, получая X2
размерности (time_steps, N)
- Изменить форму
X2
до (N, time_steps, 1)
. Затем я могу добавить его к выводу другой части модели.
- Шаг назад: поскольку это просто линейная модель, градиент
W
по отношению к выходному сигналу равен X1
Как я могу это реализовать? Нужен ли пользовательский слой?
Я строю идеи из этой статьи , на случай, если вам интересно, что стоит за всем этим.
РЕДАКТИРОВАТЬ : После публикации я заметил, что использовал только переменную времени, а не сам временной ряд. Подгонка TCN с отсроченной серией идеально подходит к уникальной части серии (в любом случае, в выборке). Но мой основной вопрос остается в силе - я хочу объединить два типа сетей.