人工智能-深度学习

部署运行你感兴趣的模型镜像

目录

一、概述与基础认知

1.1 深度学习定义
1.2 核心区别(与机器学习)
1.3 优缺点
1.4 发展历史
1.5 常见算法与模型

二、应用场景

三、核心工具:流行框架与张量

3.1 流行深度学习框架
3.2 张量(Tensor):深度学习的核心数据结构

四、PyTorch框架核心模块

4.1 环境安装
4.2 自动微分模块(反向传播求梯度)
4.3 梯度问题:消失与爆炸

五、人工神经网络(ANN)核心技术

5.1 神经元结构与网络构成
5.2 激活函数(面试常问)
5.3 7大参数初始化方法
5.4 损失函数(面试常问)
5.5 优化器:学习率与参数更新的核心(面试重点)
5.6 正则化:解决过拟合的核心技术

六、综合案例:手机价格分类任务

6.1 任务需求
6.2 实现步骤
6.3 案例关键说明

七、核心知识点总结

7.1 技术选型速查表
7.2 常见问题与解决方案

学习目标

  • 理解深度学习定义、与机器学习的核心区别及典型应用场景,建立对深度学习的基础认知。

  • 掌握PyTorch框架核心操作,包括张量创建与运算、自动微分原理、模型构建与训练流程。

  • 精通人工神经网络(ANN)核心技术,涵盖激活函数、参数初始化、损失函数、优化器及正则化方法的选型与应用。

  • 熟悉深度学习常见模型(CNN、RNN、Transformer等)的适用场景,理解批量归一化(BN)、Dropout等关键技术的作用机制。

  • 能够独立完成深度学习实战任务,包括数据处理、模型搭建、训练优化及结果评估,解决实际问题。

一、概述与基础认知

1.1 深度学习定义

深度学习是机器学习算法的重要分支,以人工神经网络为核心模型,能够自动提取数据特征,无需人工干预特征工程,实现端到端的学习与预测。

1.2 核心区别(与机器学习)

  • 特征提取方式:机器学习需人工设计并提取特征;深度学习通过网络结构自动学习和提取特征。
  • 模型复杂度:深度学习模型层级更深、参数更多,可处理更复杂的数据模式。

1.3 优缺点

1.3.1 优点

  • 精度高,在计算机视觉、自然语言处理等领域性能优于传统机器学习算法,部分场景超过人类水平。
  • 随着计算机硬件(GPU/TPU)的发展,可近似拟合任意非线性函数,解决复杂问题。
  • 生态完善,学界和业界支持度高,有大量成熟框架(如PyTorch、TensorFlow)可供调用。

1.3.2 缺点

  • “黑箱”特性,模型决策过程难以解释,缺乏可解释性。
  • 训练时间长,需要大量计算资源支撑,对硬件要求较高。
  • 网络结构复杂,超参数调优难度大,需大量经验积累。
  • 对小数据集适应性差,易出现过拟合问题。

1.4 发展历史

  • 1943年:提出McCulloch-Pitts神经元模型,为人工神经网络奠定基础。
  • 1956年:约翰·麦卡锡、香农等人主持达特茅斯会议,首次提出“人工智能”术语。
  • 1960年:多层感知器(输入层-隐藏层-输出层)出现,推动神经网络结构发展。
  • 2012年:卷积神经网络(CNN)诞生,在图像识别任务中取得突破性成果,引爆深度学习革命。
  • 2017年:Transformer框架提出,革新自然语言处理领域的技术路线。
  • 2022年:ChatGPT发布,标志着大模型AIGC时代来临。
  • 2023年:大模型技术实现爆发式突破,引发全球人工智能研发浪潮。
  • 2024年:AI应用大规模落地,硬件与实际场景深度融合。
  • 2025年:开启智能体(Agent)时代,AI自主性与决策能力显著提升。

1.5 常见算法与模型

  • ANN(人工神经网络):基础网络结构,适用于简单非线性问题。
  • CNN(卷积神经网络):擅长处理网格结构数据,核心应用于计算机视觉领域。
  • RNN(循环神经网络):针对序列数据设计,可捕捉时间依赖关系,适用于语音、文本等任务。
  • Transformer:基于自注意力机制,是当前大语言模型、多模态模型的核心架构(2017年提出)。
  • 生成对抗网络(GAN):通过生成器与判别器的对抗训练生成逼真数据,适用于图像生成、风格迁移等场景。

二、应用场景

  • 计算机视觉(CV):图像识别(如人脸识别、物体识别)、图像分割(如医学影像病灶分割)、目标检测(如自动驾驶障碍物检测)。
  • 自然语言处理(NLP):聊天机器人(如智能客服)、语音翻译(如实时跨境翻译)、生成式AI(如文本创作、代码生成)。
  • 推荐系统:电商商品推荐、视频平台内容推荐、电影/音乐/文章个性化推荐。
  • 多模态大模型:融合文本、图像、语音等多种数据类型,实现跨模态理解与生成(如文生图、图生文)。

三、核心工具:流行框架与张量

3.1 流行深度学习框架

  • TensorFlow:由谷歌开发,工业界应用广泛,生态成熟,支持分布式训练。
  • PyTorch:由Meta(原Facebook)开发,API简洁直观,动态计算图特性适合科研实验,是学术界首选框架。
  • PaddlePaddle(飞桨):百度自研框架,对中文场景支持友好,无GPU环境下也能高效运行。
  • ONNX(开放神经网络交换格式):跨框架的模型存储格式,可实现不同框架(如PyTorch转TensorFlow)的模型互转,被誉为“万物先转ONNX,ONNX转万物”。

3.2 张量(Tensor):深度学习的核心数据结构

张量是多维数组的抽象概念,是深度学习中数据存储和运算的基本单元。维度划分:0维(标量)、1维(向量)、2维(矩阵)、3维(如文本序列:批次×长度×特征)、4维(如图像数据:批次×通道×高度×宽度,在3维基础上增加时间/批次轴)。

3.2.1 张量创建

