pytorch 张量详解
基本概念
pytorch 张量(tensor)是 pytorch 中的核心数据结构,类似于 numpy 的 ndarray,但具有 gpu 加速能力。张量是一个多维数组,可以包含标量(0维)、向量(1维)、矩阵(2维)以及更高维度的数据。在深度学习应用中,张量通常用于表示神经网络的输入数据、权重参数和梯度信息。
张量的维度与详细示例
0维张量(标量)
0维张量是最基本的张量形式,仅包含一个数值,不包含任何维度信息。在pytorch中创建时不需要使用方括号包裹。
- 示例1:
torch.tensor(3.14)表示一个简单的浮点数值 - 示例2:
torch.tensor(true)表示一个布尔值 - 应用场景:神经网络中的损失值、准确率等单一指标的表示
1维张量(向量)
1维张量包含一个轴(维度),可以看作是一组有序的数值集合。通常用于表示特征向量、时间序列等。
- 示例1:
torch.tensor([1, 2, 3])表示一个包含3个元素的行向量 - 示例2:
torch.tensor([0.1, 0.5, 0.9])表示神经网络的输出概率 - 形状表示:
(n,)其中n是向量长度 - 应用场景:全连接层的输入/输出、词嵌入表示等
2维张量(矩阵)
2维张量包含两个轴,通常表示为行和列的结构。在深度学习中广泛用于权重矩阵、特征矩阵等。
- 示例1:
torch.tensor([[1, 2], [3, 4]])表示一个2×2的矩阵 - 示例2:
torch.zeros((3, 4))创建3行4列的全零矩阵 - 形状表示:
(m, n)其中m是行数,n是列数 - 应用场景:全连接层的权重参数、批量处理时的特征矩阵等
3维张量
3维张量在计算机视觉中特别常见,通常用于表示批量的图像数据或序列数据。
典型形状:
(batch_size, channels, height, width)batch_size:一次处理的样本数量channels:颜色通道数(rgb图像为3,灰度图为1)height:图像高度(像素数)width:图像宽度(像素数)
示例1:
torch.randn(16, 3, 224, 224)表示16张224×224像素的rgb图像示例2:
torch.zeros(32, 1, 28, 28)表示32张28×28像素的灰度图应用场景:卷积神经网络的输入、视频数据处理、自然语言处理中的词序列等
与 numpy 数组的比较
与 numpy 数组相比,pytorch 张量具有以下独特优势:
gpu 加速支持
- 可以轻松将张量转移到 gpu 上进行高效计算
- 使用方法:tensor.cuda() 或 tensor.to('cuda')
- 示例:在图像分类任务中,可以将批量图像张量转移到 gpu 加速卷积运算
自动微分能力
- 内置支持自动微分,便于神经网络训练
- 通过设置 requires_grad=true 启用自动求导
- 示例:在训练 cnn 时,pytorch 会自动计算损失函数对网络参数的梯度
动态计算图
- 支持动态构建计算图,灵活性更高
- 计算图在每次前向传播时动态构建
- 应用场景:在rnn处理变长序列时特别有用
实际应用场景
- 计算机视觉:4d张量表示图像批次 (batch, channel, height, width)
- 自然语言处理:3d张量表示文本序列 (batch, sequence_length, embedding_dim)
- 强化学习:2d张量表示状态空间 (batch, state_dimension)
性能优化建议
- 尽量使用矢量化操作代替循环
- 合理使用 inplace 操作节省内存
- 注意 cpu 和 gpu 之间的数据传输开销
张量创建方式
从 python 列表创建
import torch # 创建一维张量(向量) tensor1d = torch.tensor([1.0, 2.0, 3.0]) # 浮点型向量 tensor1d_int = torch.tensor([1, 2, 3]) # 整型向量 # 创建二维张量(矩阵) tensor2d = torch.tensor([[1, 2, 3], [4, 5, 6]]) # 2x3矩阵 tensor2d_float = torch.tensor([[1., 2.], [3., 4.]]) # 2x2浮点矩阵 # 创建三维张量 tensor3d = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) # 2x2x2张量
特殊张量创建
# 创建全零张量(常用于初始化) zeros = torch.zeros(3, 4) # 3行4列的全零矩阵 zeros_3d = torch.zeros(2, 3, 4) # 2x3x4的三维零张量 # 创建全一张量 ones = torch.ones(2, 3) # 2行3列的全一矩阵 ones_like = torch.ones_like(zeros) # 创建与zeros形状相同的全一张量 # 创建随机张量(常用于权重初始化) rand_tensor = torch.rand(5, 5) # 5x5的随机矩阵,值在[0,1)之间均匀分布 randn_tensor = torch.randn(3, 3) # 3x3的正态分布随机矩阵,均值0,方差1 # 创建单位矩阵(常用于线性变换初始化) eye_matrix = torch.eye(4) # 4x4的单位矩阵 eye_with_offset = torch.eye(3, 4, k=1) # 3x4的矩阵,对角线偏移1位 # 创建等差数列张量 arange_tensor = torch.arange(0, 10, 2) # [0, 2, 4, 6, 8] linspace_tensor = torch.linspace(0, 1, 5) # [0.0, 0.25, 0.5, 0.75, 1.0]
张量属性
每个张量都有以下重要属性,这些属性决定了张量的行为和计算方式:
tensor = torch.rand(3, 4) # 数据类型 - 决定张量存储的数值类型 print(tensor.dtype) # 如torch.float32、torch.int64等 # 常用类型:torch.float32, torch.float64, torch.int32, torch.int64 # 存储设备 - 决定张量存储在cpu还是gpu上 print(tensor.device) # 如'cpu'或'cuda:0' # 可以通过.to(device)方法在设备间移动张量 # 形状 - 描述张量的维度信息 print(tensor.shape) # 如torch.size([3, 4]) print(tensor.size()) # 同shape的另一种访问方式 print(tensor.ndim) # 张量的维度数,这里是2 # 梯度计算标志 - 决定张量是否需要计算梯度 print(tensor.requires_grad) # 默认为false # 当设置为true时,pytorch会跟踪对此张量的所有操作以计算梯度 # 其他属性 print(tensor.is_leaf) # 是否为叶节点(用户直接创建的张量) print(tensor.is_cuda) # 是否存储在gpu上 print(tensor.grad) # 存储的梯度值(如果有)
张量操作
算术运算
a = torch.tensor([1, 2, 3], dtype=torch.float32) b = torch.tensor([4, 5, 6], dtype=torch.float32) # 加法(逐元素相加) c = a + b # 直接运算符 c = torch.add(a, b) # 函数形式 c = a.add(b) # 方法形式 # 原地加法(不创建新张量) a.add_(b) # 等价于 a += b # 乘法(逐元素相乘) d = a * b # [1*4, 2*5, 3*6] = [4, 10, 18] d = torch.mul(a, b) d = a.mul(b) # 除法(逐元素相除) e = a / b # [1/4, 2/5, 3/6] e = torch.div(a, b) # 矩阵乘法 mat_a = torch.rand(3, 4) # 3x4矩阵 mat_b = torch.rand(4, 5) # 4x5矩阵 mat_prod = torch.matmul(mat_a, mat_b) # 3x5结果矩阵 mat_prod = mat_a @ mat_b # python 3.5+支持的运算符 # 广播机制示例 a = torch.rand(5, 1, 4) b = torch.rand( 1, 3) c = a + b # 广播后形状为(5,3,4)
索引和切片
pytorch 张量的索引与 numpy 类似,支持丰富的索引操作:
tensor = torch.arange(12).reshape(3, 4)
"""
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
"""
# 基本索引
print(tensor[0]) # 第一行: tensor([0, 1, 2, 3])
print(tensor[-1]) # 最后一行: tensor([ 8, 9, 10, 11])
print(tensor[:, 1]) # 第二列: tensor([1, 5, 9])
print(tensor[1:3, 2]) # 第二三行的第三列元素: tensor([6, 10])
# 高级索引
print(tensor[[0, 2], [1, 3]]) # 第0行第1列和第2行第3列: tensor([1, 11])
print(tensor[tensor > 5]) # 所有大于5的元素: tensor([6, 7, 8, 9, 10, 11])
# 修改子张量
tensor[1:, 2:] = 0 # 将第二行开始的右下2x2子矩阵置零
形状操作
# 改变形状(不改变数据) tensor = torch.rand(4, 6) reshaped = tensor.reshape(3, 8) # 总元素数必须保持不变 viewed = tensor.view(2, 12) # 与reshape类似,但对内存连续性有要求 # 转置 transposed = tensor.t() # 仅适用于2d张量 permuted = tensor.permute(1, 0) # 通用转置方法 # 增加/减少维度 tensor = torch.rand(3, 4) unsqueezed = tensor.unsqueeze(0) # 在0维增加1维,变为1x3x4 squeezed = unsqueezed.squeeze() # 去除所有长度为1的维度 # 连接张量 a = torch.rand(2, 3) b = torch.rand(2, 3) cat_0 = torch.cat([a, b], dim=0) # 沿0维连接,结果为4x3 cat_1 = torch.cat([a, b], dim=1) # 沿1维连接,结果为2x6 # 分割张量 chunks = torch.chunk(tensor, 3, dim=0) # 沿0维分成3块 splits = torch.split(tensor, 2, dim=1) # 沿1维每2列分一块
张量与 numpy 互转
pytorch 张量和 numpy 数组可以高效互转,因为它们共享底层内存(当张量在cpu上时):
import numpy as np # 张量转 numpy tensor = torch.ones(5) numpy_array = tensor.numpy() # 共享内存,修改一个会影响另一个 # 注意:gpu上的张量需要先移动到cpu gpu_tensor = torch.rand(5, device='cuda') cpu_tensor = gpu_tensor.cpu() numpy_array = cpu_tensor.numpy() # numpy 转张量 np_array = np.array([1, 2, 3]) torch_tensor = torch.from_numpy(np_array) # 同样共享内存 # 不共享内存的创建方式 torch_tensor_copy = torch.tensor(np_array) # 创建新副本
gpu 加速
pytorch 张量的 gpu 加速功能可以显著提升深度学习模型的训练速度:
# 检查gpu是否可用
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(f"using device: {device}")
# 创建张量并移动到gpu
tensor = torch.rand(10, 10).to(device)
# 直接在目标设备上创建张量
gpu_tensor = torch.rand(5, 5, device='cuda')
# 在gpu上执行运算
result = tensor * 2 # 如果tensor在gpu上,result也会在gpu上
# 将结果移回cpu
cpu_result = result.cpu()
# 多gpu示例(需要多gpu环境)
if torch.cuda.device_count() > 1:
tensor = tensor.to('cuda:1') # 显式指定第二个gpu
自动微分
pytorch 的自动微分功能(autograd)是其核心特性之一,使得神经网络训练变得简单:
# 创建需要计算梯度的张量
x = torch.tensor(2.0, requires_grad=true)
w = torch.tensor(1.0, requires_grad=true)
b = torch.tensor(0.5, requires_grad=true)
# 构建计算图
y = w * x + b # 线性函数
z = y**2 # 非线性变换
# 反向传播计算梯度
z.backward() # 计算dz/dx, dz/dw, dz/db
# 查看梯度
print(x.grad) # dz/dx = 2*(w*x+b)*w = 2*(1*2+0.5)*1 = 5.0
print(w.grad) # dz/dw = 2*(w*x+b)*x = 2*(1*2+0.5)*2 = 10.0
print(b.grad) # dz/db = 2*(w*x+b)*1 = 2*(1*2+0.5)*1 = 5.0
# 梯度清零(重要!在训练循环中需要)
x.grad.zero_()
w.grad.zero_()
b.grad.zero_()
# 禁用梯度跟踪(用于推理阶段)
with torch.no_grad():
y = w * x + b # 不会在计算图中记录
高级特性
内存共享
# 视图操作共享内存 a = torch.rand(4, 5) b = a.view(20) # b与a共享内存 c = a[1:3, 2:4] # c与a共享内存 # clone()创建独立副本 d = a.clone() # d与a不共享内存
稀疏张量
# 创建稀疏张量 indices = torch.tensor([[0, 1, 2], [2, 0, 1]]) # 非零元素的坐标 values = torch.tensor([3, 4, 5], dtype=torch.float32) # 非零元素的值 shape = torch.size([3, 3]) # 稀疏张量的形状 sparse_tensor = torch.sparse_coo_tensor(indices, values, shape) print(sparse_tensor.to_dense()) # 转换为稠密张量
分布式张量
# 分布式训练中的张量分片
import torch.distributed as dist
if dist.is_initialized():
# 将张量分片到不同进程
tensor = torch.rand(10, 10)
shard = tensor.chunk(dist.get_world_size(), dim=0)[dist.get_rank()]

