Skip to content
  1. 简述矩阵特征值和特征向量的数学含义,并借助 matlab 或 python 等编程工具计算如下数据的协方差矩阵以及其特征值和特征向量。数据矩阵每一行为一位学生的特征向量。
X=[11.234.622.135423.15.3353.24.342183439]

数学意义:Av=λvv 为特征向量,λ 为特征值。 从几何意义上,低维可视化条件下,λ 代表了在特征向量方向上的拉伸倍数。特征向量经过矩阵变化后,方向不变,只改变长度。扩展到高维,虽然无法直观“看见”方向,但特征向量仍代表数据或系统内在结构中“保持不变的演化轴”,而 λ 依然量化了沿该轴的缩放强度,揭示了高维空间中最本质的变换模式与数据主干结构,进一步可用于 PCA 降维(例如 768 维词向量投影 2/3 维,主成分滤波器实现图片压缩)。

计算:

python
import torch

X = torch.tensor(
    [
        [1.0, 1.2, 3.0, 4.6],
        [2.0, 2.1, 3.0, 5.0],
        [4.0, 2.0, 3.1, 5.3],
        [3.0, 5.0, 3.2, 4.3],
        [4.0, 2.0, 1.0, 8.0],
        [3.0, 4.0, 3.0, 9.0],
    ],
    dtype=torch.float32,
)
mean = torch.mean(X, dim=0, keepdim=True)

X_centered = X - mean

X_samples = X_centered.shape[0]
cov_matrix = torch.mm(X_centered.t(), X_centered / (X_samples - 1))

print(f"Sigma: \n{cov_matrix}\n")

eigenvalues, eigenvectors = torch.linalg.eigh(cov_matrix)
print(f"Eigenvalues: \n{eigenvalues}\n")
print(f"Eigenvectors: \n{eigenvectors}\n")

结果:

python
Sigma: 
tensor([[ 1.3667,  0.4433, -0.4367,  1.0267],
        [ 0.4433,  2.1137,  0.3637,  0.3553],
        [-0.4367,  0.3637,  0.7137, -0.8707],
        [ 1.0267,  0.3553, -0.8707,  3.8667]])

Eigenvalues:
tensor([0.2858, 0.9982, 2.2325, 4.5442])

Eigenvectors:
tensor([[-0.3348,  0.8635, -0.1562,  0.3434],
        [ 0.2861, -0.1221, -0.9369,  0.1597],
        [-0.8856, -0.3016, -0.2700, -0.2279],
        [-0.1477, -0.3855,  0.1580,  0.8970]])
  1. 请将给定的上述彩色图像,利用 matlab 或 python 等软件变换为灰度图像,缩放至 256 像素 * 256 像素,并利用奇异值分解将其分解与压缩。 (请详细阐述奇异值分解的图像压缩原理)

奇异值分解:

A=UΣVT

矩阵 ARm×n 描述了一个从 n - 维空间到 m - 维空间的线性变换,而 SVD 通过分解揭示了这一变换的内在几何结构。

VT:将输入向量投影到右奇异向量(即主成分方向)构成的正交基上,实现输入空间的坐标系对齐;
Σ:沿各主成分方向按奇异值进行拉伸或压缩,并可通过截断最小奇异值实现降维
U:将缩放后的结果映射到左奇异向量构成的输出空间正交基中,完成最终变换。

整体流程:旋转 → 缩放 → 再旋转

接下来利用这个机制,通过构造低秩矩阵,截断奇异值,实现图像压缩。

Ak=UkΣkVkT

也就是说,原来 n,(nk) 的矩阵,现在我们用 k 个基底去近似,保留前 k 个最重要的方向,将多出的维度丢弃。然后再还原回原维度,但是已经是重构矩阵 Ak 这个低秩结果。 此时我们不需要存储原单通道灰度矩阵,而是只要存储三个变换矩阵:Uk,Σk,VkT,最终计算出近似重构矩阵 Ak。当然,如果满足: $$k=rank (A)=\text{非零奇异向量个数}$$ 则图片无损。

python
import numpy as np
from torchvision import transforms
from PIL import Image

image = Image.open('./test.png')

transform = transforms.Compose([
    transforms.Grayscale(num_output_channels=1),
    transforms.Resize((256, 256)),
])
gray_image = transform(image)

gray_image.save('./test_gray.png')

A = np.array(gray_image, dtype=float)        # 转为浮点数组
U, s, Vt = np.linalg.svd(A)                  # SVD 分解
k = 20                                       # 保留前 20 个奇异值
A_k = U[:, :k] @ np.diag(s[:k]) @ Vt[:k, :]  # 重构低秩近似
Image.fromarray(np.clip(A_k, 0, 255).astype(np.uint8), mode='L').save('./test_compressed.png')
print(f"rank(A) = {len(s)} -> {k}")

压缩前 k=256image.png 压缩后 k=20image.png