keras_4_关于Keras的Layer

1. 公共函数

  1. layer.get_weights(): 以含有Numpy矩阵的列表形式返回层的权重。

  2. layer.set_weights(weights): 从含有Numpy矩阵的列表中设置层的权重(与get_weights的输出形状相同)。

  3. layer.get_config(): 返回包含层配置的字典。此图层可以通过以下方式重置:

    layer = Dense(32)
    config = layer.get_config()
    reconstructed_layer = Dense.from_config(config)
    
    # 或者
    from keras import layers
    config = layer.get_config()
    layer = layers.deserialize({'class_name': layer.__class__.__name__,
                                'config': config})
    
  4. 如果一个层具有单个节点 (i.e. 如果它不是共享层), 你可以得到它的输入张量,输出张量,输入尺寸和输出尺寸:

    • layer.input
    • layer.output
    • layer.input_shape
    • layer.output_shape
  5. 如果层有多个节点 (参见: 层节点和共享层的概念), 您可以使用以下函数:

    • layer.get_input_at(node_index)
    • layer.get_output_at(node_index)
    • layer.get_input_shape_at(node_index)
    • layer.get_output_shape_at(node_index)

2. 核心网络层

  1. Dense

  2. Activation

  3. Dropout

  4. Flatten

  5. Input

  6. Reshape

  7. Permute

    • 根据给定的模式置换输入的维度。在某些场景下很有用,例如将 RNN 和 CNN 连接在一起。

      model = Sequential()
      model.add(Permute((2, 1), input_shape=(10, 64)))
      # 现在: model.output_shape == (None, 64, 10) # 等价于执行了矩阵转置
      # 注意: None 是批表示的维度
      
  8. RepeatVector

  9. Lambda

  10. ActivityRegularization

  11. Masking

  12. SpatialDropout1D

    • Dropout 的 Spatial 1D 版本
  13. SpatialDropout2D

    • Dropout 的 Spatial 2D 版本,此版本的功能与 Dropout 相同,但它会丢弃整个 2D 的特征图而不是丢弃单个元素。
    • 如果特征图中相邻的像素是强相关的(通常是靠前的卷积层中的情况),那么常规的 dropout 将无法使激活正则化,且导致有效的学习速率降低。在这种情况下,SpatialDropout2D 将有助于提高特征图之间的独立性,应该使用它来代替 dropout。
  14. SpatialDropout3D

    • Dropout 的 Spatial 3D 版本,此版本的功能与 Dropout 相同,但它会丢弃整个 3D 的特征图而不是丢弃单个元素。使用场景同上述2D

3. 卷积层(Convolution)

  1. Conv1D (比如时序卷积)

  2. Conv2D (比如图像中的二维卷积)

  3. SeparableConv1D (depth方向的可分离1D卷积)

    • 首先执行深度方向的空间卷积 (分别作用于每个输入通道),然后再执行一个将所得输出通道 混合在一起的逐点卷积。depth_multiplier 参数控 制深度步骤中每个输入通道生成多少个输出通道。可分离的卷积可以理解为一种将卷积核分解成 两个较小的卷积核的方法,或者作为 Inception 块的 一个极端版本。
  4. SeparableConv2D

    • 首先执行深度方向的空间卷积 (分别作用于每个输入通道),紧接一个将所得输出通道 混合在一起的逐点卷积。其余描述同上的1D
  5. Conv2DTranspose (同理会有3D)

    • 转置卷积(或反卷积),或者叫Deconvolution
  6. Conv3D

    • 立体空间卷积:比如对一个视频(一个视频可以形式化为包含N帧的二维image,比如NxWxHxC。之前Conv2D处理的是二维image,即WxHxC)
  7. Cropping1D

    • 1D 输入的裁剪层(例如时间序列),它沿着时间维度(第 1 个轴)裁剪。
    • 入参,如cropping=(4,5): 整数或整数元组(长度为 2)。 在裁剪维度(第 1 个轴)的开始和结束位置 应该裁剪多少个单位(此处分别是4,5)。 如果只提供了一个整数,那么这两个位置将使用 相同的值。
  8. Croppong2D

    • 2D 输入的裁剪层(例如图像),它沿着空间维度裁剪,即宽度和高度。

      # 裁剪输入的 2D 图像或特征图
      model = Sequential()
      model.add(Cropping2D(cropping=((2, 2), (4, 4)),
                           input_shape=(28, 28, 3)))
      # 现在 model.output_shape == (None, 24, 20, 3)
      model.add(Conv2D(64, (3, 3), padding='same')) # padding='same'保持原有的W,H
      model.add(Cropping2D(cropping=((2, 2), (2, 2))))
      # 现在 model.output_shape == (None, 20, 16. 64)
      
  9. Cropping3D

    • 3D 数据的裁剪层(例如空间或时空)。
  10. Upsampling1D

    • 1D 输入的上采样层,沿着时间轴重复每个时间步 size 次。
  11. Upsampling2D

    • 2D 输入的上采样层,沿着数据的行和列分别重复 size[0]size[1] 次。
  12. Upsampling3D

  13. ZeroPadding1D

    • 1D 输入的零填充层(例如,时间序列)。
  14. ZeroPadding2D:

    • 2D 输入的零填充层(例如图像)。该图层可以在图像张量的顶部、底部、左侧和右侧添加零表示的行和列。
  15. ZeroPadding3D

    • 3D 数据的零填充层(空间或时空)。

