这一章初学建议看该视频学习,讲得歪瑞古德: 《统计学习方法》李航 第15章奇异值分解
1.矩阵的奇异值分解是指将
m
×
n
m \times n
m×n实矩阵
A
A
A表示为以下三个实矩阵乘积形式的运算
A
=
U
Σ
V
T
A = U \Sigma V ^ { T }
A=UΣVT
其中
U
U
U是
m
m
m阶正交矩阵,
V
V
V是
n
n
n阶正交矩阵,
Σ
\Sigma
Σ是
m
×
n
m \times n
m×n矩形对角矩阵
Σ
=
diag
(
σ
1
,
σ
2
,
⋯
,
σ
p
)
,
p
=
min
{
m
,
n
}
\Sigma = \operatorname { diag } ( \sigma _ { 1 } , \sigma _ { 2 } , \cdots , \sigma _ { p } ) , \quad p = \operatorname { min } \{ m , n \}
Σ=diag(σ1,σ2,⋯,σp),p=min{m,n}
其对角线元素非负,且满足
σ
1
≥
σ
2
≥
⋯
≥
σ
p
≥
0
\sigma _ { 1 } \geq \sigma _ { 2 } \geq \cdots \geq \sigma _ { p } \geq 0
σ1≥σ2≥⋯≥σp≥0
2.任意给定一个实矩阵,其奇异值分解一定存在,但并不唯一。
3.奇异值分解包括紧奇异值分解和截断奇异值分解。紧奇异值分解是与原始矩阵等秩的奇异值分解,截断奇异值分解是比原始矩阵低秩的奇异值分解。
4.奇异值分解有明确的几何解释。奇异值分解对应三个连续的线性变换:一个旋转变换,一个缩放变换和另一个旋转变换。第一个和第三个旋转变换分别基于空间的标准正交基进行。
5.设矩阵 A A A的奇异值分解为 A = U Σ V T A = U \Sigma V ^ { T } A=UΣVT,则有 A T A = V ( Σ T Σ ) V T A A T = U ( Σ Σ T ) U T \left. \begin{array} { l } { A ^ { T } A = V ( \Sigma ^ { T } \Sigma ) V ^ { T } } \\ { A A ^ { T } = U ( \Sigma \Sigma ^ { T } ) U ^ { T } } \end{array} \right. ATA=V(ΣTΣ)VTAAT=U(ΣΣT)UT
即对称矩阵 A T A A^TA ATA和 A A T AA^T AAT的特征分解可以由矩阵 A A A的奇异值分解矩阵表示。
6.矩阵 A A A的奇异值分解可以通过求矩阵 A T A A^TA ATA的特征值和特征向量得到: A T A A^TA ATA的特征向量构成正交矩阵 V V V的列;从 A T A A^TA ATA的特征值 λ j \lambda _ { j } λj的平方根得到奇异值 σ i \sigma _ { i } σi,即 σ j = λ j , j = 1 , 2 , ⋯ , n \sigma _ { j } = \sqrt { \lambda _ { j } } , \quad j = 1,2 , \cdots , n σj=λj,j=1,2,⋯,n
对其由大到小排列,作为对角线元素,构成对角矩阵 Σ \Sigma Σ;求正奇异值对应的左奇异向量,再求扩充的 A T A^T AT的标准正交基,构成正交矩阵 U U U的列。
7.矩阵 A = [ a i j ] m × n A = [ a _ { i j } ] _ { m \times n } A=[aij]m×n的弗罗贝尼乌斯范数定义为 ∥ A ∥ F = ( ∑ i = 1 m ∑ j = 1 n ( a i j ) 2 ) 1 2 \| A \| _ { F } = ( \sum _ { i = 1 } ^ { m } \sum _ { j = 1 } ^ { n } ( a _ { i j } ) ^ { 2 } ) ^ { \frac { 1 } { 2 } } ∥A∥F=(i=1∑mj=1∑n(aij)2)21在秩不超过 k k k的 m × n m \times n m×n矩阵的集合中,存在矩阵 A A A的弗罗贝尼乌斯范数意义下的最优近似矩阵 X X X。秩为 k k k的截断奇异值分解得到的矩阵 A k A_k Ak能够达到这个最优值。奇异值分解是弗罗贝尼乌斯范数意义下,也就是平方损失意义下的矩阵最优近似。
8.任意一个实矩阵
A
A
A可以由其外积展开式表示
A
=
σ
1
u
1
v
1
T
+
σ
2
u
2
v
2
T
+
⋯
+
σ
n
u
n
v
n
T
A = \sigma _ { 1 } u _ { 1 } v _ { 1 } ^ { T } + \sigma _ { 2 } u _ { 2 } v _ { 2 } ^ { T } + \cdots + \sigma _ { n } u _ { n } v _ { n } ^ { T }
A=σ1u1v1T+σ2u2v2T+⋯+σnunvnT
其中
u
k
v
k
T
u _ { k } v _ { k } ^ { T }
ukvkT为
m
×
n
m \times n
m×n矩阵,是列向量
u
k
u _ { k }
uk和行向量
v
k
T
v _ { k } ^ { T }
vkT的外积,
σ
k
\sigma _ { k }
σk为奇异值,
u
k
,
v
k
T
,
σ
k
u _ { k } , v _ { k } ^ { T } , \sigma _ { k }
uk,vkT,σk通过矩阵
A
A
A的奇异值分解得到。
奇异值分解的计算
1. 计算 A T A A^T A ATA 的特征向量和特征值
- 设 A A A 是一个 m × n m \times n m×n 的矩阵, r a n k ( A ) = r rank(A)=r rank(A)=r。
- 计算 W = A T A W=A^T A W=ATA,它是一个 n × n n \times n n×n 的对称矩阵。
W = A T A ∈ R n × n W=A^T A \in \mathbb{R}^{n \times n} W=ATA∈Rn×n
- 计算 A T A A^T A ATA 的特征值和特征向量:
A T A v i = λ i v i , i = 1 , 2 , … , n A^T A \mathbf{v}_i = \lambda_i \mathbf{v}_i, \quad i = 1, 2, \ldots, n ATAvi=λivi,i=1,2,…,n
其中, λ 1 ≥ λ 2 ≥ … ≥ λ n ≥ 0 \lambda_1\geq\lambda_2\geq\ldots\geq\lambda_n\geq0 λ1≥λ2≥…≥λn≥0 , v i \mathbf{v}_i vi 是对应的特征向量。
2. 求 m × n m \times n m×n 对角矩阵 Σ \Sigma Σ
- 特征值的平方根即为奇异值:
σ i = λ i , i = 1 , 2 , … , n \sigma_i = \sqrt{\lambda_i}, \quad i = 1, 2, \ldots, n σi=λi,i=1,2,…,n
则
Σ = d i a g ( σ 1 , σ 2 , … , σ n ) \Sigma=diag(\sigma_1,\sigma_2,\ldots,\sigma_n) Σ=diag(σ1,σ2,…,σn)
3. 计算 n n n 阶正交矩阵 V V V 矩阵
- V V V 矩阵由 A T A A^T A ATA 的特征向量组成:
V = [ v 1 , v 2 , … , v n ] V = [\mathbf{v}_1, \mathbf{v}_2, \ldots, \mathbf{v}_n] V=[v1,v2,…,vn]
4. 计算 U 1 U_1 U1
- 对 A A A 的前 r r r 个正奇异值,通过下面的公式计算 U 1 U_1 U1:
U 1 = [ A v 1 σ 1 , A v 2 σ 2 , … , A v r σ r ] U_1 = \left[ \frac{A \mathbf{v}_1}{\sigma_1}, \frac{A \mathbf{v}_2}{\sigma_2}, \ldots, \frac{A \mathbf{v}_r}{\sigma_r} \right] U1=[σ1Av1,σ2Av2,…,σrAvr]
5. 计算 A T A^T AT 的零空间
- 使用 A T A^T AT 的零空间的标准正交基作为 U 2 U_2 U2:
U 2 = n u l l _ s p a c e ( A T ) U2 = {null\_space} (A^T) U2=null_space(AT)
其中,null_space
是一个函数,用于计算矩阵零空间的标准正交基。
6. 合并 U 1 U_1 U1 和 U 2 U_2 U2
- 将 U 1 U_1 U1 和 U 2 U_2 U2 合并,构成 m m m 阶正交矩阵 U U U:
U = [ U 1 , U 2 ] U = [U_1, U_2] U=[U1,U2]
7.得到奇异值分解
A = U Σ V T A=U\Sigma V^T A=UΣVT
习题15.1
试求矩阵 A = [ 1 2 0 2 0 2 ] A = \left[ \begin{array}{lll} 1 & 2 & 0 \\ 2 & 0 & 2 \\ \end{array} \right] A=[122002]的奇异值分解。
解答:
手算见该链接
使用numpy实现奇异值分解
import numpy as np
A = np.array([[1, 2, 0], [2, 0, 2]])
# 调用numpy的svd方法
U, S, VT = np.linalg.svd(A)
# 设置NumPy打印选项,将小数点后保留两位数字并抑制科学计数法(即不使用科学计数法显示较小的数字)
np.set_printoptions(precision=2, suppress=True)
print("U=", U)
print("S=", S)
print("V=", VT.T)
Sigma = np.zeros_like(A, float)
np.fill_diagonal(Sigma, S)
calc = np.dot(np.dot(U, Sigma), VT)
print("A=", calc)
U= [[ 0.45 -0.89]
[ 0.89 0.45]]
S= [3. 2.]
V= [[ 0.75 0. -0.67]
[ 0.3 -0.89 0.33]
[ 0.6 0.45 0.67]]
A= [[ 1. 2. 0.]
[ 2. -0. 2.]]
自编程实现奇异值分解
import numpy as np
from scipy.linalg import null_space
def my_svd(A):
m = A.shape[0]
# (1) 计算对称矩阵 A^T A 的特征值与特征向量,
W = np.dot(A.T, A)
# 返回的特征值lambda_value是升序的,特征向量V是单位化的特征向量
lambda_value, V = np.linalg.eigh(W)
# 并按特征值从大到小排列
lambda_value = lambda_value[::-1]
lambda_value = lambda_value[lambda_value > 0]
# (2)计算n阶正交矩阵V
V = V[:, -1::-1]
# (3) 求 m * n 对角矩阵
sigma = np.sqrt(lambda_value)
S = np.diag(sigma) @ np.eye(*A.shape) # *A.shape 使用形状参数来创建一个与 A 形状相同的单位矩阵 I。@为矩阵乘法运算符
# (4.1) 求A的前r个正奇异值
r = np.linalg.matrix_rank(A)
U1 = np.hstack([(np.dot(A, V[:, i]) / sigma[i])[:, np.newaxis] # [:, np.newaxis] 将结果转化为列向量
for i in range(r)]) # np.hstack([...]) 将所有列向量水平堆叠,形成矩阵 U1
# (4.2) 求A^T的零空间的一组标准正交基
U = U1
if r < m:
U2 = null_space(A.T)
U = np.hstack([U, U2])
return U, S, V
A = np.array([[1, 2, 0], [2, 0, 2]])
np.set_printoptions(precision=2, suppress=True)
U, S, V = my_svd(A)
print("U=", U)
print("S=", S)
print("V=", V)
calc = np.dot(np.dot(U, S), V.T)
print("A=", calc)
U= [[-0.45 -0.89]
[-0.89 0.45]]
S= [[3. 0. 0.]
[0. 2. 0.]]
V= [[-0.75 -0. -0.67]
[-0.3 -0.89 0.33]
[-0.6 0.45 0.67]]
A= [[ 1. 2. -0.]
[ 2. -0. 2.]]
习题15.2
试求矩阵
A
=
[
2
4
1
3
0
0
0
0
]
A = \left[ \begin{array}{lll} 2 & 4 \\ 1 & 3 \\ 0 & 0 \\ 0 & 0 \end{array} \right]
A=
21004300
的奇异值分解并写出其外积展开式。
矩阵 A A A的奇异值分解 U Σ V T U \Sigma V^T UΣVT也可以由外积形式表示。事实上,若将 A A A的奇异值分解看成矩阵 U Σ U \Sigma UΣ和 V T V^T VT的乘积,将 U Σ U \Sigma UΣ按列向量分块,将 V T V^T VT按行向量分块,即得
U
Σ
=
[
σ
1
u
1
σ
2
u
2
⋯
σ
n
u
n
]
V
T
=
[
v
1
T
v
2
T
⋮
v
n
T
]
\begin{array}{l} U \Sigma = \big[ \sigma_1 u_1 \ \sigma_2 u_2 \ \cdots \ \sigma_n u_n \big] \\ V^T = \left[ \begin{array}{c} v_1^T \\ v_2^T \\ \vdots \\ v_n^T \end{array} \right] \end{array}
UΣ=[σ1u1 σ2u2 ⋯ σnun]VT=
v1Tv2T⋮vnT
则
A
=
σ
1
u
1
v
1
T
+
σ
2
u
2
v
2
T
+
⋯
+
σ
n
u
n
v
n
T
A = \sigma_1 u_1 v_1^T + \sigma_2 u_2 v_2^T + \cdots + \sigma_n u_n v_n^T
A=σ1u1v1T+σ2u2v2T+⋯+σnunvnT
称为矩阵
A
A
A的外积展开式,其中
u
k
v
k
T
u_k v_k^T
ukvkT为
m
×
n
m \times n
m×n矩阵,是列向量
u
k
u_k
uk和行向量
v
k
T
v_k^T
vkT的外积,其第
i
i
i行第
j
j
j列元素为
u
k
u_k
uk的第
i
i
i个元素与
v
k
T
v_k^T
vkT的第
j
j
j个元素的乘积。即
u
i
v
j
T
=
[
u
1
i
u
2
i
⋮
u
m
i
]
[
v
1
j
v
2
j
⋯
v
n
j
]
=
[
u
1
i
v
1
j
u
1
i
v
2
j
⋯
u
1
i
v
n
j
u
2
i
v
1
j
u
2
i
v
2
j
⋯
u
2
i
v
n
j
⋮
⋮
⋮
u
m
i
v
1
j
u
m
i
v
2
j
⋯
u
m
i
v
n
j
]
u_i v_j^T = \left[ \begin{array}{c} u_{1i} \\ u_{2i} \\ \vdots \\ u_{mi} \end{array} \right] \big[ v_{1j} \ v_{2j} \ \cdots \ v_{nj} \big] = \left[ \begin{array}{cccc} u_{1i} v_{1j} & u_{1i} v_{2j} & \cdots & u_{1i} v_{nj} \\ u_{2i} v_{1j} & u_{2i} v_{2j} & \cdots & u_{2i} v_{nj} \\ \vdots & \vdots & & \vdots \\ u_{mi} v_{1j} & u_{mi} v_{2j} & \cdots & u_{mi} v_{nj} \end{array} \right]
uivjT=
u1iu2i⋮umi
[v1j v2j ⋯ vnj]=
u1iv1ju2iv1j⋮umiv1ju1iv2ju2iv2j⋮umiv2j⋯⋯⋯u1ivnju2ivnj⋮umivnj
A
A
A的外积展开式也可以写成下面的形式
A
=
∑
k
=
1
n
A
k
=
∑
k
=
1
n
σ
k
u
k
v
k
T
A = \sum_{k=1}^n A_k = \sum_{k=1}^n \sigma_k u_k v_k^T
A=k=1∑nAk=k=1∑nσkukvkT
其中
A
k
=
σ
k
u
k
v
k
T
A_k = \sigma_k u_k v_k^T
Ak=σkukvkT是
m
×
n
m \times n
m×n矩阵。上式将矩阵
A
A
A分解为矩阵的有序加权和。
总之,任意一个实矩阵
A
A
A可以由其外积展开式表示
A
=
σ
1
u
1
v
1
T
+
σ
2
u
2
v
2
T
+
⋯
+
σ
n
u
n
v
n
T
A = \sigma_1 u_1 v_1^T + \sigma_2 u_2 v_2^T + \cdots + \sigma_n u_n v_n^T
A=σ1u1v1T+σ2u2v2T+⋯+σnunvnT
其中 u k v k T u_k v_k^T ukvkT为 m × n m \times n m×n矩阵,是列向量 u k u_k uk和行向量 v k T v_k^T vkT的外积, σ k \sigma_k σk为奇异值, u k , v k T , σ k u_k, v_k^T, \sigma_k uk,vkT,σk通过矩阵 A A A的奇异值分解得到。
import numpy as np
A = np.array([[2, 4],
[1, 3],
[0, 0],
[0, 0]])
# 调用numpy的svd方法
U, S, VT = np.linalg.svd(A)
np.set_printoptions()
print("U=", U)
print("S=", S)
print("V=", VT.T)
U= [[-0.82 -0.58 0. 0. ]
[-0.58 0.82 0. 0. ]
[ 0. 0. 1. 0. ]
[ 0. 0. 0. 1. ]]
S= [5.46 0.37]
V= [[-0.4 -0.91]
[-0.91 0.4 ]]
根据奇异值分解的结果,写出
A
A
A的外积展开式:
A
=
σ
1
u
1
v
1
T
+
σ
2
u
2
v
2
T
A = \sigma_1 u_1 v_1^T + \sigma_2 u_2 v_2^T
A=σ1u1v1T+σ2u2v2T
其中
σ
1
=
5.46
,
σ
2
=
0.37
u
1
=
[
−
0.82
−
0.58
0
0
]
,
u
2
=
[
−
0.58
0.82
0
0
]
v
1
T
=
[
−
0.4
,
−
0.91
]
,
v
2
T
=
[
−
0.91
,
0.4
]
\sigma_1 = 5.46, \sigma_2 = 0.37 \\ u_1 = \left [ \begin{array}{c} -0.82 \\ -0.58 \\ 0 \\ 0 \end{array} \right], u_2 = \left[ \begin{array}{c} -0.58 \\ 0.82 \\ 0 \\ 0 \end{array} \right ] \\ v_1^T = [ -0.4, -0.91 ] , v_2^T = [ -0.91,0.4 ]
σ1=5.46,σ2=0.37u1=
−0.82−0.5800
,u2=
−0.580.8200
v1T=[−0.4,−0.91],v2T=[−0.91,0.4]
calc = S[0] * np.outer(U[:, 0], VT[0, :]) + S[1] * np.outer(U[:, 1], VT[1, :])
print("A=", calc)
A= [[ 2. 4.]
[ 1. 3.]
[-0. 0.]
[-0. 0.]]
习题15.3、15.4
见链接
习题15.5
搜索中的点击数据记录用户搜索时提交的查询语句,点击的网页URL以及点击的次数构成一个二部图,其中一个结点集合
{
q
i
}
\{q_i\}
{qi}表示查询,另一个结点集合
{
u
j
}
\{u_j\}
{uj}表示URL,边表示点击关系,边上的权重表示点击次数。图15.2是一个简化的点击数据例。点击数据可以由矩阵表示,试对该矩阵进行奇异值分解,并解释得到的三个矩阵所表示的内容。
第1步:根据二部图写出矩阵 A A A
A
=
[
0
20
5
0
0
10
0
0
3
0
0
0
0
0
1
0
0
1
0
0
]
A=\left[ \begin{array}{cccc} 0 & 20 & 5 & 0 & 0 \\ 10 & 0 & 0 & 3 & 0 \\ 0 & 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 & 0 \end{array} \right]
A=
0100020000500103000010
其中,行向量分别对应
(
q
1
,
q
2
,
q
3
,
q
4
)
(q_1, q_2, q_3, q_4)
(q1,q2,q3,q4),列向量分别对应
(
u
1
,
u
2
,
u
3
,
u
4
,
u
5
)
(u_1, u_2, u_3, u_4, u_5)
(u1,u2,u3,u4,u5) 。
第2步:对矩阵 A A A 进行奇异值分解;
import numpy as np
A = np.array([[0, 20, 5, 0, 0],
[10, 0, 0, 3, 0],
[0, 0, 0, 0, 1],
[0, 0, 1, 0, 0]])
# 调用numpy的svd方法
U, S, VT = np.linalg.svd(A)
print("U=", U)
print("S=", S)
print("V=", VT.T)
U= [[ 1. -0. 0. -0.01]
[ 0. 1. 0. -0. ]
[ 0. 0. 1. 0. ]
[ 0.01 0. 0. 1. ]]
S= [20.62 10.44 1. 0.97]
V= [[ 0. 0.96 -0. -0. 0.29]
[ 0.97 -0. 0. -0.24 -0. ]
[ 0.24 0. 0. 0.97 0. ]
[ 0. 0.29 0. 0. -0.96]
[ 0. 0. 1. 0. 0. ]]
第3步:解释奇异值分解得到的矩阵 U U U、 Σ \Sigma Σ、 V V V代表的内容
根据题意,可知搜索中的点击数据记录用户搜索时提交的查询语句为 { q i } \{q_i\} {qi},点击的网页URL为 { u j } \{u_j\} {uj},点击的次数为矩阵的值。根据奇异值分解定理,可知:
- U U U表示用户输入的查询语句与网页特征之间的关系矩阵
- V V V表示网页与网页特征之间的相似性
- Σ \Sigma Σ表示用户输入的查询语句映射到网页的权重
举个例子:从矩阵 U U U的第一列可以表示查询语句 q 1 q_1 q1与网页特征1的关系密切,通过矩阵 V V V可以表示网页 u 2 u_2 u2与特征1的相似度最高,所以查询 q 1 q_1 q1的时候点击网页 u 2 u_2 u2的次数是最多的。
奇异值分解的另一个作用就是提取网页的特征来将用户输入与网页映射到一个低纬度空间中。通过第2步的计算,可以发现 σ 1 , σ 2 \sigma_1,\sigma_2 σ1,σ2的值比较大,计算截断的矩阵外积展开 A ′ = σ 1 u 1 v 1 T + σ 2 u 2 v 2 T A' = \sigma_1u_1v_1^T+\sigma_2u_2v_2^T A′=σ1u1v1T+σ2u2v2T,可以发现其与矩阵 A A A大体上是相等的。奇异值下降的速度越快,那么矩阵包含的更多信息就越集中分布在前面几个值比较大的特征上面。
两个小案例
机器学习领域利用奇异值分解(SVD)的案例是在推荐系统中的应用,可以使用 movielens 数据集来演示这一点。movielens 数据集包含电影评分数据,通常用于推荐系统的研究和开发。
数据集下载地址:https://grouplens.org/datasets/movielens/
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from scipy.sparse.linalg import svds
from scipy.sparse import csr_matrix
# 加载数据集
ratings = pd.read_csv('./data/ml-latest-small/ratings.csv')
# 创建用户-电影评分矩阵
ratings_matrix = ratings.pivot(index='userId',
columns='movieId',
values='rating').fillna(0)
# 将评分矩阵转换为稀疏矩阵格式
ratings_matrix_sparse = csr_matrix(ratings_matrix.values)
# 奇异值分解
U, sigma, Vt = svds(ratings_matrix_sparse, k=50)
# 重构评分矩阵
predicted_ratings = np.dot(np.dot(U, np.diag(sigma)), Vt)
# 将重构的评分矩阵转换为DataFrame
predicted_ratings_df = pd.DataFrame(predicted_ratings,
columns=ratings_matrix.columns,
index=ratings_matrix.index)
# 示例:为用户ID为1的用户推荐电影
userId = 1
user_row_number = userId - 1 # 用户ID在索引中从0开始
sorted_user_predictions = predicted_ratings_df.iloc[
user_row_number].sort_values(ascending=False)
# 输出前5个推荐电影
sorted_user_predictions.head()
movieId
1196 6.421784
260 6.330851
1210 6.026762
1291 6.024242
1198 5.970028
Name: 1, dtype: float64
示例:图像压缩与重构
使用scikit-learn库中的digits数据集来演示奇异值分解(SVD)在图像压缩和重构中的应用。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn.decomposition import TruncatedSVD
# 加载digits数据集
digits = load_digits()
X = digits.data # 数据归一化到0-1之间
# 随机选择一个样本进行展示
sample_index = np.random.randint(len(X))
sample_image = X[sample_index].reshape(8, 8)
# 显示原始图像
plt.figure(figsize=(4, 4))
plt.imshow(sample_image, cmap='gray')
plt.title(f'Original Image (Label: {digits.target[sample_index]})')
plt.axis('off')
plt.show()
# 奇异值分解(SVD)进行图像压缩和重构
svd = TruncatedSVD(n_components=10, random_state=42)
X_reduced = svd.fit_transform(X)
X_reconstructed = svd.inverse_transform(X_reduced)
# 重构后的图像
reconstructed_image = X_reconstructed[sample_index].reshape(8, 8)
# 显示重构后的图像
plt.figure(figsize=(4, 4))
plt.imshow(reconstructed_image, cmap='gray')
plt.title('Reconstructed Image')
plt.axis('off')
plt.show()
# 计算压缩率
compression_ratio = 100 * (X_reduced.nbytes / X.nbytes)
print(f'Compression ratio: {compression_ratio:.2f}%')
# 显示奇异值能量贡献
plt.figure(figsize=(8, 4))
plt.plot(np.cumsum(svd.explained_variance_ratio_))
plt.xlabel('Number of Components')
plt.ylabel('Cumulative Explained Variance')
plt.title('Cumulative Explained Variance vs. Number of Components')
plt.grid(True)
plt.show()
Compression ratio: 15.62%
使用书籍:李航《机器学习方法》
习题解答来自:https://datawhalechina.github.io/statistical-learning-method-solutions-manual/#/