Я пытаюсь реализовать облегченную (минимальную библиотечную зависимость) версию графа 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);