ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

PyTorch零基础入门:从张量到可运行模型的实操指南

PyTorch零基础入门:从张量到可运行模型的实操指南

简介:这是一本面向深度学习初学者的PyTorch系统性入门指南,聚焦从零构建神经网络能力,特别适合高校学生、转行开发者及自学者夯实基础。全书以PyTorch为核心框架,覆盖Numpy基础、Tensor操作与Autograd自动求导机制、nn模块建模、数据加载与可视化(含tensorboardX)、CNN/RNN/VAE/GAN等主流模型原理与实现,并延伸至人脸检测、迁移学习等实战场景,每章均配有代码示例与关键函数详解。资源为单文件PDF,共1个21.68MB高清电子书,内容完整对应机械工业出版社2019年出版的《Python深度学习:基于PyTorch》(ISBN 978-7-111-63717-2),结构清晰、循序渐进,兼顾理论推导与工程实践。目前已有5668人学习下载,是初学者理解PyTorch底层逻辑、掌握深度学习全流程开发的高性价比入门读物。

1. 这本《Python深度学习:基于PyTorch》到底是什么?——给零基础新手的一把“入门钥匙”

你是不是也这样:刷到“AI”“深度学习”“PyTorch”这些词,心里一热,点进去却满屏是“张量”“反向传播”“计算图”“梯度爆炸”……像看天书?
或者,你刚装好Python,试了两行print("Hello"),正想往前走一步,却发现网上教程要么跳着讲(“先装CUDA再配cuDNN最后改环境变量”),要么堆概念(“动态图 vs 静态图”“Autograd机制”),连“第一个能跑出来的代码”都找不到在哪一页?

别慌——这本《Python深度学习:基于PyTorch》就是专为这样的你写的。
它不是一本“写给博士看的理论手册”,也不是“只教你怎么调包”的速成课;它是一本从你电脑里那个空白的Python终端开始,手把手带你搭出第一个能识别图片、能预测走势、能生成文字的模型的实操指南。
书里所有代码,都默认用最基础的CPU环境就能跑通(不用GPU也能学);所有概念,比如“Tensor”“广播”“自动求导”,都先用你熟悉的Python列表、Excel表格、甚至买菜记账本打比方,再落到代码上;每一步操作背后,都写着“为什么这么写”“不这么写会怎样”“报错时第一眼该看哪一行”。
它适合谁?——
✅ 完全没碰过深度学习,但会写几行Python(哪怕只会for i in range(3): print(i));
✅ 学过一点机器学习,但看到“卷积”就卡住,不知道它和“滤镜”有什么关系;
✅ 想转行做AI相关工作,但被网上五花八门的框架(TensorFlow、Keras、JAX……)绕晕,不知从哪下手。
这本书的答案很实在:先选PyTorch,因为它像Python一样自然,像Numpy一样熟悉,调试起来像修自家电饭锅——哪儿冒烟,你就拧开哪儿看。
接下来,我们就从“第一个能动起来的例子”出发,不讲大道理,只做一件事:让你在30分钟内,亲手跑通一段真正属于自己的深度学习代码。


2. 为什么新手一定要从PyTorch起步:不是因为它“最火”,而是因为它“最不像黑匣子”

很多新手第一次接触深度学习,常被两件事劝退:
一是“安装失败”——配环境像解九连环,CUDA版本、cuDNN版本、PyTorch版本三者稍有不匹配,终端就报红字;
二是“运行成功但不懂发生了什么”——复制粘贴完代码,模型真跑起来了,可问一句“这一行loss.backward()到底干了啥?”,立刻哑火。
这本书选PyTorch,正是因为它在这两点上,对新手最友好。我们不讲虚的,直接拆开看:

2.1 PyTorch的“动态图”不是术语,是你每天都在用的Python逻辑

