Keras:如何将 CNN 模型与决策树连接起来

Posted

技术标签:

【中文标题】Keras:如何将 CNN 模型与决策树连接起来【英文标题】:Keras: How to connect a CNN model with a decision tree 【发布时间】:2019-09-17 21:58:29 【问题描述】:

我想训练一个模型来根据物理信号预测一个人的情绪。我有一个物理信号并将其用作输入特征;

心电图(心电图)

我想使用 CNN 架构从数据中提取特征,然后使用这些提取的特征来输入经典的“决策树分类器”。下面,您可以看到我的 CNN 方法没有决策树;

model = Sequential()
model.add(Conv1D(15,60,padding='valid', activation='relu',input_shape=(18000,1), strides = 1,  kernel_regularizer=regularizers.l1_l2(l1=0.1, l2=0.1)))
model.add(MaxPooling1D(2,data_format='channels_last'))
model.add(Dropout(0.6))
model.add(BatchNormalization())
model.add(Conv1D(30, 60, padding='valid', activation='relu',kernel_regularizer = regularizers.l1_l2(l1=0.1, l2=0.1), strides=1))
model.add(MaxPooling1D(4,data_format='channels_last'))
model.add(Dropout(0.6))
model.add(BatchNormalization())
model.add(Flatten())
model.add(Dense(3, activation = 'softmax'))

我想编辑这段代码,以便在输出层中有工作的决策树,而不是model.add(Dense(3, activation = 'softmax'))。我试图像这样保存最后一个卷积层的输出;

output = model.layers[-6].output

当我打印出output 变量时,结果是这样的;

输出:Tensor("conv1d_56/Relu:0", shape=(?, 8971, 30), dtype=float32)

我猜,output 变量保存了提取的特征。现在,如何使用存储在 output 变量中的这些数据来提供我的 决策树 分类器模型?这是来自 scikit learn 的决策树;

from sklearn.tree import DecisionTreeClassifier

dtc = DecisionTreeClassifier(criterion = 'entropy')
dtc.fit()

我应该如何提供fit() 方法?提前致谢。

【问题讨论】:

你在做监督分类吗?你想联合训练你的 DL 模型和决策树(这是不可能的......)?您可以做的一件事是使用 FC 层训练您的 DL 模型,然后将其替换为决策树... @ma3oun,是的,它是一个有监督的分类。我希望 CNN 模型从我的数据中提取特征,然后我将使用这些提取的特征来提供决策树模型。 一种方法是添加一些 FC 层并训练您的网络,然后使用您训练过的网络提取特征并将它们输入决策树(从而替换 FC 层)。另一种方法是训练自动编码器来提取特征,然后使用收缩数据向量作为决策树的输入...... 【参考方案1】:

要提取可以传递给另一个算法的特征向量,您需要在 softmax 层之前有一个全连接层。像这样的东西会在你的 softmax 层之前添加一个 128 维的层:

model = Sequential()
model.add(Conv1D(15,60,padding='valid', activation='relu',input_shape=(18000,1), strides = 1,  kernel_regularizer=regularizers.l1_l2(l1=0.1, l2=0.1)))
model.add(MaxPooling1D(2,data_format='channels_last'))
model.add(Dropout(0.6))
model.add(BatchNormalization())
model.add(Conv1D(30, 60, padding='valid', activation='relu',kernel_regularizer = regularizers.l1_l2(l1=0.1, l2=0.1), strides=1))
model.add(MaxPooling1D(4,data_format='channels_last'))
model.add(Dropout(0.6))
model.add(BatchNormalization())
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(3, activation = 'softmax'))

如果您随后运行model.summary(),您可以看到图层的名称:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv1d_9 (Conv1D)            (None, 17941, 15)         915       
_________________________________________________________________
max_pooling1d_9 (MaxPooling1 (None, 8970, 15)          0         
_________________________________________________________________
dropout_10 (Dropout)         (None, 8970, 15)          0         
_________________________________________________________________
batch_normalization_9 (Batch (None, 8970, 15)          60        
_________________________________________________________________
conv1d_10 (Conv1D)           (None, 8911, 30)          27030     
_________________________________________________________________
max_pooling1d_10 (MaxPooling (None, 2227, 30)          0         
_________________________________________________________________
dropout_11 (Dropout)         (None, 2227, 30)          0         
_________________________________________________________________
batch_normalization_10 (Batc (None, 2227, 30)          120       
_________________________________________________________________
flatten_6 (Flatten)          (None, 66810)             0         
_________________________________________________________________
dense_7 (Dense)              (None, 128)               8551808   
_________________________________________________________________
dropout_12 (Dropout)         (None, 128)               0         
_________________________________________________________________
dense_8 (Dense)              (None, 3)                 387       
=================================================================
Total params: 8,580,320
Trainable params: 8,580,230
Non-trainable params: 90
_________________________________________________________________

一旦您的网络经过训练,您就可以创建一个新模型,其中输出层变为“dense_7”,它将生成 128 维特征向量:

feature_vectors_model = Model(model.input, model.get_layer('dense_7').output)
dtc_features = feature_vectors_model.predict(your_X_data)  # fit your decision tree on this data

【讨论】:

your_X_data 表示 train_x ?另外,我运行了多少个 epoch 很重要吗? 是的 train_x、test_x 等。用于生成特征的新模型不需要训练,因为它使用从拟合“模型”中学到的权重。对于原始模型,最好使用在验证损失停止改善时结束训练的回调。 好吧,我试过了,它显然是有效的。但我想问,这是最好的方法吗?比方说,在我的conv1d 节点中,我使用了 10 个过滤器,这就是为什么应该提取 10 个特征。之后,我将应用一个具有 128 密集度的全连接层,并使用它来提供我的决策树。因此,我有 128 个功能而不是 10 个。

以上是关于Keras:如何将 CNN 模型与决策树连接起来的主要内容,如果未能解决你的问题,请参考以下文章

如何将图像文件夹中的数据与在 Keras 中保存分类详细信息的 excel 结合起来

尝试使用 Keras 功能 API 构建 CNN 模型时图形断开连接

Pipeline

决策树是啥东东?

将 CNN 模型代码从 Keras 转换为 Pytorch

如何求CNN模型(keras)的ROC曲线和AUC分数