奇异值分解(Singular Value Decomposition)简称SVD,主要作用是简化数据,提取信息。
SVD的公式: A m × n = U m × m Σ m × n V n × n T A_{m\times n}=U_{m\times m} \Sigma_{m\times n} V_{n\times n}^T Am×n=Um×mΣm×nVn×nT
这个公式中, U 和 V 都是正交矩阵,即:
U U T = U T U = E m × m V V T = V T V = E n × n UU^T=U^TU=E_{m\times m} \qquad VV^T=V^TV=E_{n\times n} UUT=UTU=Em×mVVT=VTV=En×n
原矩阵A是一个m行n列的矩阵,它被分解成了三个矩阵,分别是:
矩阵 | 别称 | 维度 | 计算方法 |
---|---|---|---|
U U U 矩阵 | A的左奇异向量 | m行n列 | 列由 A A T AA^T AAT的特征向量构成,且特征向量为单位列向量 |
Σ \Sigma Σ 矩阵 | A的奇异值 | m行n列 | 对角元素来源于 A A T AA^T AAT或 A T A A^TA ATA的特征值的平方根,并且是按从大到小的顺序排列的 |
V V V 矩阵 | A的右奇异向量 | n行n列 | 列由 A T A A^TA ATA的特征向量构成,且特征向量为单位列向量 |
import numpy as np
from numpy import linalg as la
from numpy import *
M = [[1, 1, 1, 0, 0],
[2, 2, 2, 0, 0],
[1, 1, 1, 0, 0],
[5, 5, 5, 0, 0],
[1, 1, 0, 2, 2],
[0, 0, 0, 3, 3],
[0, 0, 0, 1, 1]]
# 7x5
Data = mat(M)
U, Sigma, VT = linalg.svd(Data)
# 构建Sig矩阵,上面的Sigma只是Sig的对角元素
Signn = mat(np.diag(Sigma)) # 以Sigma为主对角线创建矩阵(5x5)
Sigmn = mat([[Sigma[0], 0, 0, 0, 0], [0, Sigma[1], 0, 0, 0], [0, 0, Sigma[2], 0, 0], [0, 0, 0, Sigma[3], 0], [0, 0, 0, 0, Sigma[4]], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]])
print(U[:, :Data.shape[1]] * Signn * VT)
print(U * Sigmn * VT)
'''
最后一个是公式的原始样式,但构建Sigmm没有Signn来得来得快
而且Sigmn的倒数x (x=Data.shape[0]-len(Sigma))行都是由0组成的,与U的最后x列相乘的结果也是0,所以截掉不影响最后结果
U[:, :Data.shape[1]] * Signn * VT 等于 U * Sigmn * VT
'''
import numpy as np
# 从0开始 取30个数 两两之间相差1
n = np.arange(0, 30, 1)
nn = n.reshape(6, 5)
# 相当于形成一个等差数列, 首项是0,尾项是4,一共9个
o = np.linspace(0, 4, 9)
o.resize(3, 3)
# reshape有返回值,不改变内存 resize无返回值,改变内存
a = np.ones((3, 4)) # 3行4列全是1
b = np.zeros((2, 4)) # 2行3列全是0
e = np.eye(3) # 3维单位矩阵
x = [4, 5, 6]
y = np.diag(x) # 以x为主对角线创建矩阵(3x3)
c = np.random.randint(0, 10, (4,3)) # 在0到10之间随机出数,创建4x3矩阵
# 水平拼接行数要相同,竖直拼接列数要相同
p = np.ones([2, 3], int)
pp = np.hstack([p, 2*p]) # 水平拼接
sp = np.vstack([a, b]) # 竖直拼接