你写过if x > 0: y = x * 2 else: y = x + 1吗?这就是动态图。
PyTorch的神经网络,不是先画好一张固定图纸(静态图),再按图施工;而是你写一行,它实时建一个节点;你加个判断,它立刻分叉;你删掉一层,整个计算路径当场重连。
这意味着什么?
→ 调试时,你可以像调试普通Python函数一样,在任意位置加print(x.shape)、设断点、检查中间变量值;
→ 学习时,你不会被“图怎么构建”“会话怎么启动”这些框架层细节卡住,注意力能100%放在“数据怎么流”“梯度怎么传”这些核心思路上;
→ 实战时,遇到需要动态改变结构的任务(比如RNN处理不同长度句子、GAN里生成器和判别器交替训练),你不用查文档翻半天,代码自然就长成那样。

2.2 它和Numpy长得太像,像到你会怀疑自己没学新东西

翻开书的第1章,全是Numpy:

import numpy as np a = np.array([[1, 2], [3, 4]]) b = np.array([10, 20]) c = a + b # 广播:[1,2]+10=[11,12];[3,4]+20=[23,24]

再翻到第2章,PyTorch登场:

import torch a = torch.tensor([[1, 2], [3, 4]]) b = torch.tensor([10, 20]) c = a + b # 一模一样的写法!结果也一样!

区别在哪?
→np.array→torch.tensor(就换了个名字);
→np.sum()→torch.sum()(函数名几乎不变);
→a.reshape(2, -1)→a.view(2, -1)(就一个字母差别)。
这种“无缝迁移感”,让新手省下大量时间去记“新语法”,转而专注理解“为什么需要reshape”“为什么这里要view”。
书里专门用一整章(第1章)讲Numpy,不是凑页数——它是PyTorch的“母语”。你掌握它,等于提前掌握了PyTorch 70%的直觉。

2.3 它不隐藏关键步骤,反而逼你亲手写出来

对比一下:

  • Keras里,你写model.compile(optimizer='adam', loss='sparse_categorical_crossentropy'),然后model.fit()——优化器、损失、反向传播,全被封装进一个黑盒;
  • PyTorch里,你必须亲手写:
optimizer = torch.optim.Adam(model.parameters(), lr=0.001) criterion = torch.nn.CrossEntropyLoss() for epoch in range(10): for data, target in train_loader: optimizer.zero_grad() # ① 清空上一轮梯度(新手常忘!) output = model(data) # ② 前向传播,得到预测 loss = criterion(output, target) # ③ 计算损失 loss.backward() # ④ 反向传播,算出每个参数要怎么调 optimizer.step() # ⑤ 用梯度更新参数

看起来步骤多?但好处是:
→ 每一步你都看得见、改得了、打断点查得着;
→ 出错了,你知道是zero_grad()漏了,还是backward()前忘了requires_grad=True;
→ 后续学迁移学习、对抗攻击、强化学习,这些底层逻辑全都能复用,不用推倒重学。
这本书第2章“PyTorch基础”里,就带着你从torch.tensor创建开始,一步步走到上面这个完整训练循环——不是给你成品,而是陪你把轮子一块块装上去。

提示:如果你现在打开终端,输入pip install torch torchvision(CPU版),5分钟内就能装完。不需要显卡驱动、不需要CUDA——这是本书默认的入门起点。等你跑通第一个例子,再考虑GPU加速,节奏才不乱。


3. 第一步:从“打印张量形状”开始,亲手跑通你的第一个PyTorch代码

别急着建模型、别急着下数据集。新手最容易翻车的地方,往往不在算法,而在“连张量长什么样都没见过”。
这本书的聪明之处,就是把“第一个可执行代码”设计成:只做一件事——创建一个张量,打印它的形状、类型、数值,并验证它和Numpy数组能互相转换。
这就像学开车,先不挂挡不踩油门,而是坐进驾驶座,摸清方向盘在哪、档把怎么动、仪表盘怎么看。我们来照着书第2章2.4节动手:

3.1 创建你的第一个Tensor:三行代码,看清“张量”本质

