☰
Dive into Deep Learning 预备知识章节全解析:张量操作、数据预处理与数学基础
2026/10/3 16:47:57 网站建设 项目流程
  • 文档
  • 教程
  • 人工智能
  • 深度学习
  • NLP
  • 计算机视觉
  • 强化学习

【免费下载链接】d2l-en

Interactive deep learning book with multi-framework code, math, and discussions. Adopted at 500 universities from 70 countries including Stanford, MIT, Harvard, and Cambridge.

项目地址:https://gitcode.com/gh_mirrors/d2/d2l-en
点击查看免费下载

本章是《动手学深度学习》(Dive into Deep Learning, d2l-en)全书的"生存技能"章节,位于 chapter_preliminaries/index.md,目标是在进入神经网络之前,一次性补齐数据存储与操作、数据摄取与预处理、线性代数、微积分、自动微分、概率以及查文档这七项基本功。读完本文,你将掌握:四大主流深度学习框架(MXNet、PyTorch、TensorFlow、JAX)下张量的创建、索引、广播与内存管理;用 pandas 把真实 CSV 数据清洗成可直接喂给模型的标准流程;以及支撑全书所有后续章节的线性代数与范数概念,为理解"参数如何被调整、损失如何被下降"打下坚实基础。

章节定位:深度学习前的七项生存技能

index.md开篇明确列出读者需要的七项能力,这正是全书的技术地基:

  1. 存储与操作数据的技术(张量);
  2. 从多种来源摄取并预处理数据的库(pandas);
  3. 应用于高维数据元素的基本线性代数运算;
  4. 足够用的微积分,以判断每个参数应向哪个方向调整才能降低损失函数;
  5. 自动计算导数的能力,从而可以"忘记"大部分手算微积分;
  6. 概率论的基本熟练度——在不确定性下进行推理的核心语言;
  7. 遇到困难时在官方文档中寻找答案的能力。

章节通过toc指令组织为七个子章节:ndarray、pandas、linear-algebra、calculus、autograd、probability、lookup-api。全文的每个技术小节都采用"MXNet / PyTorch / TensorFlow / JAX"四框架并排的代码形式(.input代码块配合tab.interact_select切换),这正是本仓库的特色——同一概念给出四种框架的等价实现。

数据操作:张量(Tensor)与 NumPy 的本质差异

对应文档 chapter_preliminaries/ndarray.md。本节解决"如何存储和处理数据"。现代深度学习框架中的张量类(MXNet 的ndarray、PyTorch 与 TensorFlow 的Tensor)与 NumPy 的ndarray高度相似,但多出两个杀手级特性:支持自动微分、可利用 GPU 加速数值计算(NumPy 仅运行在 CPU 上)。正是这两个特性让神经网络"既好写又跑得快"。

创建张量:四框架的入口

各框架导入与创建方式几乎一一对应:

框架导入等间隔向量全 0 张量全 1 张量
MXNetfrom mxnet import np, npx; npx.set_np()np.arange(12)np.zeros((2, 3, 4))np.ones((2, 3, 4))
PyTorchimport torchtorch.arange(12, dtype=torch.float32)torch.zeros((2, 3, 4))torch.ones((2, 3, 4))
TensorFlowimport tensorflow as tftf.range(12, dtype=tf.float32)tf.zeros((2, 3, 4))tf.ones((2, 3, 4))
JAXimport jax; from jax import numpy as jnpjnp.arange(12)jnp.zeros((2, 3, 4))jnp.ones((2, 3, 4))

要点说明:

  • 命名差异:MXNet 中np模块包含 NumPy 兼容函数,npx模块是面向深度学习的扩展,使用张量前几乎总是调用npx.set_np()以保证与 MXNet 其他组件兼容;PyTorch 包名是torch;TensorFlow 惯例使用别名tf。
  • 元素个数与形状:arange/range(n)生成从 0(含)到 n(不含)、间隔为 1 的等距向量;默认新张量存放在主内存、面向 CPU 计算。元素总数可通过 MXNet/JAX 的x.size、PyTorch 的x.numel()、TensorFlow 的tf.size(x)查看;形状则统一通过x.shape属性获得。对向量而言 shape 只有一个元素,与 size 相同。
  • 随机初始化:神经网络参数常随机初始化。标准高斯(均值 0、标准差 1)采样:MXNetnp.random.normal(0, 1, size=(3, 4))、PyTorchtorch.randn(3, 4)、TensorFlowtf.random.normal(shape=[3, 4])。JAX 特殊:任何随机函数调用都必须显式指定key,且同一 key 永远产生同一采样结果,例如jax.random.normal(jax.random.PRNGKey(0), (3, 4))。
  • 按值构造:传入(可能嵌套的)Python 列表,最外层对应轴 0、内层对应轴 1。例如torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])构造 3×4 矩阵;TensorFlow 对应tf.constant(...)。

