《推荐系统笔记(五)》svd降维 —— 以图片处理为例

理论部分

任何一个 m × n m\times n m×n矩阵 A A A,通过svd分解,可以分解为三个矩阵相乘
A = P Σ Q T A=P\Sigma Q^T A=PΣQT

其中, Σ \Sigma Σ是一个 m × n m\times n m×n对角矩阵,除了对角线上的元素之外,其余位置元素全部为0。

我们假设 P = [ P 1 , P 2 , . . . , P m ] P=[P_1, P_2, ..., P_m] P=[P1,P2,...,Pm],其中, P i P_i Pi m m m维列向量; Q = [ Q 1 , Q 2 , . . . , Q n ] Q=[Q_1, Q_2, ..., Q_n] Q=[Q1,Q2,...,Qn],其中, Q j Q_j Qj n n n维列向量; Σ \Sigma Σ的对角线元素为 σ 1 , σ 2 , . . . , σ m i n ( m , n ) \sigma_1, \sigma_2, ..., \sigma_{min(m, n)} σ1,σ2,...,σmin(m,n),其中, σ 1 ≥ σ 2 ≥ . . . ≥ σ m i n ( m , n ) \sigma_1\ge\sigma_2\ge...\ge\sigma_{min(m, n)} σ1σ2...σmin(m,n)

我们仅考虑 m ≥ n m\ge n mn的情形(情形 m ≤ n m\le n mn类似)。此时,矩阵 A A A可以分解为
A = P Σ Q T = [ P 1 , P 2 , . . . , P m ] Σ [ Q 1 T , Q 2 T , . . . , Q n T ] T = σ 1 P 1 Q 1 T + σ 2 P 2 Q 2 T + . . . + σ n P n Q n T \begin{array}{lll} A&=&P\Sigma Q^T\\ &=&[P_1, P_2, ..., P_m]\Sigma[Q_1^T, Q_2^T, ..., Q_n^T]^T\\ &=&\sigma_1 P_1 Q_1^T+\sigma_2 P_2 Q_2^T+...+\sigma_nP_nQ_n^T \end{array} A===PΣQT[P1,P2,...,Pm]Σ[Q1T,Q2T,...,QnT]Tσ1P1Q1T+σ2P2Q2T+...+σnPnQnT

更重要的是,对角线上的元素按照从大到小,从上到下进行排列,并且往往最大的几个元素比最小的几个元素大得多,以至于较小元素可以忽略。

比如,我们有100个特征值,前10%的特征值比后90%的特征值大得多,我们就选取前10%的特征值,而将后90%的特征值略掉。这样,我们就用了10%的内容,保留了矩阵 A A A的绝大部分信息。

此时,保留前 k k k个特征值,
A ≈ σ 1 P 1 Q 1 T + σ 2 P 2 Q 2 T + . . . + σ k P k Q k T A\approx\sigma_1 P_1 Q_1^T+\sigma_2 P_2 Q_2^T+...+\sigma_kP_kQ_k^T Aσ1P1Q1T+σ2P2Q2T+...+σkPkQkT

实际操作

我们随便挑选一个图片作为例子,保存为dog.jpg
在这里插入图片描述
我们可以从图片处理中,看看svd降维的效果。

# 第三方库
from PIL import Image
from scipy.linalg import svd
import numpy as np
# 加载图片
image = Image.open('D:/myfile/开课吧/推荐系统/第六节/dog.jpg')

# 转化为灰度图
grey_image = image.convert('L')
grey_image.show()

转化为灰度图,如下
在这里插入图片描述

# 转化为矩阵
A = np.array(grey_image)

# svd分解
p, s, q = svd(A)
print('左奇异矩阵p的大小为', p.shape)
print('矩阵A的特征值个数为', len(s))
print('其中,前4个特征值为', s[:4])
print('后4个特征值为', s[-4:])
print('右奇异矩阵q的大小为', q.shape)
左奇异矩阵p的大小为 (683, 683)
矩阵A的特征值个数为 683
其中,前4个特征值为 [109075.24   28300.275  16735.781  10259.204]4个特征值为 [28.534803 27.757359 26.593216 23.755302]
右奇异矩阵q的大小为 (1024, 1024)

可以看到,前4个特征值要比后4个特征值大得多,所以将后四个特征值忽略,并不影响图片质量。

# 定义函数get_k_features,选择矩阵A的前k个特征值,返回图像矩阵
# 注意:该函数仅适用于m<n的A矩阵
def get_k_features(k):
    # 生成sigma矩阵
    sigma = np.diag(list(s)+[0]*(len(q)-len(s)))[:len(s), :] # m*n矩阵,其中,对角线上是m个特征值
    
    # 选取前k个特征值
    sigma_k = sigma[:k, :] # k*n矩阵
    
    # 近似还原A矩阵
    A_approx = p[:, :k].dot(sigma_k).dot(q) # p矩阵需要取前k列,变成m*k矩阵;sigma_k是k*n矩阵;q是n*n矩阵
    
    return A_approx
# 取前5%的特征值
image_1 = get_k_features(30)
# 取前10%的特征值
image_2 = get_k_features(60)
# 取前20%的特征值
image_3 = get_k_features(120)
# 依次生成图片
Image_1 = Image.fromarray(np.uint8(image_1))
Image_1.show()

Image_2 = Image.fromarray(np.uint8(image_1))
Image_2.show()

Image_3 = Image.fromarray(np.uint8(image_1))
Image_3.show()

选取的特征值数量从小到大,图片依次为
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到,原图片总共有683个特征值,当我们仅仅选取前60个特征值时,如果不追求细节,图片基本能辨认出来;当我们提取更多的特征值时,图片质量也就越来越高。

综上,svd可以通过选择较少的主要特征值来保留大部分信息,也就是达到了降维的效果。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值