Репликация TensorFlow Conv2D, работающая с использованием собственных тензоров - PullRequest
1 голос
/ 05 апреля 2019

Я пытаюсь реализовать облегченную (минимальную библиотечную зависимость) версию графа TensorFlow в c ++, и я пытаюсь использовать объекты Eigen Tensor для выполнения операций над графами. Прямо сейчас я застрял, пытаясь использовать метод Eigen Tensor.convolve(), чтобы попытаться повторить поведение операции Conv2D TensorFlow. Для простоты моя начальная операция Conv2D не имеет отступов и шагов.

Вход в сверточный слой - тензор 51x51x1, который свернут с набором фильтров размером 3x3x1x16. В тензорном потоке это генерирует выходной тензор размером 49x49x16. Настройка этой же операции в C ++ с использованием приведенного ниже кода Eigen заполняет только первый канал выходного тензора, поэтому верхние ячейки 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);

Я предполагаю, что я неправильно понимаю, что делают эти функции и что они не выполняют одну и ту же операцию. Чтобы моя реализация работала, я попытался перебрать 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);
  }

Этот код создает следующую ошибку где-то внутри кода Eigen Tensor. Возможно, он имеет какое-то отношение к присваиванию результатов метода среза, но я не уверен. Если результат присваивается автоматическому типу, он компилируется, но не при последующем анализе результата.

Если кто-нибудь знает, как устранить эту ошибку или, в более общем смысле, как я могу реплицировать операцию 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);
...