个人对Numpy中transpose()函数的理解

NumPy中的transpose()函数用于对数组进行转置:

如果函数中不传递任何参数,它将进行标准的矩阵转置;

如果传递了一个轴序列,NumPy将按照这个序列重新排列轴。

二维的转置很好理解,就是线性代数中的矩阵转置。但高纬度的转置就有点抽象了,反正我一开始确实没太懂它是怎么进行转置/轴变换的。

numpy官方的文档没什么用,就不贴出来了,想看的自己去看。

下面是GPT的解释:

在 NumPy 中,多维数组的 `transpose` 通过重新排列步长(`strides`)来实现轴的重新排列。以下是具体的操作流程:

1. **原始数据和步长**:NumPy 数组的底层数据是连续存储的,每个维度的步长决定了沿该维度移动一个元素的字节数。

2. **获取形状和步长**:`transpose` 函数首先获取数组的当前形状和步长。

3. **根据新轴顺序重新排列**:假设我们有一个 3D 数组 `A`,形状是 `(2, 3, 4)`,步长是 `(48, 16, 4)`。如果新轴顺序是 `(1, 2, 0)`,则 `transpose` 会按顺序排列新步长 `(16, 4, 48)` 和新形状 `(3, 4, 2)`。

4. **创建视图而非复制数据**:`transpose` 会根据新步长和新形状生成一个新的视图,这样读取时将按新的轴顺序访问数据,但数据在内存中的实际位置没有改变。

这种操作方式能高效地实现多维数组的轴变换。

在 NumPy 中,步长(`strides`)表示在每个维度上移动一个元素所需的字节数。对于多维数组,步长帮助确定如何在内存中访问元素。比如,一个数组的步长指示从一个元素跳到下一个元素时,应该跳过多少字节。步长在执行诸如转置(`transpose`)等操作时非常重要,因为它决定了如何根据新的轴顺序访问原始数据而不需复制。

 简单来说,轴重新排列就是把原来的轴的读取顺序换成了新的轴的读取顺序,然后又改回了原来(0,1,2,3)顺序的表现。可能还是有点抽象,我直接举个具体的例子来说。

a = np.array([5,15,8,41,39,30,39,18,23,42,25,13,15,6,36,25,14,4,42,20,44,3,19,7,24,36,45,38,14,47,23,42,18,31,8,2,20,21,41,8,8,2,11,33,32,31,32,47]).reshape(2,3,2,4)

a是一个四维的矩阵。打印出来的a是这样的

[[[[ 5 15  8 41][39 30 39 18]][[23 42 25 13][15  6 36 25]][[14  4 42 20][44  3 19  7]]][[[24 36 45 38][14 47 23 42]][[18 31  8  2][20 21 41  8]][[ 8  2 11 33][32 31 32 47]]]]

 那么,a.transpose是什么样的呢?

[[[[ 5, 24],[23, 18],[14,  8]],[[39, 14],[15, 20],[44, 32]]],[[[15, 36],[42, 31],[ 4,  2]],[[30, 47],[ 6, 21],[ 3, 31]]],[[[ 8, 45],[25,  8],[42, 11]],[[39, 23],[36, 41],[19, 32]]],[[[41, 38],[13,  2],[20, 33]],[[18, 42],[25,  8],[ 7, 47]]]]

问题来了,这个转置后的a的轴的顺序是什么样的?答案是(3,2,1,0)

不过如果我们在不知道答案的情况下,怎么看出来这个答案呢?

首先,我们以(0,0,0,0)为起点往四根轴看。

3号轴 [5 15 8 41]

2号轴 [5,39]

1号轴 [5 23 14]

0号轴 [5 24]

这应该很容易能看出来。如果不知道轴怎么排的,我在文末有补充。

然后我们看下转置后的4根轴

3号轴 [5 24]

2号轴 [5 23 14]

1号轴 [5 39]

0号轴 [5 15 8 41]

