深度学习概念

pytorch安装

cmd 复制代码
conda install pytorch torchvision torchaudio cpuonly -c pytorch

jupyter notebook 安装

复制代码
conda install jupyter notebook

分类

分类问题的常见损失函数被称为交叉熵

回归

均方误差是回归问题中最常用、最直观的损失函数。

什么是回归

需要模型输出一个或多个连续数值的任务

联合概率

第一个被称为联合概率(joint probability)
P ( A = a , B = b ) P(A = a, B = b) P(A=a,B=b)

给定任意值a和b,联合概率可以回答:
A = a , B = b A =a,B = b A=a,B=b

同时满足的概率是多少?请注意,对于任何a和b的取值,
P ( A = a , B = b ) ≤ P ( A = a ) P(A = a, B = b) ≤ P(A = a) P(A=a,B=b)≤P(A=a)

这点是确定

的,因为要同时发生A = a和B = b, A = a就必须发生, B = b也必须发生(反之亦然)。因此, A = a和B = b同

时发生的可能性不大于A = a或是B = b单独发生的可能性

条件概率

联合概率的不等式带给我们一个有趣的比率:
0 ≤ P ( A = a , B = b ) P ( A = a ) ≤ 1 0\le \frac{ P(A=a,B=b)}{P(A=a)} \le 1 0≤P(A=a)P(A=a,B=b)≤1

我们称这个比率为条件概率(conditional

probability),并用P(B = b | A = a)表示它:它是B = b的概率,前提是A = a已发生。

贝叶斯定理

使用条件概率的定义,我们可以得出统计学中最有用的方程之一: Bayes定理(Bayes' theorem)。根据乘法法

则(multiplication rule )可得到P(A, B) = P(B | A)P(A)。根据对称性,可得到P(A, B) = P(A | B)P(B)。

假设P(B) > 0,求解其中一个条件变量,我们得到
P ( A ∣ B ) = P ( A ∣ B ) P ( A ) P ( B ) P(A|B)=\frac{ P(A|B)P(A)}{P(B)} P(A∣B)=P(B)P(A∣B)P(A)

期望和方差

为了概括概率分布的关键特征,我们需要一些测量方法。一个随机变量X的期望(expectation,或平均值

(average))表示为

E\[X\]=\\sum_{x}xP(X=x) 衡量随机变量 X 与其期望值的偏置。这可以通过方差来量化 衡量随机变量X与其期望值的偏置。这可以通过方差来量化 衡量随机变量X与其期望值的偏置。这可以通过方差来量化 Var\[X\]=E\[(X)-E\[x\])^2\]=E\[x^2\]-E\[x\]\^2

模型

在开始寻找最好的模型参数(model parameters) w和b之前,我们还需要两个东西:

(1)一种模型质量的度量方式;

(2)一种能够更新模型以提高模型预测质量的方法

模型质量的度量方式

损失函数

通常我们会选择非负数作为损失,且数值越小表示损失越小, 完美预测时的损失为0。

回归问题中最常用的损失函数是平方误差函数

