transpose算子也叫做permute算子,根据白嫖有道英汉大词典的结果,他俩都是转置,改变排列顺序的意思。

算法逻辑是:

  1. 通过当前输出的一维偏移量(offset)计算输入矩阵对应的高维索引

  2. 然后根据参数pos重新排列输出索引,进而得到输出索引。

  3. 将输出索引转换成输入偏移量.

  4. 最后进行数据移动,整个过程的示意图如下.

上代码,pos[]数组表示将输入矩阵的pos[i]维,映射到输出矩阵的第i维。

/** ===========================================================================================**       Filename:  transpose.c**    Description:  transpose operator impl.**        Version:   *         Create:  2021-11-07 14:08:50*       Revision:  none*       Compiler:  GCC:version 7.2.1 20170904 (release),ARM/embedded-7-branch revision 255204**         Author:  *   Organization:  Last Modified : 2021-11-07 20:22:56** ===========================================================================================*/
#include <stdio.h>
#include <stdlib.h>#define DBG(fmt, ...)   do{ printf("%s line %d, "fmt"\n", __func__, __LINE__, ##__VA_ARGS__); } while(0)void transpose_matrix(float *matrix_A, float **matrix_B, int *shape_A, int dims_A, int *pos)
{float *B;int element_count;int i;element_count = 1;for(i = 0; i < dims_A; i ++){element_count *= shape_A[i];}B = (float *)malloc(element_count * sizeof(float));if(B == NULL){DBG("malloc buffer for B failure.");return;}int* shape_B = (int *)malloc(sizeof(int) * dims_A);if(shape_B == NULL){DBG("malloc shape buffer for B failure.");return;}for(int i = 0; i < dims_A; i++){shape_B[i] = shape_A[pos[i]];}int* indexA = (int*)malloc(sizeof(int) * dims_A);if(indexA == NULL){DBG("failure to malloc matrix A index.");return;}int* indexB = (int*)malloc(sizeof(int) * dims_A);if(indexB == NULL){DBG("failure to malloc matrix B index.");return;}for(int src = 0; src < element_count; src++){int temp = src;for(i = dims_A-1; i >= 0; i--){indexA[i] = temp % shape_A[i];temp = temp / shape_A[i];}for(i = 0; i < dims_A; i++){indexB[i] = indexA[pos[i]];}int dst = 0;temp = 1;for(i = dims_A - 1; i >= 0; i--){dst = dst + indexB[i] * temp;temp = temp * shape_B[i];}B[dst] = matrix_A[src];}free(indexA);free(indexB);indexA = indexB = NULL;*matrix_B=B;return;
}void print_tensor(const float* A, int* shape, int dim)
{                     int elem = 1;     for(int i = 0; i < dim; i++){                 elem = elem * shape[i];}                 printf("Array size: %d\n", elem);for(int i = 0; i < elem; i++){                 printf( "%f ", A[i] );int split = 1;         for(int j = dim-1; j > 0; j--){                      split = split * shape[j];if( (i+1) % split == 0){printf("\n");}         }             }
} int main(void)
{float* B;float A[24] ={ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};  int shapeA[] = {2, 3, 4}; int dimA = 3;print_tensor(A, shapeA, dimA);// Transposeint perm[] = { 2, 0, 1}; transpose_matrix(A, &B, shapeA, dimA, perm);// Print Bint shapeB[] = {4, 2, 3}; int dimB = 3;print_tensor(B, shapeB, dimB);int shapeM[] = {2, 2, 2, 3}; int dimM = 4;print_tensor(A, shapeM, dimM);// Transposeint permM[] = {3, 0, 1, 2}; transpose_matrix(A, &B, shapeM, dimM, permM);// Print Bint shapeO[] = {3, 2, 2, 2}; int dimO = 4;print_tensor(B, shapeO, dimO); // Free memoryfree(B);return 0;
}

运行结果