基本创建方式

  • torch.tensor(data=, dtype=):可同时指定数据和数据类型(如torch.float32、torch.int64),灵活性高。
  • torch.Tensor(data=, size=()):既可以传入原始数据,也可直接指定张量形状。
  • torch.IntTensor()/FloatTensor():直接通过类型后缀指定张量类型创建空张量或初始化张量。

线性与随机张量

  • 线性张量
            torch.arange(start=, end=, step=):生成指定范围的连续整数,左闭右开(end不包含),step为步长。
  • torch.linspace(start=, end=, steps=):在指定区间内生成均匀分布的steps个数值,左闭右闭(end包含)。

随机张量
        torch.rand(size=()):生成0到1之间均匀分布的浮点数。

torch.randn(size=()):生成标准正态分布(均值0,方差1)的浮点数。

torch.randint(low=, high=, size=()):生成[low, high)区间内的随机整数。

随机种子torch.manual_seed(常数)设置随机种子(保证实验可复现);torch.initial_seed()查看当前随机种子。

0/1/指定值张量

  • torch.zeros(size=())/torch.ones(size=()):根据指定形状生成全0/全1张量。
  • torch.zeros_like(input=tensor)/torch.ones_like(input=tensor):根据输入张量的形状生成全0/全1张量,避免手动匹配形状。
  • torch.full(size=(), fill_value=):生成指定形状且所有元素为fill_value的张量。
  • torch.full_like(input=tensor, fill_value=):根据输入张量形状生成填充指定值的张量。

3.2.2 类型转换

  • 张量转NumPy数组
            tensor.numpy():转换后的数据与原张量共享内存,修改一方会影响另一方。
  • tensor.numpy().copy():深拷贝转换,不共享内存,双方独立。

NumPy数组转张量
        torch.from_numpy(data=ndarray):共享内存,适合大数据快速转换。

torch.tensor(data=ndarray):深拷贝转换,不共享内存,数据更安全。

标量与单元素张量互转
        标量转张量:torch.tensor(标量值)(如torch.tensor(5.0))。

单元素张量转标量:tensor.item()(仅适用于包含一个元素的张量)。

3.2.3 数字计算

基础运算

  • 运算符:+、-、*、/(元素级运算)。
  • 函数形式:torch.add()、torch.sub()、torch.mul()、torch.div(),功能与运算符一致,支持更多参数配置。
  • 原位运算:tensor.add_()、sub_()、mul_()、div_(),直接修改原张量数据,不创建新对象,节省内存。
  • 负号操作:tensor.neg()(返回新张量)、tensor.neg_()(原位修改)。

矩阵乘法运算

  • 运算规则:若张量A形状为(n, m),张量B形状为(m, p),则乘积C形状为(n, p),即“前矩阵列数=后矩阵行数”。
  • 实现方式:
            PyTorch:@运算符或torch.matmul()(支持高维张量批量矩阵乘法);注意torch.dot()仅支持1维张量的点积。
  • NumPy:@np.matmul()np.dot()(高维场景下与matmul有差异)。

3.2.4 运算函数

  • min/max/mean/sum(dim=)
            不指定dim:对张量所有元素计算全局结果(返回单元素张量)。
  • 指定dim:沿指定维度计算(dim=0为列方向,dim=1为行方向),返回该维度压缩后的张量。

sqrt():计算每个元素的平方根。

log()/log2()/log10()/log1p():分别计算自然对数、以2为底的对数、以10为底的对数、log(1+x)(避免x接近0时的计算误差)。

pow(exponent=):计算每个元素的exponent次幂(如pow(2)为平方)。

exp():计算每个元素的自然指数e^x。

数学模块辅助示例

import math

print(math.e)          # 自然常数e
print(math.pi)         # 圆周率π
print(math.sqrt(16))   # 平方根,结果4.0
print(math.log(math.e))# 自然对数,结果1.0
print(math.log(math.e, 2)) # 以2为底e的对数
print(math.log10(1000))# 以10为底1000的对数,结果3.0
print(math.log2(16))   # 以2为底16的对数,结果4.0
print(math.exp(1))     # e的1次幂,结果≈2.718
print(math.pow(2, 3))  # 2的3次幂,结果8.0

3.2.5 索引操作

核心作用:根据索引定位并获取张量中指定位置的数据,支持单元素、行列、切片、布尔索引等多种方式,核心语法为张量名[行索引, 列索引](多维张量可扩展为[0轴, 1轴, 2轴,...])。

基础索引方式

  • 单独获取行列
            指定行:张量名[行索引, :](如data[1, :]获取第2行),可简化为张量名[行索引]
  • 指定列:张量名[:, 列索引](如data[:, 1]获取第2列),可简化为张量名[..., 1](...表示匹配所有前置维度)。
  • 指定行列交点:张量名[行索引, 列索引](如data[2, 3]获取第3行第4列元素)。

批量获取多行列
        指定多行:张量名[[行索引1, 行索引2], :](如data[[0,2], :]获取第1、3行)。

指定多列:张量名[:, [列索引1, 列索引2]](如data[:, [0,2]]获取第1、3列)。

多行多列交集:张量名[[行1,行2], [列1,列2]](返回(行1,列1)、(行2,列2)的元素)。

多行多列子矩阵:张量名[[[行1],[行2]], [列1,列2]](返回行1-2与列1-2的交集子矩阵)。

切片获取连续数据张量名[行切片, 列切片],切片语法为start:end:step(默认start=0, end=维度长度, step=1),如data[0:3, :]获取前3行。

布尔索引张量名[布尔张量],仅保留布尔值为True的位置元素(如data[data>5]获取所有大于5的元素)。

多维张量索引:按轴顺序指定索引,如3维张量data[0, 1:3, 2]表示获取0轴第1个数据、1轴第2-3个数据、2轴第3个元素。

索引操作代码示例

import torch

# 设置随机种子保证结果可复现
torch.manual_seed(666)
# 创建4行5列的浮点型张量
data = torch.randint(1, 10, size=(4, 5), dtype=torch.float32)
print("原始张量:\n", data)
print("形状:", data.shape, "维度:", data.ndim)
print("="*50)

