是否可以根据 Keras 中的输入实现层之间的切换?

Posted

技术标签:

【中文标题】是否可以根据 Keras 中的输入实现层之间的切换?【英文标题】:Is it possible to implement switching between layers based on input in Keras? 【发布时间】:2020-12-19 02:10:57 【问题描述】:

有可能在 Keras 中实现这样结构的神经网络吗?

思路如下:

在输入中,模型接收一个整数 i(标记为红色)和其他一些东西 v(在图片中是 0.12345)。接下来,有几个类似的并行层。根据 i 的值,v 进入 i 第层,忽略其他层,然后该层的输出进入输出层。

换句话说,除了i之外的所有层都被忽略了。

【问题讨论】:

你应该清楚地添加你的特殊层的规范,希望它会更有帮助。 这能回答你的问题吗? Combining the outputs of multiple models into one model 相信前面的这些问题可以回答这个:***.com/questions/43150635/…和***.com/questions/43151775/… @ashraful 很抱歉没有把问题表述得足够清楚。我已经用更详细的描述更新了问题 @cddt 恐怕它们不相关。我已经用更详细的描述更新了我的问题,以使其更清晰 【参考方案1】:

如果我正确理解了您的问题,我认为这里最简单的解决方案是根据您的 i 值分离您的数据集。

因此,将您的X_train 拆分为X_train_1X_train_2 等。同样将您的X_test 拆分为X_test_1X_test_2 等。

from keras.models import Sequential, Model
from keras.layers import *
from keras.utils import plot_model

然后设置单独的模型:

model1 = Sequential()
model1.add(Conv2D(32, kernel_size=(3,3), activation="relu", input_shape=(24,24,3)))
model1.add(MaxPooling2D(pool_size=(2,2)))
model1.add(Flatten())
model1.add(Dropout(0.5))
model1.add(Dense(512, activation = "relu"))
model2 = Sequential()
model2.add(Conv2D(32, kernel_size=(3,3), activation="relu", input_shape=(24,24,3)))
model2.add(MaxPooling2D(pool_size=(2,2)))
model2.add(Flatten())
model2.add(Dropout(0.5))
model2.add(Dense(512, activation = "relu"))

您将希望使用函数式 API 来组合它们。我用过Concatenate(),其他选项见文档here。

outputs = Concatenate()([model1.output,model2.output])
outputs = Dense(256, activation='relu')(outputs)
outputs = Dropout(.5)(outputs)
outputs = Dense(5, activation='softmax')(outputs)

现在配置您的最终模型,指定输入和输出:

model = Model(inputs=[model1.inputs, model2.inputs], outputs=outputs)

查看model.summary(),可以看到每一层是如何连接的:

__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
conv2d_input (InputLayer)       [(None, 24, 24, 3)]  0                                            
__________________________________________________________________________________________________
conv2d_1_input (InputLayer)     [(None, 24, 24, 3)]  0                                            
__________________________________________________________________________________________________
conv2d (Conv2D)                 (None, 22, 22, 32)   896         conv2d_input[0][0]               
__________________________________________________________________________________________________
conv2d_1 (Conv2D)               (None, 22, 22, 32)   896         conv2d_1_input[0][0]             
__________________________________________________________________________________________________
max_pooling2d (MaxPooling2D)    (None, 11, 11, 32)   0           conv2d[0][0]                     
__________________________________________________________________________________________________
max_pooling2d_1 (MaxPooling2D)  (None, 11, 11, 32)   0           conv2d_1[0][0]                   
__________________________________________________________________________________________________
flatten (Flatten)               (None, 3872)         0           max_pooling2d[0][0]              
__________________________________________________________________________________________________
flatten_1 (Flatten)             (None, 3872)         0           max_pooling2d_1[0][0]            
__________________________________________________________________________________________________
dropout (Dropout)               (None, 3872)         0           flatten[0][0]                    
__________________________________________________________________________________________________
dropout_1 (Dropout)             (None, 3872)         0           flatten_1[0][0]                  
__________________________________________________________________________________________________
dense (Dense)                   (None, 512)          1982976     dropout[0][0]                    
__________________________________________________________________________________________________
dense_1 (Dense)                 (None, 512)          1982976     dropout_1[0][0]                  
__________________________________________________________________________________________________
concatenate (Concatenate)       (None, 1024)         0           dense[0][0]                      
                                                                 dense_1[0][0]                    
__________________________________________________________________________________________________
dense_2 (Dense)                 (None, 256)          262400      concatenate[0][0]                
__________________________________________________________________________________________________
dropout_2 (Dropout)             (None, 256)          0           dense_2[0][0]                    
__________________________________________________________________________________________________
dense_3 (Dense)                 (None, 5)            1285        dropout_2[0][0]                  
==================================================================================================
Total params: 4,231,429
Trainable params: 4,231,429
Non-trainable params: 0
__________________________________________________________________________________________________

但使用plot_model(model, to_file='image.png', show_shapes=True) 更容易可视化模型:

然后为了训练模型,您需要输入不同的输入,不要忘记您的测试(或验证)数据:

model.fit([X_train_1, X_train_2], y_train, validation_data = ([X_test_1, X_test_2], y_val), ...)    

注意:子模型(此处为 model1model2 等)不必具有相同的结构。它们可以有不同大小的层、不同数量的层和不同类型的层。这也是您可以在模型中包含具有不同类型特征的数据集的方式。

【讨论】:

以上是关于是否可以根据 Keras 中的输入实现层之间的切换?的主要内容,如果未能解决你的问题,请参考以下文章

Keras 输入层和 TensorFlow 占位符之间的区别

Keras中基础知识

如何在 Keras 的两个 LSTM 层之间添加注意力层

Keras 不同注意力层之间的差异

keras 中全局池化层和(正常)池化层之间的区别

Keras 中连接多输入深度神经网络的正确最后一层是啥?