vgg模型-卷积核2D转化3D

vgg模型源码(之前网上搜vgg模型,下了之后一直当源码模型用,本源码是参考PyCharm的源码):

from keras.models import Sequential
from keras.layers import Dense,Conv2D,MaxPooling2D,Flatten

def vgg():
    model = Sequential()
    model.add(Conv2D(64, (3, 3),
           activation='relu',
           padding='same',
           name='block1_conv1',
           dim_ordering='tf',
           input_shape=(255,255,3)))
    model.add(Conv2D(64, (3, 3),
           activation='relu',
           padding='same',
           name='block1_conv2'))
    model.add(MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool'))

    model.add(Conv2D(128, (3, 3),
                      activation='relu',
                      padding='same',
                      name='block2_conv1'))
    model.add(Conv2D(128, (3, 3),
           activation='relu',
           padding='same',
           name='block2_conv2'))
    print(model.output.shape)
    model.add(MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool'))
    model.add(Conv2D(256, (3, 3),
                      activation='relu',
                      padding='same',
                      name='block3_conv1'))
    model.add(Conv2D(256, (3, 3),
                      activation='relu',
                      padding='same',
                      name='block3_conv2'))
    model.add(Conv2D(256, (3, 3),
                      activation='relu',
                      padding='same',
                      name='block3_conv3'))
    model.add(MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool'))
    model.add(Conv2D(512, (3, 3),
                      activation='relu',
                      padding='same',
                      name='block4_conv1'))
    model.add(Conv2D(512, (3, 3),
                      activation='relu',
                      padding='same',
                      name='block4_conv2'))
    model.add(Conv2D(512, (3, 3),
                      activation='relu',
                      padding='same',
                      name='block4_conv3'))
    model.add(MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool'))
    model.add(Conv2D(512, (3, 3),
                      activation='relu',
                      padding='same',
                      name='block5_conv1'))
    model.add(Conv2D(512, (3, 3),
                      activation='relu',
                      padding='same',
                      name='block5_conv2'))

    model.add(Conv2D(512, (3, 3),
                      activation='relu',
                      padding='same',
                      name='block5_conv3'))
    model.add(MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool'))

    model.add(Flatten(name='flatten'))
    model.add(Dense(4096, activation='relu',name='fc1'))

    model.add(Dense(4096, activation='relu', name='fc2'))

    model.add(Dense(2, activation='sigmoid', name='predictions'))
    print(model.summary())
    return model

if __name__ == '__main__':
    vgg()

因为需要训练四维的图片,所以这里面卷积核,池化层都需要改成3D的,先附上修改好的代码,再说坑:

from keras.models import Sequential
from keras.layers import Dense,Conv3D,MaxPooling3D,Flatten


def vgg():
    model = Sequential()
    model.add(Conv3D(64, (3, 3,3),
           activation='relu',
           padding='same',
           name='block1_conv1',
           dim_ordering='tf',
           input_shape=(255,255,3,4)))
    model.add(Conv3D(64, (3, 3,3),
           activation='relu',
           padding='same',
           name='block1_conv2'))
    model.add(MaxPooling3D(
            pool_size=(2, 2,2),
            strides=(2, 2,2),
            name='block1_pool',
            padding='same'))
    model.add(Conv3D(128, (3, 3,3),
                      activation='relu',
                      padding='same',
                      name='block2_conv1'))
    model.add(Conv3D(128, (3, 3,3),
           activation='relu',
           padding='same',
           name='block2_conv2'))


    model.add(MaxPooling3D((2,2, 2), strides=(2,2, 2),padding='same', name='block2_pool'))

    model.add(Conv3D(256, (3, 3,3),
                      activation='relu',
                      padding='same',
                      name='block3_conv1'))
    model.add(Conv3D(256, (3,3, 3),
                      activation='relu',
                      padding='same',
                      name='block3_conv2'))
    model.add(Conv3D(256, (3,3, 3),
                      activation='relu',
                      padding='same',
                      name='block3_conv3'))
    model.add(MaxPooling3D((2,2, 2), strides=(2,2, 2),padding='same', name='block3_pool'))
    model.add(Conv3D(512, (3,3, 3),
                      activation='relu',
                      padding='same',
                      name='block4_conv1'))
    model.add(Conv3D(512, (3,3, 3),
                      activation='relu',
                      padding='same',
                      name='block4_conv2'))
    model.add(Conv3D(512, (3,3, 3),
                      activation='relu',
                      padding='same',
                      name='block4_conv3'))
    model.add(MaxPooling3D((2,2, 2), strides=(2,2, 2),padding='same', name='block4_pool'))
    model.add(Conv3D(512, (3,3, 3),
                      activation='relu',
                      padding='same',
                      name='block5_conv1'))
    model.add(Conv3D(512, (3,3, 3),
                      activation='relu',
                      padding='same',
                      name='block5_conv2'))

    model.add(Conv3D(512, (3,3, 3),
                      activation='relu',
                      padding='same',
                      name='block5_conv3'))
    model.add(MaxPooling3D((2,2, 2), strides=(2,2, 2),padding='same', name='block5_pool'))

    model.add(Flatten(name='flatten'))
    model.add(Dense(4096, activation='relu',name='fc1'))

    model.add(Dense(4096, activation='relu',name='fc2'))

    model.add(Dense(2, activation='sigmoid', name='predictions'))
    print(model.summary())
    return model

if __name__ == '__main__':
    vgg()

如果按照2D的源码修改,无非就是把2D改3D,然后,卷积核和池化层都改成3维的,验证了那句话,理想很骨感,现实很残忍。

现来看看报什么错:

ValueError: Negative dimension size caused by subtracting 2 from 1 for 'block2_pool/MaxPool3D'

报错的位置在这一句:model.add(MaxPooling3D((2,2, 2), strides=(2,2, 2),#padding='same',name='block2_pool'))

看语法也没错啊,网上搜了一下都是说tf和th的问题,发现我代码不存在这个问题,无奈只能一层一层的打印(对比之前随便写的一个3D模型),果然发现了问题:padding='same',

先来看一下padding这个参数的解释:参考https://blog.csdn.net/wuzqchom/article/details/74785643

我在第一个MaxPooling3D层,没有设置padding这个参数,默认的padding='VALID',看下对应的网络结构(只看前四层):

Layer (type)                 Output Shape              Param #   
=================================================================
block1_conv1 (Conv3D)        (None, 255, 255, 3, 64)   6976      
_________________________________________________________________
block1_conv2 (Conv3D)        (None, 255, 255, 3, 64)   110656    
_________________________________________________________________
block1_pool (MaxPooling3D)   (None, 127, 127, 1, 64)   0         
_________________________________________________________________
block2_conv1 (Conv3D)        (None, 127, 127, 1, 128)  221312    
_________________________________________________________________
block2_conv2 (Conv3D)        (None, 127, 127, 1, 128)  442496    
=================================================================

加了padding='same',再看网络结构(只看前四层):

Layer (type)                 Output Shape              Param #   
=================================================================
block1_conv1 (Conv3D)        (None, 255, 255, 3, 64)   6976      
_________________________________________________________________
block1_conv2 (Conv3D)        (None, 255, 255, 3, 64)   110656    
_________________________________________________________________
block1_pool (MaxPooling3D)   (None, 128, 128, 2, 64)   0         
_________________________________________________________________
block2_conv1 (Conv3D)        (None, 128, 128, 2, 128)  221312    
_________________________________________________________________
block2_conv2 (Conv3D)        (None, 128, 128, 2, 128)  442496    

就是这里的问题,能力有限暂时解释不了这个原因。

所有2D改3D的时候,在所有的池化层加上参数padding='same',整个3D模型就ok了。

 

 

你可能感兴趣的:(工作日记)