pin_drop当前位置:知识文库 ❯ 图文

NumPy数组形状操作教程 - reshape、flatten、transpose详解


一、数组形状操作概述

NumPy数组的形状(shape)决定了数据的组织方式。形状操作包括reshape(重塑)、flatten(展平)、transpose(转置)、squeeze(去除长度为1的维度)和expand_dims(增加维度)等。灵活调整数组形状是数据处理和机器学习中的常见需求。

形状操作的核心原则是元素总数不变。无论您如何将一维数组重塑为二维或三维,数组中的元素数量必须保持一致。NumPy提供了丰富的API来满足不同的形状变换需求。

小贴士

在深度学习中,数据形状的正确性是模型训练的关键。例如,图像数据通常需要(batch_size, channels, height, width)的格式,而表格数据则需要(samples, features)。掌握形状操作是数据预处理的第一步。

二、常用形状操作方法

NumPy提供了多种形状操作方法,每种方法都有其特定的用途和返回值类型:

方法/函数 参数 说明
reshape(shape) shape: 新形状元组 重塑数组形状,元素总数不变
flatten() 返回一维副本
ravel() 返回一维视图(尽量)
T 转置属性
transpose(axes) axes: 轴顺序 按指定顺序转置
squeeze(axis) axis: 指定轴 去除长度为1的维度
expand_dims(axis) axis: 插入位置 增加一个维度
reshape(-1) -1: 自动计算 NumPy自动推断该维度大小

三、reshape重塑数组

reshape是最常用的形状操作方法,它可以在保持元素总数不变的前提下,将数组重塑为任意合法的形状。使用-1可以让NumPy自动推断该维度的大小:

代码示例

import numpy as np

arr = np.arange(12)
print(f"原数组: {arr}, shape: {arr.shape}")

# 重塑为3x4
a = arr.reshape(3, 4)
print(f"reshape(3,4):\n{a}")

# 重塑为2x6
b = arr.reshape(2, 6)
print(f"reshape(2,6):\n{b}")

# 使用-1自动推断
c = arr.reshape(3, -1)  # 自动计算列数
print(f"reshape(3,-1):\n{c}")

# 重塑为3维
d = arr.reshape(2, 2, 3)
print(f"reshape(2,2,3), shape: {d.shape}")

输出结果:

代码示例

原数组: [ 0  1  2  3  4  5  6  7  8  9 10 11], shape: (12,)
reshape(3,4):
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
reshape(2,6):
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]]
reshape(3,-1):
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
reshape(2,2,3), shape: (2, 2, 3)

提示:reshape要求新形状的元素总数与原数组一致,否则会抛出ValueError。使用-1时,只能有一个维度使用-1,NumPy会根据其他维度和总元素数自动计算该维度大小。

四、flatten与ravel展平数组

flattenravel都可以将多维数组展平为一维数组,但它们在内存行为上有重要区别:

代码示例

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])

# flatten:返回副本
flat = arr.flatten()
print(f"flatten: {flat}")
flat[0] = 99
print(f"修改flatten后原数组: {arr}")

# ravel:返回视图(尽量)
rav = arr.ravel()
print(f"ravel: {rav}")
rav[0] = 99
print(f"修改ravel后原数组: {arr}")

# 按列展平(order='F')
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(f"按行展平(C): {arr2.flatten('C')}")
print(f"按列展平(F): {arr2.flatten('F')}")

输出结果:

代码示例

flatten: [1 2 3 4 5 6]
修改flatten后原数组: [[1 2 3]
 [4 5 6]]
ravel: [1 2 3 4 5 6]
修改ravel后原数组: [[99  2  3]
 [ 4  5  6]]
按行展平(C): [1 2 3 4 5 6]
按列展平(F): [1 4 2 5 3 6]

五、维度增减与转置

在深度学习和科学计算中,经常需要增加或减少数组的维度。squeeze去除长度为1的维度,expand_dims增加维度,transpose则用于改变轴的顺序:

代码示例

import numpy as np

# squeeze:去除长度为1的维度
arr = np.array([[[1, 2, 3]]])  # shape: (1, 1, 3)
print(f"原shape: {arr.shape}")
print(f"squeeze后: {arr.squeeze().shape}")

