深度学习 V2.2.0 前 41 页完整笔记

对应范围:第 1 章~第 4 章(深度学习概述→PyTorch 基础→张量核心→神经网络基础 + 完整训练流程)

笔记特点:标注⭐必考、⚠️易错点、必背代码,可直接用于复习、作业和考试


第 1 章 深度学习概述(第 1 页)

核心概念

  1. 深度学习定义:基于多层人工神经网络的机器学习分支,通过数据自动学习特征和规律,无需人工手动设计特征
  2. 核心工具:PyTorch(工业界主流,动态图)、TensorFlow(静态图,适合部署)
  3. 应用领域:计算机视觉(CV)、自然语言处理(NLP)、语音识别、推荐系统、自动驾驶

第 2 章 PyTorch 介绍与安装(第 2~10 页 ⭐必考)

2.1 PyTorch 简介

  • 开发者:原 Meta AI 团队,现隶属于 Linux 基金会

  • 核心优势

    • 动态计算图:边运行边构建,调试方便
    • Python 原生语法:学习门槛低
    • 生态完善:支持 HuggingFace、PyTorch Lightning 等工具
  • 核心能力

    1. 类 NumPy 的张量计算,支持 GPU/MPS 硬件加速
    2. 内置自动微分系统,原生支持反向传播
  • 官方地址:https://pytorch.org/

2.2 PyTorch 安装(步骤必须背)

前置准备

安装 Anaconda(用于管理虚拟环境,避免版本冲突)

标准安装步骤
  1. 创建并激活虚拟环境
# 创建名为dl的虚拟环境,Python版本3.12
conda create -n dl python=3.12 -y
# 激活虚拟环境(Windows/Mac/Linux通用)
conda activate dl
  1. 配置清华 PyPI 镜像(加速安装)
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
  1. 安装 PyTorch
  • CPU 版(无 NVIDIA 显卡):直接复制官网最新命令

    pip3 install torch torchvision torchaudio
    
  • GPU 版(必须 NVIDIA 显卡):

    1. 检查显卡算力:≥3.0(近 5 年显卡都满足)

    2. 查看显卡支持的最高 CUDA 版本:nvidia-smi

    3. 选择≤最高版本的稳定版 CUDA,复制官网命令

      # 示例:CUDA12.6版本
      pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
      
  1. 测试安装是否成功
import torch
# 查看PyTorch版本
print(torch.__version__)
# Windows/NVIDIA显卡测试GPU
print(torch.cuda.is_available())  # 输出True则成功
# Mac M系列芯片测试GPU
print(torch.backends.mps.is_available())  # 输出True则成功
⚠️ 安装易错点
  1. 必须在激活的虚拟环境中安装,否则会装到 base 环境
  2. GPU 版无需单独安装 CUDA 和 cuDNN,PyTorch 已内置
  3. Mac M 系列只能用 CPU 版或 MPS 加速,不支持 CUDA

第 3 章 张量(Tensor)基础(第 11~30 页 ⭐⭐⭐重中之重)

张量是 PyTorch 的核心数据结构,所有深度学习运算都基于张量完成

3.1 张量是什么

  • 定义:NumPy 数组的升级版,不仅能存储多维数据,还支持 GPU 加速和自动微分

  • 维度与应用场景对应表

    | 维度 | 名称 | 应用场景 | 形状示例 |

    |------|------|----------|----------|

    | 0 维 | 标量 | 存储损失值、准确率 | torch.Size ([]) |

    | 1 维 | 向量 | 特征向量、序列数据 | torch.Size ([4]) |

    | 2 维 | 矩阵 | 批量格数据、特征矩阵 | torch.Size ([2,3]) |

    | 3 维 | 三维张量 | 单张彩色图像 [H,W,C]、单条时间序列 | torch.Size ([2,2,3]) |

    | 4 维 | 四维张量 | 批量彩色图像 [N,H,W,C]、视频帧序列 | torch.Size ([10,224,224,3]) |

  • ⭐核心规律:输入数据的嵌套层数 = 张量的维度数

3.2 张量创建(7 种方法,必考)

3.2.1 基于内容创建(最常用)

torch.tensor(data):传入任意 Python 列表、NumPy 数组,自动推断类型

import torch
import numpy as np