(base) caozilong@caozilong-Vostro-3268:~/Workspace/transpose$ ./a.out
Array size: 24
1.000000 2.000000 3.000000 4.000000
5.000000 6.000000 7.000000 8.000000
9.000000 10.000000 11.000000 12.000000 13.000000 14.000000 15.000000 16.000000
17.000000 18.000000 19.000000 20.000000
21.000000 22.000000 23.000000 24.000000 Array size: 24
1.000000 5.000000 9.000000
13.000000 17.000000 21.000000 2.000000 6.000000 10.000000
14.000000 18.000000 22.000000 3.000000 7.000000 11.000000
15.000000 19.000000 23.000000 4.000000 8.000000 12.000000
16.000000 20.000000 24.000000 Array size: 24
1.000000 2.000000 3.000000
4.000000 5.000000 6.000000 7.000000 8.000000 9.000000
10.000000 11.000000 12.000000 13.000000 14.000000 15.000000
16.000000 17.000000 18.000000 19.000000 20.000000 21.000000
22.000000 23.000000 24.000000 Array size: 24
1.000000 4.000000
7.000000 10.000000 13.000000 16.000000
19.000000 22.000000 2.000000 5.000000
8.000000 11.000000 14.000000 17.000000
20.000000 23.000000 3.000000 6.000000
9.000000 12.000000 15.000000 18.000000
21.000000 24.000000 (base) caozilong@caozilong-Vostro-3268:~/Workspace/transpose$

通过这个程序,发现一个很有意思的规律,大概描述如下,在N维空间下,<=N的tensor做转置,不需要对tensor做结构上的改变,只需要转换观察角度即可,因为空间维度容的下数据向各个方向的扩展.

以三维空间为例,对于二维矩阵的转置操作,我们只需要分别从列向量和行向量的方向上观察即可,不需要做矩阵做调整。

对于三维的物体也是一样,我们以魔方为例在说明:

不管魔方是几阶的,它都是三维的,都可以用一个三维的数组来表示。A[M][N][P],对于,M,N,P全排列中的任何一个,我们都可以通过切换观察视角来理解它的转置操作,而不需要对它做结构上的调整。

但是,当高维矩阵在内存中存储时,由于内存模型是线性表模型,它是一维的,一维的空间容不下多个维度,所以必须要扁平化 “降维” 成1维。对于N维tensor来说,这个降维排布方式有N!种方式。对应了高维空间中的几种观察视角的变化切换。

那么四维空间中魔方该如和表示置换操作呢?我们生活的空间是三维的,对于四维空间,我们缺乏像对三维空间那样直观的认识,更别说四维的魔方了。它超出了我们的认知范围,但是从数学的角度看,我们可以通过将第四维看成是是在某个三维方向上的拓展或者对某个维度的复用,还是以魔方为例,我们可以通过将组成魔方的每个小方块在划分维度,比如1维,2维。。。等等,想象一个魔方中的魔方,每个小方块还是一个魔方,那就是3*3*3*(3*3*3)六个维度,通过这种方式,我们可以定义任意维度的魔方,构造上有点像俄罗斯套娃。

但是,理解这种构造魔方的转置还有一个局限,就是它的维度已经超过了所在空间的维度,所有,有些维度会复用,造成“冲突”,还是以魔方为例,俄罗斯套娃方式构造的魔方,每个小方框其实都是对三维空间的复用,它不存在真正的它所在的高维对应的维度,所以,如果要完成置换,可能需要对魔方的构造进行调整,而不单单是仅仅是进行视角的变化。

这是由矩阵转置联想到的一点粗浅的理解,可能有错误,但这并不重要,每个人的认识都是在不断的纠正错误中前进的,权且记录下来,以便日后思考,更正吧。

总结:

代码中,shape和数组形式定义的维度序关系如下:

imple by myself:

#include <stdio.h>int main(void)
{static int abc = 0;int a[6][6][3];int b[3][6][6];int i,j,k;for(i = 0; i < 6; i ++){for(j = 0; j < 6; j ++){for(k = 0; k < 3; k ++)a[i][j][k] =  abc ++;}}for(i = 0; i < 6; i ++){for(j = 0; j < 6; j ++){for(k = 0; k < 3; k ++)printf("%3d ", a[i][j][k]);printf("\n");}printf("\n");printf("\n");}printf("========================================\n");for(i = 0; i < 3; i ++){for(j = 0; j < 6; j ++){for(k = 0; k < 6; k ++)b[i][j][k] =  a[j][k][i];}}for(i = 0; i < 3; i ++){for(j = 0; j < 6; j ++){for(k = 0; k < 6; k ++)printf("%3d ", b[i][j][k]);printf("\n");}printf("\n");printf("\n");}return 0;
}

RGB图像transform的一种方式。

RGB图像的三个维度是长,宽,和 色彩(可以理解为高),长宽转置没有意义(也不能完全说没有意义,内存是一维的,存储方向肯定发生了变化),所以可以将长宽看成一个维度,所以,RGBRGBRGB。。。。排列方式和RRRRR。。。GGGGG。。。BBBBB两种方式的区别在于颜色和【XY】的转置。


