Tensorflow中的tensor Dimension问题

Posted tonydandelion2014

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tensorflow中的tensor Dimension问题相关的知识,希望对你有一定的参考价值。

记录一个耗时一天多才排除的bug

起因: 在一份代码(A)上添加了另外一份代码(B)的部分内容

原代码(A)在python脚本开始时做了如下声明

K.set_image_data_format('channels_first')

将全局所有含有data_format参数的keras.layer都设置了data_format='channels_first'

而实际上keras.layer默认data_format='channels_last'

data_format='channels_first'data_format='channels_last的区别是指定这一层的输入哪一个维度是channel

而待移植代码(B)没有做声明, 就保持了默认的data_format='channels_last.

结果: 移植代码(B)的过程中忽视了data_format这个全局参数

将另一份代码(B)的部分移植到原来的代码(A)上时, Dense层一直报错. 报错如下

ValueError: Dimensions must be equal, but are 32 and 256 for 'dense_1/add' (op: 'Add') with input shapes: [?,32,256], [1,256,1].

原因在于, 当设置了全局K.set_image_data_format('channels_first')之后, 前面的网络层生成都按照第一维为通道数的逻辑, 到Dense层, 也就是全连接层再进行相乘时就无法继续正常完成矩阵相乘了.

解决

  1. 尝试将代码A向代码B上移植, 在这个过程中, 由于没有设置K.set_image_data_format('channels_first'), 所以全局默认data_format='channels_last, Dense层不再报错.
  2. 在Dense层不再报错的情况下, 发现步骤1获得的代码输出与预计不一样, 主要表现在输出不一致, 执行同样一段代码, 进行卷积操作结果却不一样.
spec_x = Conv2D(filters=_cnn_nb_filt, kernel_size=(3, 3), padding='same')(spec_x)


上图左侧是实际结果(代码B) 2,256,40 卷积之后变成了 2,256,128 以最后一维为channel(错误结果).
上图右侧是目标输出结果(代码A), 2,256,40 卷积之后变成了 128, 256,40 以第一维为channel(正确结果).

由于K.set_image_data_format('channels_first')是在文件最开始, 浪费了很多时间都没有发现, 最终通过仔细阅读文档中Conv2D的部分, 才发现可能是data_format这个参数的问题. 最终取消全局设置K.set_image_data_format('channels_first'), 只在特殊层手动设置data_format='channels_first'的方法实现了输出维度的可控, 至此解决了这问题.

教训

  1. 进行代码合并融合时, 一定要多关注诸如K.set_image_data_format('channels_first')这样的公共设置.
  2. 当发现直接将B的部分代码移植到A之上有报错但B单独运行就能正常运行的时候, 尝试新开一个文件夹, 将A的部分代码移植到B上, 看看还能不能正常运行.
  3. 如果出现像上述情况, 执行一样的代码spec_x = Conv2D(filters=_cnn_nb_filt, kernel_size=(3, 3), padding='same')(spec_x), 输入维度一样却出现不一样的输出, 千万不要懵逼, 记得使用pycharm等ide, 打上断点, 看看两边执行到这里之后, 除了filterskernel_size这种显式声眀的参数以外其他参数是否有区别, 这样就能较快的发现是哪一个参数的区别导致了输出的变化. 如果IDE无法确认参数, 就仔细看文档, 确认区别.

以上是关于Tensorflow中的tensor Dimension问题的主要内容,如果未能解决你的问题,请参考以下文章

Tensorflow中的tensor Dimension问题

如何保存Tensorflow中的Tensor参数,保存训练中的中间参数,存储卷积层的数据

ValueError: Tensor 必须来自与 Tensorflow 中具有双向 RNN 的 Tensor 相同的图

获取tensorflow中tensor的值

tensorflow中张量(tensor)的属性——维数(阶)形状和数据类型

tensorflow打印tensor的值