我有一系列长的一维向量(3000位数字),我尝试对它们进行分类。我之前已经实现了一个简单的CNN来对它们进行分类,并且取得了相对的成功:
def create_shallow_model(shape,repeat_length,stride): model = Sequential() model.add(Conv1D(75,repeat_length,strides=stride,padding='same', input_shape=shape, activation='relu')) model.add(MaxPooling1D(repeat_length)) model.add(Flatten()) model.add(Dense(1, activation='sigmoid')) model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy']) return model
然而,我希望通过在网络末端叠加LSTM/RNN来提高性能。
我在这方面遇到了困难,因为我似乎找不到让网络接受数据的方法。
def cnn_lstm(shape,repeat_length,stride): model = Sequential() model.add(TimeDistributed(Conv1D(75,repeat_length,strides=stride,padding='same', activation='relu'),input_shape=(None,)+shape)) model.add(TimeDistributed(MaxPooling1D(repeat_length))) model.add(TimeDistributed(Flatten())) model.add(LSTM(6,return_sequences=True)) model.add(Dense(1,activation='sigmoid')) model.compile(loss='sparse_categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy']) return modelmodel=cnn_lstm(X.shape[1:],1000,1)tprs,aucs=calculate_roc(model,3,100,train_X,train_y,test_X,test_y,tprs,aucs)
但我得到了以下错误:
ValueError: Error when checking input: expected time_distributed_4_input to have 4 dimensions, but got array with shape (50598, 3000, 1)
我的问题是:
-
这是分析这些数据的正确方法吗?
-
如果是的话,我怎样才能让网络接受并分类输入序列?
回答:
没有必要添加那些TimeDistributed
包装器。目前,在添加LSTM层之前,你的模型看起来像这样(我假设repeat_length=5
和stride=1
):
Layer (type) Output Shape Param # =================================================================conv1d_2 (Conv1D) (None, 3000, 75) 450 _________________________________________________________________max_pooling1d_1 (MaxPooling1 (None, 600, 75) 0 _________________________________________________________________flatten_2 (Flatten) (None, 45000) 0 _________________________________________________________________dense_4 (Dense) (None, 1) 45001 =================================================================Total params: 45,451Trainable params: 45,451Non-trainable params: 0_________________________________________________________________
所以如果你想添加一个LSTM层,你可以在MaxPooling1D
层之后直接添加,如model.add(LSTM(16, activation='relu'))
,并移除Flatten
层。现在模型看起来像这样:
_________________________________________________________________Layer (type) Output Shape Param # =================================================================conv1d_4 (Conv1D) (None, 3000, 75) 450 _________________________________________________________________max_pooling1d_3 (MaxPooling1 (None, 600, 75) 0 _________________________________________________________________lstm_1 (LSTM) (None, 16) 5888 _________________________________________________________________dense_5 (Dense) (None, 1) 17 =================================================================Total params: 6,355Trainable params: 6,355Non-trainable params: 0_________________________________________________________________
如果你愿意,可以向LSTM
层传递return_sequences=True
参数,并保留Flatten
层。但只有在你尝试了第一种方法并且结果不理想之后才这样做,因为添加return_sequences=True
可能完全没有必要,它只会增加模型大小并降低模型性能。
顺便提一下:为什么你在第二个模型中将损失函数改为sparse_categorical_crossentropy
?没有必要这样做,因为binary_crossentropy
可以很好地工作。