引言

线性代数是AI算法工程师必须掌握的基础数学工具。无论是机器学习中的数据表示,还是深度学习中的矩阵运算,线性代数都扮演着至关重要的角色。本文将介绍AI学习中最重要的线性代数概念,帮助大家打好数学基础。

一、向量:数据的表示方式

1.1 向量的基本概念

向量是线性代数的基本单位,在AI中用于表示数据样本或特征。

import numpy as np

# 创建向量
v = np.array([1, 2, 3, 4, 5])
print("向量 v:", v)
print("向量形状:", v.shape)

# 向量运算
u = np.array([2, 4, 6, 8, 10])

# 加法
print("\n向量加法:")
print("u + v =", u + v)

# 数乘
print("\n标量乘法:")
print("2 * v =", 2 * v)

# 点积
print("\n向量点积:")
print("u · v =", np.dot(u, v))

# 向量范数(模长)
print("\n向量范数:")
print("||v|| =", np.linalg.norm(v))

1.2 向量的应用场景

在机器学习中,向量通常用于表示:

  • 样本特征:一个样本的所有特征值组成一个向量
  • 权重向量:线性模型中的参数
  • 词向量:NLP中的词语表示(Word2Vec)
# 示例:用向量表示一个图像样本(28x28展平为784维)
image_vector = np.random.rand(784)  # 模拟MNIST图像
print("图像向量形状:", image_vector.shape)

# 示例:用向量表示词嵌入
word_embedding = {
    'word': np.random.rand(300),  # 300维词向量
    'embedding': np.random.rand(300),
    'vector': np.random.rand(300)
}

二、矩阵:批量数据的表示

2.1 矩阵的基本概念

矩阵是二维数组,在AI中用于表示批量数据或线性变换。

# 创建矩阵
A = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])

print("矩阵 A:")
print(A)
print("\n矩阵形状:", A.shape)

# 矩阵基本运算
B = np.array([[9, 8, 7],
              [6, 5, 4],
              [3, 2, 1]])

# 矩阵加法
print("\n矩阵加法:")
print("A + B =")
print(A + B)

# 矩阵乘法
print("\n矩阵乘法:")
print("A @ B =")
print(np.dot(A, B))

# 矩阵转置
print("\n矩阵转置:")
print("A.T =")
print(A.T)

# 单位矩阵
I = np.eye(3)
print("\n3x3单位矩阵:")
print(I)

# 逆矩阵
A_square = np.array([[1, 2], [3, 4]])
A_inv = np.linalg.inv(A_square)
print("\n矩阵逆运算:")
print("A的逆矩阵:")
print(A_inv)
print("A @ A^{-1} =")
print(np.dot(A_square, A_inv))

2.2 矩阵在AI中的应用

# 示例1:用矩阵表示批量图像数据
# 假设有100张28x28的图像,展平后构成(100, 784)的矩阵
batch_images = np.random.rand(100, 784)
print("图像批量矩阵形状:", batch_images.shape)

# 示例2:用矩阵表示全连接层的权重
# 输入层784维,输出层10维
W = np.random.randn(784, 10)  # 权重矩阵
b = np.random.randn(10)       # 偏置向量
print("权重矩阵形状:", W.shape)

# 前向传播计算
input_vector = np.random.randn(784)
output = np.dot(input_vector, W) + b
print("输出向量形状:", output.shape)

# 示例3:用矩阵表示卷积核
# 假设3个通道,3x3卷积核,输出16个特征图
conv_kernel = np.random.randn(3, 3, 3, 16)
print("卷积核形状:", conv_kernel.shape)

三、特征值与特征向量

3.1 概念解释

特征值和特征向量用于理解矩阵的"本质"变换:

  • 特征向量:在矩阵变换后方向不变的向量
  • 特征值:特征向量在变换后的伸缩倍数
# 计算特征值和特征向量
A = np.array([[4, 1],
              [2, 3]])

eigenvalues, eigenvectors = np.linalg.eig(A)

print("矩阵 A:")
print(A)
print("\n特征值:")
print(eigenvalues)
print("\n特征向量:")
print(eigenvectors)

3.2 特征值分解的应用

# PCA降维中的特征值分解
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt

# 加载数据
iris = load_iris()
X = iris.data
y = iris.target

# PCA降维到2维
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)

print("原始数据形状:", X.shape)
print("PCA后数据形状:", X_pca.shape)
print("各主成分解释的方差比例:", pca.explained_variance_ratio_)
print("特征值:", pca.explained_variance_)

# 可视化
plt.figure(figsize=(8, 6))
colors = ['navy', 'turquoise', 'darkorange']
for i, color in enumerate(colors):
    plt.scatter(X_pca[y == i, 0], X_pca[y == i, 1], 
                c=color, label=iris.target_names[i], alpha=0.8)
plt.xlabel('First Principal Component')
plt.ylabel('Second Principal Component')
plt.title('PCA of IRIS Dataset')
plt.legend()
plt.tight_layout()
plt.savefig('pca_visualization.png', dpi=150)
plt.show()

四、奇异值分解(SVD)

4.1 概念解释

SVD是矩阵分解的更通用形式,任何矩阵都可以分解为三个矩阵的乘积:

$$A = U \cdot \Sigma \cdot V^T$$

# SVD分解
A = np.array([[1, 2, 3],
              [4, 5, 6]])

U, s, Vt = np.linalg.svd(A)

print("原始矩阵 A:")
print(A)
print("\nU 矩阵:")
print(U)
print("\n奇异值向量 s:")
print(s)
print("\nVt 矩阵:")
print(Vt)

# 重构矩阵
Sigma = np.zeros_like(A)
np.fill_diagonal(Sigma, s)
A_reconstructed = U @ Sigma @ Vt
print("\n重构的矩阵:")
print(A_reconstructed)