形状变换:reshape 与 -1 推断

reshape可在不改变元素个数与取值的前提下改变张量形状,例如把 shape 为(12,)的向量x变为(3, 4)的矩阵X(元素按行逐个铺开,故x[3] == X[0, 3])。由于已知总元素数 n 与目标形状 (h, w) 时 w = n/h,可用-1让框架自动推断某一分量:x.reshape(-1, 4)与x.reshape(3, -1)等价于x.reshape(3, 4)。

索引、切片与赋值:各框架的语义差异

与 Python 列表一致:索引从 0 开始,可用负索引从尾部访问,切片X[start:stop]含首不含尾;对 k 阶张量只给一个索引时作用于轴 0,如X[-1]取最后一行、X[1:3]取第二三行。

赋值能力因框架而异:

  • MXNet / PyTorch:可直接写入,X[1, 2] = 17;批量赋值把索引放在赋值左侧,X[:2, :] = 12(:表示沿轴 1 取全部列)。
  • TensorFlow:Tensor不可变、不能被赋值,需用可变容器tf.Variable:X_var = tf.Variable(X); X_var[1, 2].assign(9)。注意 TensorFlow 的梯度不会通过Variable赋值反向传播。
  • JAX:数组不可变,.at索引更新算子会创建携带修改的新数组:X.at[1, 2].set(17)、X.at[:2, :].set(12)。

元素级运算、拼接与逻辑比较

元素级(elementwise)运算把标准标量运算施加到张量的每个元素上:一元算子形如 $f: \mathbb{R} \rightarrow \mathbb{R}$(如exp),二元算子形如 $f: \mathbb{R}, \mathbb{R} \rightarrow \mathbb{R}$;对两个同形状张量,+、-、*、/、**都被"提升"为对应位置元素对逐元素运算。例如x = [1, 2, 4, 8]、y = [2, 2, 2, 2]时,x * y = [2, 4, 8, 16]。

拼接用concatenate/cat/concat沿指定轴把多个张量首尾相接成更大的张量:沿轴 0(行)拼接后轴 0 长度是两者之和(3+3=6),沿轴 1(列)拼接后轴 1 长度是两者之和(4+4=8)。逻辑语句构造二值张量:X == Y在对应位置相等时取 1,否则取 0;全量求和 MXNet/PyTorch/JAX 为X.sum(),TensorFlow 为tf.reduce_sum(X)。

广播机制:形状不同也能逐元素运算

广播(broadcasting) 让形状不完全相同的张量也能逐元素做二元运算,分两步:① 沿长度为 1 的轴复制元素扩充一个或两个数组,使二者形状一致;② 对结果数组逐元素运算。例如a = np.arange(3).reshape(3, 1)(3×1 矩阵)与b = np.arange(2).reshape(1, 2)(1×2 矩阵)形状不匹配,但a + b会先把 a 沿列复制、b 沿行复制,生成 3×2 矩阵后再相加。广播是所有现代框架"形状推断"机制的核心,后续章节(如非归约求和配合广播做行归一化)将反复使用。

节省内存:原地更新与不可变框架的对策

运行运算会为新结果分配新内存:执行Y = Y + X后id(Y)会指向新的内存地址(Python 先求值Y + X、分配新内存、再让Y指向新位置)。这在机器学习中不可取——我们常有数百 MB 的参数且每秒多次更新,应该原地更新;而且多个变量可能指向同一批参数,不原地更新容易产生内存泄漏或引用到过期参数。

  • MXNet / PyTorch:用切片记法Y[:] = <expression>写入预分配数组;若X之后不再使用,可用X[:] = X + Y或X += Y减少内存开销(用id(X)前后对比可验证地址不变)。
  • TensorFlow:Tensor不可变、梯度不流过Variable赋值,因此没有显式的单算子原地操作;但tf.function装饰器会把计算包装进编译优化的计算图中,自动剪除无用中间值、复用不再需要的旧分配,从而最小化内存开销。
  • JAX:数组不支持原地操作,这是其函数式纯函数设计使然。

