动手学深度学习

本文最后更新于:2025年3月21日 凌晨

参考知名教程《动手学深度学习》,系统学一下~

杂七杂八

Linux的系统盘和数据盘

由于博主的电脑配置太辣鸡,所以选择在autodl租用显卡进行相关学习。公共资源需要靠抢,所以常常需要复制镜像,每次都随机抢不同的显卡……

  • 镜像保存了Linux除了数据盘以外的所有数据;
    • 数据盘的内容需要拷贝,只能在同一地区的显卡上拷贝数据。
  • Linux数据盘和系统盘的查看
    • 系统盘如同Windows的C盘。 使用df -lh查看,根路径下的都属于系统盘。
    • 如果单独有数据盘,且数据盘没有分区和挂载,使用df -l命令是看不到的。可以使用fdisk -l,可以看到有哪些硬盘。

环境配置

配置一个环境来运行 Python、Jupyter Notebook、相关库以及运行本书所需的代码,以快速入门并获得动手学习经验。

安装Miniconda

Miniconda 是一个轻量级的 Conda 发行版,主要用于管理 Python 环境和软件包。简而言之,Miniconda 的作用是管理 Python 版本和依赖,比如你电脑中运行了多个项目,这些项目需要不同的 Python 版本和库,就可以用 Miniconda 创建独立的虚拟环境,避免相互干扰。

Linux 系统中安装和部署 Miniconda 的详细教程

检查pytorch是否安装成功、查看torch和cuda的版本

预备知识

数据操作

PyTorch:一个开源的深度学习框架,支持GPU加速计算和动态计算图

核心组件:

  • torch.Tensor:支持梯度追踪的多维数组。
  • torch.nn:神经网络层和损失函数。
  • torch.optim:优化算法(如SGD、Adam)。

导入torch。请注意,虽然它被称为PyTorch,但是代码中使用torch而不是pytorch。

1
import torch

张量

张量表示一个由数值组成的数组,这个数组可能有多个维度。 具有一个轴的张量对应数学上的向量(vector); 具有两个轴的张量对应数学上的矩阵(matrix); 具有两个轴以上的张量没有特殊的数学名称。

  • 张量中的每个值都称为张量的元素(element)。
  • 除非额外指定,新的张量将存储在内存中,并采用基于CPU的计算。
  • 使用 arange 创建一个行向量 x。这个行向量包含以0开始的前12个整数,它们默认创建为整数。也可指定创建类型为浮点数。
    • 可以通过张量的shape属性来访问张量(沿每个轴的长度)的形状 。如果只想知道张量中元素的总数,即形状的所有元素乘积,可以检查它的大小(size)。
    • 改变一个张量的形状而不改变元素数量和元素值,可以调用reshape函数。注意,通过改变张量的形状,张量的大小不会改变。
      • 例如,可以把张量x从形状为(12,)的行向量转换为形状为(3,4)的矩阵。 这个新的张量包含与转换前相同的值,但是它被看成一个3行4列的矩阵。 要重点说明一下,虽然张量的形状发生了改变,但其元素值并没有变。
      • 通过-1来调用此自动计算出维度的功能。即我们可以用x.reshape(-1,4)x.reshape(3,-1)来取代x.reshape(3,4)
    • 使用全0、全1、其他常量,或者从特定分布中随机采样的数字来初始化矩阵。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      x = torch.arange(12)
      x.shape
      x.numel()
      X = x.reshape(3, 4)
      torch.zeros((2, 3, 4)) # 创建一个形状为(2,3,4)的张量,其中所有元素都设置为0
      torch.ones((2, 3, 4))
      torch.randn(3, 4) # 随机初始化参数的值,每个元素都从均值为0、标准差为1的标准高斯分布(正态分布)中随机采样。
      torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]) # 通过提供包含数值的Python列表(或嵌套列表),来为所需张量中的每个元素赋予确定值。
      print(X) # 打印输出X的值

独热编码(One-Hot Encoding)

定义:用二进制向量表示离散类别。又称为一位有效编码,主要是采用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效。
例如:

  • 类别1 → [1, 0, 0]
  • 类别2 → [0, 1, 0]
  • 类别3 → [0, 0, 1]