# 1. 单独获取行列
print("第2行数据:", data[1, :])  # 等价于data[1]
print("第2列数据:", data[:, 1])  # 等价于data[..., 1]
print("(2,3)位置元素:", data[1, 2])
print("="*50)

# 2. 批量获取多行列
print("第1、3行数据:\n", data[[0, 2], :])
print("第1、3列数据:\n", data[:, [0, 2]])
print("(0,0)和(2,2)位置元素:", data[[0,2], [0,2]])
print("第1、3行与第1、3列的交集子矩阵:\n", data[[[0],[2]], [0,2]])
print("="*50)

# 3. 切片获取连续数据
print("前3行数据:\n", data[:3, :])
print("前3列数据:\n", data[:, :3])
print("前3行前3列子矩阵:\n", data[:3, :3])
print("步长为2取数据:\n", data[0::2, 0::2])  # 行和列都按步长2取
print("="*50)

# 4. 布尔索引
print("大于5的元素:", data[data>5])
print("第1行大于5的元素:", data[0][data[0]>5])
print("第1列大于5的数据所在行:\n", data[data[:,0]>5, :])

3.2.6 形状操作

核心目标:在保持张量数据不变的前提下,调整其维度结构,适配不同运算需求。

shape与reshape

  • tensor.shape:获取张量形状,与tensor.size()功能完全一致(如data.shape[0]获取行数)。
  • tensor.reshape(shape=):修改张量形状,核心要求是“修改前后元素总数一致”;支持用-1自动计算某一维度长度(如(6,)->reshape(2,-1)自动得到(2,3)),可处理连续与非连续张量。

contiguous与view

  • tensor.is_contiguous():判断张量在内存中是否连续存储。
  • tensor.contiguous():将非连续张量转换为连续张量,通过复制数据实现。
  • tensor.view(shape=):功能与reshape类似,但仅支持连续张量,非连续张量需先调用contiguous()。

squeeze与unsqueeze(降维与升维)

  • 降维(squeeze)tensor.squeeze(dim=),默认删除所有维度值为1的维度;指定dim时仅删除该维度(若其值为1)。
  • 升维(unsqueeze)tensor.unsqueeze(dim=),在指定维度插入一个值为1的维度;dim取值范围为[-当前维度数, 当前维度数](如1维张量dim可取值-2,-1,0,1)。
  • 补充:通过索引也可升维,如tensor[None, :, None]在0轴和2轴各插入一个维度。

transpose与permute(维度交换)

  • tensor.transpose(dim0, dim1):仅交换指定的两个维度(如3维张量transpose(0,1)交换0轴和1轴),交换后张量通常变为非连续。
  • tensor.permute(dims=()):支持任意维度的重新排列(如3维张量permute(2,0,1)将2轴移到最前),灵活性更高,同样可能导致非连续。

形状操作代码示例

import torch

# 1. shape与reshape
t = torch.tensor([[1,2,3],[4,5,6]])
print("原始张量:", t)
print("形状:", t.shape, "size:", t.size())
print("reshape(3,2):", t.reshape(3,2))
print("reshape(1,6):", t.reshape(1,6))
print("reshape(6,1):", t.reshape(6,1))
print("="*50)

# 2. squeeze与unsqueeze
t1 = torch.tensor([1,2,3,4,5,6])  # 形状(6)
t2 = t1.unsqueeze(dim=0)  # 形状(1,6)
t3 = t1.unsqueeze(dim=1)  # 形状(6,1)
t4 = t2.squeeze()         # 形状(6),恢复原始维度
print("升维(1,6):", t2.shape)
print("升维(6,1):", t3.shape)
print("降维后:", t4.shape)
print("="*50)

# 3. 多维张量维度交换
t5 = torch.randint(1,10, size=(2,3,4))  # 形状(2,3,4)
t6 = t5.transpose(0,2)  # 交换0轴和2轴,形状变为(4,3,2)
t7 = t5.permute(2,0,1)  # 重排维度为2,0,1,形状变为(4,2,3)
print("原始形状:", t5.shape)
print("transpose后形状:", t6.shape)
print("permute后形状:", t7.shape)

3.2.7 拼接操作

核心用于将多个结构相似的张量合并,分为“拼接(cat)”和“堆叠(stack)”两种方式,均需指定合并维度dim。

  • torch.cat([t1, t2, ...], dim=)
            核心规则:除合并维度dim外,其他维度的形状必须完全一致。
  • 效果:在dim维度上拼接,不增加新维度,dim维度的长度为各张量对应维度长度之和(如两个(2,3)张量沿dim=0拼接后为(4,3))。

torch.stack([t1, t2, ...], dim=)
        核心规则:所有输入张量的形状必须完全一致。

效果:在指定dim维度插入新维度,新维度的长度为输入张量的个数(如两个(2,3)张量沿dim=0堆叠后为(2,2,3))。

四、PyTorch框架核心模块

4.1 环境安装

pip install torch  # 基础安装,根据系统自动匹配版本
# 如需指定CUDA版本,需参考PyTorch官网命令

4.2 自动微分模块(反向传播求梯度)

自动微分(Automatic Differentiation, AD)是PyTorch的核心特性,能够自动计算函数的导数(梯度),为神经网络反向传播提供基础。核心要求:参与梯度计算的张量必须是float类型,且创建时指定requires_grad=True

核心原理

  • 梯度的作用:通过梯度反映参数变化对损失函数的影响,用于更新模型权重(w)和偏置(b),找到最优参数。
  • 参数更新公式:w1 = w0 - lr * grad(w0为旧参数,w1为新参数,lr为学习率,grad为梯度)。
  • 关键注意点:反向传播时梯度会自动累加,每次迭代前需手动清零(w.grad.zero_()),避免梯度累积影响结果。

自动微分代码示例

import torch

# 示例1:单元素张量求梯度
x = torch.tensor([2.0], requires_grad=True)  # 开启自动微分
y = x ** 3  # 定义函数y=x³
y.backward()  # 反向传播求梯度
print("x=2时y=x³的梯度:", x.grad)  # 结果tensor([12.]), 对应导数3x²=12
print("="*50)