结束!

转置算子(transpose)的一种实现相关推荐

  1. transpose算子优化的几种常见场景

    很难写一个kernel就能同时在transpose的所有场景都最优,归纳transpose的几种常见场景可以针对性优化.这里只列出了transpose对轴变换的几种情况,没有考虑shape大小.因此在 ...

  2. vba 将数组作为参数传递_将VBA数组写入工作表时转置(Transpose)的利用

    大家好,最近推出的内容是"VBA信息获取与处理"中的部分内容,这套教程面向中高级人员,涉及范围更广,实用性更强,现在的内容是第四个专题"EXCEL工作表数据的读取.回填和 ...

  3. numpy之高维数组的转置:transpose方法——通过几何体来迅速理解

    首先说明,这个方法是博主在理解高维数组转置的transpose 方法时所提出的,因此严谨性和正确性有待考察,但私以为完全可以这样理解,因此做个记录,如果对你有帮助的话欢迎点赞收藏,如果认为有错误的话请 ...

  4. vba put 语名 delphi 用什么语句_将VBA数组写入工作表时转置(Transpose)的利用

    大家好,最近推出的内容是"VBA信息获取与处理"中的部分内容,这套教程面向中高级人员,涉及范围更广,实用性更强,现在的内容是第四个专题"EXCEL工作表数据的读取.回填和 ...

  5. 转置卷积transpose convolution

    参考: A guide to convolution arithmetic for deep learning.(Vincent Dumoulin, Francesco Visin).[https:/ ...

  6. numpy使用diagonal函数和sum函数计算矩阵的迹(trace)、使用T函数对矩阵进行转置(transpose matrix)

    numpy使用diagonal函数和sum函数计算矩阵的迹(trace).使用T函数对矩阵进行转置(transpose matrix) 目录

  7. TensorFlow——多维矩阵的转置(transpose)

    TensorFlow--多维矩阵的转置(transpose)_Andy的博客-CSDN博客_tensorflow 转置

  8. 转置(transpose)的理解

    目录 1 .T,适用于一.二维数组 arr.T #求转置 transpose 的原理其实是根据维度(shape)索引决定的,举个栗子: 2. 高维数组 3. swapaxes 转置可以对数组进行重置, ...

  9. 矩阵转置(transpose、T)

    1.T T 适用于一.二维数组的转置 transpose 适用于高维数组,需要用到一个由轴编号组成的元组,才能进行转置 In [1]: import numpy as npIn [2]: arr = ...

最新文章

  1. 使用Application.GetResourceStream从XAP安装包加载任意资源
  2. 刷新4项文档智能任务纪录,百度TextMind打造ERNIE-Layout登顶文档智能权威榜单
  3. c#大文件读取和写入数据库
  4. java的lookingat_Java Matcher.lookingAt()部分匹配字符串
  5. Google Megastore介绍
  6. vue项目中阻止浏览器返回上一页
  7. 针对服务器操作系统安全,浅谈等级保护中的服务器操作系统安全
  8. DataNode逻辑结构
  9. spymemcached 的 useNagle 问题与 TCP/IP延迟发送数据
  10. 字符串处理 BestCoder Round #43 1001 pog loves szh I
  11. java取整和java四舍五入方法
  12. 100个java编程实例_100个java编程实例
  13. 三菱plc指令dediv_三菱PLC指令[]学习指导书.ppt
  14. gg修改器修改数值没有用怎么办_gg修改器怎么用教学 gg修改器修改游戏方法介绍...
  15. 阿里本地生活电话面试
  16. 计算机应用 一级学科,一级学科、二级学科,考研专业哪个包含了计算机考研方向...
  17. appcrash事件怎么解决?三种方法教你
  18. P9:最大池化的使用
  19. 键盘布局及各按键功能介绍(超超超详细的哟~)
  20. 虚拟内存(为什么要有虚拟内存)

热门文章

  1. 【SIGAI综述】行人检测算法(转)
  2. Python-数据类型:bytes
  3. 海阔凭鱼跃,天空任鸟飞,你也一定可以
  4. 机器学习与气象数据_利用机器学习方法综合物候和气象数据预测水稻产量
  5. ubuntu中伪分布式hadoop搭建
  6. 微信支付接口 订单号重复
  7. mysql如何直接打开表_Navicat for MySQL:如何打开 MySQL 表,需要技巧
  8. 红外成像原理及常用静脉血管影像分割论文
  9. ProcessingJoy —— 坍缩的立方体【JAVA】
  10. Gradle学习笔札