与其他 Python 对象互转

各框架均可与 NumPy 互转:MXNet 用X.asnumpy()/np.array(A)(转换结果不共享内存,避免 CPU/GPU 计算被 NumPy 的并发操作打断);PyTorch 用X.numpy()/torch.from_numpy(A)(共享底层内存,原地修改会相互影响);TensorFlow 用X.numpy()/tf.constant(A);JAX 用jax.device_get(X)/jax.device_put(A)。把单元素张量转成 Python 标量可用a.item()、float(a)、int(a)。

数据预处理:pandas 实战——从 CSV 到张量

对应文档 chapter_preliminaries/pandas.md。上一节处理的是现成的合成张量,真实世界里数据是"任意格式的脏数据",pandas 承担了绝大部分重活。本节以房产小数据集house_tiny.csv走完"读文件 → 清洗 → 转张量"全流程。

读取数据集:创建并加载 CSV

CSV(逗号分隔值)是存储表格数据的通用格式:每行一条记录、由若干逗号分隔的字段组成。文档演示用 Python 直接写一个 4 行 3 列(NumRooms房间数、RoofType屋顶类型、Price价格)的数据文件:

import os os.makedirs(os.path.join('..', 'data'), exist_ok=True) data_file = os.path.join('..', 'data', 'house_tiny.csv') with open(data_file, 'w') as f: f.write('''NumRooms,RoofType,Price NA,NA,127500 2,NA,106000 4,Slate,178100 NA,NA,140000''') import pandas as pd data = pd.read_csv(data_file) print(data)

注意 CSV 中的NA被 pandas 自动替换为特殊的NaN(not a number)——空条目(如"3,,,270000")同样如此。这就是"缺失值",是数据科学中无处不在的"臭虫"。

数据准备:分离输入与目标、处理缺失值

监督学习中要区分输入列与目标列,可按列名或按整数位置索引iloc选取:inputs, targets = data.iloc[:, 0:2], data.iloc[:, 2]。

缺失值处理的两大流派是填充(imputation)——用估计值替换缺失值,与删除(deletion)——直接丢弃含缺失值的行或列。文档给出两个常用启发式:

  1. 类别型字段把NaN当做一个类别。RoofType取值Slate和NaN,pd.get_dummies(inputs, dummy_na=True)会把该列拆成RoofType_Slate与RoofType_nan两列:屋顶是 Slate 的行,两列取值分别为 1 和 0;缺失屋顶类型的行反之。
  2. 数值型缺失用列均值填充:inputs = inputs.fillna(inputs.mean())。

转换为张量格式:打通 pandas 与深度学习

所有条目变为数值后即可装载为张量,四框架统一先经 NumPy 过渡:

# MXNet from mxnet import np X, y = np.array(inputs.to_numpy(dtype=float)), np.array(targets.to_numpy(dtype=float)) # PyTorch import torch X = torch.tensor(inputs.to_numpy(dtype=float)) y = torch.tensor(targets.to_numpy(dtype=float)) # TensorFlow import tensorflow as tf X = tf.constant(inputs.to_numpy(dtype=float)) y = tf.constant(targets.to_numpy(dtype=float)) # JAX from jax import numpy as jnp X = jnp.array(inputs.to_numpy(dtype=float)) y = jnp.array(targets.to_numpy(dtype=float))

本节能力可概括为:分离数据列、填充缺失变量、把 pandas 数据载入张量。文档同时提醒真实工程中数据处理远比这复杂:数据可能分散在关系数据库的多个表(如电商中客户地址与购买记录分表);数据类型除类别与数值外还有文本、图像、音频、点云,常常需要高级工具与高效算法避免数据预处理成为机器学习流水线的最大瓶颈;真实数据集常受异常值、传感器故障测量与记录错误困扰,喂给模型前必须处理,可用 seaborn、Bokeh、matplotlib 等可视化工具人工检查数据、建立直觉。

线性代数:深度学习所需的全部核心概念

对应文档 chapter_preliminaries/linear-algebra.md。本节从标量算术一路攀升到矩阵乘法与范数,是理解后续"神经网络每一层输出计算"的直接基础。

