深度学习(前四章)
深度学习 V2.2.0 前 41 页完整笔记
对应范围:第 1 章~第 4 章(深度学习概述→PyTorch 基础→张量核心→神经网络基础 + 完整训练流程)
笔记特点:标注⭐必考、⚠️易错点、必背代码,可直接用于复习、作业和考试
第 1 章 深度学习概述(第 1 页)
核心概念
- 深度学习定义:基于多层人工神经网络的机器学习分支,通过数据自动学习特征和规律,无需人工手动设计特征
- 核心工具:PyTorch(工业界主流,动态图)、TensorFlow(静态图,适合部署)
- 应用领域:计算机视觉(CV)、自然语言处理(NLP)、语音识别、推荐系统、自动驾驶
第 2 章 PyTorch 介绍与安装(第 2~10 页 ⭐必考)
2.1 PyTorch 简介
-
开发者:原 Meta AI 团队,现隶属于 Linux 基金会
-
核心优势:
- 动态计算图:边运行边构建,调试方便
- Python 原生语法:学习门槛低
- 生态完善:支持 HuggingFace、PyTorch Lightning 等工具
-
核心能力:
- 类 NumPy 的张量计算,支持 GPU/MPS 硬件加速
- 内置自动微分系统,原生支持反向传播
-
官方地址:https://pytorch.org/
2.2 PyTorch 安装(步骤必须背)
前置准备
安装 Anaconda(用于管理虚拟环境,避免版本冲突)
标准安装步骤
- 创建并激活虚拟环境
# 创建名为dl的虚拟环境,Python版本3.12
conda create -n dl python=3.12 -y
# 激活虚拟环境(Windows/Mac/Linux通用)
conda activate dl
- 配置清华 PyPI 镜像(加速安装)
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
- 安装 PyTorch
-
CPU 版(无 NVIDIA 显卡):直接复制官网最新命令
pip3 install torch torchvision torchaudio -
GPU 版(必须 NVIDIA 显卡):
-
检查显卡算力:≥3.0(近 5 年显卡都满足)
-
查看显卡支持的最高 CUDA 版本:
nvidia-smi -
选择≤最高版本的稳定版 CUDA,复制官网命令
# 示例:CUDA12.6版本 pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
-
- 测试安装是否成功
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则成功
⚠️ 安装易错点
- 必须在激活的虚拟环境中安装,否则会装到 base 环境
- GPU 版无需单独安装 CUDA 和 cuDNN,PyTorch 已内置
- 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.float64、torch.int32、torch.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))
-
⭐选择原则
- 隐藏层:优先 ReLU → 效果不好换 LeakyReLU/GELU
- 二分类输出层:Sigmoid
- 多分类输出层:Softmax(训练时
CrossEntropyLoss自带,不用手动加) - 回归输出层:不用激活函数
4.3 搭建神经网络
4.3.1 自定义模型(继承 nn.Module,灵活,推荐)
必须实现两个核心方法:
__init__():定义网络的所有层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 页易错点汇总
torch.tensor()和torch.Tensor()的区别- 张量与 NumPy 互转的内存共享问题
- 矩阵乘法的维度匹配规则
- 多分类任务输出层不用手动加 Softmax
- 训练时必须调用
optimizer.zero_grad()清零梯度 - 模型保存只存
state_dict,不存整个模型
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)