python - 将时间序列神经网络与前馈神经网络连接起来
问题描述
考虑以下示例问题:
# 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
时间序列,他们有一个遵循共同流程的组件,以及另一个与序列本身不同的组件。为简单起见,假设您先验地知道凹凸在 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])
我想用keras来联合估计时间序列分量和特质分量。 主要问题是前馈网络(线性回归是一个特例)形成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)
我试图拟合与 model1 相同的模型,但形状不同,以便它与 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 非常适合该系列的特殊部分(无论如何都在样本中)。但我的基本问题仍然存在——我想合并这两种类型的网络。
解决方案
所以,我解决了我自己的问题。答案是创建虚拟交互(因此是一个非常稀疏的设计矩阵),然后重塑数据。
###########################
# interaction model
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
from patsy import dmatrix
def shift5(arr, num, fill_value=np.nan):
result = np.empty_like(arr)
if num > 0:
result[:num] = fill_value
result[num:] = arr[:-num]
elif num < 0:
result[num:] = fill_value
result[:num] = arr[-num:]
else:
result = arr
return result
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])
# define interaction model
inp = Input(shape=(None, 2))
x = inp
x = Dense(1)(x)
model = Model(inputs = inp, outputs = x)
model.compile(optimizer = Adam(), loss='mean_squared_error')
model.summary()
from patsy import dmatrix
df = pd.DataFrame(data = {"fips": np.concatenate((np.zeros(100), np.ones(100))),
"brk": np.concatenate((brk.reshape(100), brk.squeeze()))})
df.brk = df.brk.astype(int)
tm = np.asarray(dmatrix("brk:C(fips)-1", data = df))
brkint = np.concatenate(( \
tm[:100,:].reshape(1,100,2),
tm[100:200,:].reshape(1,100,2)
), axis = 0)
y_train = np.transpose(y).reshape(2,100,1)
history = model.fit(brkint, y_train,
batch_size=2,
epochs=1000,
verbose = 1)
yhat = model.predict(brkint)
plt.clf()
plt.plot(time, y[:,0])
plt.plot(time, y[:,1])
plt.plot(time, yhat[0,:,:])
plt.plot(time, yhat[1,:,:])
输出形状与 TCN 相同,可以简单地按元素添加。
推荐阅读
- laravel - laravel pdf 使用 (Barryvdh\DomPDF) 查看添加水印
- c - 如何在 C 中为多个等待线程解锁未命名的信号量?
- java - 是否有任何优化方法来创建页面对象?
- typescript - 有没有办法为非核心材料 UI 组件添加主题?
- twitter - 处理 Twitter API 数据以获取特定信息
- javascript - 如何在 Object 中创建自执行匿名函数?
- javascript - 处理未定义的 JavaScript api 响应属性“0”
- reactjs - 在 React 中处理身份验证持久性(使用 Redux 和 Firebase)
- flutter - 在flutter中使用bloc将数据发送到firestore和firestorage
- android - 如何使用颤振在firestore中特定文档的字段内检索地图值?