【深度学习-Day 2】图解线性代数:从标量到张量,理解深度学习的数据表示与运算
Langchain系列文章目录
01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南
02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖
03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南
04-玩转 LangChain:从文档加载到高效问答系统构建的全程实战
05-玩转 LangChain:深度评估问答系统的三种高效方法(示例生成、手动评估与LLM辅助评估)
06-从 0 到 1 掌握 LangChain Agents:自定义工具 + LLM 打造智能工作流!
07-【深度解析】从GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
PyTorch系列文章目录
机器学习系列文章目录
深度学习系列文章目录
01-【深度学习-Day 1】为什么深度学习是未来?一探究竟AI、ML、DL关系与应用
02-【深度学习-Day 2】图解线性代数:从标量到张量,理解深度学习的数据表示与运算
文章目录
- Langchain系列文章目录
- PyTorch系列文章目录
- 机器学习系列文章目录
- 深度学习系列文章目录
- 前言
- 一、数据在深度学习中的表示:从标量到张量
- 1.1 标量 (Scalar)
- 1.1.1 什么是标量?
- 1.1.2 深度学习中的标量示例
- 1.1.3 Python 表示
- 1.2 向量 (Vector)
- 1.2.1 什么是向量?
- 1.2.2 深度学习中的向量示例
- 1.2.3 Python (NumPy) 表示
- 1.3 矩阵 (Matrix)
- 1.3.1 什么是矩阵?
- 1.3.2 深度学习中的矩阵示例
- 1.3.3 Python (NumPy) 表示
- 1.4 张量 (Tensor)
- 1.4.1 什么是张量?
- 1.4.2 深度学习中的张量示例
- 1.4.3 Python (NumPy/Frameworks) 表示
- 二、线性代数核心运算
- 2.1 基本元素级运算 (Element-wise Operations)
- 2.1.1 加法与减法 (Addition & Subtraction)
- 2.1.2 标量乘法 (Scalar Multiplication)
- 2.1.3 哈达玛积 (Hadamard Product / Element-wise Product)
- 2.2 转置 (Transpose)
- 2.2.1 向量转置 (Vector Transpose)
- 2.2.2 矩阵转置 (Matrix Transpose)
- 2.3 点积/内积 (Dot Product / Inner Product) 与 矩阵乘法 (Matrix Multiplication)
- 2.3.1 向量点积 (Vector Dot Product)
- 2.3.2 矩阵乘法 (Matrix Multiplication)
- 三、实践:NumPy 实现
- 四、常见问题与提示
- 4.1 维度不匹配 (Dimension Mismatch)
- 4.2 区分哈达玛积与矩阵乘法
- 4.3 理解张量的轴 (Understanding Tensor Axes)
- 五、总结
前言
大家好!欢迎来到深度学习系列博客的第二篇。在上一篇中,我们初步了解了深度学习是什么以及它的重要性。从今天开始,我们将深入学习构建深度学习模型所必需的基础知识。而其中,线性代数扮演着至关重要的角色。
你可能会问:“为什么需要线性代数?” 简单来说,深度学习本质上是对数据进行一系列复杂的变换和计算。而线性代数正是描述和操作这些数据(通常以数组形式存在)的强大数学语言。无论是输入数据(如图像像素、文本词语)、模型参数(权重和偏置),还是中间计算结果,都可以用线性代数中的概念(向量、矩阵、张量)来表示。理解线性代数的核心概念和运算,是你看懂模型原理、高效实现算法、甚至排查错误的关键。
本篇文章将聚焦于深度学习中最常用、最核心的线性代数知识点,力求用通俗易懂的语言和实例,帮助你扫清障碍,为后续学习打下坚实基础。我们将涵盖:
- 数据表示:标量、向量、矩阵、张量是什么,它们如何表示深度学习中的数据?
- 核心运算:加减法、标量乘法、转置、点积、矩阵乘法等基本操作及其意义。
- 实践应用:如何使用强大的 Python 库 NumPy 来执行这些运算。
不必担心复杂的证明和推导,我们的目标是理解概念并知道如何在实践中运用它们。让我们一起开始吧!
一、数据在深度学习中的表示:从标量到张量
在深度学习的世界里,我们处理的所有信息,无论是图像、文本、声音还是表格数据,最终都需要转化为机器能够理解和处理的数字形式。线性代数提供了一套优雅而高效的结构来组织这些数字。
1.1 标量 (Scalar)
1.1.1 什么是标量?
标量是最简单的数据结构,它就是一个单独的数字。可以把它想象成一个零维的数组。
1.1.2 深度学习中的标量示例
- 损失值 (Loss Value): 在模型训练中,衡量模型预测与真实值差距的损失函数通常输出一个标量值。
- 学习率 (Learning Rate): 控制模型参数更新幅度的超参数,是一个标量。
- 样本标签 (某些情况): 对于回归任务,单个样本的标签可能是一个标量(例如预测房价)。
- 偏置项 (Bias): 神经网络层中的偏置通常是一个标量(虽然实践中为了广播机制,常表示为向量或更高维张量)。
1.1.3 Python 表示
在 Python 中,标量通常用基本的数字类型 int
或 float
表示。
# 标量示例
learning_rate = 0.001
loss = 0.54
integer_scalar = 10print(f"Type of learning_rate: {type(learning_rate)}")
print(f"Type of integer_scalar: {type(integer_scalar)}")
1.2 向量 (Vector)
1.2.1 什么是向量?
向量是一组有序排列的数字,可以看作是一个一维数组。它有方向和大小。在线性代数中,向量通常默认指列向量(一列多行),但有时也表示为行向量(一行多列)。
1.2.2 深度学习中的向量示例
- 特征向量 (Feature Vector): 一个数据样本(如用户、图片)的多个特征可以用一个向量表示。例如,一个用户的特征向量可能包含年龄、性别(编码后)、购买次数等
[25, 1, 15]
。 - 词嵌入 (Word Embedding): 在自然语言处理中,每个词可以被表示为一个稠密的数值向量,捕捉其语义信息。
- 神经网络的输出 (某些情况): 对于多分类任务,模型最后一层(Softmax之前)的输出通常是一个向量,每个元素代表对应类别的得分。
- 偏置向量 (Bias Vector): 神经网络层中的偏置项,通常表示为一个向量,其长度等于该层神经元的数量。
1.2.3 Python (NumPy) 表示
我们通常使用 NumPy 库来创建和操作向量。
import numpy as np# 创建一个行向量 (实际上NumPy创建的是一维数组,没有严格区分行列)
feature_vector = np.array([25, 1, 15])
print(f"Feature Vector (1D array): {feature_vector}")
print(f"Shape: {feature_vector.shape}") # 输出 (3,) 表示一维,3个元素# 可以显式创建行向量 (1xN 矩阵)
row_vector = np.array([[25, 1, 15]])
print(f"Row Vector (2D array): {row_vector}")
print(f"Shape: {row_vector.shape}") # 输出 (1, 3)# 创建列向量 (Nx1 矩阵)
column_vector = np.array([[25], [1], [15]])
print(f"Column Vector (2D array): \n{column_vector}")
print(f"Shape: {column_vector.shape}") # 输出 (3, 1)
注意: NumPy 的一维数组在进行某些运算(如矩阵乘法)时,会根据上下文自动判断是行向量还是列向量,这有时会带来便利,但也可能导致混淆。在严格的数学表达中,区分行向量和列向量很重要。
1.3 矩阵 (Matrix)
1.3.1 什么是矩阵?
矩阵是一个二维数组,由数字排列成的矩形网格构成,包含行 (rows) 和列 (columns)。一个矩阵的大小由其行数和列数定义,例如一个 m × n m \times n m×n 矩阵有 m m m 行 n n n 列。
1.3.2 深度学习中的矩阵示例
- 灰度图像: 一个灰度图像可以表示为一个矩阵,每个元素代表对应像素的亮度值(例如 0-255)。
- 数据批次 (Batch of Data): 在训练时,我们通常一次处理一小批数据。如果每个数据样本是一个特征向量,那么一个批次的数据就可以表示为一个矩阵,其中每一行是一个样本的特征向量。
- 权重矩阵 (Weight Matrix): 神经网络中连接两层的权重通常组织成一个矩阵。如果输入层有 n n n 个神经元,输出层有 m m m 个神经元,那么它们之间的权重可以表示为一个 m × n m \times n m×n 或 n × m n \times m n×m 的矩阵(取决于约定)。
- 混淆矩阵 (Confusion Matrix): 用于评估分类模型性能,显示预测类别与真实类别的对应关系。
1.3.3 Python (NumPy) 表示
import numpy as np# 创建一个 3x2 的矩阵 (3 行 2 列)
matrix_A = np.array([[1, 2],[3, 4],[5, 6]])
print(f"Matrix A:\n{matrix_A}")
print(f"Shape: {matrix_A.shape}") # 输出 (3, 2)# 模拟一个数据批次,假设有 2 个样本,每个样本有 4 个特征
data_batch = np.array([[0.1, 0.5, -0.2, 1.0],[-0.4, 0.8, 0.0, 0.3]])
print(f"\nData Batch:\n{data_batch}")
print(f"Shape: {data_batch.shape}") # 输出 (2, 4)
1.4 张量 (Tensor)
1.4.1 什么是张量?
张量是线性代数中数据结构的一般化形式,可以看作是多维数组。它是标量、向量、矩阵的自然扩展:
- 0 阶张量 (0D Tensor): 标量 (Scalar)
- 1 阶张量 (1D Tensor): 向量 (Vector)
- 2 阶张量 (2D Tensor): 矩阵 (Matrix)
- 3 阶及以上张量 (nD Tensor): 高维数组
张量的“阶” (rank) 或“维数” (number of dimensions/axes) 指的是其索引的数量。例如,一个 3 阶张量需要 3 个索引来定位其中的一个元素,如 T i j k T_{ijk} Tijk。
1.4.2 深度学习中的张量示例
张量是深度学习框架(如 TensorFlow, PyTorch)处理数据的标准方式。
- 彩色图像: 一张彩色图像通常表示为 3 阶张量,维度通常是 (高度, 宽度, 通道数)。例如,一张 256x256 像素的 RGB 图像可以表示为 ( 256 , 256 , 3 ) (256, 256, 3) (256,256,3) 的张量。
- 图像批次: 一批彩色图像则是一个 4 阶张量,维度通常是 (批次大小, 高度, 宽度, 通道数)。例如,一批 32 张 256x256 的 RGB 图像是 ( 32 , 256 , 256 , 3 ) (32, 256, 256, 3) (32,256,256,3) 的张量。
- 视频数据: 可以表示为 5 阶张量 (批次大小, 帧数, 高度, 宽度, 通道数)。
- 自然语言处理 (NLP): 一批句子(每个句子由词嵌入向量序列组成)可以表示为 3 阶张量 (批次大小, 序列长度, 嵌入维度)。
- 循环神经网络 (RNN) 的隐藏状态: 随时间步变化的隐藏状态序列也可以用张量表示。
1.4.3 Python (NumPy/Frameworks) 表示
NumPy 以及深度学习框架都原生支持张量操作。
import numpy as np# 创建一个 3 阶张量 (例如,模拟一个 2x3x2 的张量)
tensor_3d = np.array([[[1, 2], [3, 4], [5, 6]],[[7, 8], [9, 10], [11, 12]]])
print(f"3D Tensor:\n{tensor_3d}")
print(f"Shape: {tensor_3d.shape}") # 输出 (2, 3, 2)
print(f"Number of dimensions (rank): {tensor_3d.ndim}") # 输出 3# 访问元素
print(f"Element at index (0, 1, 1): {tensor_3d[0, 1, 1]}") # 输出 4
理解这些基本的数据结构是进行后续线性代数运算和理解深度学习模型的基础。
二、线性代数核心运算
掌握了数据的表示方法后,下一步就是了解如何对这些数据进行运算。这些运算构成了深度学习模型中信息流动和转换的基础。
2.1 基本元素级运算 (Element-wise Operations)
元素级运算指的是对两个具有相同形状的张量(向量、矩阵或更高维张量)的对应元素执行某种运算,生成一个形状完全相同的结果张量。
2.1.1 加法与减法 (Addition & Subtraction)
- 规则: 两个张量必须具有完全相同的形状。对应位置的元素进行相加或相减。
- 公式: 若 C = A + B C = A + B C=A+B, 则 C i j = A i j + B i j C_{ij} = A_{ij} + B_{ij} Cij=Aij+Bij。减法同理。
- 应用: 融合信息(如残差连接 ResNet 中的 X + F ( X ) X + F(X) X+F(X)),调整数值。
import numpy as npA = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])# 加法
C_add = A + B
print(f"A + B:\n{C_add}")
# 输出:
# [[ 6 8]
# [10 12]]# 减法
C_sub = A - B
print(f"\nA - B:\n{C_sub}")
# 输出:
# [[-4 -4]
# [-4 -4]]# 形状不同会报错
# C = np.array([1, 2])
# try:
# A + C
# except ValueError as e:
# print(f"\nError when adding A and C: {e}")
2.1.2 标量乘法 (Scalar Multiplication)
- 规则: 将一个标量与一个张量(向量、矩阵等)相乘。张量中的每个元素都乘以该标量。结果张量的形状与原张量相同。
- 公式: 若 C = s × A C = s \times A C=s×A, 则 C i j = s × A i j C_{ij} = s \times A_{ij} Cij=s×Aij。
- 应用: 缩放数值(如调整梯度、应用学习率)。
import numpy as npA = np.array([[1, 2], [3, 4]])
scalar = 10C_scalar_mul = scalar * A # 或者 A * scalar
print(f"scalar * A:\n{C_scalar_mul}")
# 输出:
# [[10 20]
# [30 40]]
2.1.3 哈达玛积 (Hadamard Product / Element-wise Product)
- 规则: 对两个相同形状的张量,将对应位置的元素相乘。结果张量的形状也相同。注意:这与后面要讲的矩阵乘法完全不同!
- 公式: 若 C = A ⊙ B C = A \odot B C=A⊙B, 则 C i j = A i j × B i j C_{ij} = A_{ij} \times B_{ij} Cij=Aij×Bij。
- 应用: 在某些神经网络结构中用于门控机制(如 LSTM 中的门计算),或者对特征进行加权。
import numpy as npA = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])# 哈达玛积 (在 NumPy 中使用 * 运算符)
C_hadamard = A * B
print(f"A * B (Hadamard Product):\n{C_hadamard}")
# 输出:
# [[ 5 12]
# [21 32]]
关键区分: 在 NumPy 中,*
运算符默认执行的是元素级乘法(哈达玛积)。
2.2 转置 (Transpose)
转置是一种重要的矩阵操作,它将矩阵的行和列进行互换。
2.2.1 向量转置 (Vector Transpose)
- 将行向量转换为列向量,或将列向量转换为行向量。
- 对于 NumPy 的一维数组,
.T
属性对其本身没有效果,因为它没有严格的行列区分。需要先将其视为二维数组(矩阵)。
import numpy as np# NumPy 一维数组
vec = np.array([1, 2, 3])
print(f"Original vec shape: {vec.shape}, Transposed vec.T: {vec.T}, Shape: {vec.T.shape}")
# 输出: Original vec shape: (3,), Transposed vec.T: [1 2 3], Shape: (3,)# 显式创建行向量 (1xN 矩阵)
row_vec = np.array([[1, 2, 3]]) # Shape (1, 3)
col_vec = row_vec.T
print(f"\nRow vector shape: {row_vec.shape}")
print(f"Transposed to column vector:\n{col_vec}")
print(f"Column vector shape: {col_vec.shape}") # Shape (3, 1)
2.2.2 矩阵转置 (Matrix Transpose)
- 规则: 将矩阵 A A A 的第 i i i 行变成结果矩阵 A T A^T AT 的第 i i i 列,或者说将 A A A 的第 j j j 列变成 A T A^T AT 的第 j j j 行。如果 A A A 是一个 m × n m \times n m×n 矩阵,那么它的转置 A T A^T AT 是一个 n × m n \times m n×m 矩阵。
- 公式: ( A T ) i j = A j i (A^T)_{ij} = A_{ji} (AT)ij=Aji。
- 应用: 改变矩阵维度以满足乘法要求,某些数学推导和公式表达,数据重塑。
import numpy as npA = np.array([[1, 2, 3],[4, 5, 6]]) # Shape (2, 3)A_T = A.T
print(f"Original Matrix A (shape {A.shape}):\n{A}")
print(f"\nTransposed Matrix A_T (shape {A_T.shape}):\n{A_T}")
# 输出:
# Original Matrix A (shape (2, 3)):
# [[1 2 3]
# [4 5 6]]
#
# Transposed Matrix A_T (shape (3, 2)):
# [[1 4]
# [2 5]
# [3 6]]
2.3 点积/内积 (Dot Product / Inner Product) 与 矩阵乘法 (Matrix Multiplication)
点积和矩阵乘法是线性代数中极其重要的运算,是神经网络中信息传递和转换的核心。
2.3.1 向量点积 (Vector Dot Product)
- 规则: 两个长度相同的向量 a \mathbf{a} a 和 b \mathbf{b} b 的点积,是它们对应元素的乘积之和。结果是一个标量。
- 公式: a ⋅ b = ∑ i = 1 n a i b i = a 1 b 1 + a 2 b 2 + ⋯ + a n b n \mathbf{a} \cdot \mathbf{b} = \sum_{i=1}^{n} a_i b_i = a_1 b_1 + a_2 b_2 + \dots + a_n b_n a⋅b=i=1∑naibi=a1b1+a2b2+⋯+anbn
- 几何意义 (初步了解): 点积可以衡量两个向量的相似性或对齐程度。如果两个向量方向大致相同,点积为正且较大;如果方向相反,点积为负;如果相互垂直,点积为 0。它也与向量投影有关。
- 应用: 计算加权和(神经网络神经元的计算核心之一),衡量向量相似度,计算向量长度(向量与其自身的点积的平方根)。
import numpy as npa = np.array([1, 2, 3])
b = np.array([4, 5, 6])# 计算点积
dot_product = np.dot(a, b)
# 或者使用 @ 运算符 (Python 3.5+)
# dot_product_at = a @ b
print(f"Dot product of a and b: {dot_product}")
# 输出: Dot product of a and b: 32 (1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32)
2.3.2 矩阵乘法 (Matrix Multiplication)
- 规则: 两个矩阵 A A A (形状 m × n m \times n m×n) 和 B B B (形状 n × p n \times p n×p) 的乘积 C = A B C = AB C=AB 是一个 m × p m \times p m×p 的矩阵。 C C C 中的每个元素 C i j C_{ij} Cij 是 A A A 的第 i i i 行与 B B B 的第 j j j 列的点积。
- 维度兼容性: 要进行矩阵乘法 A B AB AB,第一个矩阵 A A A 的列数 ( n n n) 必须等于第二个矩阵 B B B 的行数 ( n n n)。
- 公式: C i j = ∑ k = 1 n A i k B k j C_{ij} = \sum_{k=1}^{n} A_{ik} B_{kj} Cij=k=1∑nAikBkj
- 重要特性: 矩阵乘法不满足交换律,即 A B ≠ B A AB \neq BA AB=BA (除非在特殊情况下)。
- 应用: 线性变换(旋转、缩放、投影),神经网络中的层与层之间的计算(输入通过权重矩阵变换得到输出),状态转移。
import numpy as npA = np.array([[1, 2],[3, 4]]) # Shape (2, 2)
B = np.array([[5, 6, 7],[8, 9, 10]]) # Shape (2, 3)# 矩阵乘法 C = AB
# A的列数(2) == B的行数(2),可以相乘
# 结果 C 的形状是 (A的行数, B的列数) = (2, 3)
C_matmul = np.dot(A, B)
# 或者使用 @ 运算符
# C_matmul_at = A @ Bprint(f"Matrix A (shape {A.shape}):\n{A}")
print(f"Matrix B (shape {B.shape}):\n{B}")
print(f"\nMatrix Multiplication C = AB (shape {C_matmul.shape}):\n{C_matmul}")
# 输出:
# Matrix A (shape (2, 2)):
# [[1 2]
# [3 4]]
# Matrix B (shape (2, 3)):
# [[ 5 6 7]
# [ 8 9 10]]
#
# Matrix Multiplication C = AB (shape (2, 3)):
# [[21 24 27] # C[0,0] = A[0,:] dot B[:,0] = [1,2] dot [5,8] = 1*5+2*8=21
# [47 54 61]] # C[1,0] = A[1,:] dot B[:,0] = [3,4] dot [5,8] = 3*5+4*8=47
# ...以此类推计算其他元素
我们可以用一个简单的图示来说明矩阵乘法中元素的计算过程:
graph LRsubgraph Matrix A (m x n)direction TBA_row_i("Row i: [A<sub>i1</sub>, A<sub>i2</sub>, ..., A<sub>in</sub>]")endsubgraph Matrix B (n x p)direction TBB_col_j("Column j: <br>[B<sub>1j</sub>]<br>[B<sub>2j</sub>]<br>...<br>[B<sub>nj</sub>]")endsubgraph Result Matrix C (m x p)C_ij("Element C<sub>ij</sub>")endA_row_i -- 点积 (Dot Product) --> C_ij;B_col_j -- 点积 (Dot Product) --> C_ij;note for C_ij "$$C_{ij} = A_{i1}B_{1j} + A_{i2}B_{2j} + \dots + A_{in}B_{nj} = \sum_{k=1}^{n} A_{ik}B_{kj}$$"
掌握这些核心运算是理解神经网络如何处理信息的关键一步。
三、实践:NumPy 实现
理论学习固然重要,但动手实践更能加深理解。Python 的 NumPy 库是进行科学计算,特别是线性代数运算的标准库。下面我们用 NumPy 来实践前面介绍的概念和运算。
import numpy as np# 确保前面的导入已执行print("--- 3.1 创建标量、向量、矩阵、张量 ---")
# 标量 (虽然 NumPy 中通常用 0 维数组表示,但直接用 Python 类型更常见)
scalar_val = 10
print(f"Scalar: {scalar_val}, Type: {type(scalar_val)}")# 向量 (1D Array)
vector_v = np.array([1.0, 2.5, -3.0])
print(f"\nVector v: {vector_v}")
print(f"Shape: {vector_v.shape}") # (3,)# 矩阵 (2D Array)
matrix_M = np.array([[1, 2, 3],[4, 5, 6]])
print(f"\nMatrix M:\n{matrix_M}")
print(f"Shape: {matrix_M.shape}") # (2, 3)# 张量 (3D Array)
tensor_T = np.arange(12).reshape((2, 3, 2)) # 创建一个 0 到 11 的数组,并重塑为 2x3x2
print(f"\nTensor T:\n{tensor_T}")
print(f"Shape: {tensor_T.shape}") # (2, 3, 2)print("\n--- 3.2 执行基本运算 ---")# 准备用于运算的矩阵 (确保形状兼容)
A = np.array([[1, 0], [-1, 2]]) # Shape (2, 2)
B = np.array([[3, -2], [1, 4]]) # Shape (2, 2)
C = np.array([[5], [6]]) # Shape (2, 1) - 列向量
s = 2 # 标量# 元素级加法 (需要相同形状)
print(f"\nElement-wise Addition (A + B):\n{A + B}")# 元素级减法
print(f"\nElement-wise Subtraction (A - B):\n{A - B}")# 标量乘法
print(f"\nScalar Multiplication (s * A):\n{s * A}")# 哈达玛积 (元素级乘法)
print(f"\nHadamard Product (A * B):\n{A * B}")# 矩阵转置
print(f"\nMatrix Transpose (A.T):\n{A.T}")
print(f"Shape of A: {A.shape}, Shape of A.T: {A.T.shape}") # (2, 2) -> (2, 2)
print(f"\nMatrix Transpose (C.T):\n{C.T}")
print(f"Shape of C: {C.shape}, Shape of C.T: {C.T.shape}") # (2, 1) -> (1, 2)# 向量点积 (需要长度相同)
v1 = np.array([1, 2, 3])
v2 = np.array([4, 5, 6])
print(f"\nVector Dot Product (v1 . v2): {np.dot(v1, v2)}") # 32
# 或者 v1 @ v2# 矩阵乘法 (需要内维匹配)
# A(2x2) @ B(2x2) -> (2x2)
print(f"\nMatrix Multiplication (A @ B):\n{A @ B}") # 使用 @ 运算符
# 或者 np.dot(A, B)# A(2x2) @ C(2x1) -> (2x1)
print(f"\nMatrix Multiplication (A @ C):\n{A @ C}")# 尝试不兼容的乘法 B(2x2) @ C.T(1x2) -> 会报错
try:B @ C.T
except ValueError as e:print(f"\nError multiplying B(2x2) and C.T(1x2): {e}")# C.T(1x2) @ A(2x2) -> (1x2)
print(f"\nMatrix Multiplication (C.T @ A):\n{C.T @ A}")
这段代码演示了如何在 NumPy 中轻松地创建和操作这些线性代数对象。熟练使用 NumPy 是进行深度学习实践的基础。
四、常见问题与提示
在学习和应用线性代数,特别是在编程实现时,新手常常会遇到一些问题。这里列举几个常见点:
4.1 维度不匹配 (Dimension Mismatch)
- 问题: 这是最常见的错误之一,尤其是在进行矩阵乘法和元素级运算时。例如,试图将一个 3 × 2 3 \times 2 3×2 矩阵和一个 3 × 3 3 \times 3 3×3 矩阵进行元素级相加,或者将一个 2 × 3 2 \times 3 2×3 矩阵和一个 2 × 2 2 \times 2 2×2 矩阵进行矩阵乘法,都会导致维度不匹配错误。
- 排查建议:
- 在进行运算前,务必使用
print(matrix.shape)
检查参与运算的张量的形状。 - 牢记矩阵乘法 A B AB AB 的要求: A A A 的列数必须等于 B B B 的行数。
- 牢记元素级运算的要求:参与运算的张量必须具有完全相同的形状(或者满足广播机制,后续文章会介绍)。
- 仔细阅读报错信息,它通常会明确指出哪个操作在哪一步维度不匹配。
- 在进行运算前,务必使用
4.2 区分哈达玛积与矩阵乘法
- 问题: 初学者容易混淆元素级乘法(哈达玛积)和矩阵乘法,尤其是在 NumPy 中,它们对应不同的运算符。
- 排查建议:
- 哈达玛积 (Element-wise): 使用
*
运算符。要求两个张量形状相同。 - 矩阵乘法 (Dot Product): 使用
@
运算符 (Python 3.5+) 或np.dot()
函数。要求内维匹配。 - 明确你的计算意图:你是想让对应元素相乘,还是想进行标准的线性变换?根据意图选择正确的运算。
- 哈达玛积 (Element-wise): 使用
4.3 理解张量的轴 (Understanding Tensor Axes)
- 问题: 当处理三维或更高维张量时,理解每个轴(维度)代表什么变得至关重要,尤其是在进行求和、取最大值、转置等操作时指定
axis
参数。 - 提示:
- 通常,深度学习中张量的轴有约定俗成的含义,例如图像的
(batch, height, width, channels)
或 NLP 中的(batch, sequence_length, embedding_dim)
。 - 在调用 NumPy 或框架函数时,注意
axis
参数的用法。例如,np.sum(tensor, axis=0)
会沿着第一个轴(通常是批次维度)求和。 - 多打印中间结果的形状 (
.shape
) 来确认操作是否符合预期。
- 通常,深度学习中张量的轴有约定俗成的含义,例如图像的
五、总结
恭喜你完成了深度学习数学基础的第一部分——线性代数核心!回顾一下本篇的主要内容:
- 数据表示的重要性: 线性代数是深度学习中表示和操作数据的通用语言。标量、向量、矩阵和张量是构建模型和处理信息的基本数据结构。
- 核心数据结构:
- 标量 (Scalar): 单个数值 (0D)。
- 向量 (Vector): 一维有序数组 (1D),用于表示特征、词嵌入等。
- 矩阵 (Matrix): 二维数组 (2D),用于表示图像、数据批次、权重等。
- 张量 (Tensor): 多维数组 (nD),是前三者的推广,深度学习框架中的标准数据格式。
- 关键运算:
- 元素级运算 (加、减、哈达玛积): 对相同形状张量的对应元素进行操作。
- 标量乘法: 用标量缩放张量中的每个元素。
- 转置: 交换矩阵的行和列 ( A T A^T AT)。
- 点积/内积: 向量运算,结果为标量,衡量相似度。
- 矩阵乘法: 核心运算,实现线性变换,是神经网络信息传递的关键,注意维度匹配和不可交换性。
- NumPy 实践: NumPy 提供了高效实现这些线性代数运算的工具,熟练使用 NumPy 是深度学习编程的基础。
- 关键提示: 注意维度匹配、区分哈达玛积与矩阵乘法、理解张量轴是避免常见错误的关键。
线性代数构成了深度学习算法的骨架。虽然我们没有深入探讨所有理论细节,但理解这些核心概念和运算对于你阅读后续内容、理解模型工作原理以及动手实践至关重要。
在下一篇文章 【深度学习-Day 3】必备数学(二) - 微积分关键 中,我们将探讨另一个数学基石——微积分,特别是导数、偏导数和链式法则,它们是理解模型如何“学习”(优化参数)的关键。敬请期待!