l ( i ) ( w , b ) = 1 2 ( y ′ ( i ) − y ( i ) ) 2 l^{(i)}(w, b) = \frac{1}{2} ( y^{'}(i) − y(i))^2 l(i)(w,b)=21(y′(i)−y(i))2
由于平方误差函数中的二次方项,估计值 y ˆ ( i ) yˆ(i) yˆ(i)和观测值 y ( i ) y(i) y(i)之间较大的差异将导致更大的损失。为了度量模型
在整个数据集上的质量,我们需计算在训练集n个样本上的损失均值(也等价于求和)

L ( w , b ) = 1 n ∑ i = 1 n 1 2 ( y ′ ( i ) − y ( i ) ) 2 L(w, b) = \frac{1}{n} \sum_{i=1}^{n} \frac{1}{2} ( y^{'}(i) − y(i))^2 L(w,b)=n1i=1∑n21(y′(i)−y(i))2

python 复制代码
import torch
def loss(W, b, X, y):
    """
    函数1:计算损失值 + 反向传播求梯度(不更新参数)
    功能:前向传播算预测值,计算损失,反向传播将梯度存入 W.grad 和 b.grad
    参数说明:
        W: 权重张量,shape=(n_features, 1),需设置 requires_grad=True
        b: 偏置张量,shape=(1,),需设置 requires_grad=True
        X: 输入特征矩阵,shape=(n_samples, n_features)
        y: 真实标签,shape=(n_samples, 1)
    返回:
        loss_val: 损失值(Python标量)
    """
    # 1. 前向传播:y_pred = X·W + b 计算预测值
    y_pred = torch.matmul(X, W) + b  
    # 2. 计算损失
    loss = torch.mean((y_pred - y) ** 2)
    return loss.item()

提高模型预测质量的方法

随机梯度下降

算法的步骤如下:

(1)初始化模型参数的值,如随机初始化;

(2)从数据集中随机抽取小批量样 本且在负梯度的方向上更新参数,

python 复制代码
import torch
def update_params(W, b, lr=0.01):
    """
    函数2:仅更新参数(依赖已计算的梯度)
    功能:使用 W.grad 和 b.grad,按梯度下降公式更新参数,更新后清零梯度
    参数说明:
        W: 权重张量(已通过函数1计算出 W.grad)
        b: 偏置张量(已通过函数1计算出 b.grad)
        lr: 学习率,默认0.01
    返回:
        updated_W: 更新后的权重 W
        updated_b: 更新后的偏置 b
    """
    # 1. 手动更新参数(关闭梯度追踪,不影响计算图)
    with torch.no_grad():
        W.data -= lr * W.grad  # W = W - lr * 梯度
        b.data -= lr * b.grad  # b = b - lr * 梯度
    
    # 2. 梯度清零(关键!避免下次梯度累积)
    W.grad.zero_()
    b.grad.zero_()
    return W, b

正态分布

\\begin{flalign} \&方 差\\sigma\^2,标准差\\sigma,均值\\mu \\ \&\\sigma=\\sqrt\[\]{\\frac{1}{n} \\sum_{i=1}\^{n}{(X_i - \\mu )\^2} } \\ \&正态分布 = p(x) = \\frac{1}{\\sqrt{2\\pi\\sigma\^2 } } e\^{-\\frac{1}{2\\sigma ^2}(x-u)^2 }\& \\end{flalign}

全连接层

对于线性回归,每个输入都与每个输出相连,我们将这种变换称为全连接层或称为稠密层

定义模型步骤

定义模型

python 复制代码
#%%
# nn是神经网络的缩写
from torch import nn

net = nn.Sequential(nn.Linear(2, 1))

初始化模型参数

python 复制代码
net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)

计算均方误差方法

python 复制代码
loss = nn.MSELoss()

定义优化算法

python 复制代码
trainer = torch.optim.SGD(net.parameters(), lr=0.03)

训练

python 复制代码
num_epochs = 3
for epoch in range(num_epochs):
    for X, y in data_iter:
        l = loss(net(X) ,y)
        trainer.zero_grad()
        l.backward()
        trainer.step()
    l = loss(net(features), labels)
    print(f'epoch {epoch + 1}, loss {l:f}')

softmax

softmax回归的输出层也是全连接层

softmax输出的是属于哪一类的概率,属于激活函数

多层感知机

发挥多层架构的潜力,我们还需要一个额外的关键要素:在仿射变换之后对每个隐藏单元应用非线性的激活函数 激活函数的输出被称为活性值。一般来说,

有了激活函数,就不可能再将我们的多层感知机退化成线性模型:

激活函数

ReLU函数

sigmoid函数

tanh函数

解决过拟合

权重衰减

权重衰减是一种正则化技术,通过在损失函数中添加惩罚项来抑制模型过拟合,提高模型的泛化能力

我们在实例化优化器时直接通过weight_decay指定weight decay超参数。 默认情况下,PyTorch同时衰减权重和偏移

暂退法

暂退法在前向传播过程中,计算每一内部层的同时注入噪声,这已经成为训练神经网络的常用技术。 这种方法之所以被称为暂退法,因为我们从表面上看是在训练过程中丢弃(drop out)一些神经元。 在整个训练过程的每一次迭代中,标准暂退法包括在计算下一层之前将当前层中的一些节点置零。

对于深度学习框架的高级API,我们只需在每个全连接层之后添加一个Dropout层, 将暂退概率作为唯一的参数传递给它的构造函数。 在训练时,Dropout层将根据指定的暂退概率随机丢弃上一层的输出(相当于下一层的输入)。 在测试时,Dropout层仅传递数据。

python 复制代码
net = nn.Sequential(nn.Flatten(),
        nn.Linear(784, 256),
        nn.ReLU(),
        # 在第一个全连接层之后添加一个dropout层
        nn.Dropout(dropout1),
        nn.Linear(256, 256),
        nn.ReLU(),
        # 在第二个全连接层之后添加一个dropout层
        nn.Dropout(dropout2),
        nn.Linear(256, 10))

def init_weights(m):
    if type(m) == nn.Linear:
        nn.init.normal_(m.weight, std=0.01)

net.apply(init_weights);

自定义块

python 复制代码
class MLP(nn.Module):
    # 用模型参数声明层。这里,我们声明两个全连接的层
    def __init__(self):
        # 调用MLP的父类Module的构造函数来执行必要的初始化。
        # 这样,在类实例化时也可以指定其他函数参数,例如模型参数params(稍后将介绍)
        super().__init__()
        self.hidden = nn.Linear(20, 256)  # 隐藏层
        self.out = nn.Linear(256, 10)  # 输出层

    # 定义模型的前向传播,即如何根据输入X返回所需的模型输出
    def forward(self, X):
        # 注意,这里我们使用ReLU的函数版本,其在nn.functional模块中定义。
        return self.out(F.relu(self.hidden(X)))

保存和加载

保存模型

保存整个模型(含结构 + 参数)

python 复制代码
# 保存整个模型
torch.save(model, "entire_model.pth")

# 加载整个模型
loaded_entire_model = torch.load("entire_model.pth")
loaded_entire_model.eval()  # 若用于推理,建议开启eval模式(关闭Dropout等)

# 验证加载结果
x = torch.randn(1, 10)  # 随机输入一个样本
output = loaded_entire_model(x)
print("\n加载整个模型的输出:\n", output)
print("加载后模型参数:\n", loaded_entire_model.linear.weight)

保存整个模型:加载即能用,无需关心结构定义,适合快速验证:

python 复制代码
# 加载后直接调用,不用写模型类
loaded_model = torch.load("entire_model.pth")
loaded_model(x)  # 直接推理

仅保存模型参数(权重)(推荐)

python 复制代码
# 保存模型参数(state_dict)
torch.save(model.state_dict(), "model_params.pth")

# 加载模型参数
loaded_model = SimpleModel()  # 先实例化模型结构
loaded_model.load_state_dict(torch.load("model_params.pth"))
loaded_model.eval()

# 验证加载结果
x = torch.randn(1, 10)
output = loaded_model(x)
print("\n加载参数后模型的输出:\n", output)
print("加载后模型参数:\n", loaded_model.linear.weight)

仅保存参数:必须先「还原模型结构」,再加载参数,步骤多一步但灵活:

python 复制代码
# 第一步:先定义和训练时完全一致(或兼容)的模型结构
class SimpleModel(nn.Module):  # 必须和保存参数时的模型结构一致(层名、维度匹配)
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(10, 2)  # 若这里改成 nn.Linear(10, 3),加载会失败

# 第二步:实例化模型 + 加载参数
model = SimpleModel()
model.load_state_dict(torch.load("model_params.pth"))  # 关键:先有结构,再填参数

1.只加载参数的时候后续使用需要重新定义模型

2.若已经训练的参数不想改变可以进行冻结

python 复制代码
# 冻结linear1层(复用层)的参数
for param in new_model.linear1.parameters():
    param.requires_grad = False

卷积层

构造一个二维卷积层,它具有1个输出通道和形状为(1, 2)的卷积核

python 复制代码
conv2d = nn.Conv2d(1,1, kernel_size=(1, 2), bias=False)

# 定义卷积层:1 输入通道 → 16 输出通道,3×3 卷积核,padding=1(保持输出尺寸与输入一致)
conv1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=3, padding=1)

汇聚层((pooling))

通常当我们处理图像时,我们希望逐渐降低隐藏表示的空间分辨率、聚集信息,这样随着我们在神经网络中层叠的上升,每个神经元对其敏感的感受野(输入)就越大。

而我们的机器学习任务通常会跟全局图像的问题有关(例如,"图像是否包含一只猫呢?"),所以我们最后一层的神经元应该对整个输入的全局敏感。通过逐渐聚合信息,生成越来越粗糙的映射,最终实现学习全局表示的目标,同时将卷积图层的所有优势保留在中间层。

汇聚(pooling)层,它具有双重目的:降低卷积层对位置的敏感性,同时降低对空间降采样表示的敏感性。

python 复制代码
pool2d = nn.MaxPool2d((2, 3), stride=(2, 3), padding=(0, 1)) #最大汇聚层
pool2d = nn.Conv2d(1, 6, kernel_size=5, padding=2) #平均汇聚层

LeNet

通过下面的LeNet代码,可以看出用深度学习框架实现此类模型非常简单。我们只需要实例化一个Sequential块并将需要的层连接在一起。

python 复制代码
import torch
from torch import nn
from d2l import torch as d2l

net = nn.Sequential(
    nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2, stride=2),
    nn.Conv2d(6, 16, kernel_size=5), nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2, stride=2),
    nn.Flatten(),
    nn.Linear(16 * 5 * 5, 120), nn.Sigmoid(),
    nn.Linear(120, 84), nn.Sigmoid(),
    nn.Linear(84, 10))

