降维方法——SVD奇异值分解

奇异值分解(SVD)是一种矩阵分解的方法,
假设有矩阵 A A m n n 列,那么通过SVD,我们可以得到如下式子:

Am×n=Um×mΣm×nVn×nT

其中 U U 定义为A的左奇异向量, V V 定义为右奇异向量,Σ对角线上的值为 A A 的奇异值。
这里U可以看成 m m 列的列向量组成的m×m的正交矩阵; V V 可以看成n行的行向量组成的 n×n n × n 的正交矩阵;
所以要求矩阵A的奇异值分解值主要有一下四个部分。
- 分别计算正交矩阵 AAT A A T ATA A T A
- U U 中的列由AAT的单位特征向量组成。
- V V 中的列由ATA的单位特征向量组成。
- Σ Σ 对角线上的值由 ATA A T A 的特征值的平方根得出。

SVD的应用可以应用在很多场景,如在对数据处理时可以通过SVD选取重要的维度即 Σ Σ 中的特征值(其实按照从大到小的顺序排列),也可以对图像进行做特征提取处理,同时也可以应用于基于协同过滤的推荐中,也可以对数据进行压缩处理。

这里我们举例,SVD对图像中基本的特征提取应用。

#!/usr/bin/python
# -*- coding:utf-8 -*-

import  numpy as np
import  os
from  PIL import  Image
import  matplotlib.pyplot as plt
import  matplotlib as mpl
from pprint import  pprint


def restorel(sigma, u, v, K):
    m = len(u)
    n = len(v[0])
    a = np.zeros((m,n))
    for k in range(K):
        print("==============",u.shape)
        uk = u[:,k].reshape(m,1)
        vk = v[k].reshape(1,n)
        print("=======================")
        print(sigma[k].shape)
        a += sigma[k]*np.dot(uk,vk)
    print("a:",a.shape)
    print("**********************")
    print(a)
    a[a < 0] = 0
    a[a > 255] = 255
    return np.rint(a).astype('uint8')



if __name__ == "__main__":
    A = Image.open("A.png",'r')
    print(A)
    output_path = r'.\Pic'
    if not os.path.exists(output_path):
        os.mkdir(output_path)
    a = np.array(A)
    # print(a.shape)
    K = 50
    u_r, sigma_r, v_r = np.linalg.svd(a[:,:,0])
    u_g, sigma_g, v_g = np.linalg.svd(a[:,:,1])
    u_b, sigma_b, v_b = np.linalg.svd(a[:,:,2])
    # print("====================")
    # print(u_r.shape)
    # print(sigma_r.shape)
    # print(v_r.shape)
    plt.figure(figsize=(10,10),facecolor='w')
    mpl.rcParams['font.sans-serif'] = [u'simHei']
    mpl.rcParams['axes.unicode_minus'] = False
    for k in range(1,K+1):
        print(k)
        R = restorel(sigma_r, u_r, v_r, k)
        G = restorel(sigma_g, u_g, v_g, k)
        B = restorel(sigma_b, u_b, v_b, k)
        I = np.stack((R,G,B),axis=2)
        Image.fromarray(I).save("%s\\svd_%d.png"%(output_path,k))
        if k <= 12:
            plt.subplot(3, 4, k)
            plt.imshow(I)
            plt.axis('off')
            plt.title(u'奇异值个数:%d' % k)
    plt.suptitle(u'SVD与图像分解',fontsize = 20)
    plt.tight_layout(0.3, rect=(0,0,1,0.92))
    plt.show()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值