作用:将分类标签转换为模型可处理的数值形式。具体参考:

机器学习:数据预处理之独热编码(One-Hot)详解

  • 标签(Label):真实答案,此处表示样本属于第一个类别。
    1
    target = torch.tensor([1.0, 0.0, 0.0])  # 独热编码

交叉熵损失 (Cross-Entropy Loss)

衡量预测概率分布与真实分布的差异。

1
loss = -torch.sum(target * torch.log(prob))

计算过程:

  • target * torch.log(prob) → 仅保留真实类别对应的概率对数。
  • -sum(…) → 取负数得到损失值(越小表示预测越准)。

反式传播

  • 原理:通过链式法则自动计算损失对参数的梯度,只需调用backward()。
    1
    2
    loss.backward()
    print("梯度:", x.grad) # 输出如 [-0.3410, 0.2424, 0.0986]
  • 步骤:
    • 从loss开始,反向遍历计算图。
    • 计算每个参与运算的张量的梯度。
  • 结果:梯度存储在x.grad中。

梯度

  • 意义:表示损失函数对x各元素的敏感度。
    • 例如:输出 [-0.3410, 0.2424, 0.0986]
      • 负梯度(如-0.3410)→ 增大x[0]可减少损失,概率越接近1,损失越小
      • 正梯度(如0.2424)→ 减小x[1]可减少损失。
  • 应用:通过优化器(如SGD)更新参数:x = x - 学习率 * x.grad
  • 梯度下降的直观理解
    将损失函数想象为一座山,目标是找到山谷最低点(最小损失):
    • 梯度:指向当前所在位置最陡的上坡方向。
    • 负梯度方向:下山最快的方向。
    • 学习率:决定每一步迈多大。
      • 步子太小 → 下山慢。
      • 步子太大 → 可能跨过山谷或摔倒(发散)。

优化器

随机梯度下降(SGD)的参数更新公式为:

$$\theta_{t+1} = \theta_t - \eta \cdot \nabla_\theta J(\theta_t)$$

其中,$\theta$ 是模型参数,$\eta$ 是学习率,$\nabla_\theta J(\theta_t)$是损失函数对参数的梯度。

1
torch.optim.SGD(params, lr=0.1)
  • 学习率($\eta$)的作用
    • 过小,如 $\eta = 0.001$ :更新步长小,收敛速度慢。
    • 过大,如 $\eta = 1.0$ :可能跳过最优解,甚至发散。
    • 合理选择:通常通过实验调整
优化器 适用场景 核心特点 常见应用领域
SGD 简单模型/凸优化问题 基础更新,收敛稳定但需手动调学习率 线性回归/简单分类任务
Momentum 高维非凸优化场景 引入动量项加速收敛,减少参数更新振荡 计算机视觉/复杂网络结构
Adagrad 稀疏数据特征处理 自适应调整学习率,对低频特征更敏感,内存消耗较大 NLP词向量训练
RMSprop 非平稳目标/循环网络 改进Adagrad的学习率衰减问题,采用指数移动平均 RNN/LSTM训练
Adam 通用深度学习任务(默认首选) 结合动量+自适应学习率,收敛速度快,超参数鲁棒性好 CNN/GAN/大多数深度学习模型
AdamW 需要精细权重衰减的任务 解耦权重衰减项,解决Adam中权重衰减与梯度更新耦合的问题 Transformer/BERT系列模型

运算符

按元素(elementwise)运算。

  • 它们将标准标量运算符应用于数组的每个元素。 对于将两个数组作为输入的函数,按元素运算将二元运算符应用于两个数组中的每对位置对应的元素。 我们可以基于任何从标量到标量的函数来创建按元素函数。
    1
    2
    3
    4
    x = torch.tensor([1.0, 2, 4, 8])
    y = torch.tensor([2, 2, 2, 2])
    x + y, x - y, x * y, x / y, x ** y # **运算符是求幂(y次方)
    torch.exp(x) # 计算输入张量 x 中每个元素的指数函数值(即自然常数 e 的对应元素次方)