RNN (循环神经网络)

统计次的出现频率

对时间序列有要求

python 复制代码
num_hiddens = 256
rnn_layer = nn.RNN(len(vocab), num_hiddens)
#len(vocab) 是词汇表大小,通常对应「one-hot 编码的词向量维度」(比如词汇表有 1000 个词,one-hot 编码后每个词是 1000 维向量,故 input_size=1000)。
#「隐藏层的神经元数量」(核心超参数)。决定 RNN 捕捉序列信息的能力:数值越大,模型容量越强(但易过拟合),通常取 50、128、256 等。输出的隐藏态维度 = hidden_size。

GRU(门控循环单元)

核心背景:为什么需要 GRU?

传统 RNN 是处理序列数据(如文本、时序信号)的基础模型,但它存在致命缺陷:当序列过长(如长句子、长时序数据)时,反向传播过程中梯度会逐渐衰减(梯度消失)或无限放大(梯度爆炸),导致模型无法学习到 "早期关键信息与后期信息的关联"(即 "长序列依赖问题")。

GRU其核心设计目标是:解决传统 RNN 处理长序列时的 "梯度消失 / 爆炸" 问题,

通过双门控机制,GRU 能自主判断 "哪些信息需要长期保留""哪些信息可以丢弃",彻底克服了传统 RNN 的梯度消失问题。