4. 池化层(Pooling)

  1. MaxPooling1D
  2. MaxPooling2D
  3. MaxPooling3D
  4. AveragePooling1D
  5. AveragePooling2D
  6. AveragePooling3D
  7. GlobalMaxPooling1D
  8. GlobalMaxPooling2D
  9. GlobalMaxPooling3D
  10. GlobalAveragePooling1D
  11. GlobalAveragePooling2D
  12. GlobalAveragePooling3D

5. 局部连接层(Locally-connected)

  1. LocallyConnected1D (还有2D,但3D还不知道是否有?)

    • LocallyConnected1D 层与 Conv1D 层的工作方式相同,除了权值不共享外, 也就是说,在输入的每个不同部分应用不同的一组过滤器。

    • # 将长度为 3 的非共享权重 1D 卷积应用于
      # 具有 10 个时间步长的序列,并使用 64个 输出滤波器
      model = Sequential()
      model.add(LocallyConnected1D(64, 3, input_shape=(10, 32))) # 32应该是指channel?
      # 现在 model.output_shape == (None, 8, 64) # W_2 = (W_1-F)/S + 1, so 10->8
      # 在上面再添加一个新的 conv1d
      model.add(LocallyConnected1D(32, 3)) # (8-3)/1 + 1 = 6
      # 现在 model.output_shape == (None, 6, 32) # so 8->6
      
      
      # 2D的例子
      # 在 32x32 图像上应用 3x3 非共享权值和64个输出过滤器的卷积
      # 数据格式 `data_format="channels_last"`:
      model = Sequential()
      model.add(LocallyConnected2D(64, (3, 3), input_shape=(32, 32, 3)))
      # 现在 model.output_shape == (None, 30, 30, 64) # (32-3)/1 + 1 = 30
      # 注意这一层的参数数量为 (30*30)*(3*3*3*64) + (30*30)*64 
      # 每次做卷积都是一组新的参数
      # 30x30次卷积,才会得到30x30的feature map,每次卷积的参数量为:3x3x3x64,是因为64个3x3x3的filter;第二项(30x30)x64是bias的数量,因为一共64个filter,每个filter做一次卷积配一个bias
      
      # 在上面再加一个 3x3 非共享权值和 32 个输出滤波器的卷积:
      model.add(LocallyConnected2D(32, (3, 3)))
      # 现在 model.output_shape == (None, 28, 28, 32)
      

6. 循环层 Recurrent

  1. RNN
  2. SimpleRNN
  3. GRU
  4. LSTM
  5. ConvLSTM2D
  6. SimpleRNNCell
  7. GRUCell
  8. LSTMCell
  9. StackedRNNCells
  10. tensorflow支持的
    • CuDNNGRU
    • CuDNNLSTM

7. 嵌入层 Embedding

  1. Embedding

    model = Sequential()
    model.add(Embedding(1000, 64, input_length=10)) # 1000 -> 64 ?
    # 模型将输入一个大小为 (batch, input_length) 的整数矩阵。
    # 输入中最大的整数(即词索引)不应该大于 999 (词汇表大小)
    # 现在 model.output_shape == (None, 10, 64),其中 None 是 batch 的维度。
    
    input_array = np.random.randint(1000, size=(32, 10)) # 原本是
    
    model.compile('rmsprop', 'mse')
    output_array = model.predict(input_array)
    assert output_array.shape == (32, 10, 64)
    