torch.exp()函数的应用场景

  • Softmax函数:用于将神经网络的输出转换为概率分布(所有值在0~1之间,且和为1):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import torch

    # 定义输入(假设是神经网络的原始输出)
    x = torch.tensor([2.0, 1.0, 0.1]) # 原始分数

    # 数值稳定的Softmax实现
    def softmax(x):
    # 1. 减去最大值,避免指数爆炸(数值稳定性技巧)
    max_x = torch.max(x)
    shifted_x = x - max_x

    # 2. 计算指数
    exp_x = torch.exp(shifted_x)

    # 3. 计算概率分布
    sum_exp = torch.sum(exp_x)
    probabilities = exp_x / sum_exp

    return probabilities

    # 调用函数
    prob = softmax(x)
    print("Softmax结果:", prob) # 输出如 [0.6590, 0.2424, 0.0986],每个值表示对应类别的概率,总和为1。

  • 激活函数:如高斯误差线性单元(GELU):

    • GELU是一种平滑的激活函数,常用于Transformer模型(如BERT)。GELU近似于用概率门控机制决定是否激活神经元,公式为(0.044715为经验系数):

    $$\text{GELU}(x) = 0.5x \left( 1 + \tanh\left( \sqrt{\frac{2}{\pi}} \left( x + 0.044715x^3 \right) \right) \right)$$

    • GELU vs ReLU:
      • ReLU:当输入>0时输出原值,否则输出0(不光滑)。
      • GELU:通过双曲正切函数(tanh)实现平滑过渡,更适合复杂模型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import torch

# 定义GELU函数
def gelu(x):
# 数学公式中的常数项
sqrt_2_over_pi = torch.sqrt(torch.tensor(2.0 / torch.pi)) # √(2/π)
alpha = 0.044715 # 经验系数

# 计算GELU的核心部分
inner = x + alpha * x**3
scaled_inner = sqrt_2_over_pi * inner
tanh_output = torch.tanh(scaled_inner)

# 最终结果
return 0.5 * x * (1 + tanh_output)

# 示例输入
x = torch.tensor([1.0, -1.0, 0.5])
output = gelu(x)
print("GELU输出:", output) # 输出如 [0.8413, -0.1587, 0.3457]
  • 如果 x 是需计算梯度的张量(requires_grad=True),torch.exp(x) 的梯度会自动计算,用于反向传播更新权重。
    • 梯度是函数在某一点的导数,表示该点对输出的影响程度。
    • 在训练神经网络时,梯度告诉我们应该如何调整参数(如 x)以减少误差。例如,如果梯度为7.3891,说明 x 增加1,y 会增加约7.3891。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
import torch

# 创建一个需要计算梯度的张量
x = torch.tensor(2.0, requires_grad=True) # requires_grad=True表示跟踪梯度

# 定义计算过程
y = torch.exp(x) # 计算 y = e^x

# 反向传播计算梯度
y.backward() # 自动计算 dy/dx

# 查看梯度
print("梯度值:", x.grad) # 输出 tensor(7.3891),即 e^2 ≈ 7.3891

一些语法解释

  1. x - max_x这样的操作默认会对张量(矩阵)中的每个元素进行运算,但具体行为取决于max_x的维度。
  • 假设x是一个矩阵,而max_x是通过torch.max(x)得到的全局最大值标量,此时x - max_x会对x中的每个元素都减去这个标量值。
  • 如果max_x是通过指定维度(如dim=1)计算得到的向量,PyTorch会通过广播机制自动对齐维度,确保逐元素减法正确执行。
    • 在按维度计算最大值时,keepdim=True会保留原始维度信息,确保广播正确。
      1
      2
      3
      4
      5
      6
      7
      8
      x = torch.tensor([[3.0, 5.0], 
      [2.0, 4.0]])

      max_x = torch.max(x, dim=1, keepdim=True).values # max_x是按行(dim=1)计算的最大值,形状为(2, 1)。
      print(max_x) # 输出 tensor([[5.0], [4.0]])

      shifted_x = x - max_x
      print(shifted_x)
      广播规则下,max_x会被扩展为与x同形状,最终每个元素减去对应行的最大值。

综合示例 (结合Softmax、梯度与优化器)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import torch