标量、向量、矩阵与高阶张量

  • 标量:单个数字,用小写字母表示,全体实数记为 $\mathbb{R}$;x ∈ ℝ表示 x 是实数标量。代码中标量实现为只含一个元素的张量:torch.tensor(3.0),可做+ - * / **运算。
  • 向量:固定长度的标量数组,元素又称 entry/component,用粗体小写字母表示。代码中是 1 阶张量,长度(dimensionality)用len(x)或x.shape获取。注意区分两个易混概念:**order(阶)**专指轴的数量,**dimensionality(维数)**专指分量个数。向量默认竖向堆叠展示为列向量;x[2]取第二个元素。
  • 矩阵:2 阶张量,用粗体大写字母表示,$\mathbf{A} \in \mathbb{R}^{m \times n}$ 表示 m 行 n 列。代码中由 shape 为 (m, n) 的张量表示,A = torch.arange(6).reshape(3, 2)。转置交换行列:$\mathbf{B} = \mathbf{A}^\top$ 时 $b_{ij} = a_{ji}$,转置一个 $m \times n$ 矩阵得到 $n \times m$ 矩阵(PyTorch/JAXA.T,TensorFlowtf.transpose(A))。对称矩阵是等于自身转置的方阵:$\mathbf{A} = \mathbf{A}^\top$,代码中可用A == A.T验证。
  • 高阶张量:张量类对象之所以叫"tensor",正因它们可有任意数量的轴。图像是 3 阶张量(高、宽、通道轴,每个空间位置的红绿蓝强度沿通道堆叠);一批图像是 4 阶张量(第一轴索引不同图像),例如torch.arange(24).reshape(2, 3, 4)。

张量算术的基本性质与归约

  • 元素级运算输出与操作数同形状;两个同形状矩阵的元素级乘积叫Hadamard 积(记作 $\odot$);标量加/乘张量保持原形状。
  • 归约(reduction):sum默认沿所有轴归约得到标量,也可指定轴。A.sum(axis=0)沿行归约,该轴从输出形状中消失;A.sum(axis=[0, 1])等价于A.sum()。均值同理:A.mean(),且A.mean(axis=0)等价于A.sum(axis=0) / A.shape[0]。
  • 非归约求和:加keepdims=True可保持轴数不变,从而配合广播使用。经典用法:sum_A = A.sum(axis=1, keepdims=True)得到每行之和的列向量,A / sum_A借助广播把每一行归一化为和为 1。累积和用cumsum(axis=0),设计上不归约任何轴。

点积、矩阵-向量积与矩阵乘法

  • 点积(内积):$\mathbf{x}^\top \mathbf{y} = \sum_{i=1}^{d} x_i y_i$,等价于逐元素相乘再求和(torch.sum(x * y))。实际用途广泛:加权和、权重非负且和为 1 时的加权平均、两单位向量归一化后的余弦夹角。
  • 矩阵-向量积:把 $m \times n$ 矩阵视为 m 个行向量,$\mathbf{A}\mathbf{x}$ 是长度为 m 的列向量,其第 i 个元素为第 i 行与 x 的点积;可看作把向量从 $\mathbb{R}^n$ 投影到 $\mathbb{R}^m$ 的变换(旋转、神经网络层输出计算都属此类)。要求 A 的列维(轴 1 长度)等于 x 的维数。API:MXNetnp.dot(A, x)、PyTorchtorch.mv(A, x)或A @ x、TensorFlowtf.linalg.matvec(A, x)、JAXjnp.matmul(A, x)。
  • 矩阵乘法:$\mathbf{C} = \mathbf{AB} \in \mathbb{R}^{n \times m}$,元素 $c_{ij}$ 是 A 第 i 行与 B 第 j 列的点积;可视为 m 次矩阵-向量积或 m×n 次点积拼接。要求 A 的列数等于 B 的行数。示例:A(2×3)与 B(3×4)相乘得 2×4 矩阵(torch.mm(A, B)/A @ B/tf.matmul(A, B))。"矩阵乘法"绝不等于 Hadamard 积;矩阵乘法计算时间约为三次方量级(相对 Hadamard 积的平方量级),成本显著更高。

范数:度量向量与矩阵的"大小"

