keras中Conv1D和TimeDistributed参数理解

为了将卷积神经网络和长短时记忆网络结合起来实现异常检测,我用到了keras中的Conv1D和TimeDistributed层,记录一下对涉及的参数的理解。
好像有种更简单的写法,直接用Conv1D和LSTM就好了,不用借助TimeDistributed层,那种写法后续有机会再研究吧,不过使用TimeDistributed层也是有他的好处的,模型的映射更为自由(结合CNN时,一般体现在时间步的映射),能够实现一对多、多对一、多对多的映射。

Conv1D
卷积层中一些常见参数就不介绍了,重点介绍结合TimeDistributed层使用时要注意的一些参数。

keras.layers.Conv1D(filters, kernel_size, strides=1, padding='valid', data_format='channels_last', dilation_rate=1, activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)

filters:卷积核个数,也是使用完这层卷积后输出变量的维度
kernel_size:卷积核大小,卷积核的大小其实是kernel_size*输入变量的维度(输入变量维度不用在这里显式设置,网络会自适应得出)

结合下面官方文档中给出的输入输出尺寸,
输入尺寸:
3D 张量 ,尺寸为 (batch_size, steps, input_dim)。
输出尺寸:
3D 张量,尺寸为 (batch_size, new_steps, filters)。 由于填充或窗口按步长滑动,steps 值可能已更改。

如果卷积层写为:
conv1 = Conv1D(filters,kernel_size)(inputs)
则该模型卷积核的大小为kernel_size*input_dim

TimeDistributed

tf.keras.layers.TimeDistributed(layer, **kwargs)

TimeDistributed的作用是将放入TimeDistributed中的层用于输入的每个时间步

以下面代码为例,将Conv1D和TimeDistributed结合,看看各参数改变会导致什么变化。
注意看注释文字。

timestep = 10
batchsize = 64
lstmnodes = 100
filters1 = 16
filters2 = 32

def reshape_conv1d(conv_1d_layer):
    return tf.reshape(conv_1d_layer, [-1,timestep ,filters1, 1])
def CNNLSTM(): 
    # 1代表网络层中每次向CNN输入的都是一个时间点的dims (1*dims)
    inputs = Input(shape=(timestep, 1, dims))
    # 16个卷积核,卷积核大小为1*dims (自动适应上一步的深度,此处上一步的深度就是dims)
    # Conv1D中的1与上面shape中的1有关,Conv1D中1位置的值只能小于等于shape中1位置的值,由上面的介绍可知:TimeDistributed将Conv1D用于输入的每个时间步
    # 针对本文的inputs,输入到TimeDistributed中张量的维度其实是(1*dims),Conv1D中卷积核的大小为(1*dims),个数为filters1 = 16 个
    conv_1d_layer = TimeDistributed(Conv1D(filters1,1))(inputs) 
    # 输入到TimeDistributed中张量的维度其实是(1*filters1),Conv1D中卷积核的大小为(1*filters1),个数为filters2 = 32 个
    conv_1d_layer = TimeDistributed(Conv1D(filters2,1))(conv_1d_layer)
    flatten_layer = TimeDistributed(Flatten())(conv_1d_layer)
    lstm_layer = LSTM(lstmnodes)(flatten_layer)
    layer = Dropout(0.3)(lstm_layer)
    layer = Dense(32)(layer)
    layer = Dropout(0.3)(layer)
    out = Dense(1)(layer)
    model = Model(inputs = inputs, outputs = out, name = 'ResNet50')
    return model
model=CNNLSTM()
model.summary()

第一个conv_1d_layer 做的卷积操作(第二个同理):
TimeDistributed的作用是将放入TimeDistributed中的层用于输入的每个时间步,所以一个input要做timestep=10次操作。

输出网络结构:
keras中Conv1D和TimeDistributed参数理解_第1张图片
代码中,Input中timestep参数其实更类似于batchsize的作用,其后的1称为timestep更合适,之所以采用代码中的叫法,是因为我的逻辑是把一个timestep当作一个输入(batchsize),然后其后的参数自然就为1了(timestep),后面卷积核大小也相应的设为1,相当于对这单个timestep做卷积。
如果想要构造多对多的映射关系,就修改Input中的第二个参数,相应地,Conv1D中的kernel_size参数也可以随之修改,因为kernel_size就是对Input中的第二个参数做卷积(kernel_size设置的大于Input中的第二个参数就会报错)。
修改一下Input中的第二个参数和Conv1D中的kernel_size参数:

# 我的代码修改后含义为输入10个时间步,
# 第一层卷积是将 每两个时间步的数据做一次卷积
timestep = 10
batchsize = 64
lstmnodes = 100
filters1 = 16
filters2 = 32

def reshape_conv1d(conv_1d_layer):
    return tf.reshape(conv_1d_layer, [-1,timestep ,filters1, 1])
def CNNLSTM(): 
    # 10代表网络层中每次向CNN输入的都是一个时间点的dims (10*dims)
    inputs = Input(shape=(timestep, 10, dims))
    # 16个卷积核,卷积核大小为2*dims (自动适应上一步的深度,此处上一步的深度就是dims)
    # 针对本文的inputs,输入到TimeDistributed中张量的维度其实是(10*dims),Conv1D中卷积核的大小为(2*dims),个数为filters1 = 16 个
    conv_1d_layer = TimeDistributed(Conv1D(filters1,2))(inputs) 
    # 输入到TimeDistributed中张量的维度其实是(9*filters1),Conv1D中卷积核的大小为(1*filters1),个数为filters2 = 32 个
    conv_1d_layer = TimeDistributed(Conv1D(filters2,1))(conv_1d_layer)
    flatten_layer = TimeDistributed(Flatten())(conv_1d_layer)
    lstm_layer = LSTM(lstmnodes)(flatten_layer)
    layer = Dropout(0.3)(lstm_layer)
    layer = Dense(32)(layer)
    layer = Dropout(0.3)(layer)
    out = Dense(1)(layer)
    model = Model(inputs = inputs, outputs = out, name = 'ResNet50')
    return model
model=CNNLSTM()
model.summary()

第一个conv_1d_layer 做的卷积操作(第二个同理):
TimeDistributed的作用是将放入TimeDistributed中的层用于输入的每个时间步,所以一个input要做timestep=10次操作。
keras中Conv1D和TimeDistributed参数理解_第2张图片
keras中Conv1D和TimeDistributed参数理解_第3张图片
应该是有更简单的写法的,比如代码中input的第二个参数直接设置为LSTM的timestep,Conv1D中的kernel_size设置为1,其实就达到了对每个时间步做卷积的目的。不过batchsize参数就要相应做一下调整,或者修改一个fed进网络的数据形式。
一开始理解没透彻,写的很复杂,不过也实现目的了,小伙伴们加油,简化一下代码吧~

参考链接:
keras中TimeDistributed的用法
keras文档:Conv1D
keras文档:TimeDistributed layer

你可能感兴趣的:(CNN,python,深度学习)