# 示例2:多元素张量求梯度(需先将结果转为标量)
x = torch.tensor([2.0, 3.0], requires_grad=True)
y = x ** 3  # 结果为[8.0, 27.0],非标量
y.sum().backward()  # 求和转为标量后求梯度
print("x=[2,3]时y=x³的梯度:", x.grad)  # 结果tensor([12., 27.]), 对应3x²
print("="*50)

# 示例3:结合线性模型的梯度计算
x = torch.ones(2, 5)  # 输入数据(2个样本,5个特征)
y = torch.zeros(2, 3) # 真实标签(2个样本,3个类别)

# 定义可学习参数(权重w和偏置b,均开启自动微分)
w = torch.randn(5, 3, requires_grad=True, dtype=torch.float)
b = torch.randn(3, requires_grad=True, dtype=torch.float)

# 计算预测值和损失
loss_fn = torch.nn.MSELoss()  # 均方误差损失函数
z = x.matmul(w) + b  # 线性模型z=wx+b
loss = loss_fn(z, y)  # 计算损失

# 反向传播求梯度
if w.grad is not None:
    w.grad.zero_()  # 梯度清零(避免累积)
    b.grad.zero_()
loss.backward()  # 自动计算w和b的梯度

print("w的梯度:\n", w.grad)
print("b的梯度:\n", b.grad)

4.3 梯度问题:消失与爆炸

4.3.1 梯度消失(Vanishing Gradient)

深层网络中,反向传播时梯度通过链式求导不断连乘,若激活函数导数小于1(如sigmoid导数最大0.25),经过多层后梯度会趋近于0,导致浅层参数无法更新,模型训练停滞。

4.3.2 梯度爆炸(Exploding Gradient)

若权重初始化过大或激活函数导数大于1,反向传播时梯度会不断放大,导致参数更新幅度过大,模型权重异常,训练不稳定(如损失值变为NaN)。

解决思路

  • 选用合适的激活函数(如ReLU)。
  • 采用规范化的参数初始化方法(如He初始化、Xavier初始化)。
  • 使用批量归一化(BatchNorm)稳定梯度。
  • 限制梯度范围(如梯度裁剪)。

五、人工神经网络(ANN)核心技术

5.1 神经元结构与网络构成

5.1.1 单个神经元

核心构成:输入层(接收特征数据)→ 加权求和(输入与权重相乘后加偏置:z=wx+b)→ 激活函数(引入非线性:a=σ(z))→ 输出层(输出结果)。

5.1.2 多个神经元(神经网络)

由多层神经元组成,包括:输入层(接收原始数据)、隐藏层(提取特征)、输出层(输出预测结果)。层与层之间全连接(每个神经元与下一层所有神经元相连),即全连接神经网络(FCN)。

5.1.3 前向传播与反向传播

  • 前向传播:从输入层到输出层,通过加权求和和激活函数计算预测值的过程,得到模型输出与损失值。
  • 反向传播:从输出层到输入层,通过自动微分计算各层参数的梯度,利用梯度下降更新参数,最小化损失值。

5.2 激活函数(核心基础)

核心作用:为神经网络引入非线性因素,使模型能够拟合复杂的非线性关系(若缺少激活函数,多层网络与单层线性模型等价)。

常用激活函数对比

激活函数

值域

导数特性

优缺点

适用场景

Sigmoid

[0,1]

[0,0.25]

优点:输出可表示概率;缺点:梯度消失严重,无负信号

二分类任务输出层

Tanh

[-1,1]

[0,1]

优点:有负信号,梯度消失比Sigmoid慢;缺点:仍存在梯度消失

浅层网络隐藏层

ReLU

[0,+∞)

0或1

优点:梯度不消失,计算高效;缺点:存在“神经元死亡”问题

深层网络隐藏层(优先选择)

Leaky ReLU

(-∞,+∞)

α或1(α为小常数)

优点:解决ReLU的神经元死亡问题

深层网络隐藏层

Softmax

[0,1](和为1)

复杂(与交叉熵联合优化)

优点:输出可表示多分类概率分布

多分类任务输出层

5.3 7大参数初始化方法

参数初始化是为模型权重(w)和偏置(b)设置初始值,核心目标:防止梯度消失/爆炸、打破神经元对称性(使各神经元学习不同特征)。偏置b通常初始化为0。

常用初始化方法及API

  • 随机均匀初始化torch.nn.init.uniform_(param),权重在均匀分布中随机取值。
  • 随机正态分布初始化torch.nn.init.normal_(param, mean=0, std=1),权重服从正态分布。
  • 全0初始化torch.nn.init.zeros_(param),适用于偏置b,权重不建议全0(打破对称性)。
  • 全1初始化torch.nn.init.ones_(param),需谨慎使用(易导致梯度问题)。
  • 固定值初始化torch.nn.init.constant_(param, value=),权重设为指定固定值。
  • He(Kaiming)初始化
            API:kaiming_uniform_()kaiming_normal_()
  • 特点:针对ReLU及其变体设计,仅考虑输入层维度,缓解ReLU负半轴输出为0的问题。

Xavier初始化
        API:xavier_uniform_()xavier_normal_()

特点:考虑输入和输出层维度,适用于Sigmoid、Tanh等激活函数。

初始化代码示例

import torch

# 创建一个线性层(输入3维,输出5维)
linear = torch.nn.Linear(in_features=3, out_features=5, bias=True)

# 1. 随机均匀初始化
torch.nn.init.uniform_(linear.weight)
print("随机均匀初始化权重:\n", linear.weight)

# 2. 正态分布初始化(均值0,标准差0.1)
torch.nn.init.normal_(linear.weight, mean=0, std=0.1)
print("正态分布初始化权重:\n", linear.weight)

# 3. 全0初始化(偏置常用)
torch.nn.init.zeros_(linear.bias)
print("偏置全0初始化:\n", linear.bias)

# 4. He正态初始化(适用于ReLU)
torch.nn.init.kaiming_normal_(linear.weight)
print("He正态初始化权重:\n", linear.weight)