也就是说原来的3号轴现在变成了0号,2号变成了1号,1号变成了2号,0号变成了3号。所以答案是(3,2,1,0)。可以验证:

所以如果我们需要将轴重新排列,也可以用同样的方法进行,只要将主要的几根轴变完了,其他元素按相对位置填进去就可以了。

我空间想象力不行,就不做可视化的分析了,这里直接贴链接。

下面是我用C++实现的transpose。虽然我感觉也许可能会更难理解?只有少量的必要的注释,结合前文自己理解吧,这注释确实不太好写

#include <bits/stdc++.h>
using namespace std;
void printArray(int *arr, const int len, const int dim, int *dims, int *axis)
{
//	printf("dims:");for (int i=0; i<dim; i++) printf("%d%c", dims[i], i==dim-1?'\n':' ');int sufMul[dim]; //后缀乘积 用于计算每个维度的步长strideint idx=0;sufMul[dim-1]=1;for (int i=dim-2; i>=0; i--){sufMul[i] = sufMul[i+1]*dims[i+1];}
//	printf("sufMul:");for (int i=0; i<dim; i++) printf("%d%c", sufMul[i], i==dim-1?'\n':' ');int stride[dim]; // 步长stride,即沿某一维度走一步,在底层的一维数组移动了多少步 for (int i=0; i<dim; ++i){stride[i] = sufMul[axis[i]];}
//	printf("stride:");for (int i=0; i<dim; i++) printf("%d%c", stride[i], i==dim-1?'\n':' ');int newDim[dim]; // 轴变换后,新的每个轴的长度 for (int i=0; i<dim; ++i){newDim[i] = dims[axis[i]];}
//	printf("newDim:");for (int i=0; i<dim; i++) printf("%d%c", newDim[i], i==dim-1?'\n':' ');int newSufMul[dim]; // 轴变换后的后缀乘积,只是用于格式打印输出换行 newSufMul[dim-1]=1;for (int i=dim-2; i>=0; i--){newSufMul[i] = newSufMul[i+1]*newDim[i+1];}
//	printf("sufMul:");for (int i=0; i<dim; i++) printf("%d%c", newSufMul[i], i==dim-1?'\n':' ');idx = 0; // idx表示输出到第几个元素 while (idx < len){int index=0, tmp=idx, i=dim; // index表示该元素在arr中的下标 while (i--){index += (tmp%newDim[i]) * stride[i]; // tmp%newDim[i] 表示在某一维度的下标// vec.push_back(tmp%newDim[i])  // idx新轴序下的坐标 tmp /= newDim[i];}printf("%d,", arr[index]);
//		printf("index=%d, idx=%d\n", index, idx);for (int t=0; t<dim-1; ++t){
//			printf("**t=%d, sumMul[t]=%d, dix+1=%d**", t, sufMul[t], idx);if (((idx+1) % newSufMul[t]) == 0){for (int i=0; i<dim-t-1; i++) printf("\n");break;}}idx++;}
}
int main()
{srand(time(0));int dim;printf("input dimension:");scanf("%d", &dim);int dims[dim];int len=1;printf("input shape(split by space):");for (int i=0; i<dim; ++i){scanf("%d", &dims[i]);len *= dims[i];}printf("input %d numbers(split by space):", len);int arr[len];for (int i=0; i<len; ++i){
//		scanf("%d", &arr[i]);arr[i] = rand()%50;}for (int i=0; i<len; i++) printf("%d%c", arr[i], i==len-1?'\n':',');int axis[dim];for (int i=0; i<dim; i++) axis[i]=i;printArray(arr, len, dim, dims, axis); //打印原始的形状 printf("input axis[0-%d](split by space):", dim-1);for (int i=0; i<dim; i++){scanf("%d", &axis[i]);}printArray(arr, len, dim, dims, axis); // 打印重排轴之后的形状 
}

或许我应该放个python的实现会更合适一点?这里就先挖个坑下次再填吧

如果不太明白轴的顺序,我简单说一下。最先填充的方向轴序号最大,最后填充的方向是0轴。

就像一维是从左到右填充的,最后填充的方向就是从左到右的,所以从左到右就是0号轴。

二维是先从左到右,然后从上到下填充的,最先是从左到右的,所以从左到右是1号轴。一行填完之后从上往下填,所以从上到下是0号轴。

同理,三维的填充顺序就是先填完一层二维的,然后从前往后填充,所以前后方向是0号轴,每一层的填充顺序与二维一致,所以二维的轴的编号加个一就是三维里的编号了。

更高维的也是一样的道理,新的方向是0轴,原来的轴就依次加一。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/464015.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【运动的&足球】足球运动员球守门员裁判检测系统源码&数据集全套:改进yolo11-DBBNCSPELAN

改进yolo11-FocalModulation等200全套创新点大全&#xff1a;足球运动员球守门员裁判检测系统源码&#xff06;数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.10.28 注意&#xff1a;由于项目一直在更新迭代&#xff0c;上面“1.图片效果展示”和“2.视频效果展示…

流畅!HTMLCSS打造网格方块加载动画

效果演示 这个动画的效果是五个方块在网格中上下移动&#xff0c;模拟了一个连续的加载过程。每个方块的动画都是独立的&#xff0c;但是它们的时间间隔和路径被设计为相互协调&#xff0c;以创建出流畅的动画效果。 HTML <div class"loadingspinner"><…

面试题:JVM(二)

1. 面试题 简述 Java 类加载机制?&#xff08;百度&#xff09; JVM类加载机制 &#xff08;滴滴&#xff09; JVM中类加载机制&#xff0c;类加载过程&#xff0c;什么是双亲委派模型&#xff1f; &#xff08;腾讯&#xff09; JVM的类加载机制是什么&#xff1f; &#x…

【c++日常刷题】两个数字的交集、点击消除、最小花费爬楼梯

两个数字的交集⭐ 两个数组的交集_牛客题霸_牛客网 (nowcoder.com) 题目描述&#xff1a; 解题思路&#xff1a; 通过遍历num1&#xff0c;如果遍历到的元素如果在num2中能找到&#xff0c;则这是num1和num2的公告元素&#xff1b; 这里需要借助两个数组来实现&#xff1a;…

energy 发布 v2.4.5

更新内容 修复 energy cli install 命令安装开发环境 修复 动态库加载error未暴露 增加 JS ipc.on 监听模式&#xff0c;异步返回结果 修复 energy cli 不能强制退出问题 修复 MacOS 开发模式 debug 时不更新 helper 进程 优化 energy cli 在 MacOS 开发模式和安装包制作 link…

LeetCode 19. 删除链表的倒数第 N 个结点(java)

目录 题目描述: 代码: 第一种: 第二种: 题目描述: 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;h…

IMU应用于监测进食

最近&#xff0c;日本研究团队成功研发了一种创新的进食速度监测系统&#xff0c;巧妙融合IMU技术&#xff0c;旨在深入研究并有效评估个体在自由生活环境下的进食习惯。 实验中&#xff0c;科研团队把IMU传感器固定在受试者佩戴的腕带中&#xff0c;以监测并记录进食手腕时的运…

WSL开发--利用Git连接远程仓库(详细步骤)

这篇文章主要介绍了如何将本地项目推送到 GitLab 上&#xff0c;并且避免每次提交都需要输入用户名和密码。文中分步讲解了配置 GitLab SSH 密钥以及配置 Git 远程仓库地址的方法。以下是文章的优化和简洁版&#xff1a; 将本地项目推送到 GitLab 并配置 SSH 免密登录 为了方便…

LeetCode100之盛最多水的容器(11)--Java

1.问题描述 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量 注意 你不能倾斜容器 示例1 输入&…

算法实现 - 快速排序(Quick Sort) - 理解版

文章目录 算法介绍算法分析核心思想三个版本运行过程挖坑法Hoare 原版前后指针法 算法稳定性和复杂度稳定性时间复杂度平均情况O(nlogn)最差情况O( n 2 n^2 n2) 空间复杂度 算法介绍 快速排序是一种高效的排序算法&#xff0c;由英国计算机科学家C. A. R. Hoare在1960年提出&a…

设备搜索相关协议使用

一、实现原理 首先&#xff0c;Client -> Gateway : 发送 UDP 广播包&#xff08;含厂商自定义协议)这一步表示客户端开始向网络中发送一个包含厂商自定义协议的 UDP 广播包&#xff0c;目的是寻找本厂商的设备&#xff08;网关&#xff09;。客户端此时处于活动状态activa…

视频去水印怎么办?两种方法教会你

视频有水印的话确实很恼火&#xff0c;想要干净的去除视频水印&#xff0c;这里分享两种简单又实用的方法。 方法一&#xff1a;美图秀秀 大家都熟悉的修图神器&#xff0c;功能超全。不仅能把照片P得美美哒&#xff0c;还能去掉照片和视频上的水印呢&#xff01;用起来挺顺手…

【案例】旗帜飘动

开发平台&#xff1a;Unity 6.0 开发工具&#xff1a;Shader Graph 参考视频&#xff1a;Unity Shader Graph 旗帜飘动特效   一、效果图 二、Shader Graph 路线图 三、案例分析 核心思路&#xff1a;顶点偏移计算 与 顶点偏移忽略 3.1 纹理偏移 视觉上让旗帜保持动态飘动&a…

PHP合成图片,生成海报图,poster-editor使用说明

之前写过一篇使用Grafika插件生成海报图的文章&#xff0c;但是当我再次使用时&#xff0c;却发生了错误&#xff0c;回看Grafika文档&#xff0c;发现很久没更新了&#xff0c;不兼容新版的GD&#xff0c;所以改用了intervention/image插件来生成海报图。 但是后来需要对海报…

智慧汇聚:十款企业培训工具打造学习型企业

在当今快速变化的商业环境中&#xff0c;企业要想保持竞争力&#xff0c;就必须不断适应新技术、新市场和新的工作方式。构建一个学习型企业&#xff0c;不仅能够促进员工的个人成长&#xff0c;还能增强团队的整体能力和企业的创新能力。为了实现这一目标&#xff0c;借助先进…

「C/C++」C/C++标准库 之 #include<cstdlib> 通用工具函数库

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

pycharm调用方法时显示为灰色

不用担心&#xff0c;亮的证明是被用过得&#xff0c;灰色的没有被用&#xff0c;引用一下就会变正常了

机器学习:我们能用机器学习来建立投资模型吗

机器学习模型能解决什么投资问题&#xff1f; 利用机器学习解决投资问题的思路&#xff0c;其实和在互联网领域解决推荐、广告问题的思路是一样的&#xff0c;只不过利用的特征完全变了。推荐、广告模型利用的是用户的年龄、性别&#xff0c;物品的类别、价格等特征&#xff0c…

ClkLog企业版(CDP)预售开启,更有鸿蒙SDK前来助力

新版本发布 ClkLog在上线近1年后&#xff0c;获得了客户的一致肯定与好评&#xff0c;并收到了不少客户对功能需求的反馈。根据客户的反馈&#xff0c;我们在今年三季度对ClkLog的版本进行了重新的规划与调整&#xff0c;简化了原有的版本类型&#xff0c;方便客户进行选择。 与…

【Java设计模式】16-26章

行为型模式&#xff1a; 第16章 12模板方法模式(Template) 16.1 豆浆制作问题 16.2 模板方法模式基本介绍 16.3 模板方法模式原理类图 16.4 模板方法模式解决豆浆制作问题 package com.atguigu.template;//抽象类&#xff0c;表示豆浆 public abstract class SoyaMilk {//模板…