打开你最喜欢的编辑器(推荐VS Code或Jupyter Notebook),新建一个.py文件或Notebook单元,输入:

import torch import numpy as np # ① 从Python列表创建Tensor x = torch.tensor([1, 2, 3, 4]) print("x =", x) print("x.shape =", x.shape) print("x.dtype =", x.dtype) print("x.device =", x.device)

运行后,你会看到:

x = tensor([1, 2, 3, 4]) x.shape = torch.Size([4]) x.dtype = torch.int64 x.device = cpu

白话解释这四行输出:

  • tensor([1, 2, 3, 4]):这就是PyTorch里的“张量”,你可以把它想象成一个升级版的Python列表——它自带数学运算能力,且能自动记录“怎么算出来的”,为后续求导铺路;
  • torch.Size([4]):说明这是1维张量,含4个元素(对比Numpy:np.array([1,2,3,4]).shape输出(4,),几乎一样);
  • torch.int64:表示里面存的是64位整数(类似Python的int,但更省内存、更快);
  • cpu:说明它当前在CPU上运行(如果你有NVIDIA显卡且装了CUDA,后面可改成.cuda(),但现在完全不用管)。

3.2 和Numpy互转:验证“它们真是亲兄弟”

接着在刚才的代码下面,加上这三行:

# ② Tensor → Numpy数组 x_np = x.numpy() print("x_np =", x_np) print("type(x_np) =", type(x_np)) # ③ Numpy数组 → Tensor y = torch.from_numpy(x_np) print("y =", y) print("y.dtype =", y.dtype) # 注意:dtype继承自Numpy,是int64

运行结果:

x_np = [1 2 3 4] type(x_np) = <class 'numpy.ndarray'> y = tensor([1, 2, 3, 4]) y.dtype = torch.int64

关键点说明:

  • x.numpy():把Tensor变成Numpy数组,要求Tensor必须在CPU上且不可求导(即requires_grad=False,默认就是);
  • torch.from_numpy():把Numpy数组变成Tensor,二者共享内存——改x_np[0] = 99,y[0]也会变成99(这点和torch.tensor()不同,后者是深拷贝);
  • 为什么强调这个?因为后续读图像、加载CSV数据,你拿到的几乎都是Numpy数组,必须熟练转换。

3.3 动手改一改:验证你的理解是否到位

现在,请你暂停10秒,合上屏幕,自己默写一遍:

  1. 怎么创建一个2×3的全0张量?
  2. 怎么把它变成Numpy数组?
  3. 怎么再变回来,并确保它dtype是float32?

写完再对照答案(别偷看!):

# 答案: z = torch.zeros(2, 3) # ① 2行3列全0 z_np = z.numpy() # ② 变Numpy z_back = torch.from_numpy(z_np).float() # ③ 变回Tensor,并转为float32 print(z_back.dtype) # 输出 torch.float32

注意:torch.zeros(2,3)默认是float32,但torch.from_numpy()会继承原数组dtype(z_np是float64),所以必须加.float()强制转换。这是新手第一天就可能踩的坑——类型不一致会导致后续计算报错,比如CrossEntropyLoss只接受float32。

3.4 为什么这三步比“直接跑MNIST”更重要?

因为:

  • 它帮你建立了最底层的直觉:张量不是魔法,它就是带属性的数组;
  • 它暴露了真实开发中的高频操作:数据加载→转Tensor→送入模型,每一步都涉及类型、设备、形状;
  • 它让你第一次亲手触发PyTorch的“自动求导”开关(下一节就用到)。
    这本书没有一上来就扔给你一个几百行的CNN,而是用整整一章(第2章)陪你把tensor、autograd、nn.Module这些基石一块块垒稳。你今天花15分钟搞懂torch.tensor,后面学卷积、学RNN时,节省的是3小时调试时间。

4. 新手必踩的5个坑:从“报错看不懂”到“一眼定位问题”

