【SVD】分解



2019年01月20日    Author:Guofei

文章归类: 0x31_降维    文章编号: 341

版权声明:本文作者是郭飞。转载随意,但需要标明原文链接,并通知本人
原文链接:https://www.guofei.site/2019/01/20/svd.html


定义

定义 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)

svd_example1

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))

svd_example1

推荐系统

有书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)

svd_example1

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')

svd_example1

参考文献

https://www.cnblogs.com/lzllovesyl/p/5243370.html


您的支持将鼓励我继续创作!