使用Keras构建LSTM + Conv2D模型

时间:2018-12-23 15:07:16

标签: python tensorflow machine-learning keras text-classification

我想建立一个类似于该架构的模型: enter image description here

我当前的LSTM模型如下:-

x = Embedding(max_features, embed_size, weights=[embedding_matrix],trainable=False)(inp)
x = SpatialDropout1D(0.1)(x)
x = Bidirectional(CuDNNLSTM(128, return_sequences=True))(x)
x = Bidirectional(CuDNNLSTM(64, return_sequences=True))(x)
avg_pool = GlobalAveragePooling1D()(x)
max_pool = GlobalMaxPooling1D()(x)
conc = concatenate([avg_pool, max_pool])
conc = Dense(64, activation="relu")(conc)
conc = Dropout(0.1)(conc)
outp = Dense(1, activation="sigmoid")(conc) 
model = Model(inputs=inp, outputs=outp)
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=[f1])

在BiLSTM之后如何将Conv2D层与2D Max Pooling层一起使用?

2 个答案:

答案 0 :(得分:1)

Conv2d需要形状为(batch, rows, col, channel)的4D张量。在NLP问题中,与计算机视觉不同,我们没有渠道。 该怎么办?

我们可以使用expand_dims函数为充当通道的张量添加额外的尺寸。例如,如果我们的张量具有(batch, seq, dim)的形状,那么在展开后,它将转换为(batch, seq, dim, 1)

lstm = Bidirectional(LSTM(128, return_sequences=True))(embed)
lstm = K.expand_dims(lstm, axis=-1)
conv2d = Conv2D(filters=128, kernel_size=2, padding='same')(lstm)

答案 1 :(得分:0)

创建此(相当复杂)模型需要注意的几个重点。

以下是使用功能性API创建的模型本身:

def expand_dims(x):
    return K.expand_dims(x, -1)

inp = Input(shape=(3,3))
lstm = Bidirectional(LSTM(128, return_sequences=True))(inp)
lstm = Lambda(expand_dims)(lstm)
conv2d = Conv2D(filters=128, kernel_size=2, padding='same')(lstm)
max_pool = MaxPooling2D(pool_size=(2, 2),)(conv2d)
predictions = Dense(10, activation='softmax')(max_pool)
model = Model(inputs=inp, outputs=predictions)
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

分步说明

首先,创建您的输入形状。从上面的图像中,您好像使用了7个样本,一个包含3个特征和3个特征的窗口->形状为(7, 3, 3)的张量。显然,您可以更改为自己喜欢的任何东西。将输入层用作双向LSTM层。

inp = Input(shape=(3,3))
lstm = Bidirectional(LSTM(128, return_sequences=True))(inp)

第二,如@Amir所述,如果要使用Conv2D层,则需要扩展尺寸。但是,仅使用keras后端是不够的,因为功能性api创建的模型将要求您仅包含keras层。检查此答案here是否有错误NoneType' object has no attribute '_inbound_nodes。因此,您需要将expand_dim提取到其自己的函数中并环绕Lambda层:

def expand_dims(x):
    return K.expand_dims(x, -1)

lstm = Lambda(expand_dims)(lstm)

其余在上述排序后非常简单:

conv2d = Conv2D(filters=128, kernel_size=2, padding='same')(lstm)
max_pool = MaxPooling2D(pool_size=(2, 2),)(conv2d)
predictions = Dense(10, activation='softmax')(max_pool)
model = Model(inputs=inp, outputs=predictions)
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')

模型的摘要如下:

Layer (type)                 Output Shape              Param #   
=================================================================
input_67 (InputLayer)        (None, 3, 3)              0         
_________________________________________________________________
bidirectional_29 (Bidirectio (None, 3, 256)            135168    
_________________________________________________________________
lambda_7 (Lambda)            (None, 3, 256, 1)         0         
_________________________________________________________________
conv2d_19 (Conv2D)           (None, 3, 256, 128)       640       
_________________________________________________________________
max_pooling2d_14 (MaxPooling (None, 1, 128, 128)       0         
_________________________________________________________________
dense_207 (Dense)            (None, 1, 128, 10)        1290      
=================================================================
Total params: 137,098
Trainable params: 137,098
Non-trainable params: 0
_________________________________________________________________
None

这是可视化

enter image description here