8. 融合层 Merge

  1. Add

    • 计算一个列表的输入张量的和。相加层接受一个列表的张量, 所有的张量必须有相同的输入尺寸, 然后返回一个张量(和输入张量尺寸相同)

      import keras
      
      input1 = keras.layers.Input(shape=(16,))
      x1 = keras.layers.Dense(8, activation='relu')(input1) # 8-dim的tensor
      input2 = keras.layers.Input(shape=(32,))
      x2 = keras.layers.Dense(8, activation='relu')(input2) # 8-dim的tensor
      added = keras.layers.Add()([x1, x2])  # 相当于 added = keras.layers.add([x1, x2]) # 16-dim的tensor ??
      
      out = keras.layers.Dense(4)(added)
      model = keras.models.Model(inputs=[input1, input2], outputs=out)
      
  2. Subtract:

    • 计算两个输入张量的差。相减层接受一个长度为 2 的张量列表, 两个张量必须有相同的尺寸,然后返回一个值为 (inputs[0] - inputs[1]) 的张量, 输出张量和输入张量尺寸相同。

      import keras
      
      input1 = keras.layers.Input(shape=(16,))
      x1 = keras.layers.Dense(8, activation='relu')(input1) # 8-dim
      input2 = keras.layers.Input(shape=(32,))
      x2 = keras.layers.Dense(8, activation='relu')(input2) # 8-dim
      # 相当于 subtracted = keras.layers.subtract([x1, x2])
      subtracted = keras.layers.Subtract()([x1, x2]) # 8-dim
      
      out = keras.layers.Dense(4)(subtracted) # out:  4-dim
      model = keras.models.Model(inputs=[input1, input2], outputs=out)
      
  3. Multiply

    • 计算一个列表的输入张量的(逐元素间的,elem-wise)乘积。相乘层接受一个列表的张量, 所有的张量必须有相同的输入尺寸, 然后返回一个张量(和输入张量尺寸相同)。
  4. Average

    • 计算一个列表的输入张量的平均值。平均层接受一个列表的张量, 所有的张量必须有相同的输入尺寸, 然后返回一个张量(和输入张量尺寸相同)。
  5. Maximum

    • 计算一个列表的输入张量的(逐元素间的)最大值。最大层接受一个列表的张量, 所有的张量必须有相同的输入尺寸, 然后返回一个张量(和输入张量尺寸相同)。
  6. Concatenate

    • 串联一个列表的输入张量。串联层接受一个列表的张量, 除了串联轴之外,其他的尺寸都必须相同, 然后返回一个由所有输入张量串联起来的输出张量。(比如对于二维image,depth-wise的cancat,结果是depth-add,W,H不变)
  7. Dot

    • 计算两个张量之间样本的点积。
    • 例如,如果作用于输入尺寸为 (batch_size, n) 的两个张量 ab, 那么输出结果就会是尺寸为 (batch_size, 1) 的一个张量。 在这个张量中,每一个条目 ia[i]b[i] 之间的点积。
  8. add

    • Add 层的函数式接口。keras.layers.add(inputs)
  9. subtract

    • Subtract 层的函数式接口。keras.layers.subtract(inputs)

      import keras
      
      input1 = keras.layers.Input(shape=(16,)) 
      x1 = keras.layers.Dense(8, activation='relu')(input1) # out: 8-dim
      input2 = keras.layers.Input(shape=(32,))
      x2 = keras.layers.Dense(8, activation='relu')(input2) # 8-dim
      subtracted = keras.layers.subtract([x1, x2]) # out: 8-dim
      
      out = keras.layers.Dense(4)(subtracted) # out: 4-dim
      model = keras.models.Model(inputs=[input1, input2], outputs=out)
      
  10. multiply

    • Multiply 层的函数式接口。keras.layers.multiply(inputs)
  11. average

    • Average 层的函数式接口。keras.layers.average(inputs)
  12. maximum

    • Maximum 层的函数式接口。keras.layers.maximum(inputs)
  13. concatenate

    • Concatenate 层的函数式接口。keras.layers.concatenate(inputs, axis=-1)
  14. dot

    • Dot 层的函数式接口。keras.layers.dot(inputs, axes, normalize=False)

9. 高级激活层 Advanced Activations

  1. LeakyReLU
  2. PReLU
  3. ELU
  4. ThresholdedReLU
  5. Softmax
    • Softmax 激活函数。keras.layers.Softmax(axis=-1)
  6. ReLU
    • ReLU 激活函数。keras.layers.ReLU(max_value=None)

10. 标准化层 Normalization

  1. BatchNormalization
    • 批量标准化层 (Ioffe and Szegedy, 2014)。在每一个批次的数据中标准化前一层的激活项, 即,应用一个维持激活项平均值接近 0,标准差接近 1 的转换。

