Skip to content

知识点卡片:向量与矩阵运算

基本信息

属性内容
知识点向量与矩阵运算
掌握程度★★★★★
学习优先级P0
预估时间8小时
面试频率★★★★★

核心原理

向量和矩阵是神经网络计算的基本数学对象:

  • 向量:一维数组,表示空间中的点或方向
  • 矩阵:二维数组,表示线性变换

神经网络中的矩阵运算

python
import numpy as np

# 神经网络前向传播 = 矩阵乘法
# input: (batch_size, input_dim)
# weight: (input_dim, hidden_dim)
# output: (batch_size, hidden_dim)

X = np.random.randn(32, 784)  # batch_size=32, 784维输入(如MNIST)
W = np.random.randn(784, 256) # 权重矩阵
Y = X @ W                     # 矩阵乘法

核心运算

1. 矩阵乘法

python
# 神经网络中的全连接层
# y = x @ W + b
def fully_connected(x, W, b):
    return x @ W + b

2. 逐元素运算

python
# 激活函数(ReLU)
# y = max(0, x)
y = np.maximum(0, x)

# Sigmoid
# y = 1 / (1 + exp(-x))
y = 1 / (1 + np.exp(-x))

3. 转置

python
# Transformer中的Q @ K^T
# Q: (batch, heads, seq, d_k)
# K: (batch, heads, seq, d_k)
attn_scores = Q @ K.transpose(-2, -1)

4. 批量矩阵乘法

python
# Multi-Head Attention中的批量乘法
# Q: (B, H, T, D)  K: (B, H, T, D)
# 输出: (B, H, T, T)
scores = torch.bmm(q.view(B*H, T, D), k.view(B*H, T, D).transpose(1, 2))

面试高频问题

Q1: 矩阵乘法和逐元素乘法的区别?

  • 矩阵乘法(@):(m,n) @ (n,k) → (m,k),涉及行-列点积
  • 逐元素乘法(*):形状必须相同,对应位置相乘
python
A = [[1,2], [3,4]]
B = [[5,6], [7,8]]

# 矩阵乘法
A @ B = [[1*5+2*7, 1*6+2*8], [3*5+4*7, 3*6+4*8]] = [[19, 22], [43, 50]]

# 逐元素乘法
A * B = [[5, 12], [21, 32]]

Q2: 为什么神经网络用矩阵乘法而不是循环?

  • 并行计算:GPU对矩阵乘法有高度优化
  • 计算效率:O(n³) vs 循环的O(n²)但更慢
  • 数学简洁:便于理论分析

Q3: 神经网络中的偏置项有什么用?

  • 增加模型的表达能力
  • 打破对称性(否则多层等价于单层)
  • 调整激活函数的输出位置
python
# 有偏置
y = x @ W + b

# 无偏置:所有样本的输出都会偏移原点
y = x @ W

代码练习

python
import numpy as np

# 1. 实现一个全连接层的前向传播
def fully_connected_forward(X, W, b):
    """
    X: (batch_size, input_dim)
    W: (input_dim, output_dim)
    b: (output_dim,)
    返回: (batch_size, output_dim)
    """
    return X @ W + b

# 2. 实现ReLU激活函数
def relu(x):
    return np.maximum(0, x)

# 3. 实现Softmax
def softmax(x):
    exp_x = np.exp(x - np.max(x, axis=-1, keepdims=True))  # 数值稳定
    return exp_x / np.sum(exp_x, axis=-1, keepdims=True)

# 4. 验证维度
X = np.random.randn(32, 784)
W = np.random.randn(784, 256)
b = np.zeros(256)

y = fully_connected_forward(X, W, b)
print(f"输入: {X.shape} → 输出: {y.shape}")
# 期望: 输入: (32, 784) → 输出: (32, 256)

必读资料


相关知识点