重置门 更新门

python 复制代码
num_inputs = vocab_size
gru_layer = nn.GRU(num_inputs, num_hiddens)
model = d2l.RNNModel(gru_layer, len(vocab))
model = model.to(device)
d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, device)

长短期记忆网络(LSTM)

核心背景:为什么需要 LSTM?

传统 RNN 的核心缺陷是 "长序列依赖问题":当处理长文本、长时序数据时,反向传播的梯度会随序列长度衰减或放大,导致模型无法学习到早期信息与后期信息的关联

LSTM 彻底解决了传统 RNN 的梯度消失问题,能精准捕捉长序列中 "早期关键信息与后期信息的关联":

输入门、忘记门和输出门

python 复制代码
num_inputs = vocab_size
lstm_layer = nn.LSTM(num_inputs, num_hiddens)
model = d2l.RNNModel(lstm_layer, len(vocab))
model = model.to(device)
d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, device)

深度循环神经网络

python 复制代码
vocab_size, num_hiddens, num_layers = len(vocab), 256, 2
device = d2l.try_gpu()
lstm_layer = rnn.LSTM(num_hiddens, num_layers)
model = d2l.RNNModel(lstm_layer, len(vocab))

双向循环神经网络

双向循环神经网络使用了过去的和未来的数据

python 复制代码
num_inputs = vocab_size
lstm_layer = nn.LSTM(num_inputs, num_hiddens, num_layers, bidirectional=True)