4.2 SVD的典型应用

# 应用1:图像压缩
from skimage import data, color
from skimage.transform import resize
import matplotlib.image as mpimg

# 加载图像并转为灰度
img = color.rgb2gray(mpimg.imread('example_image.jpg'))
print("图像形状:", img.shape)

# SVD分解
U, s, Vt = np.linalg.svd(img)
print("奇异值数量:", len(s))

# 用前k个奇异值重构图像
def reconstruct_image(U, s, Vt, k):
    Sigma = np.zeros_like(img)
    np.fill_diagonal(Sigma[:k, :k], s[:k])
    return U @ Sigma @ Vt

# 比较不同k值的效果
fig, axes = plt.subplots(1, 4, figsize=(16, 4))
k_values = [5, 20, 50, 100]

for ax, k in zip(axes, k_values):
    img_reconstructed = reconstruct_image(U, s, Vt, k)
    ax.imshow(img_reconstructed, cmap='gray')
    ax.set_title(f'k={k}')
    ax.axis('off')

plt.suptitle('SVD Image Compression')
plt.tight_layout()
plt.savefig('svd_compression.png', dpi=150)
plt.show()

# 应用2:推荐系统中的协同过滤
def matrix_factorization(R, k, learning_rate=0.01, epochs=100):
    """
    简单的矩阵分解用于推荐系统
    R: 用户-物品评分矩阵
    k: 隐因子数量
    """
    m, n = R.shape
    np.random.seed(42)
    
    # 初始化
    U = np.random.randn(m, k)
    V = np.random.randn(n, k)
    
    # 梯度下降
    for epoch in range(epochs):
        for i in range(m):
            for j in range(n):
                if R[i, j] > 0:
                    error = R[i, j] - np.dot(U[i], V[j])
                    U[i] += learning_rate * error * V[j]
                    V[j] += learning_rate * error * U[i]
    
    return U, V

# 示例用户评分矩阵
R = np.array([
    [5, 3, 0, 1],
    [4, 0, 0, 1],
    [1, 1, 0, 5],
    [1, 0, 0, 4],
    [0, 1, 5, 4]
])

U, V = matrix_factorization(R, k=2)
print("用户矩阵 U:")
print(U)
print("\n物品矩阵 V:")
print(V)

五、矩阵运算在神经网络中的应用

5.1 全连接层的矩阵运算

class FullyConnectedLayer:
    """全连接层的前向传播"""
    
    def __init__(self, input_size, output_size):
        # Xavier初始化
        self.W = np.random.randn(input_size, output_size) * np.sqrt(2.0 / input_size)
        self.b = np.zeros(output_size)
    
    def forward(self, x):
        # y = xW + b
        self.x = x  # 保存输入用于反向传播
        return np.dot(x, self.W) + self.b
    
    def backward(self, grad_output, learning_rate=0.01):
        # 计算梯度
        grad_input = np.dot(grad_output, self.W.T)
        grad_W = np.dot(self.x.T, grad_output)
        grad_b = np.sum(grad_output, axis=0)
        
        # 更新参数
        self.W -= learning_rate * grad_W
        self.b -= learning_rate * grad_b
        
        return grad_input

# 测试全连接层
layer = FullyConnectedLayer(input_size=784, output_size=10)
x = np.random.randn(100, 784)  # 100个样本
output = layer.forward(x)
print("输入形状:", x.shape)
print("输出形状:", output.shape)

5.2 卷积运算的矩阵实现

def im2col(X, kernel_size, stride=1, pad=0):
    """
    将图像块转换为列,方便卷积运算
    X: 输入图像 (H, W, C)
    """
    H, W, C = X.shape
    X_padded = np.pad(X, ((pad, pad), (pad, pad), (0, 0)), mode='constant')
    
    # 计算输出尺寸
    out_h = (H + 2 * pad - kernel_size) // stride + 1
    out_w = (W + 2 * pad - kernel_size) // stride + 1
    
    # 提取所有图像块
    patches = []
    for i in range(out_h):
        for j in range(out_w):
            patch = X_padded[i*stride:i*stride+kernel_size,
                             j*stride:j*stride+kernel_size, :]
            patches.append(patch.reshape(-1))
    
    return np.array(patches).T  # (kernel_size*kernel_size*C, out_h*out_w)

def convolution_matrix(X, kernel, stride=1, pad=0):
    """
    使用矩阵乘法实现卷积
    """
    # 展开输入
    X_col = im2col(X, kernel.shape[0], stride, pad)
    
    # 展开卷积核
    K_flat = kernel.reshape(-1, 1)
    
    # 矩阵乘法实现卷积
    out = X_col.T @ K_flat
    
    # 恢复形状
    H, W, C = X.shape
    out_h = (H + 2 * pad - kernel.shape[0]) // stride + 1
    out_w = (W + 2 * pad - kernel.shape[0]) // stride + 1
    
    return out.reshape(out_h, out_w, -1).squeeze()

# 测试
X_test = np.random.randn(8, 8, 3)  # 8x8的RGB图像
kernel_test = np.random.randn(3, 3, 3)  # 3x3卷积核

output = convolution_matrix(X_test, kernel_test, stride=1, pad=0)
print("输入形状:", X_test.shape)
print("卷积核形状:", kernel_test.shape)
print("输出形状:", output.shape)

六、总结

本文介绍了AI学习中最重要的线性代数概念:

  • 向量与矩阵的基本运算
  • 特征值分解与SVD
  • 矩阵运算在神经网络中的应用

这些数学知识是后续学习机器学习和深度学习的基础,建议大家多动手实践,加深理解。


下期预告:🚀 第3篇 | AI工程师必备数学基础:概率论与统计

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