我第一次跟着这本书跑代码时,在第2章就卡了整整两天。不是算法难,而是几个看似微小的细节,让报错信息像天书。后来我把这些血泪经验整理成清单,现在原样交给你——避开它们,你能少走80%的弯路。

4.1 坑:RuntimeError: Input, output and weights must be on the same device

现象:模型在GPU上,数据在CPU上,或者反过来,一运行就报这个错。
原因:PyTorch严格区分设备。model.cuda()把模型搬到GPU,但data还是CPU张量,两者无法相乘。
解决:

  • 统一设备:device = torch.device("cuda" if torch.cuda.is_available() else "cpu");
  • 所有张量和模型都显式搬运:model.to(device),data.to(device),target.to(device);
  • 新手口诀:“模型、数据、标签,三者设备必须同”。书里第2章2.2.2节GPU安装后,第3章实例就强制用to(device),就是防这个。

4.2 坑:RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn

现象:调用loss.backward()时报错,说某个张量“不支持求导”。
原因:你用了torch.tensor([...])创建张量,但默认requires_grad=False;而求导链必须从一个requires_grad=True的张量开始(通常是模型参数)。
解决:

  • 模型参数自动requires_grad=True(不用管);
  • 手动创建的输入张量,如果要参与求导(比如GAN里的噪声z),必须加.requires_grad_(True);
  • 更安全的做法:用torch.randn(10, 5, requires_grad=True)直接创建。

血泪经验:我曾把z = torch.randn(10,100)喂给生成器,死活不更新,最后发现少写了requires_grad=True——因为生成器参数在更新,但z本身不动,整个生成过程就静止了。

4.3 坑:ValueError: Expected input batch_size (32) to match target batch_size (64)

现象:loss = criterion(output, target)报错,说batch size不匹配。
原因:output是模型输出(比如32张图,每张10类概率,shape=[32,10]),target是标签(应该是32个数字,shape=[32]),但你传了64个标签。
解决:

  • 检查DataLoader的batch_size是否和target长度一致;
  • 重点检查target的shape:分类任务中,target必须是1维张量([N]),不能是[N,1]或[N,10];
  • 用target.squeeze()或target.view(-1)修正。
    书里第4章torchvision.datasets.ImageFolder的示例,就明确写出target是LongTensor且shape为[batch_size],就是为防这个。

4.4 坑:TypeError: can't convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.

现象:GPU上训练完,想用plt.imshow()画图,结果报这个错。
原因:Numpy无法直接读取GPU内存,必须先搬回CPU。
解决:

  • 所有要转Numpy或画图的张量,加.cpu():img_tensor.cpu().numpy();
  • 如果张量带梯度,还要加.detach():img_tensor.cpu().detach().numpy()(.detach()切断求导链,避免内存泄漏)。

这个坑在第4章可视化工具(4.4节)里被反复强调,因为tensorboardX和matplotlib都依赖Numpy,是GPU用户每日必过关。

4.5 坑:UserWarning: Using a non-full backward hook when the forward contains multiple autograd Nodes

现象:没报错,但终端刷出黄色警告,说“backward hook不完整”。
原因:你在模型某层用了register_backward_hook(),但该层内部有多个计算节点(比如nn.Sequential里嵌了Conv2d+ReLU+BatchNorm),钩子只挂到了部分节点。
解决:

  • 新手请暂时忽略此警告——它不影响训练,只是提示“钩子没覆盖全”;
  • 真需要精确监控梯度?用torch.autograd.grad()手动求,或等学到第14章对抗攻击时再深入(那里必须精准控制梯度流)。
    书里直到第14章才讲钩子,前面所有实例都不用,就是避免新手被警告干扰信心。

提示:这些坑,90%都源于“张量的三个属性没对齐”——设备(device)、类型(dtype)、形状(shape)。每次报错,先打印x.device, x.dtype, x.shape,80%的问题当场解决。


5. 下一步学什么:从“跑通代码”到“真正理解模型”,我的三步通关路径

