首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何转置C++中的4D张量?

如何转置C++中的4D张量?
EN

Stack Overflow用户
提问于 2022-06-08 18:20:18
回答 1查看 207关注 0票数 0

我需要预处理一个ML模型的输入到正确的形状。为了做到这一点,我需要从ncnn在C++中转换一个张量。API不提供transpose,所以我尝试实现自己的转置函数。

输入张量具有形状(1, 640, 640, 3) (对于batchxycolor),我需要将其重塑为形状(1, 3, 640, 640)

如何正确有效地转换张量?

代码语言:javascript
复制
ncnn:Mat& preprocess(const cv::Mat& rgba) {
    int width = rgba.cols;
    int height = rgba.rows;

    // Build a tensor from the image input
    ncnn::Mat in = ncnn::Mat::from_pixels(rgba.data, ncnn::Mat::PIXEL_RGBA2RGB, width, height);

    // Set the current shape of the tesnor 
    in = in.reshape(1, 640, 640, 3);

    // Normalize
    const float norm_vals[3] = {1 / 255.f, 1 / 255.f, 1 / 255.f};
    in.substract_mean_normalize(0, norm_vals);

    // Prepare the transposed matrix
    ncnn::Mat transposed = new ncnn::Mat(in.w, in.c, in.h, in.d, sizeof(float));
    ncnn::Mat shape = transposed->shape();

    // Transpose
    
    for (int i = 0; i < in.w; i++) {
        for (int j = 0; j < in.h; j++) {
            for (int k = 0; k < in.d; k++) {
                for (int l = 0; l > in.c; l++) {
                    int fromIndex = ???;
                    int toIndex = ???;
                    transposed[toIndex] = in[fromIndex];
                }
            }
        }
    }

    return transposed; 
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-08 21:38:00

我只讨论索引计算,而不是我不熟悉的ncnn。

你设置

代码语言:javascript
复制
fromIndex = i*A + j*B + k*C + l*D;
  toIndex = i*E + j*F + k*G + l*H; 

根据源和目标布局计算A B C D E F G H。多么?

让我们先看一个简单的2D转位。将hw布局矩阵转换为wh布局矩阵(最慢的变化维数优先):

代码语言:javascript
复制
  for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
          int fromIndex = i * w + j * 1;
          //              ^       ^
          //              |       |
          //             i<h     j<w        <---- hw layout

          int   toIndex = j * h + i * 1;
          //              ^       ^
          //              |       |
          //             j<w     i<h        <---- wh layout
      }      
  }      

因此,在计算fromIndex时,从源布局(hw)开始,删除第一个字母(h),剩下的(w)是与i一起的系数,然后删除下一个字母(w),剩下的(1)是与j一起的系数。不难看出,相同的模式在任意数量的维度中都是有效的。例如,如果源布局为dchw,则

代码语言:javascript
复制
fromIndex = i * (c*h*w) + j * (h*w) + k * (w) + l * (1);
//          ^             ^           ^         ^
//          |             |           |         |
//         i<d           j<c         k<h       l<w   <---- dchw

toIndex呢?同样的事情,但重新排列字母从最慢的变化到变化最快的目标布局。例如,如果您的目标布局是hwcd,那么顺序将是k l j i (因为I是在源布局和目标布局中范围都超过[0..d]的索引,等等)。所以

代码语言:javascript
复制
  toIndex = k * (w*c*d) + l * (c*d) + j * (d) + i * (1);
  //        ^             ^           ^         ^
  //        |             |           |         |
  //       k<h           l<w         j<c       i<d   <---- hwcd

我不是故意用你的布局的。做几次自己的计算。你想培养一些关于这件事的直觉。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72550479

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档