范数 $| \cdot |$ 是把向量映射到标量的函数,满足三条公理:① 缩放一致性 $|\alpha \mathbf{x}| = |\alpha| |\mathbf{x}|$;② 三角不等式 $|\mathbf{x} + \mathbf{y}| \leq |\mathbf{x}| + |\mathbf{y}|$;③ 非负且仅在零向量时取 0。常用范数:

  • $\ell_2$ 范数(欧几里得长度):$|\mathbf{x}|2 = \sqrt{\sum{i=1}^n x_i^2}$,torch.norm(u)/tf.norm(u)等直接计算,如[3, -4]的 $\ell_2$ 范数为 5。
  • $\ell_1$ 范数(曼哈顿距离):$|\mathbf{x}|1 = \sum{i=1}^n |x_i|$,对异常值不如 $\ell_2$ 敏感,可用绝对值加和实现(如torch.abs(u).sum();JAX 为jnp.linalg.norm(u, ord=1))。两者都是更一般的 $\ell_p$ 范数 $\left(\sum_{i=1}^n |x_i|^p \right)^{1/p}$ 的特例。
  • Frobenius 范数:矩阵范数中最易计算的一种,$|\mathbf{X}|\textrm{F} = \sqrt{\sum{i,j} x_{ij}^2}$,行为如同"把矩阵拉直后的 $\ell_2$ 范数",可用torch.norm(torch.ones((4, 9)))等计算(结果为 6)。

范数在深度学习中的价值:优化问题的目标(最大化观测数据概率、最大化推荐模型收益、最小化预测与真值距离、最小化同一人脸表示距离同时最大化不同人脸表示距离)中的"距离",几乎都以范数表达。

后续三节速览:微积分、自动微分与概率

index.md的 toc 还包含三个重要子章节(详见各子文档),这里给出导航式概览:

  • 微积分(calculus.md):从"如何计算圆面积"这一历史难题切入,讲解导数作为"切线斜率"的几何直觉、导数运算法则与常用导数表,以及偏导数与梯度——梯度指向函数值增长最快的方向,因此沿负梯度方向调整参数即可减小损失函数。
  • 自动微分(autograd.md):计算导数是训练的关键步骤,但既繁琐又易错,深度学习框架均内置自动微分引擎(MXNetautograd、PyTorchautograd、TensorFlowGradientTape、JAXjax.grad),把复杂模型的求导交给框架完成。
  • 概率与统计(probability.md):机器学习本质上处理不确定性,本节介绍概率论基本公理、随机变量、条件概率与贝叶斯公式、期望与方差、常用分布(正态分布、伯努利分布、多项分布等),以及从样本估计分布的统计视角——这是后面极大似然估计与训练目标设计的基础。
  • 文档查阅(lookup-api.md):四框架的 API 文档数量庞大且更新快,本节训练读者"卡住时去查官方 API 文档"的习惯,包括按函数/类名搜索、查看示例、利用 Jupyter 的交互式帮助(如help()、?)等技巧。

实践建议与延伸

本章提供的技能贯穿全书:ndarray的张量操作是所有网络代码的通用语言;pandas的预处理流水线在 chapter_linear-regression 与 chapter_linear-classification 的 Kaggle 实战(如房价预测)中会升级为更完整的数据处理方案;线性代数的矩阵乘法与范数则是 chapter_convolutional-neural-networks 等后续章节的每日工具。建议读者:

  1. 四框架对照阅读:每个代码示例都有 mxnet / pytorch / tensorflow / jax 四种 tab,选择与自身环境一致的框架运行,其余作为对照理解 API 命名差异(如sumvsreduce_sum、reshapevstf.reshape)。
  2. 动手验证关键机制:重点实验广播、原地更新(id()对比)、keepdims配合广播的行归一化,以及X == Y换成</>后的结果变化。
  3. 关注数据质量:真实数据集的异常值与缺失值必须先于模型处理,本章的填充/删除策略是进入更大规模数据工程前的必要起点。

完整的章节代码、公式与四框架实现均可在本仓库的 chapter_preliminaries 目录下逐节查看;仓库还提供了配套的 d2l 工具库(d2l/torch.py、d2l/tensorflow.py、d2l/mxnet.py、d2l/jax.py),后续章节将反复使用其中的数据加载与训练辅助函数。

  • 文档
  • 教程
  • 人工智能
  • 深度学习
  • NLP
  • 计算机视觉
  • 强化学习

【免费下载链接】d2l-en

Interactive deep learning book with multi-framework code, math, and discussions. Adopted at 500 universities from 70 countries including Stanford, MIT, Harvard, and Cambridge.

项目地址:https://gitcode.com/gh_mirrors/d2/d2l-en
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询