首页 > 解决方案 > 改变 Eigen::Tensor(Map) 的类型

问题描述

我目前正在构建一个自定义 TensorFlow Op。它应该像 Conv2D-Op 一样工作,只是它使用自定义数据类型。由于在 Eigen 中实现自定义数据类型相对容易,而在 TensorFlow 中实现相当困难,因此我决定在 TensorFlow 调用 Eigen 之前使用我的自定义数据类型将 Eigen 张量复制到新的 Eigen 张量。将 转换Eigen::TensorMap<Eigen::Tensor<float, 4, Eigen::RowMajor, Eigen::DenseIndex>, Eigen::Aligned>为 a Eigen::TensorMap<Eigen::Tensor<CustomType, 4, Eigen::RowMajor, Eigen::DenseIndex>, Eigen::Aligned>,运行计算,然后转换回floats。

我在 TensorFlows 中添加了一些代码,conv_2d.hoperator(). SpatialConvolution我写了两个辅助函数convertToCustomTypeconvertFromCustomType它们应该为我做转换。目前我并不真正关心性能。

所以基本上我在这一行之前和之后注入了我的两个转换函数:https ://github.com/tensorflow/tensorflow/blob/r1.12/tensorflow/core/kernels/conv_2d.h#L72

template<typename T>
Eigen::Tensor<CustomType, 4, Eigen::RowMajor, Eigen::DenseIndex> convertToCustomType(T &input) {
    Eigen::Tensor<CustomType, 4, Eigen::RowMajor, Eigen::DenseIndex> ret;
    ret.resize(input.dimensions());

    for (int a = 0; a < ret.size(); a++) {
        ret(a) = input(a);
    }
    return ret;
}

template<typename T1, typename T2>
void convertFromCustomType(T1 &input, T2 &output) {
    for (int a = 0; a < input.size(); a++) {
        output(a) = input(a);
    }
}

template<typename Device, typename T>
struct SpatialConvolution {
    void operator()(const Device &d, typename TTypes<T, 4>::Tensor output,
                    typename TTypes<T, 4>::ConstTensor input,
                    typename TTypes<T, 4>::ConstTensor filter, int row_stride,
                    int col_stride, int row_dilation, int col_dilation,
                    const Eigen::PaddingType &padding) {


        auto input_c = convertToCustomType(input);
        auto filter_c = convertToCustomType(filter);
        auto output_c = convertToCustomType(output);

        SpatialConvolutionFunc(d, output_c, input_c, filter_c, row_stride, col_stride, row_dilation, col_dilation, padding);

        convertFromCustomType(output_approx, output);
        output.device(d) = output;
    }
};

我还尝试分别运行张量的所有 4 个维度,这似乎也不起作用。

template <typename T>
Eigen::Tensor<ApproxType, 4, Eigen::RowMajor> convertToCustomType(T input) {
    Eigen::Tensor<ApproxType, 4, Eigen::RowMajor> ret;
    ret.resize(input.dimensions());
    for (int a = 0; a < ret.dimension(0); a++) {
        for (int b = 0; b < ret.dimension(1); b++) {
            for (int c = 0; c < ret.dimension(2); c++) {
                for (int d = 0; d < ret.dimension(3); d++) {
                    ret(a, b, c, d) = input(a, b, c, d);
                }
            }
        }
    }
    return ret;
}

两个版本都可以编译,但会产生不正确的结果。如果我用这个自定义的 Op 运行我的整个 TensorFlow 网络,它就会变得不确定,输出会在不同的运行中使用相同的输入发生变化。

0
[[-0.06590138]]
1
[[-0.04544453]]
2
[[-0.0286443]]
3
[[-0.06590138]]
4
[[-0.06590138]]
5
[[-0.04544453]]

我应该如何改变特征张量的实际类型?我注意到有一些优雅的东西,但是除了不编译之外,它还被Tensor::cast<T>()称为T其他任何东西。Eigen::half我可能在我的自定义类型中遗漏了一些东西吗?

我知道这是一个非常具体的问题,但我会很感激任何想法。

标签: tensorfloweigentensoreigen3

解决方案


显然创建张量是不够的,它必须ret.setZero()在填充之前进行初始化。


推荐阅读