NumPy 2.x 完全指南【十七】转置操作

1. 什么是转置

在线性代数中,矩阵转置是指将矩阵的行和列进行互换,即原矩阵的第 i i i 行、第 j j j 列元素,在转置后变为第 j j j 行、第 i i i 列元素。给定一个 m × n m \times n m×n 的矩阵 A A A,其转置矩阵 A T A^T AT 是一个 n × m n \times m n×m 的矩阵,满足:
( A T ) i j = A j i (A^T)_{ij} = A_{ji} (AT)ij=Aji

示例, 原矩阵 A A A
A = [ 1 2 3 4 5 6 ] ( 2 × 3 ) A = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{bmatrix} \quad (2 \times 3) A=[142536](2×3)

转置矩阵 A T A^T AT 为:
A T = [ 1 4 2 5 3 6 ] ( 3 × 2 ) A^T = \begin{bmatrix} 1 & 4 \\ 2 & 5 \\ 3 & 6 \end{bmatrix} \quad (3 \times 2) AT= 123456 (3×2)

具体表现为:

  • 原矩阵的第 1 行 转置矩阵的第 1 列
  • 原矩阵的第 2 行 转置矩阵的第 2 列
  • 以此类推

在高维数组中,转置的操作更加灵活,可以:

  • 完全反转所有轴的顺序(默认行为)。
  • 自定义轴的排列顺序(如指定轴的交换顺序)。

在机器学习中转置常用于:

  • 调整图像数据的通道顺序。
  • 将时间序列数据从 (序列长度, 特征数) 转为 (特征数, 序列长度)。
  • 神经网络中的权重矩阵维度匹配。
  • 卷积操作中的滤波器方向调整。

2. 转置操作

2.1 transpose

transpose()(转置):通过轴的重新排列改变数组的维度结构(默认返回视图)。

函数、方法定义:

# 函数
def transpose(a, axes=None)
# 方法
def transpose(self, axes: None | _ShapeLike, /) -> Self: ...

参数说明:

  • a:输入数组(支持任意维度)。
  • axes:指定新轴的排列顺序。

不同维度的行为说明:

数组维度默认行为(无 axes 参数)说明
1-D返回原数组的视图无实际转置操作,仍是 1D 数组,仅改变数组的 strides 属性)
2-D标准矩阵转置行列互换
n-D反转所有轴的顺序原轴顺序 (0,1,2) 变为 (2,1,0)

示例 1 ,转置二维数组:

# 二维数组
arr_2d = np.array([[1, 2, 3],
                   [4, 5, 6]])

# 转置
# 函数调用
transposed_2 = np.transpose(arr_2d)
print(transposed_2)
# 输出:
#[[1 4]
# [2 5]
# [3 6]]

# 方法调用
transposed_1 = arr_2d.transpose()
print(transposed_1)

注意:转置后内存共享,修改转置后的元素会影响原数组:

# 修改转置矩阵元素
transposed_2[1, 1] = 99 # 第二行第二列修改为 5-> 99
print(arr_2d)
# 原数组被修改
# [[ 1  2  3]
#  [ 4 99  6]]

示例 2 ,三维数组:

arr_3d = np.arange(24).reshape(2, 3, 4)  # 形状 (2, 3, 4)
print(arr_3d)
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
#
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

# 转置
transposed = np.transpose(arr_3d)
print(transposed.shape)  # 形状(4,3,2)
print(transposed)
# [[[ 0 12]
#   [ 4 16]
#   [ 8 20]]
#
#  [[ 1 13]
#   [ 5 17]
#   [ 9 21]]
#
#  [[ 2 14]
#   [ 6 18]
#   [10 22]]
#
#  [[ 3 15]
#   [ 7 19]
#   [11 23]]]

转置过程的核心是轴顺序的变化,每个元素的索引按新轴顺序重组,例如三维数组的转置公式为:
( A T ) i j k = n e w A k j i (A^T)_{ijk} = newA_{kji} (AT)ijk=newAkji
示例:

  • A[0,0,0] -> newA[0,0,0]
  • A[0,0,1] -> newA[1,0,0]
  • A[1,2,3] -> newA[3,2,1]
  • 依次映射所有元素

比如,案例中的三维数据,A[1,2,3] 索引即第二层第三行第四列的元素为 23 ,转置后放在 newA[3,2,1] 即第四层第三行第二列,可以看下转置后的输出,也是 23

示例 3 ,有一个形状为 (2, 3, 4) 的三维数组,轴的顺序为 (0, 1, 2) ,那么 axes 参数是包含三个整数的元组,然后可以设置不同轴顺序:

axes 参数转置后形状转置规则(原轴顺序 → 新轴顺序)示例元素映射(原位置 → 新位置)
默认(None(4, 3, 2)(0, 1, 2) → (2, 1, 0)arr[1, 2, 3] → new[3, 2, 1]
(0, 1, 2)(2, 3, 4)无变化arr[1, 0, 0] → new[1, 0, 0]
(1, 0, 2)(3, 2, 4)交换块(0轴)和行(1轴)arr[1, 2, 3] → new[2, 1, 3]
(0, 2, 1)(2, 4, 3)交换行(1轴)和列(2轴)arr[0, 1, 2] → new[0, 2, 1]
(2, 0, 1)(4, 2, 3)列→块→行arr[1, 0, 0] → new[0, 1, 0]
(2, 1, 0)(4, 3, 2)反转所有轴(等价默认)arr[0, 2, 3] → new[3, 2, 0]
(1, 2, 0)(3, 4, 2)行→列→块arr[1, 0, 0] → new[0, 0, 1]

代码示例:

arr = np.arange(24).reshape(2, 3, 4) # shape (4, 3, 2)
print(arr)
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
#
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

transposed = np.transpose(arr, axes=(1, 0, 2))
print(transposed)  # shape (3, 4, 2)
# [[[ 0  1  2  3]
#   [12 13 14 15]]
# 
#  [[ 4  5  6  7]
#   [16 17 18 19]]
# 
#  [[ 8  9 10 11]
#   [20 21 22 23]]]

扩展,在计算机视觉领域,图像通常以多维数组存储,比如彩色图的两种格式:

  • HWCHeight, Width, Channels):即(高度, 宽度, 通道)
  • CHWChannels, Height, Width):即(通道, 高度, 宽度)

在模型训练和预测的过程中,往往会涉及到格式转换,比如 OpenCV 读取图像的格式为 HWCPyTorch 要求的格式是 CHW ,需要在数据内容不变的情况下,整存储顺序,适配不同框架的计算需求。

一个常用的代码片如下:

# 读取图片(HWC格式)
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)

# 转换为 CHW 格式(使用 copy ,防止转置后的视图与原数组共享内存,避免意外的修改。)
img_chw = np.transpose(img_rgb.copy(), (2, 0, 1))

2.2 ndarray.T

NumPy 还提供了一个是一个数组对象的转置属性,即 arr.T ,等价于调用 np.transpose(arr),默认反转数组的所有轴。

示例:

arr_3d = np.arange(24).reshape(2, 3, 4)
print("原形状:", arr_3d.shape)  # (2, 3, 4)

transposed_3d = arr_3d.T
print("转置后形状:", transposed_3d.shape)  # (4, 3, 2)

2.3 moveaxis

numpy.moveaxis:将指定轴移动到目标位置,其他轴按原有顺序自动排列。

函数定义:

def moveaxis(a, source, destination)

参数说明:

  • a:输入的多维数组。
  • source:要移动的轴的原始位置。
  • destination:移动后的目标位置。

注意事项:

  • transpose 函数的一个特例。
  • 返回原数组的视图
  • 支持同时移动多个轴到不同目标位置
  • 目标位置按以下规则处理:
    • 正索引:从左到右(0 开始)。
    • 负索引:从右到左(-1 表示最后一个位置)。

示例 1 ,移动 0 轴到末尾,形状由 (3,4,5) 变为 (4,5,3),元素 a[x,y,k] 依次重新排入到 a[y,k,x] 的索引位置:

x = np.arange(60).reshape(3, 4, 5)  # shape (3,4,5)
print(x)
# [[[ 0  1  2  3  4]
#   [ 5  6  7  8  9]
#   [10 11 12 13 14]
#   [15 16 17 18 19]]
#
#  [[20 21 22 23 24]
#   [25 26 27 28 29]
#   [30 31 32 33 34]
#   [35 36 37 38 39]]
#
#  [[40 41 42 43 44]
#   [45 46 47 48 49]
#   [50 51 52 53 54]
#   [55 56 57 58 59]]]
# 移动轴 0 到末尾
y = np.moveaxis(x, 0, -1)  # shape (4,5,3)
print(y)
# [[[ 0 20 40]
#   [ 1 21 41]
#   [ 2 22 42]
#   [ 3 23 43]
#   [ 4 24 44]]
#
#  [[ 5 25 45]
#   [ 6 26 46]
#   [ 7 27 47]
#   [ 8 28 48]
#   [ 9 29 49]]
#
#  [[10 30 50]
#   [11 31 51]
#   [12 32 52]
#   [13 33 53]
#   [14 34 54]]
#
#  [[15 35 55]
#   [16 36 56]
#   [17 37 57]
#   [18 38 58]
#   [19 39 59]]]

