拓冰建站拓冰建站
首页 / 资讯中心 / 正文

PyTorch 深度学习笔记(五)张量拼接与自动微分——构建神经网络基础

系列导读本系列共 6 篇从 PyTorch 框架入门到实战案例带你系统掌握深度学习开发。上一篇张量运算与变形——数值计算与索引进阶一、张量拼接操作1.1 cat / concat沿现有维度拼接torch.cat沿现有维度连接一系列张量不改变维度数。importtorch# 初始化数据data1torch.randint(0,6,(2,3))data2torch.randint(0,6,(2,3))print(data1.shape)# torch.Size([2, 3])print(data2.shape)# torch.Size([2, 3])# 按 dim0 拼接行方向垂直堆叠datatorch.cat([data1,data2],dim0)print(data.shape)# torch.Size([4, 3])# 按 dim1 拼接列方向水平拼接datatorch.cat([data1,data2],dim1)print(data.shape)# torch.Size([2, 6])# 按 dim2 拼接需要三维张量data1torch.randint(0,6,(2,3,4))data2torch.randint(0,6,(2,3,4))datatorch.cat([data1,data2],dim2)print(data.shape)# torch.Size([2, 3, 8])关键规则拼接维度可以不一致但其他维度必须相同。1.2 stack在新维度上拼接torch.stack在新维度上连接张量增加一个新维度所有输入张量形状必须完全相同。data1torch.randint(0,10,[2,3])data2torch.randint(0,10,[2,3])# dim0新维度在最前面 → (2, 2, 3)new_datatorch.stack([data1,data2],dim0)print(new_data.shape)# torch.Size([2, 2, 3])# dim1新维度在中间 → (2, 2, 3)new_datatorch.stack([data1,data2],dim1)print(new_data.shape)# torch.Size([2, 2, 3])# dim2新维度在最后 → (2, 3, 2)new_datatorch.stack([data1,data2],dim2)print(new_data.shape)# torch.Size([2, 3, 2])经典应用单通道灰度图[H, W]三张 stack 模拟 RGB →[3, H, W]多张图片张量[C, H, W]stack 得到批次[B, C, H, W]1.3 chunk / split拆分张量化整为零各个击破大拆小小运行。datatorch.tensor([[1,2,3],[4,5,6],[7,8,9],[11,12,13]])# chunk均分成 chunks 份chunkstorch.chunk(data,chunks2,dim0)print(第1块:,chunks[0].shape)# torch.Size([2, 3])print(第2块:,chunks[1].shape)# torch.Size([2, 3])# split按指定大小拆分splitstorch.split(data,[1,1,2],dim0)print(splits[0].shape)# torch.Size([1, 3])print(splits[1].shape)# torch.Size([1, 3])print(splits[2].shape)# torch.Size([2, 3])1.4 stack 与 chunk 互逆操作# 生成 64 张 3 通道 32x32 的图片张量imgs[]foriinrange(64):imgtorch.randn(3,32,32)# 3 通道32 高32 宽imgs.append(img)# stack 拼接64 张 → (64, 3, 32, 32)imgs2torch.stack(imgs,dim0)print(imgs2.shape)# torch.Size([64, 3, 32, 32])# chunk 拆分(64, 3, 32, 32) → 64 张 (1, 3, 32, 32)imgs_restoretorch.chunk(imgs2,chunks64,dim0)print(len(imgs_restore))# 64print(imgs_restore[0].shape)# torch.Size([1, 3, 32, 32])# squeeze 降维(1, 3, 32, 32) → (3, 32, 32)imgs_newimgs_restore[0].squeeze(0)print(imgs_new.shape)# torch.Size([3, 32, 32])二、自动微分模块 autograd ⭐⭐⭐2.1 什么是自动微分自动微分 自动计算梯度 自动计算导数训练神经网络时PyTorch 会根据模型构建计算图Computational Graph跟踪哪些数据通过哪些操作组合产生输出通过反向传播算法根据损失函数的梯度调整参数模型权重torch.autograd引擎支持任意计算图的自动梯度计算2.2 计算图可视化importtorchfromtorchvizimportmake_dot# 简单模型xtorch.randn(1,requires_gradTrue)yx**2# 生成计算图图片make_dot(y,params{x:x}).render(yx²的计算图,formatpng)2.3 梯度基本概念概念解释梯度对函数求导的值梯度下降法求最优梯度使损失函数最小链式法则复合函数求导反向传播的核心反向传播从后向前求导传播梯度梯度经典语录在某一点上对函数求导得到的值就是该点的梯度在平面上梯度就是某一点上的斜率反向传播传播的是梯度链式法则中梯度相乘就是传说中的梯度传播三、梯度基本计算3.1 关键前提PyTorch 不支持向量张量对向量张量的求导只支持标量张量对向量张量的求导。x是张量 →y必须是标量一个值才能求导3.2 requires_grad梯度开关# 默认不开启自动求导xtorch.arange(9).view(3,3)print(x.requires_grad)# False# 开启自动求导xtorch.rand(3,3,requires_gradTrue)print(x.requires_grad)# True3.3 标量张量求导# 定义变量开启梯度追踪xtorch.tensor(10,requires_gradTrue,dtypetorch.float32)print(x --,x)# 定义曲线y x²yx**2print(y --,y)# 查看梯度函数类型print(y.grad_fn)# PowBackward0 object# 计算梯度y 是标量直接 backwardy.backward()# x.grad 就是导数值print(x 的梯度值是:,x.grad)# 2*10 20.0backward() 执行过程从输出y出发初始化上游梯度dy/dy 1进入PowBackward0算子套用导数公式dy/dx 2x梯度流入AccumulateGrad节点把算出的2x存入x.grad执行完毕后x.grad才有具体数值3.4 向量张量求导# 定义向量张量xtorch.tensor([10,20],requires_gradTrue,dtypetorch.float32)print(x --,x)# 定义曲线yx**2print(y --,y)# y 是向量先转成标量再求导y.sum().backward()# x.grad 保存每个元素的梯度print(x.grad --,x.grad)# tensor([20., 40.])四、梯度计算注意事项4.1 不能将求导张量转 NumPyxtorch.tensor([10,20],requires_gradTrue,dtypetorch.float64)# ❌ 报错不能直接转 NumPy# print(x.numpy())# RuntimeError: Cant call numpy() on Tensor that requires grad.# ✅ 先用 detach() 脱离计算图x2x.detach()print(x2.numpy())detach() 的作用产生一个新的张量与原始张量共享数据新张量不会自动微分requires_gradFalsex.data_ptr()和x2.data_ptr()相同共享内存id(x)和id(x2)不同不同 Python 对象4.2 梯度累加问题xtorch.tensor(2.0,requires_gradTrue)yx**2y.backward()print(x.grad)# 4.0# 再次 backward 会累加yx**2y.backward()print(x.grad)# 8.0累加了# 解决方法每次 backward 前清零x.grad.zero_()五、拼接与微分总结操作方法说明关键参数cattorch.cat(tensors, dim)沿现有维度拼接dim 指定拼接轴stacktorch.stack(tensors, dim)在新维度拼接增加一个新维度chunktorch.chunk(tensor, chunks, dim)均分张量chunks 份数splittorch.split(tensor, sizes, dim)按大小拆分sizes 每份大小requires_gradrequires_gradTrue开启梯度追踪默认 Falsebackward.backward()计算梯度标量输出直接调用detach.detach()脱离计算图共享数据无梯度grad.grad访问梯度值backward 后才有值zero_grad.grad.zero_()梯度清零避免累加六、下一篇预告PyTorch 深度学习笔记六PyTorch 实战——线性回归预测房价完整案例将使用 PyTorch 的各个组件构建一个带噪声数据的线性回归模型模拟房屋面积-房价预测任务。包括数据准备、模型构建、损失函数、优化器、训练循环和可视化全流程。如果这篇文章对你有帮助欢迎点赞、收藏、关注你的支持是我持续创作的动力。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门