PyTorch Tensor 完全指南:从基础概念到高级操作实战
PyTorch Tensor 完全指南从基础概念到高级操作实战PyTorch Tensor 完全指南从基础概念到高级操作实战摘要本文系统讲解 PyTorch 中 Tensor张量的核心概念、创建方式、数学运算、形状操作、索引切片、自动求导等知识配合大量代码示例帮助读者全面掌握 PyTorch Tensor 的使用。适用读者深度学习入门者、PyTorch 初学者 | 难度入门~中级 | 预计阅读时间30 分钟文章目录PyTorch Tensor 完全指南从基础概念到高级操作实战一、前言二、Tensor 的创建2.1 直接从 Python 数据创建2.2 创建指定形状的 Tensor2.3 随机数创建2.4 序列创建2.5 指定设备CPU/GPU2.6 稀疏张量三、Tensor 的基本数学运算3.1 算术运算3.2 三角函数与数学函数3.3 统计函数3.4 比较运算四、Tensor 的形状操作4.1 查看形状4.2 reshape / view4.3 转置与维度变换4.4 增删维度4.5 拼接与切分五、Tensor 的索引与切片5.1 clamp值裁剪六、Tensor 与 NumPy 的互转七、Tensor 的设备管理八、自动求导Autograd8.1 基本用法8.2 阻止梯度追踪8.3 自定义 autograd Function8.4 梯度累积与清零九、随机种子十、总结参考资料一、前言Tensor张量是 PyTorch 中最核心的数据结构可以理解为一个多维数组。它与 NumPy 的 ndarray 非常相似但额外支持 GPU 加速和自动求导autograd这使得它成为深度学习框架的基石。简单来说标量Scalar是 0 维张量向量Vector是 1 维张量矩阵Matrix是 2 维张量更高维度的数据统称为 N 维张量本文将从 Tensor 的创建、基本运算、形状操作、索引切片、自动求导等方面系统地讲解 PyTorch Tensor 的使用方法。二、Tensor 的创建2.1 直接从 Python 数据创建importtorch# 从列表创建atorch.tensor([[1,2],[3,4]])print(a)# tensor([[1, 2],# [3, 4]])# 注意torch.tensor()小写 t是推荐的新版写法# torch.Tensor()大写 T也可以用但行为略有不同提示推荐使用torch.tensor()小写它是新版 API能自动推断数据类型。torch.Tensor()大写始终创建FloatTensor。2.2 创建指定形状的 Tensorimporttorch# 全零张量zerostorch.zeros(2,3)print(zeros)# tensor([[0., 0., 0.],# [0., 0., 0.]])# 全一张量onestorch.ones(4,5)print(ones)# 单位矩阵eyetorch.eye(3,3)print(eye)# 形状类似的张量zeros_like / ones_likebtorch.Tensor(2,3)ftorch.zeros_like(b)# 与 b 形状相同的全零张量gtorch.ones_like(b)# 与 b 形状相同的全一张量2.3 随机数创建importtorch# 均匀分布 [0, 1)randtorch.rand(2,3)print(rand)# 正态分布均值 0标准差 1randntorch.randn(2,3)print(randn)# 指定均值和标准差的正态分布normaltorch.normal(mean0.0,stdtorch.rand(5))print(normal)# 均值和标准差都是张量normal2torch.normal(meantorch.rand(5),stdtorch.rand(5))print(normal2)# 均匀分布指定范围uniformtorch.Tensor(2,2).uniform_(-1,1)print(uniform)2.4 序列创建importtorch# 等差数列从 0 到 10步长 1arangetorch.arange(0,10,1)print(arange)# tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])# 等间距数列从 2 到 10包含 4 个数linspacetorch.linspace(2,10,4)print(linspace)# tensor([ 2.0000, 4.6667, 7.3333, 10.0000])# 随机排列randpermtorch.randperm(10)print(randperm)注意通过arange和randperm创建的是LongTensor类型其他方法默认创建FloatTensor类型。2.5 指定设备CPU/GPUimporttorch# 创建在 GPU 上的张量devtorch.device(cuda:0)atorch.tensor([2,2],dtypetorch.float32,devicedev)print(a)print(a.type())# torch.cuda.FloatTensor2.6 稀疏张量当数据中大部分元素为零时使用稀疏张量可以节省内存importtorch# 定义非零元素的位置itorch.tensor([[0,1,2],[0,1,2]])# 行索引和列索引vtorch.tensor([1,2,3])# 非零元素的值# 创建稀疏张量并转为稠密张量sparsetorch.sparse_coo_tensor(i,v,(4,4),dtypetorch.float32)densesparse.to_dense()print(dense)# tensor([[1., 0., 0., 0.],# [0., 2., 0., 0.],# [0., 0., 3., 0.],# [0., 0., 0., 0.]])三、Tensor 的基本数学运算3.1 算术运算importtorch atorch.tensor([[1,2],[3,4]],dtypetorch.float32)btorch.tensor([[5,6],[7,8]],dtypetorch.float32)# 加法print(ab)print(torch.add(a,b))# 减法print(a-b)# 乘法逐元素print(a*b)print(torch.mul(a,b))# 除法逐元素print(a/b)# 矩阵乘法print(torch.mm(a,b))# 2D 矩阵乘法print(torch.matmul(a,b))# 通用矩阵乘法支持广播print(a b)# 等价写法# 幂运算print(torch.pow(a,2))# 逐元素开方print(torch.sqrt(a))3.2 三角函数与数学函数importtorch atorch.tensor([0.0,0.5,1.0])# 三角函数print(torch.sin(a))print(torch.cos(a))print(torch.tan(a))# 取整 / 取余btorch.tensor([1.2,2.7,-0.3])print(torch.floor(b))# 向下取整print(torch.ceil(b))# 向上取整print(torch.round(b))# 四舍五入print(torch.abs(b))# 绝对值3.3 统计函数importtorch atorch.tensor([[1.0,2.0,3.0],[4.0,5.0,6.0]])# 求和print(torch.sum(a))# 所有元素求和print(torch.sum(a,dim0))# 按列求和print(torch.sum(a,dim1))# 按行求和# 最大值 / 最小值print(torch.max(a))# 全局最大值print(torch.max(a,dim0))# 每列最大值返回 (values, indices)print(torch.min(a))# 均值 / 标准差print(torch.mean(a))print(torch.std(a))# argmax / argminprint(torch.argmax(a,dim1))# 每行最大值的索引提示统计函数可以通过dim参数指定在哪个维度上操作。bincount函数只能处理一维张量。3.4 比较运算importtorch atorch.tensor([1.0,2.0,3.0])btorch.tensor([1.0,3.0,2.0])print(torch.eq(a,b))# 逐元素相等判断print(torch.gt(a,b))# 大于print(torch.lt(a,b))# 小于print(torch.ge(a,b))# 大于等于四、Tensor 的形状操作4.1 查看形状importtorch atorch.rand(2,3,4)print(a.shape)# torch.Size([2, 3, 4])print(a.size())# torch.Size([2, 3, 4])print(a.dim())# 3维度数print(a.numel())# 24元素总数4.2 reshape / viewimporttorch atorch.rand(2,6)# reshape返回新的张量ba.reshape(3,4)print(b.shape)# torch.Size([3, 4])# view返回视图共享内存要求张量在内存中连续ca.view(3,4)print(c.shape)# 自动推断维度使用 -1da.view(4,-1)# 自动计算第二个维度print(d.shape)# torch.Size([4, 3])4.3 转置与维度变换importtorch atorch.rand(2,3)# 转置2Dprint(a.t())# 交换维度btorch.rand(2,3,4)print(b.permute(2,0,1).shape)# torch.Size([4, 2, 3])# 交换两个维度print(b.transpose(0,1).shape)# torch.Size([3, 2, 4])4.4 增删维度importtorch atorch.rand(3,4)# 增加维度ba.unsqueeze(0)# 在第 0 维增加print(b.shape)# torch.Size([1, 3, 4])ca.unsqueeze(1)# 在第 1 维增加print(c.shape)# torch.Size([3, 1, 4])# 删除维度维度大小必须为 1db.squeeze(0)print(d.shape)# torch.Size([3, 4])4.5 拼接与切分importtorch atorch.rand(2,3)btorch.rand(2,3)# 拼接cat_0torch.cat([a,b],dim0)# 按行拼接print(cat_0.shape)# torch.Size([4, 3])cat_1torch.cat([a,b],dim1)# 按列拼接print(cat_1.shape)# torch.Size([2, 6])# stack增加新维度后拼接stackedtorch.stack([a,b],dim0)print(stacked.shape)# torch.Size([2, 2, 3])# 切分chunkstorch.chunk(cat_0,2,dim0)print(chunks[0].shape)# torch.Size([2, 3])# split可以指定每个块的大小splitstorch.split(cat_0,[1,3],dim0)print(splits[0].shape)# torch.Size([1, 3])print(splits[1].shape)# torch.Size([3, 3])提示split传入列表时列表中数字之和应等于该维度上的总大小。五、Tensor 的索引与切片Tensor 的索引方式与 NumPy 基本一致importtorch atorch.tensor([[1,2,3],[4,5,6],[7,8,9]],dtypetorch.float32)# 基本索引print(a[0,1])# tensor(2.) 第 0 行第 1 列print(a[0:2,1:3])# 切片# 条件索引maska5print(a[mask])# tensor([6., 7., 8., 9.])# gather按索引取值indextorch.tensor([[0,1],[1,2]])print(torch.gather(a,1,index))# 按行方向取值# index_select按维度选取indicestorch.tensor([0,2])print(torch.index_select(a,0,indices))# 选取第 0、2 行print(torch.index_select(a,1,indices))# 选取第 0、2 列5.1 clamp值裁剪将张量中的值限制在指定范围内importtorch atorch.tensor([0.5,1.5,-0.3,2.0])# 将值限制在 [0, 1] 之间clampedtorch.clamp(a,0,1)print(clamped)# tensor([0.5000, 1.0000, 0.0000, 1.0000])六、Tensor 与 NumPy 的互转importtorchimportnumpyasnp# Tensor → NumPyatorch.tensor([1,2,3])ba.numpy()print(type(b))# class numpy.ndarray# NumPy → Tensorcnp.array([4,5,6])dtorch.from_numpy(c)print(type(d))# class torch.Tensor注意torch.from_numpy()创建的 Tensor 与 NumPy 数组共享内存修改一个会影响另一个。七、Tensor 的设备管理在深度学习中数据处理通常在 CPU 上进行模型训练在 GPU 上进行。Tensor 需要在正确的设备上才能参与运算。importtorch# 检查 GPU 是否可用devicetorch.device(cudaiftorch.cuda.is_available()elsecpu)# 将 Tensor 移动到 GPUatorch.rand(3,3)aa.to(device)# 从 GPU 移回 CPUaa.cpu()# 或者使用 .to() 方法aa.to(cpu)八、自动求导AutogradPyTorch 的自动求导机制是其核心特性之一通过构建计算图来自动计算梯度。8.1 基本用法importtorch# 创建需要求导的张量xtorch.tensor([2.0,3.0],requires_gradTrue)yx**22*x1# 反向传播y.sum().backward()# 查看梯度print(x.grad)# dy/dx 2x 2 → tensor([6., 8.])8.2 阻止梯度追踪importtorch xtorch.tensor([1.0,2.0],requires_gradTrue)# 方法 1with torch.no_grad()withtorch.no_grad():yx*2print(y.requires_grad)# False# 方法 2detach()zx.detach()print(z.requires_grad)# False8.3 自定义 autograd FunctionPyTorch 允许自定义前向和反向传播逻辑importtorchclassLinearFunction(torch.autograd.Function):staticmethoddefforward(ctx,w,x,b):# 保存用于反向传播的张量ctx.save_for_backward(w,x,b)returnw*xbstaticmethoddefbackward(ctx,grad_out):w,x,bctx.saved_tensors grad_wgrad_out*x grad_xgrad_out*w grad_bgrad_out*breturngrad_x,grad_w,grad_b# 使用自定义函数wtorch.rand(2,2,requires_gradTrue)xtorch.rand(2,2,requires_gradTrue)btorch.rand(2,2,requires_gradTrue)outLinearFunction.apply(w,x,b)out.backward(torch.ones(2,2))print(w.grad)print(x.grad)print(b.grad)8.4 梯度累积与清零importtorch xtorch.tensor([1.0],requires_gradTrue)# 第一次计算yx**2y.backward()print(x.grad)# tensor([2.])# 梯度会累积yx**2y.backward()print(x.grad)# tensor([4.]) —— 累积了# 需要手动清零x.grad.zero_()yx**2y.backward()print(x.grad)# tensor([2.])重要提示在训练循环中每次迭代前必须调用optimizer.zero_grad()清零梯度否则梯度会不断累积导致错误。九、随机种子通过设置随机种子可以保证实验的可复现性importtorch# 设置随机种子torch.manual_seed(42)# 之后的随机操作会得到相同的结果atorch.rand(3)btorch.rand(3)print(a)print(b)# 再次设置相同种子torch.manual_seed(42)ctorch.rand(3)print(c)# 与 a 完全相同十、总结本文要点回顾Tensor 创建掌握torch.tensor()、torch.zeros()、torch.rand()、torch.arange()等常用创建方法数学运算算术运算、统计函数、比较运算等与 NumPy 用法类似形状操作reshape/view、cat/stack、chunk/split、unsqueeze/squeeze索引切片基本索引、条件索引、gather、index_select、clamp设备管理使用.to(device)在 CPU 和 GPU 之间移动数据自动求导requires_gradTrue、backward()、自定义Function随机种子torch.manual_seed()保证实验可复现Tensor 是 PyTorch 的基石熟练掌握这些操作是进行深度学习开发的前提。在后续的神经网络实战中这些操作会被频繁使用。参考资料PyTorch 官方文档 - TensorsPyTorch 官方教程 - What is PyTorch?PyTorch 广播机制详解