def softmax(x):
max_x = torch.max(x)
shifted_x = x - max_x
exp_x = torch.exp(shifted_x)
return exp_x / exp_x.sum() # 归一化:除以总和,得到概率。

# 创建一个需要梯度的张量, requires_grad=True:允许自动计算该张量的梯度,用于后续反向传播。
x = torch.tensor([3.0, 1.0, 0.2], requires_grad=True)

# 定义优化器(以SGD为例)
# lr=0.1:学习率,控制参数更新步长
# [x]:待优化的参数列表
optimizer = torch.optim.SGD([x], lr=0.1) # 将x传入优化器

# 假设真实标签是第一个类别
target = torch.tensor([1.0, 0.0, 0.0])

# 计算Softmax概率
prob = softmax(x) # 使用之前定义的softmax函数

# 假设真实标签是第一个类别(概率应接近1)
target = torch.tensor([1.0, 0.0, 0.0]) # 独热编码

# 模拟多次训练迭代
for epoch in range(3): # 假设训练3
# 清零梯度(重要!避免梯度累积)
optimizer.zero_grad()

# 前向传播
prob = softmax(x)
loss = -torch.sum(target * torch.log(prob))

# 反向传播
loss.backward()

# 更新参数(关键步骤)
optimizer.step()

# 打印结果
print(f"Epoch {epoch+1}:")
print(f"x = {x.detach().numpy().round(4)}") # 更新后的参数值,始终遵循 detach() → numpy() 的转换顺序。
print(f"loss = {loss.item():.4f}\n")

