首页 > 解决方案 > 为什么TensorFlow在调用1D卷积时要计算2D卷积?

问题描述

在 tf.nn.conv1d 的文档中,指出

在内部,此操作会重塑输入张量并调用 tf.nn.conv2d。例如,如果data_format不以“NC”开头,则将形状为[batch, in_width, in_channels]的张量reshape为[batch, 1, in_width, in_channels],并且filter被reshape为[1, filter_width, in_channels, out_channels]。然后将结果重新整形回 [batch, out_width, out_channels](其中 out_width 是步幅和填充的函数,如 conv2d 中一样)并返回给调用者。

我知道这些操作是等效的,但我对这个实现细节的含义有点困惑。

重塑是否会产生一些计算开销?3D 卷积有它自己的实现,那么为什么不是 1D 卷积呢?

感谢任何解释,帮助我和其他人理解 TensorFlow 的这个实现细节!

标签: tensorflowconv-neural-networkconvolution

解决方案


通过挖掘源代码,我得出结论,它可能是为了方便和实现的极简主义而完成的——细节如下。

首先,没有“重塑”,只有扩展、挤压和重新排序 dims,这会产生很小的开销;实际上没有数组元素在内存中移动 - 只有张量对象的索引说明符被更改。

其次, allconv最终路由到tf.nn_ops.convolution_internal,然后路由到gen_nn_ops.conv2dor gen_nn_ops.conv3d;aconv1d中不存在gen_nn_ops.py。请注意,由于某种原因,您不会在 Git 存储库中找到该文件 - 但它应该在您的本地安装中,/python/ops/gen_nn_ops.py.

最后,要真正回答为什么没有专门的conv1d实现,您需要询问卷积算法背后的 cuDNN 开发人员gen_nn_ops.py;他们可能没有发现性能改进,而且conv2d效果也一样快。从低级别的角度来看,这是有道理的,因为沿输入滑动带有N x 1元素的内核时的矩阵乘法的数量与沿输入M x 1的相同- 同样,唯一的区别在于索引。NM

不幸的是,开发人员决定封装最终调用,即_pywrap_tensorflow_internal.TFE_Py_FastPathExecute; 该模块由一个文件.lib和一个.pyd文件组成 - 基本上,编译的 C (Cython) 代码需要反汇编以进行自省。


TL;DR(1)“重塑”的开销很小;conv1d(2)每个备用冗余都可能缺乏专门的实现conv2d,速度也一样快;(3) 我不是 cuDNN 专家,所以如果您需要确定,最好在cuDNN询问,或阅读他们的SDK 文档。或者,TF Github的开发人员可能会有所帮助。多年来,我还没有看到 cuDNN 开发人员对 SO 的回答,所以在这里发帖可能不是最好的选择。


昏暗的重新排序性能演示

import numpy as np
from time import time

x = np.random.randn(700, 800, 900) # 504,000,000 elements

t0 = time()
for i in range(1000):
    if i % 2 == 0:
        x = x.reshape(700, 900, 800)
    else:
        x = x.reshape(700, 800, 900)
print(time() - t0)
0.0009968280792236328

推荐阅读