# 0维张量(标量)
scalar = torch.tensor(10)
# 1维张量(向量)
vec = torch.tensor([1,2,3,4])
# 2维张量(矩阵)
mat = torch.tensor([[1,2,3],[4,5,6]])
# 3维张量
tensor3d = torch.tensor([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
# NumPy数组转张量
np_arr = np.array([10,20,30])
tensor_from_np = torch.tensor(np_arr)  # 创建副本,不共享内存
tensor_from_np2 = torch.from_numpy(np_arr)  # 共享内存,改一个另一个也变
3.2.2 基于形状创建
# 全0张量
zeros = torch.zeros(2,3)
# 全1张量
ones = torch.ones(2,3)
# 全常量张量
full = torch.full((2,3), 10)
# 单位矩阵
eye = torch.eye(3)  # 3x3单位矩阵
# 未初始化张量(速度快,需手动赋值)
empty = torch.empty(2,3)
# 复制形状生成全1/全0
ones_like = torch.ones_like(mat)
3.2.3 基于区间创建
# 固定步长:[start, end),默认step=1
arange = torch.arange(2, 10, 2)  # tensor([2,4,6,8])
# 固定数量:[start, end],生成steps个均匀间隔值
linspace = torch.linspace(2, 10, 6)  # tensor([2.,3.6,5.2,6.8,8.4,10.])
# 对数间隔:默认base=10
logspace = torch.logspace(1, 3, 3)  # tensor([10.,100.,1000.])
3.2.4 随机创建
# [0,1)均匀分布
rand = torch.rand(2,3)
# 标准正态分布N(0,1)
randn = torch.randn(2,3)
# 整数均匀分布[low, high)
randint = torch.randint(1, 100, size=(2,3))
# 随机打乱0~n-1的整数(数据集洗牌用)
randperm = torch.randperm(10)

# ⭐固定随机种子,保证实验可复现
torch.manual_seed(42)
3.2.5 大写 torch.Tensor () 的坑
  • torch.Tensor(shape):按形状创建,默认固定为float32类型
  • ⚠️不推荐用它传数据:即使传入整数列表,也会强制转 float32,极易造成类型混乱
# 错误用法
t = torch.Tensor([1,2,3])
print(t.dtype)  # torch.float32,不是int64

3.3 张量数据类型

核心数据类型
  • 整数默认:torch.int64(长整型)
  • 浮点数默认:torch.float32(深度学习标准计算类型)
  • 其他常用:torch.float64torch.int32torch.bool
类型转换 3 种方法
t = torch.tensor([1,2,3])  # 默认int64
# 方法1:type()
t_float = t.type(torch.float32)
# 方法2:to()(推荐,同时支持设备转换)
t_int32 = t.to(torch.int32)
# 方法3:便捷写法
t_float2 = t.float()
t_long = t.long()
⚠️易错点

整数张量不能直接计算均值,必须先转浮点型:

# 错误
print(t.mean())  # 报错
# 正确
print(t.float().mean())

3.4 张量转换

3.4.1 Tensor ↔ NumPy
# Tensor → NumPy
t = torch.tensor([1,2,3])
a = t.numpy()  # 默认共享内存
a2 = t.numpy().copy()  # 深拷贝,不共享内存

# NumPy → Tensor
a = np.array([1,2,3])
t = torch.from_numpy(a)  # 默认共享内存
t2 = torch.from_numpy(a).clone()  # 深拷贝
3.4.2 Tensor → Python 标量
# 仅当张量只有1个元素时可用
t = torch.tensor(10)
t2 = torch.tensor([10])
t3 = torch.tensor([[10]])
print(t.item())  # 10(Python int类型)
print(t2.item())  # 10
print(t3.item())  # 10

3.5 张量运算(必考)

3.5.1 逐元素运算
运算 运算符 非原地方法 原地方法(⚠️训练不推荐)
加法 + add() add_()
减法 - sub() sub_()
乘法 * mul() mul_()
除法 / div() div_()
幂运算 ** pow() pow_()
t1 = torch.tensor([[1,2,3],[4,5,6]])
# 非原地:不修改原张量
t2 = t1 + 10
# 原地:直接修改原张量
t1.add_(10)
3.5.2 矩阵乘法(核心)

规则:前一个张量的列数 = 后一个张量的行数

t1 = torch.tensor([[1,2,3],[4,5,6]])  # (2,3)
t2 = torch.tensor([[10,20],[30,40],[50,60]])  # (3,2)

# 3种等价写法
print(t1 @ t2)  # 推荐,语法简洁
print(t1.mm(t2))  # 仅支持二维矩阵
print(t1.matmul(t2))  # 支持高维批量矩阵乘法
3.5.3 统计运算
t = torch.tensor([[1,2,3],[4,5,6]])
# 全局运算
print(t.sum())  # 所有元素求和
print(t.mean())  # 所有元素均值
print(t.max())  # 最大值
# 按维度运算(dim=N表示压缩第N维)
print(t.sum(dim=0))  # 按列求和,形状(3,)
print(t.sum(dim=1))  # 按行求和,形状(2,)
# ⭐max()返回元组:(最大值, 最大值索引)
max_val, max_idx = t.max(dim=1)
# 分类任务取预测类别:取最后一维最大值索引
y_pred_class = torch.argmax(y_pred, dim=-1)

3.6 张量索引与切片

t = torch.randint(0,10,(2,5,4))  # 形状(2,5,4)

# 1. 简单索引(逗号分隔,推荐)
print(t[0,0,0])  # 第0个矩阵、第0行、第0列
print(t[1,2])  # 第1个矩阵、第2行,形状(4,)

# 2. 范围索引(start:end:step)
print(t[1, 1:])  # 第1个矩阵,第1行到末尾
print(t[-1:, 1:4, 0:3:2])  # 复杂切片

# 3. 列表索引(提取非连续元素)
list1 = [0,1,1]
list2 = [1,3,2]
print(t[list1, list2])  # 提取(0,1)、(1,3)、(1,2)位置的行

# 4. 布尔索引(条件筛选,最常用)
print(t[t>5])  # 提取所有大于5的元素

3.7 张量形状操作(必考)

3.7.1 维度交换
t = torch.randint(1,10,(3,2,6))  # 形状(3,2,6)
# 反转所有维度
print(t.T.shape)  # (6,2,3)
# 仅交换最后两个维度(矩阵转置)
print(t.mT.shape)  # (3,6,2)
# 交换两个指定维度
print(t.transpose(0,1).shape)  # (2,3,6)
# 重新排列所有维度(最灵活)
print(t.permute(1,0,2).shape)  # (2,3,6)
3.7.2 调整形状
t = torch.randint(1,10,(2,3,4))  # 总元素24
# reshape:推荐,不要求内存连续,支持-1自动推导
print(t.reshape(6,4).shape)  # (6,4)
print(t.reshape(3, -1).shape)  # (3,8),-1自动计算为8
# view:要求内存连续,否则报错
print(t.view(2,12).shape)
3.7.3 增删维度
t = torch.randint(1,10,(2,4))  # 形状(2,4)
# 增加维度:在dim=1位置加1个维度
t_unsqueeze = t.unsqueeze(dim=1)
print(t_unsqueeze.shape)  # (2,1,4)
# 删除所有大小为1的维度
t_squeeze = t_unsqueeze.squeeze()
print(t_squeeze.shape)  # (2,4)
3.7.4 张量拼接与堆叠
t1 = torch.randint(1,10,(2,3))
t2 = torch.randint(1,10,(2,4))
# cat:按指定维度拼接,维度数不变
print(torch.cat([t1,t2], dim=1).shape)  # (2,7)
# stack:堆叠,新增1个维度,要求所有张量形状相同
t3 = torch.randint(1,10,(2,3))
print(torch.stack([t1,t3], dim=0).shape)  # (2,2,3)

第 4 章 神经网络基础(第 31~41 页 ⭐⭐⭐核心)

4.1 全连接层(nn.Linear)

  • 数学公式:(y = xW^T + b)

  • 参数说明

    • in_features:输入特征维度
    • out_features:输出特征维度
    • bias:是否启用偏置(默认 True)
  • 代码示例

import torch
import torch.nn as nn

# 定义全连接层:2个输入,3个输出
linear = nn.Linear(in_features=2, out_features=3)
# 查看参数形状(注意权重是转置的)
print(linear.weight.shape)  # torch.Size([3,2])
print(linear.bias.shape)  # torch.Size([3])
# 前向传播
x = torch.tensor([[1.0,2.0],[3.0,4.0]])  # 2个样本,每个2个特征
y = linear(x)
print(y.shape)  # torch.Size([2,3])

4.2 激活函数(必背)

  • 作用:引入非线性变换,让神经网络能拟合复杂的非线性规律

  • 常用激活函数对比表

    | 函数 | 公式 | 输出范围 | 适用场景 | 缺点 |

    |------|------|----------|----------|------|

    | ReLU | (max(0,x)) | ([0,+\infty)) | 隐藏层首选 | 神经元死亡(负数输入梯度为 0) |

    | Sigmoid | (\frac{1}{1+e^{-x}}) | ((0,1)) | 二分类输出层 | 梯度消失 |

    | Softmax | (\frac{e{x_i}}{\sum_{j=1}n e^{x_j}}) | ((0,1)),和为 1 | 多分类输出层 | - |

    | Tanh | (\frac{ex-e{-x}}{ex+e{-x}}) | ((-1,1)) | 浅层隐藏层 | 梯度消失 |

  • 代码调用方式

x = torch.tensor([0.7, -1.2, 2.5, 0, -3.1])
# 方式1:torch全局函数
print(torch.relu(x))
# 方式2:张量方法
print(x.relu())
# 方式3:nn层(模型中使用)
relu_layer = nn.ReLU()
print(relu_layer(x))
  • ⭐选择原则

    1. 隐藏层:优先 ReLU → 效果不好换 LeakyReLU/GELU
    2. 二分类输出层:Sigmoid
    3. 多分类输出层:Softmax(训练时CrossEntropyLoss自带,不用手动加)
    4. 回归输出层:不用激活函数

4.3 搭建神经网络

4.3.1 自定义模型(继承 nn.Module,灵活,推荐)

必须实现两个核心方法:

  1. __init__():定义网络的所有层
  2. forward():定义数据的前向传播逻辑
class MyNet(nn.Module):
    def __init__(self):
        super().__init__()
        # 定义层
        self.linear1 = nn.Linear(3,4)
        self.linear2 = nn.Linear(4,4)
        self.out = nn.Linear(4,2)
    
    def forward(self, x):
        # 前向传播
        x = self.linear1(x)
        x = torch.tanh(x)
        x = self.linear2(x)
        x = torch.relu(x)
        x = self.out(x)
        y = torch.softmax(x, dim=-1)
        return y

# 实例化模型
model = MyNet()
# 前向传播
x = torch.randn(10,3)  # 10个样本,每个3个特征
y = model(x)
print(y.shape)  # (10,2)
4.3.2 Sequential 快速搭建(顺序网络)

适用于无分支、无跳跃连接的简单顺序网络,无需手动写forward

model = nn.Sequential(
    nn.Linear(3,4),
    nn.Tanh(),
    nn.Linear(4,4),
    nn.ReLU(),
    nn.Linear(4,2),
    nn.Softmax(dim=-1)
)
4.3.3 查看模型
# 1. 遍历所有参数(带名称)
for name, param in model.named_parameters():
    print(f"{name}: {param.shape}")
# 2. 查看状态字典(保存加载的基础)
print(model.state_dict().keys())
# 3. 可视化模型结构(需安装torchsummary)
from torchsummary import summary
summary(model, input_size=(3,), batch_size=10)
4.3.4 模型保存与加载(⭐必考)

最佳实践:只保存模型参数(state_dict),不保存整个模型

# 保存模型
torch.save(model.state_dict(), 'my_model.pth')

# 加载模型
# 步骤1:先创建完全相同结构的模型
loaded_model = MyNet()
# 步骤2:加载参数
state_dict = torch.load('my_model.pth')
loaded_model.load_state_dict(state_dict)

4.4 损失函数

  • 作用:衡量预测值与真实值的差距,训练的目标是最小化损失
  • 常用损失函数
# 1. 回归任务
mae_loss = nn.L1Loss()  # 平均绝对误差
mse_loss = nn.MSELoss()  # 均方误差
smooth_l1_loss = nn.SmoothL1Loss()  # 鲁棒性更好

# 2. 二分类任务
bce_loss = nn.BCELoss()  # 输入需先过Sigmoid
bce_with_logits_loss = nn.BCEWithLogitsLoss()  # 自带Sigmoid,数值更稳定

# 3. 多分类任务
cross_entropy_loss = nn.CrossEntropyLoss()  # 自带Softmax,输入是原始输出

4.5 梯度下降与反向传播

4.5.1 梯度下降核心思想

沿损失函数的负梯度方向更新参数,逐步逼近最小值

  • 公式:(w_{new} = w_{old} - lr \times \frac{\partial L}{\partial w})
  • 学习率lr:控制参数更新的步长,太大震荡不收敛,太小收敛慢
4.5.2 核心概念
  • Batch Size:每次训练输入的样本数量(常用 32、64、128、256)
  • Iteration:完成一个 Batch 的前向传播 + 反向传播 + 参数更新
  • Epoch:模型完整遍历一次整个训练数据集
4.5.3 反向传播与自动微分

PyTorch 内置torch.autograd自动微分引擎,无需手动计算梯度

# 定义参数,requires_grad=True表示追踪梯度
w = torch.tensor([1.0], requires_grad=True)
b = torch.tensor([0.0], requires_grad=True)
# 前向传播
x = torch.tensor([2.0])
y_true = torch.tensor([5.0])
y_pred = w * x + b
# 计算损失
loss = nn.MSELoss()(y_pred, y_true)
# 反向传播:自动计算所有参数的梯度
loss.backward()
# 查看梯度
print(w.grad)  # dL/dw
print(b.grad)  # dL/db

4.6 数据集与 DataLoader

from torch.utils.data import TensorDataset, DataLoader

# 1. 创建数据集
x = torch.randn(100,3)
y = torch.randn(100,1)
dataset = TensorDataset(x, y)

# 2. 创建数据加载器
dataloader = DataLoader(
    dataset,
    batch_size=32,  # 每个批次32个样本
    shuffle=True,   # 每个epoch打乱数据
    drop_last=False # 不丢弃最后一个不完整的批次
)

# 3. 遍历数据
for x_batch, y_batch in dataloader:
    print(x_batch.shape, y_batch.shape)

4.7 完整训练流程(⭐⭐⭐前 41 页最终目标,必考)

标准训练循环四步:前向传播→计算损失→反向传播→更新参数→梯度清零

import torch
import torch.nn as nn
import torch.optim as optim

# 1. 准备数据
x = torch.randn(100,1)
y = x * 2.5 + 5.0 + torch.randn(100,1)*0.2  # 模拟线性数据
dataset = TensorDataset(x, y)
dataloader = DataLoader(dataset, batch_size=6, shuffle=True)

# 2. 定义模型
model = nn.Linear(1,1)

# 3. 定义损失函数和优化器
loss_fn = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 4. 训练模型
loss_list = []
for epoch in range(200):
    total_loss = 0
    for x_batch, y_batch in dataloader:
        # 步骤1:前向传播
        y_pred = model(x_batch)
        # 步骤2:计算损失
        loss = loss_fn(y_pred, y_batch)
        # 步骤3:反向传播
        loss.backward()
        # 步骤4:更新参数
        optimizer.step()
        # 步骤5:梯度清零(必须,否则梯度会累积)
        optimizer.zero_grad()
        
        total_loss += loss.item()
    
    # 记录每轮平均损失
    avg_loss = total_loss / len(dataloader)
    loss_list.append(avg_loss)
    print(f"Epoch {epoch+1}, Loss: {avg_loss:.4f}")

# 查看训练后的参数
print("训练后的斜率:", model.weight.item())  # 接近2.5
print("训练后的偏置:", model.bias.item())    # 接近5.0

前 41 页核心考点速查表

模块 必考内容
PyTorch 安装 虚拟环境创建、GPU 版要求、安装测试代码
张量 创建方法、形状操作、矩阵乘法、索引、类型转换
神经网络 全连接层参数、激活函数选择、模型搭建、保存加载
训练流程 损失函数选择、梯度下降、反向传播、标准训练循环

前 41 页易错点汇总

  1. torch.tensor()torch.Tensor()的区别
  2. 张量与 NumPy 互转的内存共享问题
  3. 矩阵乘法的维度匹配规则
  4. 多分类任务输出层不用手动加 Softmax
  5. 训练时必须调用optimizer.zero_grad()清零梯度
  6. 模型保存只存state_dict,不存整个模型
Logo

加入「COC·上海城市开发者社区」,成就更好的自己!

更多推荐