注意:

  • PyTorch默认会累积梯度(例如在RNN中可能需要)。在每次迭代前必须手动清零梯度,否则梯度会不断累加,导致更新错误。
  • 参数更新:根据优化器规则(如SGD)和当前梯度更新参数。
    1
    optimizer.step()
  • 若使用其他优化器(如Adam),只需修改定义:
    • 不同优化器需调整学习率(如Adam常用 lr=0.001)。
      1
      2
      # 替换SGD为Adam
      optimizer = torch.optim.Adam([x], lr=0.01)
  • f"...":格式化字符串,指在字符串中直接嵌入变量或表达式。
  • x.detach():分离计算图
    • 作用:将张量 x 从当前计算图中分离,返回一个不关联梯度的新张量
    • 必要性:
      • PyTorch张量若参与过梯度计算(如 requires_grad=True),直接操作可能引发错误。
      • detach() 切断与计算图的联系,避免不必要的梯度追踪。
  • .numpy():转换为NumPy数组
    • 作用:将PyTorch张量转换为NumPy数组。
    • 要求:
      • 张量必须位于CPU上(若在GPU需先 .cpu())。
      • 张量不能关联梯度(需先 .detach()
    • 为何不直接打印x?
      • PyTorch张量直接打印会显示梯度信息、设备位置(如GPU)等冗余内容,转换为NumPy数组后更简洁。
  • .round(4):数值四舍五入到指定小数位(此处保留4位)。

广播机制

当对两个形状不同的张量进行按元素操作(如加减乘除)时,PyTorch会自动触发广播机制,尝试将张量扩展为兼容的形状以完成运算。

示例:

  • 向量 + 标量
    1
    2
    3
    4
    5
    6
    7
    8
    import torch

    a = torch.tensor([1, 2, 3]) # 形状 (3,)
    b = torch.tensor(10) # 形状 () → 标量

    # PyTorch自动将b广播为[10, 10, 10],然后相加
    c = a + b
    print(c) # 输出 tensor([11, 12, 13])
  • 矩阵 + 向量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    a = torch.tensor([[1], [2], [3]])  # 形状 (3, 1)
    b = torch.tensor([10, 20, 30]) # 形状 (3,)

    # PyTorch将a扩展为 (3,3),b扩展为 (3,3):
    # a → [[1, 1, 1],
    # [2, 2, 2],
    # [3, 3, 3]]
    # b → [[10, 20, 30],
    # [10, 20, 30],
    # [10, 20, 30]]
    c = a + b
    print(c)
    # 输出:
    # tensor([[11, 21, 31],
    # [12, 22, 32],
    # [13, 23, 33]])

索引和切片

张量中的元素可以通过索引访问。第一个元素的索引是0,最后一个元素索引是-1。

基本语法:X[start:end]

  • start:起始索引(包含该位置的元素)
  • end:结束索引(不包含该位置的元素)
  • 范围:[start, end),即左闭右开区间。
1
2
3
X[-1]       # 选择最后一个元素

X[1:3] # 选择第二个和第三个元素

指定索引赋值

  • 指定单个元素
    1
    X[1, 2] = 9
  • 为多个元素赋值相同的值
    示例:
    [0:2, :]访问第1行和第2行,其中“:”代表沿轴1(列)的所有元素。
    1
    X[0:2, :] = 12

执行原地操作节省内存

使用切片表示法将操作的结果分配给先前分配的数组。

  • 使用X[:] = X + Y或X += Y来减少操作的内存开销。

将张量转换为其他Python对象

  • 转换为Python标量:.item()

    • 仅限单元素张量
  • 转换为NumPy数组:.detach().numpy()

    • NumPy数组与原始张量共享内存,修改一方会影响另一方
  • 转换为Python列表:.tolist()

完整的深度学习项目框架

之前的示例代码仅展示了深度学习流程中的核心片段(前向传播、损失计算、反向传播与参数更新)。

一个完整的深度学习项目包括:

  • 数据准备
    • 数据加载:从文件(CSV、图像等)或数据库读取原始数据。
    • 数据预处理:标准化、归一化、数据增强(图像旋转/翻转)。
    • 数据划分:分为训练集、验证集、测试集。
  • 模型定义
    • 结构化模型类:使用 nn.Module 定义网络结构。
    • 设备选择:CPU/GPU
  • 训练流程
    • 完整的训练循环:包含多个Epoch和批次训练。
    • 验证与测试:评估模型泛化性能。
  • 模型评估与优化
    • 评估指标:除准确率外,可加入混淆矩阵、F1分数等。
    • 超参数调优:使用网格搜索或自动化工具(如Optuna)。
    • 学习率调度:动态调整学习率。
  • 结果保存与部署
    • 模型保存:保存训练好的模型参数。
    • 结果可视化:绘制损失/精度曲线。
    • 部署接口:构建预测API或导出为ONNX格式。

注释:

数据预处理

读取数据集

数据集的读取方式因数据类型(如图像、文本、结构化数据)和存储形式(如本地文件、数据库、云存储)而异。

关键:

  • 使用绝对路径或统一管理路径变量。
    示例:
    1
    2
    import os
    DATA_DIR = os.path.expanduser("~/datasets/mnist") # 跨平台兼容路径
  • 数据校验:读取后检查数据量和维度是否合理。
    示例:
    1
    2
    print(f"加载图像数量: {len(dataset)}")
    print(f"单张图像形状: {dataset[0][0].shape}")
  • 文本文件需指定正确编码(如utf-8、gbk)。
  • 图像需统一通道顺序(如RGB vs BGR)。

结构化数据(CSV/Excel)

  • 常见场景:表格数据(如房价预测、用户行为分析)。
  • 核心工具:Pandas库。

第一步:读取CSV文件

1
2
3
4
5
6
7
8
9
10
11
import pandas as pd  # 导入pandas包(数据分析工具)

# 读取CSV文件
data = pd.read_csv("data.csv")

# 查看前5行
print(data.head())

# 分离特征和标签(假设最后一列为标签)
features = data.iloc[:, :-1].values # 转为NumPy数组
labels = data.iloc[:, -1].values

注释:

  • 在代码 data.iloc[:, :-1] 中,-1 是 Python 的负索引语法,表示从后向前计数。这里的 :-1 表示选取从第一列到倒数第二列的所有数据(即排除最后一列),目的是将最后一列作为标签(Label),其余列作为特征(Features)。
    • ::选取所有行。
    • -1:直接选取最后一列。

第二步:处理缺失值

1
2
3
4
5
6
7
# 策略1:删除包含缺失值的行
data.dropna(inplace=True) # inplace=True:直接修改原数据框,不返回新对象。

# 策略2:用均值填充缺失值
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy="mean") # 初始化填充器:指定填充策略为均值(strategy="mean"
features_filled = imputer.fit_transform(features) # 拟合并转换:fit_transform 会先计算各特征均值,再用均值填充缺失值