# 5. Xavier均匀初始化(适用于Sigmoid)
torch.nn.init.xavier_uniform_(linear.weight)
print("Xavier均匀初始化权重:\n", linear.weight)

5.4 损失函数(核心基础)

损失函数(代价函数)用于衡量模型预测值与真实值的差异,是参数更新的“指挥棒”——损失值越小,模型性能越好。需根据任务类型(分类/回归)选择合适的损失函数。

分类任务损失函数

1. 多分类交叉熵损失(CrossEntropyLoss)

  • 核心特性:内置Softmax激活函数,直接接收模型线性输出(logits),无需手动添加Softmax层。
  • 适用场景:多分类任务(如手写数字识别,10个类别)。
  • API:torch.nn.CrossEntropyLoss(reduction='mean')(reduction指定损失计算方式,mean为平均损失)。
import torch

# 真实标签(两种格式:热编码/类别索引)
y_true_hot = torch.tensor([[0,1,0],[0,0,1]], dtype=torch.float)  # 热编码(推荐)
y_true_idx = torch.tensor([1,2], dtype=torch.int64)  # 类别索引(直接对应热编码的1位置)

# 模型预测值(线性输出,未经过Softmax,开启自动微分)
y_pred = torch.tensor([[0.1,0.7,0.2],[0.1,0.3,0.6]], requires_grad=True, dtype=torch.float32)

# 计算损失
loss_fn = torch.nn.CrossEntropyLoss()
loss = loss_fn(y_pred, y_true_idx)  # 传入类别索引更简洁
print("多分类交叉熵损失:", loss)

2. 二分类交叉熵损失(BCELoss)

  • 核心特性:需手动在模型输出层添加Sigmoid激活函数,使预测值落在[0,1]区间。
  • 适用场景:二分类任务(如垃圾邮件识别,是/否)。
  • API:torch.nn.BCELoss(reduction='mean')
import torch

# 真实标签(0/1)
y_true = torch.tensor([0,1,0], dtype=torch.float)

# 模型预测值(经过Sigmoid,开启自动微分)
y_pred = torch.tensor([0.1,0.7,0.2], requires_grad=True, dtype=torch.float32)
y_pred_sigmoid = torch.sigmoid(y_pred)  # 手动添加Sigmoid

# 计算损失
loss_fn = torch.nn.BCELoss()
loss = loss_fn(y_pred_sigmoid, y_true)
print("二分类交叉熵损失:", loss)

回归任务损失函数

1. 平均绝对误差(MAE/L1Loss)

  • 计算方式:预测值与真实值绝对误差的平均值,公式为 :MAE = \frac{1}{n}\sum_{i=1}^{n}|y_{true,i} - y_{pred,i}|
  • 特点:对异常值鲁棒(异常值的绝对误差不会被平方放大),但在预测值与真实值相等处(0点)不可导,可能影响优化效率。
  • 适用场景:数据中存在较多异常值的回归任务(如房价预测中的极端房价样本)。
  • APItorch.nn.L1Loss(reduction='mean'),reduction可选"mean"(平均)、"sum"(求和)或"none"(返回每个样本的损失)。

2. 均方误差(MSE/L2Loss)

  • 计算方式:预测值与真实值平方误差的平均值,公式为:MSE = \frac{1}{n}\sum_{i=1}^{n}(y_{true,i} - y_{pred,i})^2
  • 特点:对异常值敏感(异常值的误差会被平方放大),但处处可导,优化过程更平滑,是回归任务最常用的损失函数。
  • 适用场景:数据分布相对均匀、异常值较少的回归任务(如气温预测、销售额预测)。
  • APItorch.nn.MSELoss(reduction='mean'),参数与L1Loss一致。

3. HuberLoss(鲁棒损失函数)

  • 核心特性:结合MAE和MSE的优势,通过超参数δ控制损失形式,是“鲁棒性”与“可导性”的折中方案。
  • 分段损失形式
      当误差绝对值 ≤ δ时:采用MSE,公式为:\frac{1}{2}(y_{true} - y_{pred})^2,保证可导性。
  • 当误差绝对值 > δ时:采用MAE的变形,公式为\delta|y_{true} - y_{pred}| - \frac{1}{2}\delta^2
  • ,降低异常值影响。
  • 适用场景:既需要平滑优化,又存在少量异常值的回归任务,δ通常取1.0(可根据数据调整)。

5.5 优化器:学习率与参数更新的核心(核心基础)

优化器的核心作用是根据损失函数的梯度,按照特定策略更新模型参数(w和b),最小化损失值。其核心参数是学习率(lr)——控制参数更新的步长,lr过大易导致参数震荡不收敛,lr过小则训练速度极慢。

5.5.1 优化器分类与核心原理

1. 基础优化器:SGD及其改进

  • 随机梯度下降(SGD)
      核心思想:每次使用一个批次(batch)的样本计算梯度,更新公式为w = w - lr \times \nabla L(w)(∇L(w)为损失对w的梯度)。
  • 特点:计算量小、内存占用低,但梯度噪声大,参数更新路径震荡明显,可能陷入局部最优。
  • 适用场景:数据量极大、对训练速度要求高的场景。
  • APItorch.optim.SGD(params=[w, b], lr=0.01)
  • SGD+动量(Momentum)
      核心思想:模拟物理“动量”概念,累加历史梯度的指数加权平均,降低更新震荡,公式为v_t = \gamma \times v_{t-1} + lr \times \nabla L(w)w = w - v_t(γ为动量系数,通常取0.9)。
  • 特点:加速收敛(沿梯度一致方向加速),抑制震荡,避免局部最优。
  • APItorch.optim.SGD(params=[w, b], lr=0.01, momentum=0.9)