pytorch 张量(tensor)是深度学习模型构建的核心数据结构,它本质上是一个多维数组,类似于 numpy 的 ndarray,但具有 gpu 加速计算和自动微分等额外功能。理解张量的特性和操作对于高效使用 pytorch 至关重要。
张量的基本特性
- 数据类型(dtype):pytorch 张量支持多种数据类型,如 torch.float32、torch.int64 等
- 形状(shape):表示张量的维度结构,例如 (3, 224, 224) 表示一个 3 通道的 224x224 图像
- 设备(device):可以存储在 cpu 或 gpu 上,通过
.to('cuda')方法可以轻松切换
张量的创建方法
pytorch 提供了多种创建张量的方式:
- 从 python 列表创建:
torch.tensor([[1, 2], [3, 4]]) - 特殊张量创建:
- 零张量:
torch.zeros(2, 3) - 单位矩阵:
torch.eye(3) - 随机张量:
torch.randn(2, 2)
- 零张量:
- 从 numpy 数组转换:
torch.from_numpy(np_array)
张量的操作
pytorch 支持丰富的张量操作:
- 数学运算:加减乘除、矩阵乘法(
@或torch.matmul()) - 形状操作:
- 改变形状:
view()或reshape() - 转置:
t()或transpose()
- 改变形状:
- 索引和切片:与 numpy 类似的索引方式
- 归约操作:
sum(),mean(),max()等
设备管理
pytorch 允许张量在 cpu 和 gpu 之间轻松切换:
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
x = x.to(device) # 将张量移动到指定设备
自动微分
pytorch 的核心特性之一是自动微分(autograd):
x = torch.tensor(2.0, requires_grad=true) y = x**2 y.backward() # 自动计算梯度 print(x.grad) # 输出梯度值 4.0
实际应用场景
- 图像处理领域
- 格式转换:将bgr/rgb格式的原始图像(h, w, c)转换为pytorch标准格式(c, h, w)张量
- 示例:处理224x224的rgb图像时,转换后得到(3, 224, 224)形状的张量
- 预处理流水线:可结合torchvision.transforms模块实现
- 标准化操作:使用normalize将像素值从[0,255]转换到[0,1]范围
- 数据增强:随机裁剪、水平翻转等操作都通过张量运算实现
- 自然语言处理领域
- 文本向量化:通过词嵌入层将单词转换为固定维度的词向量
- 典型流程:文本分词→构建词汇表→创建词向量矩阵
- 示例:使用300维glove词向量时,每个单词表示为(300,)的张量
- 序列处理:使用pack_padded_sequence处理变长文本序列
- 有效处理批量中不同长度的文本序列
- 模型训练过程
- 批量处理:将数据组织为(n, c, h, w)或(n, l, d)形式的批量张量
- n为批量大小,l为序列长度,d为特征维度
- 自动微分:通过backward()自动计算梯度
- 示例:损失函数的梯度自动传播到各层参数
- gpu加速:使用.to('cuda')将张量转移到gpu
- 典型加速比:相比cpu可实现5-50倍的训练速度提升
- 优化技巧
- 内存优化:使用torch.no_grad()减少验证时的内存占用
- 计算优化:利用torch.jit对模型进行编译优化
- 并行计算:通过dataparallel实现多gpu训练
通过这些张量操作和优化技术,开发者可以:
- 构建端到端的深度学习流水线
- 实现高效的模型训练和推理
- 充分利用现代gpu的计算能力
- 快速迭代模型结构和超参数
- 部署高性能的深度学习应用
到此这篇关于pytorch 张量的基本操作的文章就介绍到这了,更多相关pytorch 张量内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论