美文网首页
如何根据网络图写网络代码(Keras)

如何根据网络图写网络代码(Keras)

作者: 倩倩达人 | 来源:发表于2019-12-07 14:56 被阅读0次

    如何根据网络图写网络代码(Keras)


    有时候,出于某种目的,我们想要自己一步步搭建网络,不是简单的调用现成的模型,

    • 封装的太厉害,都快忘记内部结构了
    • 自己有一个小点子,想加到网络结构中,万一效果好了呢
    • 有很多专门的场合,我们有一定的先验知识,加到网络中会更好
    • 成就感爆棚,即使是实现现有的网络结构
    cmd-markdown-logo

    写在前面的话

    因为也是刚接触到深度学习这块,并且在项目(传统机器视觉项目)中也遇到了这方面的问题。项目主要是对相似度很高的图像进行分类,有点像细粒度方面的分类。模型采用预训练模型,接着进行fine-tune,但模型一直过拟合,表现形式是:训练的loss和准确率都很高,验证集的准确率和loss却很高,且与训练集的差距较大,例如训练精度90%以上,此时的验证准确率也仅仅70%+。因为,想要自己改一下网络,增加一些防止过拟合的手段,或者把先验知识加进去。因此,研究了下如何写网络代码,更深一层理解。

    什么是层[1]

    Keras中的层对象,输入一个张量,输出一个张量。

    层对象有哪些方法
    • layer.input
    • layer.output
    • layer.input_shape
    • layer.output_shape

    如果该层有多个计算节点,使用下面的方法

    • 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)

    写经典网络代码

    VGG
    vgg16

    这里我们看下VGG经典网络结构图。[2]

    优点
    • 结构简洁,整个网络都使用了同样大小的卷积核尺寸,且核尺寸较小(3x3)。
    • 采用小卷积核比采用大的卷积核更具有优势,因为多层非线性层可以增加网络深度来保证学习更复杂的模式,而且参数更少。
    缺点
    • 耗费更多计算资源,更多的内存占用(140M)。其中绝大多数的参数都是来自于第一个全连接层。

    对于上面的缺点,我们当然可以根据自己的需求去修改,有的文章称这些全连接层即使被去除,对于性能也没有什么影响,也可以把全连接层替换成1X1的卷积层,这些都可以试试。

    def KerasVGG():
        """
        模型采用VGG16 的结构:
            1使用固定尺寸的小卷积核 (3x3)
            2以2的幂次递增的卷积核数量 (64, 128, 256)
            3两层卷积搭配一层池化
            4全连接层没有采用 VGG16 庞大的三层结构,避免运算量过大,仅使用 128 个节点的单个FC
            5权重初始化采用He Normal
        :return:
        """
        inputs = Input(shape=(32, 32, 3))
        net = inputs
        # (32, 32, 3)-->(32, 32, 64)
        net = Convolution2D(filters=64, kernel_size=3, strides=1,
                            padding='same', activation='relu',
                            kernel_initializer='he_normal')(net)
        # (32, 32, 64)-->(32, 32, 64)
        net = Convolution2D(filters=64, kernel_size=3, strides=1,
                            padding='same', activation='relu',
                            kernel_initializer='he_normal')(net)
        # (32, 32, 64)-->(16, 16, 64)
        net = MaxPooling2D(pool_size=2, strides=2, padding='valid')(net)
    
        # (16, 16, 64)-->(16, 16, 128)
        net = Convolution2D(filters=128, kernel_size=3, strides=1,
                            padding='same', activation='relu',
                            kernel_initializer='he_normal')(net)
        # (16, 16, 64)-->(16, 16, 128)
        net = Convolution2D(filters=128, kernel_size=3, strides=1,
                            padding='same', activation='relu',
                            kernel_initializer='he_normal')(net)
        # (16, 16, 128)-->(8, 8, 128)
        net = MaxPooling2D(pool_size=2, strides=2, padding='valid')(net)
    
        # (8, 8, 128)-->(8, 8, 256)
        net = Convolution2D(filters=256, kernel_size=3, strides=1,
                            padding='same', activation='relu',
                            kernel_initializer='he_normal')(net)
        # (8, 8, 256)-->(8, 8, 256)
        net = Convolution2D(filters=256, kernel_size=3, strides=1,
                            padding='same', activation='relu',
                            kernel_initializer='he_normal')(net)
        # (8, 8, 256)-->(4, 4, 256)
        net = MaxPooling2D(pool_size=2, strides=2, padding='valid')(net)
    
        # (4, 4, 256) --> 4*4*256=4096
        net = Flatten()(net)
        # 4096 --> 128
        net = Dense(units=128, activation='relu',
                    kernel_initializer='he_normal')(net)
        # Dropout
        net = Dropout(0.5)(net)
        # 128 --> 10
        net = Dense(units=config.nb_classes, activation='softmax',
                    kernel_initializer='he_normal')(net)
        return inputs, net
    

    如果您想看一下tensorflow版本的vgg16程序,请点这里。[3]

    Inception

    inception的详细结构参见Google的这篇论文:Inception

    inception_v1
    from keras.layers import Conv2D, MaxPooling2D, Input
    
    input_img = Input(shape=(256, 256, 3))
    
    tower_1 = Conv2D(64, (1, 1), padding='same', activation='relu')(input_img)
    tower_1 = Conv2D(64, (3, 3), padding='same', activation='relu')(tower_1)
    
    tower_2 = Conv2D(64, (1, 1), padding='same', activation='relu')(input_img)
    tower_2 = Conv2D(64, (5, 5), padding='same', activation='relu')(tower_2)
    
    tower_3 = MaxPooling2D((3, 3), strides=(1, 1), padding='same')(input_img)
    tower_3 = Conv2D(64, (1, 1), padding='same', activation='relu')(tower_3)
    
    output = keras.layers.concatenate([tower_1, tower_2, tower_3], axis=1)
    

    这里可以看出,1X1的卷积其实在很多地方都有用,至于究竟为什么会这样,以及这些网络的背后深层原因,还需要花费更多的时间去理解,去悟,后续再见。


    再一次感谢您花费时间阅读,祝您在这里记录、阅读、分享愉快!


    1. https://keras-cn.readthedocs.io/en/latest/layers/about_layer/

    2. https://www.cs.toronto.edu/~frossard/post/vgg16/

    3. https://www.cs.toronto.edu/~frossard/vgg16/vgg16.py

    相关文章

      网友评论

          本文标题:如何根据网络图写网络代码(Keras)

          本文链接:https://www.haomeiwen.com/subject/dfsugctx.html