2. 自适应学习率优化器(主流选择)

  • Adagrad(自适应梯度)
      核心思想:为不同参数分配不同学习率——参数梯度大则学习率小,梯度小则学习率大,公式为 w = w - \frac{lr}{\sqrt{\sum_{t=1}^{T}(\nabla L(w_t))^2 + \varepsilon}} \times \nabla L(w),(\varepsilon为防止分母为0的小常数)。
  • 特点:无需手动调整lr,初始学习率大、后期小;但历史梯度累加导致学习率过早衰减,训练后期可能停滞。
  • 适用场景:高维稀疏数据(如文本分类、推荐系统)。
  • APItorch.optim.Adagrad(params=[w, b], lr=0.01)
  • RMSprop(均方根传播)
      核心思想:改进Adagrad,用“历史梯度的指数加权平均”替代“累加和”,缓解学习率衰减过快问题,公式为

        E[g^2]_t = \alpha \times E[g^2]_{t-1} + (1-\alpha) \times (\nabla L(w))^2

        w = w - \frac{lr}{\sqrt{E[g^2]_t + \varepsilon}} \times \nabla L(w)(α通常取0.99)。

  • 特点:保持自适应特性,训练稳定性优于Adagrad。
  • 适用场景:高维稀疏数据、循环神经网络(RNN)。
  • APItorch.optim.RMSprop(params=[w, b], lr=0.01, alpha=0.99)
  • Adam(自适应动量估计)
      核心思想:融合“动量法”和“RMSprop”,同时考虑梯度的一阶矩(均值,对应动量)和二阶矩(方差,对应自适应学习率),是目前最常用的优化器。
  • 特点:收敛快、稳定性好,无需手动调参,适用于绝大多数场景。
  • APItorch.optim.Adam(params=[w, b], lr=0.01, betas=(0.9, 0.99))(betas分别为一阶矩和二阶矩的系数)。
  • AdamW(Adam改进版)
      核心思想:解耦Adam中的权重衰减(L2正则化)与自适应学习率,避免正则化效果被学习率稀释,公式为在Adam更新基础上单独添加权重衰减项w = w - lr \times (g_t + \lambda \times w)(λ为权重衰减系数)。
  • 特点:泛化能力优于Adam,是大模型训练的默认优化器(如BERT、GPT系列)。
  • APItorch.optim.AdamW(params=[w, b], lr=0.01, weight_decay=1e-4)

3. 学习率调整策略(手动干预)

当使用固定学习率的优化器时,可通过调度器(Scheduler)手动调整lr,核心思路是“前期大lr加速收敛,后期小lr精细优化”。

  • 等间隔衰减(StepLR)
      规则:每训练step_size个epoch,学习率乘以gamma衰减,公式为lr = lr \times \gamma
  • APItorch.optim.lr_scheduler.StepLR(optimizer, step_size=50, gamma=0.5)(每50轮lr减半)。
  • 指定间隔衰减(MultiStepLR)
      规则:在预设的milestones(如[50, 100, 160])轮次处,lr乘以gamma衰减,灵活性更高。
  • APItorch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=[50,100], gamma=0.5)
  • 指数衰减(ExponentialLR)
      规则:每轮epoch都按指数衰减,公式为lr = lr \times gamma^{epoch},前期衰减快,后期衰减慢。
  • APItorch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.9)

5.5.2 优化器使用流程代码示例

import torch

# 1. 定义可学习参数
w = torch.tensor([1.0], requires_grad=True, dtype=torch.float32)
b = torch.tensor([0.5], requires_grad=True, dtype=torch.float32)

# 2. 选择优化器(以AdamW为例)
optimizer = torch.optim.AdamW(params=[w, b], lr=0.01, weight_decay=1e-4)

# 3. 定义学习率调度器(StepLR)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.8)

# 4. 模拟训练循环
for epoch in range(20):
    # 前向传播:假设简单线性模型 y = w*x + b,x=2,真实值y_true=5
    x = torch.tensor([2.0])
    y_pred = w * x + b
    loss = torch.nn.MSELoss()(y_pred, torch.tensor([5.0]))  # MSE损失
    
    # 反向传播与参数更新
    optimizer.zero_grad()  # 梯度清零(必须!防止累积)
    loss.backward()        # 计算梯度
    optimizer.step()       # 更新参数
    scheduler.step()       # 调整学习率
    
    # 打印日志
    current_lr = optimizer.param_groups[0]['lr']
    print(f"Epoch {epoch+1:2d} | Loss: {loss.item():.4f} | LR: {current_lr:.6f} | w: {w.item():.4f} | b: {b.item():.4f}")

5.6 正则化:解决过拟合的核心技术

过拟合是模型在训练集上表现极好,但在测试集上性能骤降的问题,核心原因是模型复杂度过高、学习了训练集的噪声。正则化通过在损失函数中添加“模型复杂度罚项”或引入随机机制,限制模型拟合能力,提升泛化性。

5.6.1 范数正则化(L1、L2)

核心思想:在原始损失函数基础上增加“权重范数”罚项,目标函数为 \( 目标函数 = 原始损失 + λ \times 正则化项 \)(λ为正则化强度,控制罚项权重)。

  • L1正则化(L1 Norm)
      数学形式:正则化项为权重的绝对值之和,即 \( L1 = \sum_{i}|w_i| \)。
  • 核心作用:将部分权重压缩至0,产生“稀疏解”——忽略不重要的特征,实现特征选择。
  • 特点:特征筛选能力强,但损失函数在权重为0处不可导,优化难度略高。
  • L2正则化(L2 Norm/权重衰减)
      数学形式:正则化项为权重的平方和,即 \( L2 = \sum_{i}w_i^2 \)。
  • 核心作用:将权重均匀缩小但不置零,避免个别权重过大导致模型过拟合。
  • 特点:损失函数可导,优化稳定,是工业界最常用的正则化方式(PyTorch中通过weight_decay参数实现)。