对比普通循环神经网络(Vanilla RNN)、深层循环神经网络(Deep RNN)、双向循环神经网络(Bi-RNN)

对比维度 普通RNN(Vanilla RNN) 深层RNN(Deep RNN) 双向RNN(Bi-RNN)
核心定义 仅含「1个隐藏层」,且隐藏层仅按「单一方向」(通常是"从左到右",即t=1→t=T)处理序列。 含「2个及以上隐藏层」(堆叠),隐藏层仍按「单一方向」处理序列,同时存在「层间状态传递」(上一层的h_t作为下一层的输入)。 含「1个或多个隐藏层」,每个隐藏层包含「两个并行的循环单元」: - 正向单元(Forward RNN):从左到右处理(t=1→t=T),捕捉"过去→现在"的依赖; - 反向单元(Backward RNN):从右到左处理(t=T→t=1),捕捉"未来→现在"的依赖; 最终输出结合两个方向的隐藏状态。
隐藏层设计核心 「单层+单向」:无层间堆叠,仅时间维度循环。 类比:一条"单层单向流水线",原料(输入)按顺序加工一次。 「多层+单向」:层间堆叠(空间维度)+ 时间维度循环。 类比:多条"单向流水线串联",原料经多层精细化加工。 「单层/多层+双向」:同一层内双方向并行(信息维度扩展)+ 可选层间堆叠。 类比:一条"双向流水线",原料同时从左到右、从右到左加工,最终融合结果。
信息利用范围 仅能利用「当前时刻之前的历史信息」(单向时序),无法获取"未来信息"。 例:处理句子"他____去了巴黎"时,仅能参考"他"之前的词,无法利用"去了巴黎"的后文。 仅能利用「当前时刻之前的历史信息」(单向时序),但能通过多层堆叠抽象"深层历史依赖"。 例:处理"淋雨→感冒→吃药"时,能捕捉"淋雨"到"吃药"的多层因果链,但仍无法利用后文信息。 能同时利用「历史信息(过去→现在)+ 未来信息(现在→未来)」(双向时序)。 例:处理句子"小明在____买了面包"时,既能参考"小明在"的前文,也能利用"买了面包"的后文,推断出"超市""便利店"等答案。
特征提取能力 仅能捕捉「浅层局部特征」(如短序列的相邻依赖、时序数据的短期波动),无法抽象复杂层级特征。 能实现「分层特征提取」: - 底层隐藏层:捕捉基础特征(如词嵌入、局部波动); - 上层隐藏层:抽象高级特征(如短语语义、长期趋势); 核心是"深度增强"。 能捕捉「上下文完整特征」: - 单层双向:同时覆盖前后局部依赖(如文本的歧义消解); - 多层双向:结合"深度+双向",既抽象高级特征,又利用完整上下文; 核心是"范围增强"。
能力边界 1. 仅适配短序列(长序列梯度消失严重); 2. 无法建模复杂依赖(如跨句逻辑、多周期时序); 3. 表达能力弱,易欠拟合。 1. 结合LSTM/GRU后,可处理长序列(缓解梯度问题); 2. 能建模复杂深层依赖(如长文本逻辑、多周期趋势); 3. 表达能力强,适配高复杂度任务。 1. 结合LSTM/GRU后,可处理长序列+上下文依赖; 2. 擅长"需要完整上下文的任务"(如歧义消解、命名实体识别); 3. 表达能力取决于层数(单层弱于深层,多层接近深层双向)。
参数与训练难度 1. 参数最少(仅1个隐藏层的权重); 2. 训练速度最快,显存占用最低; 3. 无需复杂正则化,易实现。 1. 参数多(多层权重+层间传递权重); 2. 训练速度慢、显存占用高; 3. 梯度问题更突出(时间+层间双重衰减),需Dropout、Adam优化器等正则化,否则易过拟合。 1. 参数比同层数单向RNN多1倍(正向+反向单元权重); 2. 训练速度中等(慢于普通RNN,快于同层数深层RNN); 3. 需处理"双向隐藏状态融合"(如拼接、求和),但梯度问题仅比单向略严重。
适用场景 简单短序列任务(无复杂依赖、无需上下文): - 短文本分类(单句情感分析); - 简单时序趋势预测(3天内温度); - 入门级演示。 复杂长序列任务(需深层特征抽象): - 机器翻译(基础版)、长文本摘要; - 高精度时序预测(数月股价、设备故障预警); - 语音识别(基础特征提取)。 需完整上下文的任务(依赖前后信息): - 自然语言处理:命名实体识别(NER)、句法分析、歧义句翻译; - 语音识别:语音转文本(需前后音节关联); - 时序预测:需结合前后周期的场景(如电力负荷预测)。

