Pet*_*3rd 6 python convolution eigen c++11 tensorflow
我正在尝试在 c++ 中实现轻量级(最小库依赖性)版本的 TensorFlow 图,并且我正在尝试使用 Eigen Tensor 对象来执行图操作。现在我一直在尝试使用 EigenTensor.convolve()方法来尝试复制 TensorFlow 的 Conv2D 操作的行为。为了简单起见,我最初的 Conv2D 操作没有填充,步幅为 1。
卷积层的输入是一个 51x51x1 张量,它与大小为 3x3x1x16 的滤波器组进行卷积。在张量流中,这会生成大小为 49x49x16 的输出张量。使用下面的特征代码在 C++ 中设置相同的操作仅填充输出张量的第一个通道,因此顶部 49x49x1 单元格包含正确的值,但其余 1-15 个通道不会填充。
Eigen::TensorMap<Eigen::Tensor<float,4> > filter(filter, 3, 3, 1, 16 );
Eigen::TensorMap<Eigen::Tensor<float,3> > input(inputBuffer, 51, 51, 1 );
Eigen::TensorMap<Eigen::Tensor<float,3> > output(outputBuffer, 49, 49, 16);
Eigen::array<ptrdiff_t, 2> convDims({0, 1});
output = input.convolve(filter, convDims);
Run Code Online (Sandbox Code Playgroud)
我认为我错误地理解了这些函数的作用,并且它们没有执行相同的操作。为了让我的实现正常工作,我尝试循环遍历 16 个过滤器通道,并将卷积方法单独应用于每个通道,但我遇到了编译器错误,我无法理解以下代码:
for (int s=0; s<16; ++s)
{
Eigen::array<int, 4> fOffset = {0, 0, 0, s};
Eigen::array<int, 4> fExtent = {3, 3, 1, 1};
Eigen::array<int, 3> oOffset = {0, 0, s};
Eigen::array<int, 3> oExtent = {49, 49, 1};
auto filterSlice = filter.slice(fOffset, fExtent);
output.slice(oOffset, oExtent) = input.convolve(filterSlice, convDims);
}
Run Code Online (Sandbox Code Playgroud)
此代码从特征张量代码中的某处产生以下错误,它可能与切片方法结果的分配有关,但我不确定。如果将结果分配给自动类型,则它会编译,但如果稍后计算结果则不会编译。
如果有人知道如何解决此错误,或者更一般地说,我如何使用特征张量复制 Conv2D 操作,那将是一个很大的帮助。
/home/user/tensorflow_xla/bcc-2.0.2-gcc/sparc-gaisler-elf/include/unsupported/Eigen/CXX11/src/Tensor/TensorConvolution.h: In instantiation of 'void Eigen::TensorEvaluator<const Eigen::TensorConvolutionOp<Dimensions, InputXprType, KernelXprType>, Device>::preloadKernel() [with Indices = const std::array<int, 2>; InputArgType = const Eigen::TensorMap<Eigen::Tensor<float, 3> >; KernelArgType = const Eigen::TensorSlicingOp<const std::array<int, 4>, const std::array<int, 4>, Eigen::TensorMap<Eigen::Tensor<float, 4> > >; Device = Eigen::DefaultDevice]':
/home/user/tensorflow_xla/bcc-2.0.2-gcc/sparc-gaisler-elf/include/unsupported/Eigen/CXX11/src/Tensor/TensorConvolution.h:383:18: required from 'bool Eigen::TensorEvaluator<const Eigen::TensorConvolutionOp<Dimensions, InputXprType, KernelXprType>, Device>::evalSubExprsIfNeeded(Eigen::TensorEvaluator<const Eigen::TensorConvolutionOp<Dimensions, InputXprType, KernelXprType>, Device>::Scalar*) [with Indices = const std::array<int, 2>; InputArgType = const Eigen::TensorMap<Eigen::Tensor<float, 3> >; KernelArgType = const Eigen::TensorSlicingOp<const std::array<int, 4>, const std::array<int, 4>, Eigen::TensorMap<Eigen::Tensor<float, 4> > >; Device = Eigen::DefaultDevice; Eigen::TensorEvaluator<const Eigen::TensorConvolutionOp<Dimensions, InputXprType, KernelXprType>, Device>::Scalar = float]'
/home/user/tensorflow_xla/bcc-2.0.2-gcc/sparc-gaisler-elf/include/unsupported/Eigen/CXX11/src/Tensor/TensorAssign.h:146:62: required from 'bool Eigen::TensorEvaluator<const Eigen::TensorAssignOp<LhsXprType, RhsXprType>, Device>::evalSubExprsIfNeeded(Eigen::TensorEvaluator<const Eigen::TensorAssignOp<LhsXprType, RhsXprType>, Device>::Scalar*) [with LeftArgType = Eigen::TensorSlicingOp<const std::array<int, 3>, const std::array<int, 3>, Eigen::TensorMap<Eigen::Tensor<float, 3> > >; RightArgType = const Eigen::TensorConvolutionOp<const std::array<int, 2>, const Eigen::TensorMap<Eigen::Tensor<float, 3> >, const Eigen::TensorSlicingOp<const std::array<int, 4>, const std::array<int, 4>, Eigen::TensorMap<Eigen::Tensor<float, 4> > > >; Device = Eigen::DefaultDevice; Eigen::TensorEvaluator<const Eigen::TensorAssignOp<LhsXprType, RhsXprType>, Device>::Scalar = float]'
/home/user/tensorflow_xla/bcc-2.0.2-gcc/sparc-gaisler-elf/include/unsupported/Eigen/CXX11/src/Tensor/TensorExecutor.h:45:16: required from 'static void Eigen::internal::TensorExecutor<Expression, Device, Vectorizable, Tileable>::run(const Expression&, const Device&) [with Expression = const Eigen::TensorAssignOp<Eigen::TensorSlicingOp<const std::array<int, 3>, const std::array<int, 3>, Eigen::TensorMap<Eigen::Tensor<float, 3> > >, const Eigen::TensorConvolutionOp<const std::array<int, 2>, const Eigen::TensorMap<Eigen::Tensor<float, 3> >, const Eigen::TensorSlicingOp<const std::array<int, 4>, const std::array<int, 4>, Eigen::TensorMap<Eigen::Tensor<float, 4> > > > >; Device = Eigen::DefaultDevice; bool Vectorizable = false; bool Tileable = false]'
/home/user/tensorflow_xla/bcc-2.0.2-gcc/sparc-gaisler-elf/include/unsupported/Eigen/CXX11/src/Tensor/TensorMorphing.h:448:65: required from 'Eigen::TensorSlicingOp<StartIndices, Sizes, XprType>& Eigen::TensorSlicingOp<StartIndices, Sizes, XprType>::operator=(const OtherDerived&) [with OtherDerived = Eigen::TensorConvolutionOp<const std::array<int, 2>, const Eigen::TensorMap<Eigen::Tensor<float, 3> >, const Eigen::TensorSlicingOp<const std::array<int, 4>, const std::array<int, 4>, Eigen::TensorMap<Eigen::Tensor<float, 4> > > >; StartIndices = const std::array<int, 3>; Sizes = const std::array<int, 3>; XprType = Eigen::TensorMap<Eigen::Tensor<float, 3> >]'
../tfmin_generated/terrain_model.cpp:215:92: required from here
/home/user/tensorflow_xla/bcc-2.0.2-gcc/sparc-gaisler-elf/include/unsupported/Eigen/CXX11/src/Tensor/TensorConvolution.h:527:52: error: 'Eigen::TensorEvaluator<const Eigen::TensorSlicingOp<const std::array<int, 4>, const std::array<int, 4>, Eigen::TensorMap<Eigen::Tensor<float, 4> > >, Eigen::DefaultDevice>::Dimensions {aka const struct std::array<int, 4>}' has no member named 'TotalSize'
size_t kernel_sz = m_kernelImpl.dimensions().TotalSize() * sizeof(Scalar);
Run Code Online (Sandbox Code Playgroud)
因此,我最终找到了如何仅使用特征张量函数调用来执行 2D 卷积,而不需要任何循环。帮助我到达这里的代码是@jdehesa 链接到我的Tensorflow eigen_spatial_convolutions.h文件。我链接到的行具有对行主数据和列主数据执行 Conv2D 操作所需的特征代码,因此您可能只需要其中的一半。
基本上,您需要使用 Eigen 方法 extract_image_patches 从输入张量中提取每个过滤器实例的感知场。然后,您将其输出和内核张量重塑为 2D 张量。这意味着每个核都是重构核张量的垂直列,重构图像块的每一行都是每个块。然后,您执行收缩,这实际上是这两个二维张量的矩阵乘法,并将结果重新整形回正确的维度以产生输出。
一开始我花了一段时间才明白这一点,但这是可以做到的。
outputTensor = inputTensor
.extract_image_patches(kern_w, kern_h, stride_w, stride_h, dilation_w, dilation_h, padding)
.reshape(Eigen::array<int, 2>({patch_count, kern_w*kern_h}))
.contract(kernalTensor.reshape(Eigen::array<int, 2>({kern_w*kern_h, kern_count})), {Eigen::IndexPair < int > (1, 0)})
.reshape(Eigen::array<int, 3>({ output_w, output_h, kern_count }));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3020 次 |
| 最近记录: |