Keras 踩坑记录: Keras 后端 Backend

1 问题起源

    博主最近在跑一个 github 上面的基于 Keras 的深度学习模型的时候发现如下的报错:

ValueError: Negative dimension size caused by subtracting 2 from 1 for 'MaxPool_21' (op: 'MaxPool') with input shapes: [?,1,128,128].

    初步判断是 tensor 的 shape 有问题 ,其中使用了简化版本的 vgg16 模块,使用的模型部分结构如下:

def create_vgg16_dense_kpf( input_shape, model_name = 'vgg16_dense_kpf', is_simplified = True ) :
    '''Create a CNN feature extractor that is identical to the well known VGG16 architecture
    INPUT:
        input_shape = tuple of ( nb_chs, nb_rows, nb_cols ), input image shape
        model_name  = string, name of the output model
        is_simplified = bool, whether or not use all 5 CNN blocks of VGG16
    OUTPUT:
        vgg16_cnn_featex = keras.model, output model
    '''
    img_input = Input( shape = input_shape )
    print(1, img_input.shape)
    # Block 1
    x = Convolution2D(64, 3, 3, activation='relu', border_mode='same', name= model_name + '-block1_conv1')(img_input)
    print(2, x.shape)
    x = Convolution2D(64, 3, 3, activation='relu', border_mode='same', name= model_name + '-block1_conv2')(x)
    print(3, x.shape)
    x = MaxPooling2D((2, 2), strides=(2, 2), name= model_name + '-block1_pool')(x)
    print(4, x.shape)
    # Block 2
    x = Convolution2D(128, 3, 3, activation='relu', border_mode='same', name= model_name + '-block2_conv1')(x)
    print(5, x.shape)
    x = Convolution2D(128, 3, 3, activation='relu', border_mode='same', name= model_name + '-block2_conv2')(x)
    print(6, x.shape)
    x = MaxPooling2D((2, 2), strides=(2, 2), name= model_name + '-block2_pool')(x)
    print(7, x.shape)
    # Block 3
    x = Convolution2D(256, 3, 3, activation='relu', border_mode='same', name= model_name + '-block3_conv1')(x)
    x = Convolution2D(256, 3, 3, activation='relu', border_mode='same', name= model_name + '-block3_conv2')(x)
    x = Convolution2D(256, 3, 3, activation='relu', border_mode='same', name= model_name + '-block3_conv3')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name= model_name + '-block3_pool')(x)
    print(x.shape)
    # Block 4
    x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name= model_name + '-block4_conv1')(x)
    x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name= model_name + '-block4_conv2')(x)
    x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name= model_name + '-block4_conv3')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name= model_name + '-block4_pool')(x)
    print(x.shape)

    查看每层的 x 的 shape 后,发现如下结果:

Keras 踩坑记录: Keras 后端 Backend_第1张图片

    模型的输入是 (3, 256, 256)

    讲道理,经过第一层卷积输出后的 shape 应该是(?,64, 256, 256),而非(?, 3, 256, 64),可见我的初步判断并没有错。最后的通道发生了改变

2 问题排查

    查阅 Keras 的手册,发现:

    Keras 是一个模型级的库,提供了快速构建深度学习网络的模块。Keras 并不处理如张量乘法、卷积等底层操作。这些操作依赖于某种特定的、优化良好的张量操作库。Keras 依赖于处理张量的库就称为“后端引擎”。Keras 提供了两种后端引擎Theano/Tensorflow,并将其函数统一封装,使得用户可以以同一个接口调用不同后端引擎的函数。

输入shape

‘th’模式下,输入形如(samples,channels,rows,cols)的4D张量

‘tf’模式下,输入形如(samples,rows,cols,channels)的4D张量

输出shape

‘th’模式下,为形如(samples,nb_filter, new_rows, new_cols)的4D张量

‘tf’模式下,为形如(samples,new_rows, new_cols,nb_filter)的4D张量

  th:Theano

  tf:Tensorflow

    可见我的模型是在 'tf' 模式下运行的。

3 问题解决

3.1 切换后端

    如果你至少运行过一次Keras,你将在下面的目录下找到Keras的配置文件:

~/.keras/keras.json

    如果该目录下没有该文件,你可以手动创建一个

    文件的默认配置如下:

{
"image_dim_ordering":"tf",
"epsilon":1e-07,
"floatx":"float32",
"backend":"tensorflow"
}

    将 backend 字段的值改写为你需要使用的后端:theano 或 tensorflow,即可完成后端的切换

    可以通过定义环境变量 KERAS_BACKEND 来覆盖上面配置文件中定义的后端:

KERAS_BACKEND=tensorflow python -c "from keras import backend;"
Using TensorFlow backend.

3.2 keras.json 细节

{
    "image_dim_ordering": "tf",
    "epsilon": 1e-07,
    "floatx": "float32",
    "backend": "tensorflow"
}

你可以更改以上 ~/.keras/keras.json 中的配置

其中:

image_dim_ordering:字符串,"tf" 或 "th",该选项指定了 Keras 将要使用的维度顺序

epsilon:浮点数,防止除0错误的小数字

floatx:字符串,"float16", "float32", "float64" 之一,为浮点数精度

backend:字符串,所使用的后端,为 "tensorflow " 或 "theano"

 

 

参考资料:

https://keras-cn-docs.readthedocs.io/zh_CN/latest/backend/

你可能感兴趣的:(深度学习,keras,后端,Tensorflow,theano)