在tf.nn.conv1d的文档中,声明为
在内部,此op调整输入张量的形状并调用tf.nn.conv2d。例如,如果data_format并非以“ NC”开头,则将形状为[batch,in_width,in_channels]的张量整形为[batch,1,in_width,in_channels],并将过滤器整形为[1,filter_width,in_channels, out_channels]。然后将结果重新整形为[batch,out_width,out_channels](其中out_width是conv2d中跨度和填充的函数),并返回给调用方。
我知道这些操作是等效的,但是我对实现细节的含义有些困惑。
重塑是否会产生一些计算开销?3D卷积具有自己的实现,那么为什么不使用1D卷积呢?
感谢您提供任何有助于我和其他人理解TensorFlow实施细节的解释!
深入研究源代码,我得出的结论是,这样做可能是为了方便和简化实现-下面将详细介绍。
首先,没有“重塑”,只有扩展,压缩和重新排序暗淡,这只是很小的开销;实际上,没有数组元素在内存中移动-仅更改了张量对象的索引说明符。
[其次,所有conv
最终路由到tf.nn_ops.convolution_internal
,然后路由到tf.nn_ops.convolution_internal
或gen_nn_ops.conv2d
; gen_nn_ops.conv3d
中不存在conv1d
。请注意,由于某种原因,您不会在Git存储库中找到该文件-但该文件应该在您的本地安装gen_nn_ops.py
中。
最后,要想得到为什么没有专用的/python/ops/gen_nn_ops.py
实现的真实答案,您需要询问conv1d
中发现的卷积算法背后的cuDNN开发人员;他们可能没有发现性能上的改进,并且gen_nn_ops.py
的运行速度也一样快。从低级的角度来看,这是有道理的,因为沿着conv2d
输入滑动具有N x 1
个元素的内核时,矩阵乘法的数量与沿着M x 1
的N
相同-再次是唯一的区别正在索引中。
[不幸的是,开发人员决定封装最终调用,即M
;该模块由_pywrap_tensorflow_internal.TFE_Py_FastPathExecute
和.lib
文件组成-基本上是经过编译的C(Cython)代码,需要反汇编才能进行内省。
TL; DR(1)“重塑”的开销很小; (2)每个备用冗余都可能缺少专用的.pyd
实现,因为conv1d
一样快; (3)我不是cuDNN专家,所以如果您需要确定,最好在conv2d
询问或阅读他们的cuDNN。另外,SDK Documentation的开发人员可能会提供帮助。我已经多年没有看到cuDNN开发人员对SO的回答了,所以在这里发布可能不是最好的选择。
Dim重新排序性能演示:
TF Github
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)