11. 噪声层 Noise(或者叫,某些正则化层)

  1. GaussianNoise
    • 应用以 0 为中心加性高斯噪声。这对缓解过拟合很有用 (你可以将其视为随机数据增强的一种形式)。 高斯噪声(GS)是对真实输入的腐蚀过程的自然选择。由于它是一个正则化层,因此它只在训练时才被激活。(也就是说:evaluate & test 不启动正则化项??不是!!!是这个正则化仅在训练时使用)
  2. GaussianDropout
    • 应用以 1 为中心的 乘性高斯噪声。由于它是一个正则化层,因此它只在训练时才被激活。
  3. AlphaDropout
    • Alpha Dropout是一种 Dropout,它保持输入的平均值和方差与原来的值不变, 即在 dropout 之后仍然保证数据的自规范性。 通过随机将激活设置为负饱和值,Alpha Dropout 非常适合按比例缩放的指数线性单元(SELU)。

12. 层封装器 wrappers

  1. TimeDistributed

    • 这个封装器将一个层应用于输入的每个时间片。输入至少为 3D,且第一个维度应该是时间所表示的维度。

    • 考虑 32 个样本的一个 batch, 其中每个样本是 10 个 16 维向量的序列。 那么这个 batch 的输入尺寸为 (32, 10, 16), 而 input_shape 不包含样本数量的维度,为 (10, 16)。你可以使用 TimeDistributed 来将 Dense 层独立地应用到 这 10 个时间步的每一个:

      # 作为模型第一层
      model = Sequential()
      model.add(TimeDistributed(Dense(8), input_shape=(10, 16))) # 有点像map函数
      # 现在 model.output_shape == (None, 10, 8) # 因为上一层是FC,output为8-dim,而
      # 每个时间步都被dense(8)处理了,所以有10个时间步的执行结果
      # 输出的尺寸为 (32, 10, 8)。
      
      # 在后续的层中,再使用TimeDistributed,将不再需要 input_shape:
      model.add(TimeDistributed(Dense(32)))
      # 现在 model.output_shape == (None, 10, 32) # 10个时间步,32来自FC的output-dim
      
      # TimeDistributed 可以应用于任意层,不仅仅是 Dense, 例如运用于 Conv2D 层:
      model = Sequential()
      model.add(TimeDistributed(Conv2D(64, (3, 3)),
                                input_shape=(10, 299, 299, 3)))
      
  2. Bidirectional

    • RNN 的双向封装器,对序列进行前向和后向计算。

      model = Sequential()
      model.add(Bidirectional(LSTM(10, return_sequences=True), #实现双向LSTM
                              input_shape=(5, 10))) # 第一层要指明input_shape
      model.add(Bidirectional(LSTM(10)))
      model.add(Dense(5))
      model.add(Activation('softmax'))
      model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
      

13. 编写你自己的Keras层

  1. 对于简单、无状态的自定义操作,你也许可以通过layers.core.Lambda层来实现。但是对于那些包含了可训练权重的自定义层,你应该自己实现这种层。这是一个Keras2.0中,Keras层的骨架。你只需要实现三个方法即可:

    • build(input_shape): 这是你定义权重的地方。这个方法必须设self.built = True,可以通过调用super([Layer], self).build()完成。

    • call(x): 这里是编写层的功能逻辑的地方。你只需要关注传入call的第一个参数:输入张量,除非你希望你的层支持masking。

    • compute_output_shape(input_shape): 如果你的层更改了输入张量的形状,你应该在这里定义形状变化的逻辑,这让Keras能够自动推断各层的形状。

      from keras import backend as K
      from keras.engine.topology import Layer
      import numpy as np
      
    • 下面好像是在定义了一个一层的FC,即Dense

    class MyLayer(Layer):
        def __init__(self, output_dim, **kwargs):
            self.output_dim = output_dim
            super(MyLayer, self).__init__(**kwargs) # 这属于模板语句了,可以认为必写
    
        def build(self, input_shape):
            # Create a trainable weight variable for this layer.
            self.kernel = self.add_weight(name='kernel', 
                                          shape=(input_shape[1], self.output_dim),
                                          initializer='uniform',
                                          trainable=True)
            super(MyLayer, self).build(input_shape)  # Be sure to call this somewhere!
    
        def call(self, x):
            return K.dot(x, self.kernel)
    
        def compute_output_shape(self, input_shape):
            return (input_shape[0], self.output_dim)
    
    # 已有的Keras层 就是实现层的最好的例子。不要犹豫**阅读源码**!
    
posted @ 2019-02-14 20:41  hzhang_NJU  阅读(824)  评论(0编辑  收藏  举报