5.6.2 随机失活正则化(Dropout)

  • 核心思想:训练时以概率p随机“关闭”部分神经元,使模型仅用剩余神经元学习特征,避免过度依赖某几个神经元。
  • 关键机制
      训练时:失活神经元输出设为0,未失活神经元输出需除以(1-p),保证输入数据的期望不变。
  • 测试时:关闭Dropout,所有神经元正常工作,无需调整输出。
  • 注意事项:需通过model.train()(训练模式)和model.eval()(测试模式)切换Dropout状态。
  • API与代码示例
      
    import torch
    
    # 1. 定义含Dropout的模型
    class Net(torch.nn.Module):
        def __init__(self):
            super(Net, self).__init__()
            self.linear1 = torch.nn.Linear(4, 5)  # 输入4维,隐藏层5维
            self.dropout = torch.nn.Dropout(p=0.5)  # 失活概率0.5
            self.linear2 = torch.nn.Linear(5, 1)   # 输出1维(回归任务)
        
        def forward(self, x):
            x = torch.relu(self.linear1(x))  # 线性层→激活函数
            x = self.dropout(x)              # 激活后使用Dropout(必须!)
            x = self.linear2(x)
            return x
    
    # 2. 测试Dropout效果
    model = Net()
    x = torch.randn(1, 4)  # 输入数据(1个样本,4个特征)
    
    # 训练模式:Dropout生效
    model.train()
    print("训练模式Dropout输出(每次不同):", model(x).detach())
    print("训练模式Dropout输出(再次运行):", model(x).detach())
    
    # 测试模式:Dropout关闭
    model.eval()
    print("测试模式输出(固定):", model(x).detach())

5.6.3 批量归一化(BatchNorm/BN)

BN是计算机视觉领域的常用正则化技术,核心目标是解决“内部协变量偏移(ICS)”——网络训练中各层输入分布随参数更新而变化的问题。

  • 核心原理:对每一层的输入进行标准化,使其均值为0、方差为1,再通过可学习参数γ(缩放)和β(偏移)恢复特征表达能力,公式为:
      计算批次均值:\mu_B = \frac{1}{m}\sum_{i=1}^{m}x_i
  • 计算批次方差:\sigma_B^2 = \frac{1}{m}\sum_{i=1}^{m}(x_i - \mu_B)^2
  • 标准化:\hat{x}_i = \frac{x_i - \mu_B}{\sqrt{\sigma_B^2 + \varepsilon}}
  • 缩放偏移:y_i = \gamma \times \hat{x}_i + \beta
  • 核心作用
      正则化:批次间的均值/方差差异引入轻微噪声,降低过拟合风险。
  • 加速收敛:输入分布稳定,使激活函数(如Sigmoid)避免陷入梯度饱和区。
  • 注意事项
      使用位置:线性层/卷积层之后、激活函数之前。
  • 模式切换:训练时用批次统计,测试时用全局统计(通过model.eval()切换)。
  • API选择:根据输入维度选择BatchNorm1d(1维数据,如文本)、BatchNorm2d(2维数据,如图像)、BatchNorm3d(3维数据,如视频)。
  • 代码示例
    import torch
    
    # 定义含BatchNorm的模型(图像分类场景,用BatchNorm2d)
    class CNNNet(torch.nn.Module):
        def __init__(self):
            super(CNNNet, self).__init__()
            self.conv1 = torch.nn.Conv2d(3, 16, kernel_size=3)  # 输入3通道,输出16通道
            self.bn1 = torch.nn.BatchNorm2d(16)  # 对应卷积层输出通道数
            self.relu = torch.nn.ReLU()
            self.fc = torch.nn.Linear(16*28*28, 10)  # 假设输入图像28×28
        
        def forward(self, x):
            x = self.conv1(x)       # 卷积层:(batch,3,32,32)→(batch,16,30,30)
            x = self.bn1(x)         # BN层:在卷积后、激活前
            x = self.relu(x)
            x = x.view(x.size(0), -1)  # 展平:(batch,16,30,30)→(batch,16*30*30)
            x = self.fc(x)
            return x
    
    # 测试BN效果
    model = CNNNet()
    x = torch.randn(2, 3, 32, 32)  # 输入:2个样本,3通道,32×32图像
    model.train()  # 训练模式
    print("BN输出形状:", model(x).shape)  # 输出:(2,10)(2个样本,10分类)

六、综合案例:手机价格分类任务

本案例基于2000条电脑样本数据(20个特征,4类价格标签),实现从数据处理到模型训练、评估的完整流程,融合前文所学的正则化、优化器、损失函数等核心技术。

6.1 任务需求

  • 任务类型:多分类任务(标签为0-3,对应4个价格区间)。
  • 数据规模:2000条样本,划分训练集1600条、测试集400条。
  • 核心目标:构建神经网络模型,实现电脑价格的精准分类,验证正则化与优化器的效果。

6.2 实现步骤

6.2.1 环境准备与数据加载

import torch
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 1. 加载数据(假设数据为csv格式,列名:feature_0~feature_19, price_label)
data = pd.read_csv("phone_price_data.csv")
X = data.iloc[:, :-1].values  # 特征:前20列
y = data.iloc[:, -1].values   # 标签:最后1列

# 2. 数据预处理:标准化(提升模型收敛速度)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 3. 划分训练集与测试集(随机种子保证可复现)
X_train, X_test, y_train, y_test = train_test_split(
    X_scaled, y, test_size=0.2, random_state=666
)

# 4. 转换为PyTorch张量
X_train = torch.tensor(X_train, dtype=torch.float32)
X_test = torch.tensor(X_test, dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.int64)  # 多分类标签用int64
y_test = torch.tensor(y_test, dtype=torch.int64)

# 5. 构建数据集与数据加载器(批量训练)
train_dataset = torch.utils.data.TensorDataset(X_train, y_train)
test_dataset = torch.utils.data.TensorDataset(X_test, y_test)

train_loader = torch.utils.data.DataLoader(
    train_dataset, batch_size=32, shuffle=True  # 训练集打乱
)
test_loader = torch.utils.data.DataLoader(
    test_dataset, batch_size=32, shuffle=False  # 测试集不打乱
)

6.2.2 构建正则化神经网络模型

