定义
定义 A 的 SVD 为$A=U\Sigma V^T$
其中A是$m\times n$的矩阵
$\Sigma$是$m\times n$的矩阵,且除主对角线之外的元素都是0
U,V分别是是$m\times m, n\times n$的矩阵,且$U^TU=I,V^TV=I$
分解方法
根据定义,
$A^TA=V\Sigma^T \Sigma V^T$
$AA^T=U\Sigma \Sigma^T U^T$
各自求特征值和特征向量即可
(当然,这样算法复杂度很高,往往用一些改进的算法去计算)
SVD的性质
很多情况下,前10%甚至1%的奇异值占到全部奇异值之和的99%
$A_{m\times n}=U_{m\times m}\Sigma_{m\times n}V_{n\times n}^T \thickapprox U_{m\times k}\Sigma_{k\times k} V_{k\times n}^T$
代码
# numpy 可以实现
u, sigma, vt = np.linalg.svd(dataMat)
# sklearn 也可以,区别是实现指定维度,这样可以提高计算速度。
from sklearn.decomposition import TruncatedSVD
svd = TruncatedSVD(n_components = 2)
A_transf = svd.fit_transform(A)
# Randomized SVD 是使用了近似技术,进一步提高效率。
from sklearn.utils.extmath import randomized_svd
应用示例
图片压缩
导入包,读取图片
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['figure.dpi'] = 200
img_origin = plt.imread("me1.jpg")
height, _, _ = img_origin.shape
img_origin.shape
把m×n×3的图片,变成m×k的
img_temp = img_origin.reshape(height, -1)
u, sigma, vt = np.linalg.svd(img_temp)
plt.plot(sigma)
fig,ax = plt.subplots(1, 4, figsize = (240,320))
for i,j in enumerate([10,20,40,50]):
img = np.dot(np.dot(u[:,:j],np.diag(sigma[:j])),vt[:j,:])
img = img.reshape(height,-1,3)
ax[i].imshow(img.astype(np.uint8))
ax[i].set(title=str(j))
推荐系统
有书6本abcdef,小朋友5位12345
假设真实情况是,123小朋友喜欢abc这3本书,45小朋友喜欢def这3本书,但我们事先不知道这个真实情况,怎样用算法来提取这个信息呢?
step1:导入包和数据
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame([[0.7, 0.8, 0.8, 0.3, 0.1],
[0.8, 0.8, 0.8, 0.3, 0.2],
[0.9, 0.8, 0.8, 0.1, 0.3],
[0.2, 0.2, 0.2, 0.8, 0.7],
[0.2, 0.2, 0.2, 0.6, 0.6],
[0.2, 0.2, 0.2, 0.6, 0.9]],
index=list('abcdef'),
columns=list('12345'))
df
1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|
a | 0.7 | 0.8 | 0.8 | 0.3 | 0.1 |
b | 0.8 | 0.8 | 0.8 | 0.3 | 0.2 |
c | 0.9 | 0.8 | 0.8 | 0.1 | 0.3 |
d | 0.2 | 0.2 | 0.2 | 0.8 | 0.7 |
e | 0.2 | 0.2 | 0.2 | 0.6 | 0.6 |
f | 0.2 | 0.2 | 0.2 | 0.6 | 0.9 |
step2:跑模型
u, sigma, vt = np.linalg.svd(df.values)
step3:画图并分析结果
plt.plot(sigma)
fig, ax = plt.subplots(1, 2)
ax[0].plot(u[:, 0], u[:, 1], '.')
ax[0].set(title='books')
ax[1].plot(vt[0, :], vt[1, :], '.')
ax[1].set(title='children')
参考文献
https://www.cnblogs.com/lzllovesyl/p/5243370.html