我最近学习了ResNet的跳跃连接,发现这种网络结构在训练过程中能带来很大的提升,并且它也适用于像U-Net这样的卷积网络。然而,我不知道如何在LSTM自编码器网络中实现类似的结构。我似乎被一些维度问题困扰了…我使用的是Keras的方法来实现,但一直遇到错误。以下是网络代码:
# lstm autoencoder recreate sequencefrom numpy import arrayfrom keras.models import Sequentialfrom keras.layers import LSTMfrom keras.layers import Densefrom keras.layers import RepeatVectorfrom keras.layers import TimeDistributedfrom keras.utils import plot_model# from keras import regularizersfrom keras.regularizers import l1from keras.optimizers import Adamimport keras.backend as Kmodel = Sequential()model.add(LSTM(512, activation='selu', input_shape=(n_in,1),return_sequences=True))model.add(LSTM(256, activation='selu',return_sequences=True)) model.add(LSTM(20, activation='selu')) model.add(RepeatVector(n_in))model.add(LSTM(20, activation='selu',return_sequences=True)) model.add(LSTM(256, activation='selu',return_sequences=True)) model.add(LSTM(512, activation='selu', return_sequences=True))model.add(TimeDistributed(Dense(1)))# model.addplot_model(model=model, show_shapes=True)
就像ResNet或U-Net中的跳跃连接图一样,我试图像这样修改网络:
编码器LSTM层的输出也结合(拼接或相加?)前一层的输出,作为解码器LSTM层的输入。如图所示,对应的层是对称的。这种连接方式是否可行?但我对Keras API和跳跃连接结构还不熟悉,不知道如何实现它。
回答:
首先,你需要开始使用函数式API而不是Sequential API。函数式API允许你为每层构建任意输入和输出连接,而不是堆叠网络。
了解更多关于函数式API的信息,请访问:https://keras.io/guides/functional_api/
关于从LSTM层构建跳跃连接,和构建任何类型的层一样简单。我将展示一段示例代码:
input = Input(shape=input_shape)a = LSTM(32, return_sequences=True)(input)x = LSTM(64, return_sequences=True)(a) # main1 a = LSTM(64, return_sequences=True)(a) # skip1x = LSTM(64, return_sequences=True)(x) # main1x = LSTM(64, return_sequences=True)(x) # main1b = Add()([a,x]) # main1 + skip1x = LSTM(128, return_sequences=True)(b) # main2b = LSTM(128, return_sequences=True)(b) # skip2x = LSTM(128, return_sequences=True)(x) # main2x = LSTM(128, return_sequences=True)(x) # main2c = Add()([b,x]) # main2 + skip2x = LSTM(256, return_sequences=False)(c)x = Dense(512, activation='relu')(x)x = Dense(128, activation='relu')(x)x = Dense(2, activation='softmax')(x)model = Model(input, x)
这段代码将生成以下网络:
如你所见,Add
层接收的前一个层加上块之前的层(第一个块中的a)。
由于Add需要所有参数具有相同的形状,你必须在跳跃路径上添加一个额外的LSTM
,以平衡块的开始和结束的形状(与原始ResNet相同的概念)。
当然,你应该对这个网络进行调整,添加不同类型的层,Dropout
,正则化器,Activation
,或任何你认为对你的情况有用的内容。这只是一个展示LSTM跳跃连接的简化网络。
其余部分与你已经训练过的任何其他网络基本相同。