class PhonePriceNet(torch.nn.Module):
    def __init__(self):
        super(PhonePriceNet, self).__init__()
        # 网络结构:输入层(20)→隐藏层1(64)→BN→Dropout→隐藏层2(32)→输出层(4)
        self.fc1 = torch.nn.Linear(20, 64)
        self.bn1 = torch.nn.BatchNorm1d(64)  # 1维BN,对应隐藏层输出维度
        self.dropout = torch.nn.Dropout(p=0.3)  # 失活概率0.3
        self.fc2 = torch.nn.Linear(64, 32)
        self.fc3 = torch.nn.Linear(32, 4)  # 输出4类,对应价格标签0-3
    
    def forward(self, x):
        # 前向传播:线性层→BN→激活→Dropout
        x = self.fc1(x)
        x = self.bn1(x)
        x = torch.relu(x)
        x = self.dropout(x)
        
        x = self.fc2(x)
        x = torch.relu(x)
        
        x = self.fc3(x)  # 输出logits,CrossEntropyLoss会自动加Softmax
        return x

# 初始化模型
model = PhonePriceNet()

6.2.3 配置训练组件(损失函数、优化器)

# 1. 损失函数:多分类交叉熵(内置Softmax)
loss_fn = torch.nn.CrossEntropyLoss()

# 2. 优化器:AdamW(含L2正则化,weight_decay=1e-4)
optimizer = torch.optim.AdamW(
    model.parameters(), lr=0.001, weight_decay=1e-4
)

# 3. 学习率调度器:每10轮衰减为原来的0.8
scheduler = torch.optim.lr_scheduler.StepLR(
    optimizer, step_size=10, gamma=0.8
)

6.2.4 模型训练与日志记录

def train_model(model, train_loader, loss_fn, optimizer, scheduler, epochs=50):
    model.train()  # 切换训练模式(BN、Dropout生效)
    best_acc = 0.0  # 记录最佳准确率
    
    for epoch in range(epochs):
        total_loss = 0.0
        correct = 0
        total = 0
        
        # 遍历训练集批次
        for X_batch, y_batch in train_loader:
            # 前向传播
            y_pred = model(X_batch)
            loss = loss_fn(y_pred, y_batch)
            
            # 反向传播与参数更新
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            
            # 统计损失与准确率
            total_loss += loss.item() * X_batch.size(0)
            _, predicted = torch.max(y_pred, dim=1)  # 获取预测类别(argmax)
            correct += (predicted == y_batch).sum().item()
            total += y_batch.size(0)
        
        # 调整学习率
        scheduler.step()
        
        # 计算本轮指标
        epoch_loss = total_loss / total
        epoch_acc = correct / total * 100
        
        # 保存最佳模型(基于训练准确率)
        if epoch_acc > best_acc:
            best_acc = epoch_acc
            torch.save(model.state_dict(), "best_phone_price_model.pth")
        
        # 打印日志
        print(f"Epoch {epoch+1:2d}/{epochs} | Loss: {epoch_loss:.4f} | Acc: {epoch_acc:.2f}% | Best Acc: {best_acc:.2f}%")

# 启动训练
train_model(model, train_loader, loss_fn, optimizer, scheduler, epochs=50)

6.2.5 模型评估与泛化能力验证

def evaluate_model(model, test_loader, loss_fn):
    model.eval()  # 切换测试模式(BN、Dropout关闭)
    total_loss = 0.0
    correct = 0
    total = 0
    
    # 禁用梯度计算(节省内存,加速评估)
    with torch.no_grad():
        for X_batch, y_batch in test_loader:
            y_pred = model(X_batch)
            loss = loss_fn(y_pred, y_batch)
            
            # 统计指标
            total_loss += loss.item() * X_batch.size(0)
            _, predicted = torch.max(y_pred, dim=1)
            correct += (predicted == y_batch).sum().item()
            total += y_batch.size(0)
    
    # 计算评估指标
    avg_loss = total_loss / total
    acc = correct / total * 100
    print(f"\n测试集评估结果:")
    print(f"平均损失:{avg_loss:.4f} | 准确率:{acc:.2f}%")
    return acc

# 加载最佳模型参数
model.load_state_dict(torch.load("best_phone_price_model.pth"))

# 评估模型
test_acc = evaluate_model(model, test_loader, loss_fn)

6.3 案例关键说明

  • 数据预处理:标准化(StandardScaler)消除特征量纲影响,是神经网络训练的必要步骤。
  • 正则化融合:模型同时使用BN、Dropout和L2正则化(AdamW的weight_decay),多维度抑制过拟合。
  • 模型保存:仅保存验证集准确率最高的模型参数,避免保存训练后期过拟合的模型。
  • 评估优化:使用torch.no_grad()禁用梯度计算,大幅提升评估速度并减少内存占用。

七、核心知识点总结

7.1 技术选型速查表

任务场景

推荐技术

PyTorch API

二分类任务

BCELoss + Sigmoid + AdamW

nn.BCELoss(), torch.sigmoid(), optim.AdamW()

多分类任务

CrossEntropyLoss + AdamW

nn.CrossEntropyLoss(), optim.AdamW()

回归任务(无异常值)

MSELoss + AdamW

nn.MSELoss(), optim.AdamW()

回归任务(有异常值)

MAE/HuberLoss + AdamW

nn.L1Loss(), optim.AdamW()

抑制过拟合(通用)

Dropout + L2正则化

nn.Dropout(), optim.AdamW(weight_decay=1e-4)

计算机视觉任务

BatchNorm2d + CNN + AdamW

nn.BatchNorm2d(), nn.Conv2d()

7.2 常见问题与解决方案

  • 梯度消失:使用ReLU激活函数、He初始化、BatchNorm。
  • 梯度爆炸:使用梯度裁剪(torch.nn.utils.clip_grad_norm_)、Xavier初始化。
  • 过拟合:增加数据量、增强正则化(提高Dropout概率、增大weight_decay)、简化模型结构。
  • 训练不收敛:调整学习率(增大/减小)、检查数据预处理(是否标准化)、检查标签格式(多分类标签是否为int64)。

本总结涵盖深度学习基础理论、PyTorch核心操作及实战案例,可作为入门到进阶的学习指南,实际应用中需根据具体任务调整技术选型与超参数。

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值