束搜索

注意力机制 和Transformer

Transformer 之所以能跨领域普及,核心是它提供了一种 "通用的序列建模框架"------ 无论数据是文本、语音、图像、视频还是时序信号,都能通过 "序列化 + 注意力机制" 实现全局依赖建模和高效并行计算。
一文彻底搞懂 Transformer(图解+手撕)
手撕Transformer(一):注意力机制与位置编码
Transofrmer架构详解与PyTorch实现(附代码讲解)

相关推荐
星尘安全1 小时前
研究人员发现严重 AI 漏洞,Meta、英伟达及微软推理框架面临风险
人工智能·microsoft·网络安全·程序员必看
共绩算力1 小时前
【共绩 AI 小课堂】Class 5 Transformer架构深度解析:从《Attention Is All You Need》论文到现代大模型
人工智能·架构·transformer·共绩算力
极客BIM工作室1 小时前
VideoCAD:大规模CAD UI交互与3D推理视频数据集,开启智能CAD建模新范式
人工智能·机器学习
帮帮志1 小时前
01.【AI大模型对话】通过简化大语言模型(LLM)技术来实现对话
人工智能·ai·语言模型·大模型·智能
蒋星熠1 小时前
常见反爬策略与破解反爬方法:爬虫工程师的攻防实战指南
开发语言·人工智能·爬虫·python·网络安全·网络爬虫
陈橘又青1 小时前
CANN在智能安防场景中的落地实践:释放硬件潜能,简化AI开发
人工智能·网络协议·学习·ai·编辑器
是店小二呀1 小时前
在家搭个私人影院?LibreTV+cpolar,随时随地看片自由
开发语言·人工智能
爱看科技1 小时前
智能眼镜AR领航XR市场增长浪潮,三星/微美全息布局竞速引领AI消费新势力!
人工智能·ar·xr
这张生成的图像能检测吗2 小时前
(论文速读)多任务深度学习框架下基于Lamb波的多损伤数据集构建与量化算法
人工智能·深度学习·算法·数据集·结构健康监测