你现在能创建张量、能转Numpy、能写最简训练循环——恭喜,你已经跨过了那道最高的门槛。接下来不是狂啃公式,而是用一套“最小闭环学习法”,把书里的知识真正长进自己脑子里。这是我带过几十个零基础学员后,验证最有效的路径:

5.1 第一阶段:用“抄+改+问”吃透第3章——亲手搭一个能跑的神经网络

不要跳!从第3章“PyTorch神经网络工具箱”开始,逐行抄写书中3.2节“实现神经网络实例”的全部代码(约120行)。抄完后,做三件事:

  1. 改:把input_size=784(MNIST图)改成input_size=32*32(自己生成一个32×32随机图),看模型是否还能训;
  2. 问:针对每一行,问自己——
    • nn.Linear(784, 128)这128是哪来的?(答:隐藏层神经元数,可调)
    • F.relu(x)的x是上一层输出,那F是什么?(答:torch.nn.functional,是函数式接口,和nn.ReLU()类接口等价)
    • model.train()和model.eval()切换的是什么状态?(答:Dropout和BatchNorm的行为,训练时随机失活/用batch统计,测试时关闭失活/用全局统计)
  3. 画:用纸笔画出这个网络的结构图:输入→线性层→ReLU→线性层→Softmax→输出。标出每层输入/输出shape。

这个阶段的目标不是“学会所有层”,而是建立“模型=数据流水线”的直觉。书里第3章3.3节“如何构建神经网络”用流程图拆解了前向/反向传播,比纯文字好懂十倍——务必对照代码看图。

5.2 第二阶段:用“对比实验”吃透第6章——亲手验证为什么CNN比全连接强

第6章讲卷积神经网络,新手常觉得“卷积核像魔法”。别背公式,直接做对比实验:

  • 实验1:用第3章的全连接网络(FCN)训CIFAR-10,记录准确率(通常<50%);
  • 实验2:用第6章6.5节的CNN代码(LeNet变种)训同一数据集,记录准确率(通常>65%);
  • 实验3:把CNN里的nn.Conv2d换成nn.Linear(强行展平),再跑一次,看准确率暴跌——你就亲眼见证了“局部连接”和“参数共享”的威力。

书里6.2节“卷积层”用图示展示了“3×3卷积核在图上滑动”,比任何文字都直观。配合实验,你会突然明白:
→ “填充(padding)”是为了让边缘像素也被充分计算;
→ “步幅(stride)”是控制感受野大小的阀门;
→ “池化(pooling)”不是为了降维,而是为了抗形变(平移不变性)。
这些不是考点,而是你未来调参、改模型时的决策依据。

5.3 第三阶段:用“项目驱动”吃透第10章——用迁移学习搞定自己的小任务

学到第10章“迁移学习”,你就可以告别“玩具数据集”了。选一个你真正关心的小问题:

  • 想识别家里猫狗照片?用torchvision.models.resnet18+ 自己的20张图微调;
  • 想分类手机拍的植物?用models.efficientnet_b0+ 数据增强(第10章10.3节);
  • 想给老照片去雾?直接跑第10章10.5节“清除图像中的雾霾”实例。

关键动作:

  • 不要追求SOTA(最高精度),目标是“用自己的数据跑通”;
  • 每次只改一个参数:先调learning_rate,再试batch_size,最后换pretrained=True/False;
  • 把训练曲线(loss/acc)画出来(第4章4.4节tensorboardX),观察过拟合迹象(训练loss降、验证loss升),再回头看第5章5.3节“过拟合与欠拟合”的解决方案。

从那以后我每次教新人,都强制他们做完这三步:
① 抄第3章代码并画结构图(建立骨架);
② 对比FCN和CNN在CIFAR上的表现(理解为什么);
③ 用迁移学习跑通一个自己的小任务(获得正反馈)。
三步走完,90%的人会主动去翻第7章NLP、第8章GAN——因为“我能行”的感觉,比任何教程都管用。
希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进