注释:

  • 策略1的使用场景:

    • 缺失值占比小(如<5%),删除后不影响数据量。
    • 缺失值随机分布,删除不会引入偏差。
  • 策略2中的SimpleImputer的strategy可选值:

    • “mean”(均值):是计算每个特征的均值
    • “median”(中位数)
    • “most_frequent”(众数)
    • “constant”(固定值):需配合 fill_value 参数
  • 策略2 的使用场景:

    • 特征符合正态分布或接近对称分布(均值能较好代表中心趋势)。
    • 缺失值较多或删除会导致数据不足的情况。
    • 均值策略仅适用于数值型特征。
    • 分类特征需改用众数——strategy="most_frequent"

图像数据

  • 常见场景:计算机视觉任务(分类、检测)。
  • 核心工具:PIL/Pillow、OpenCV、TensorFlow/PyTorch工具。

从文件夹读取(按类别存储)

假设数据集结构如下:

1
2
3
4
5
6
7
8
9
10
dataset/
train/
cat/
cat001.jpg
cat002.jpg
dog/
dog001.jpg
dog002.jpg
val/
...

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from torchvision.datasets import ImageFolder
from torch.utils.data import DataLoader
import torchvision.transforms as transforms

# 定义预处理转换
transform = transforms.Compose([
transforms.Resize((224, 224)), # 调整大小
transforms.ToTensor(), # 转为张量
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # 归一化
])

# 加载数据集
train_dataset = ImageFolder(root="dataset/train", transform=transform)
val_dataset = ImageFolder(root="dataset/val", transform=transform)

# 创建数据加载器(自动分批)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=32)

注释:

  • batch_size=32定义了每个批次(batch)中包含的样本数量。
    • 将整个数据集分成小批量,避免一次性加载全部数据导致内存不足,平衡内存占用与训练效率。
    • batch_size的常用值为 32、64、128
    • 每个批次计算一次梯度并更新参数(即小批量梯度下降)。
  • shuffle=True设置:在每个训练轮次(epoch)开始时,随机打乱数据顺序。
    • 防止顺序偏差:避免模型因数据排列顺序而学到非泛化性模式(如总是先看到某一类样本)。
    • 增强泛化性:打乱数据后,模型更均匀地学习不同特征,减少过拟合风险。
      • 训练阶段:shuffle通常设为 True。
      • 验证/测试阶段:通常设为 False(保持数据顺序一致)。

单张图像读取

1
2
3
4
5
from PIL import Image

# 读取图像并转换
image = Image.open("cat001.jpg").convert("RGB") # 确保RGB格式
image_tensor = transform(image) # 应用上述预处理

文本处理

  • 常见场景:自然语言处理(情感分析、机器翻译)。
  • 核心工具:Python内置文件操作、NLTK、Hugging Face Datasets。

读取文本文件

1
2
3
4
5
6
7
8
9
10
# 逐行读取
with open("text_data.txt", "r", encoding="utf-8") as f:
lines = f.readlines()

# 示例:情感分析数据(每行格式:标签\t文本)
texts, labels = [], []
for line in lines:
label, text = line.strip().split("\t")
labels.append(int(label))
texts.append(text)

使用Hugging Face数据集库

1
2
3
4
5
6
from datasets import load_dataset

# 加载公开数据集(如IMDB影评)
dataset = load_dataset("imdb")
train_texts = dataset["train"]["text"]
train_labels = dataset["train"]["label"]

音频数据

  • 常见场景:语音识别、声音分类。
  • 核心工具:Librosa、TorchAudio。
1
2
3
4
5
6
7
import librosa

# 加载音频文件
audio, sr = librosa.load("audio.wav", sr=16000) # sr为采样率

# 转换为梅尔频谱图(常见预处理)
mel_spectrogram = librosa.feature.melspectrogram(y=audio, sr=sr)

线性回归网络


动手学深度学习
http://zoechen04616.github.io/2025/03/14/动手学深度学习/
作者
Yunru Chen
发布于
2025年3月14日
许可协议