# expand_dims:增加维度
arr2 = np.array([1, 2, 3])  # shape: (3,)
print(f"\n原shape: {arr2.shape}")
print(f"axis=0扩展: {np.expand_dims(arr2, axis=0).shape}")
print(f"axis=1扩展: {np.expand_dims(arr2, axis=1).shape}")

# transpose:多维转置
arr3 = np.arange(24).reshape(2, 3, 4)
print(f"\n原shape: {arr3.shape}")
print(f"转置(0,2,1): {arr3.transpose(0, 2, 1).shape}")
print(f"T属性(2D): {np.arange(6).reshape(2,3).T.shape}")

# newaxis:另一种增加维度的方式
arr4 = np.array([1, 2, 3])
print(f"\nnewaxis行向量: {arr4[np.newaxis, :].shape}")
print(f"newaxis列向量: {arr4[:, np.newaxis].shape}")

输出结果:

代码示例

原shape: (1, 1, 3)
squeeze后: (3,)

原shape: (3,)
axis=0扩展: (1, 3)
axis=1扩展: (3, 1)

原shape: (2, 3, 4)
转置(0,2,1): (2, 4, 3)
T属性(2D): (3, 2)

newaxis行向量: (1, 3)
newaxis列向量: (3, 1)

六、实际应用场景

场景1:机器学习模型输入 — 将一维特征向量reshape为二维矩阵以适配模型输入,例如将(100,)重塑为(1, 100)(100, 1)

场景2:深度学习批次维度 — 使用expand_dims增加批次维度,适配深度学习框架。例如将单张图像(224, 224, 3)扩展为(1, 224, 224, 3)

场景3:数据可视化 — 使用flatten将多维数据展平为一维进行绘图,例如将图像的RGB通道展平后绘制直方图。

七、形状操作方法对比

方法 返回类型 是否副本 适用场景
reshape ndarray 尽量视图 改变形状
flatten ndarray 始终副本 展平为一维
ravel ndarray 尽量视图 展平为一维(高效)
T ndarray 视图 二维转置
transpose ndarray 视图 多维转置
squeeze ndarray 视图 去除长度1维度
expand_dims ndarray 视图 增加维度

注意:reshape返回视图(尽量),flatten始终返回副本,ravel尽量返回视图。reshape中使用-1只能有一个维度,NumPy会自动计算该维度大小。

八、常见问题FAQ

flatten和ravel有什么区别?

flatten始终返回数组的副本,修改展平后的数组不会影响原数组;ravel尽量返回视图,如果内存布局允许,修改ravel的结果会影响原数组。从性能角度看,ravel比flatten更高效,因为它避免了不必要的数据复制。

reshape中的-1是什么意思?

-1表示让NumPy自动推断该维度的大小。例如,一个12个元素的数组使用reshape(3, -1)会自动计算出列数为4。注意:-1只能在一个维度上使用,否则NumPy无法确定唯一的形状。

transpose和T属性有什么区别?

T属性是二维数组转置的快捷方式,等价于transpose(1, 0)。对于多维数组,transpose可以指定任意的轴顺序,例如arr.transpose(0, 2, 1)将2轴和1轴交换。T属性只能用于二维转置,transpose适用于任意维度。

newaxis和expand_dims哪个更好用?

两者功能相同,newaxis是np.newaxis的简写,本质上是None的别名。使用arr[np.newaxis, :]和np.expand_dims(arr, axis=0)效果完全一样。newaxis写法更简洁,适合在表达式中直接使用;expand_dims语义更明确,适合初学者。

reshape为什么会失败?

reshape失败的原因通常有两点:一是新形状的元素总数与原数组不匹配,例如12个元素不能reshape为5x3(需要15个元素);二是使用了多个-1导致无法唯一确定形状。检查元素总数是否匹配,并确保只有一个-1即可解决问题。

九、练习题

练习1

创建一个包含0到23的数组,分别reshape为2x12、3x8和2x3x4的形状

练习2

创建一个3x4的二维数组,分别使用flatten和ravel展平,验证flatten是副本而ravel是视图

练习3

创建一个shape为(1,3,1,4)的四维数组,使用squeeze去除所有长度为1的维度,打印变换前后的shape

标签: NumPy形状 reshape transpose flatten Python教程 数据预处理

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: NumPy数组切片教程 - 视图与副本的区别详解 下一篇: NumPy数组运算详解 - 逐元素运算与矩阵乘法完整教程

poll相关推荐