同时移动多个轴时,原位置和目标位置都是数组,且需要保持依次对应关系。示例 2 ,同时移动轴 0 和轴 1 到新位置,即 0 移动到末尾,1 移动到倒数第二位置:

x = np.arange(60).reshape(3, 4, 5)  # shape (3,4,5)
y = np.moveaxis(x, [0, 1],
                [-1, -2])  # shape (5,4,3)
print(y)
# [[[ 0 20 40]
#   [ 5 25 45]
#   [10 30 50]
#   [15 35 55]]
#
#  [[ 1 21 41]
#   [ 6 26 46]
#   [11 31 51]
#   [16 36 56]]
#
#  [[ 2 22 42]
#   [ 7 27 47]
#   [12 32 52]
#   [17 37 57]]
#
#  [[ 3 23 43]
#   [ 8 28 48]
#   [13 33 53]
#   [18 38 58]]
#
#  [[ 4 24 44]
#   [ 9 29 49]
#   [14 34 54]
#   [19 39 59]]]

2.4 rollaxis

numpy.rollaxis():将指定轴滚动到目标位置,其他轴的相对顺序保持不变。

函数定义:

def rollaxis(a, axis, start=0)

注意事项: 仅为了向后兼容性考虑,建议优先使用moveaxis,所有这里就不演示了。

2.5 permute_dims

numpy.permute_dims():通过轴的重新排列改变数组的维度结构(默认返回视图)。

函数定义:

def rollaxis(a, axis, start=0)

提示: permute_dimstranspose 的别名函数,功能完全等效。

2.6 swapaxes

swapaxes():交换数组的两个指定轴,调整数据的维度顺序而不改变数据本身。

函数、方法定义:

# 函数
def swapaxes(a, axis1, axis2):
# 方法
def swapaxes(
    self,
    axis1: SupportsIndex,
    axis2: SupportsIndex,
) -> ndarray[_Shape, _DType_co]: ...

参数说明:

  • a:输入的多维数组。
  • axis1:第一个待交换的轴索引。
  • axis2:第二个待交换的轴索引。

在之前我们学过转置函数(transpose),可以控制所有轴的顺序,而 swapaxes 可以看成它的一个特例,是一种只交换两个轴的操作。

示例 1 ,二维数组交换交换 0 轴和 1 轴:

import numpy as np

x = np.array([[1, 2], [3, 4]])  # shape (2, 2)
y = np.swapaxes(x, 0, 1)  # 交换轴 0 和轴 1
print(y)
# 输出:
# [[1 3]
#  [2 4]]

示例 2 ,三维数组交换交换 0 轴和 2 轴,轴顺序由(0,1,2)变为(2,1,0),元素 a[x,y,k] 依次重新排入到 a[k,y,x] 的索引位置:

x = np.array([[[0, 1], [2, 3]],
              [[4, 5], [6, 7]]])  # shape (2, 2, 2)
y = np.swapaxes(x, 0, 2)  # 交换轴 0(外层)和轴 2(内层)
print(y)
# 输出:
# [[[0, 4],
#   [2, 6]],
#  [[1, 5],
#   [3, 7]]]

2.7 matrix_transpose

numpy.matrix_transpose():专为转置矩阵或批量矩阵设计的函数,仅交换输入数组的最后两个维度,其他维度保持不变。适用于遵循 Array API 标准的操作。

函数定义:

def matrix_transpose(x, /)

参数说明:

  • x:输入的类数组对象,形状为 (..., M, N),其中 ... 表示任意数量的前置维度,最后两个维度 MN 构成矩阵。

返回值:

  • outndarray 类型,形状为 (..., N, M)。每个最后两维的矩阵 M×N 被转置为 N×M,前置维度完全保留。

注意事项:

  • 仅转置最后两个维度,无论输入数组维度多高,只交换最后两个轴。
  • 适合处理堆叠的矩阵(如多个样本、多个通道的数据)。
  • 遵循 Array API 标准,行为与其他框架(如 PyTorchTensorFlow)一致。

示例 1 ,二维矩阵转置:

x = [[1, 2], [3, 4]]  # 形状 (2, 2)
y = np.matrix_transpose(x)
print(y)
# [[1, 3],
#  [2, 4]]

示例 2 ,三维矩阵转置时,每个矩阵独立转置,前置维度(第一维)保持不变:

x = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]  # 形状 (2, 2, 2)
y = np.matrix_transpose(x)
print(y)
# [[[1, 3],  # 第一个矩阵转置
#   [2, 4]],
#  [[5, 7],  # 第二个矩阵转置
#   [6, 8]]]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨 禹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值