SVD笔记

基础

原理推导什么的看大佬的博客就行了,直接往最下面找参考,我这就是个笔记本。
A A T AA^T 的特征向量就是 U U A T A A^TA 的特征向量是 V V ,中间的就是 A A T AA^T 的特征值的平方根,奇异值的个数=A的秩数

在这里插入图片描述

一般使用的时候只取其中的部分:
在这里插入图片描述

其中r远小于m or n, 如果r的取值远远小于n,从计算机内存的角度来说,右边三个矩阵的存储内存要远远小于矩阵A的

奇异值的计算
在这里插入图片描述

也可以用这个求奇异值, u i , v i u_i,v_i 分别是 U , V U,V 的特征向量:
在这里插入图片描述
在这里插入图片描述

特征对应关系
在这里插入图片描述

每个特征向量都能代表一个特征,特征值代表该特征的重要程度


概念理解

在这里插入图片描述
分析观众和电影的

S矩阵只有三维,是因为 A A 的秩=3,第一个奇异值是科幻,第二个奇异值是romance,第三个不知道是啥

然后左边的U矩阵,每一行都是每个人对各个类别的喜好程度,不同的行代表不同的人,不同的列代表不同的电影种类

中间的S代表权重,分别是某一“concept”的整体重要性

这个V是指每个电影对concept(三个,科幻、浪漫、其他)的匹配度

为啥 A T A A^TA 的特征向量有这个功能?A的第一维度是people,第二维度是movies,那 A T A A^TA 就是 m o v i e s × m o v i e s movies \times movies 。所以V的维度就是 m o v i e s f e a t u r e × m o v i e s n u m movies_{feature} \times movies_{num} ,就是说有三个concept,而每一行的内容,就是每个电影对这个concept的影响程度

U U 就是 p e o p l e × p e o p l e people \times people 的特征向量,不同的观众的观影特征被分成了三种,得到 p e o p l e n u m × p e o p l e f e a t u r e people_{num} \times people_{feature} ,然后这个的特征向量和 A T A A^TA 的特征向量又是相似的 ,所有 U U 就是user对不同concept的喜欢程度

在这里插入图片描述
根据这个公式可以知道,奇异值是和两种特征向量都关联的,而且也知道
在这里插入图片描述
所以说这个特征本来就是藏在A中的,试试拿出来了,然后在不同的维度(people movies)中使用它

在这里插入图片描述

在这里插入图片描述

获取主要特征:
在这里插入图片描述

对应的显示如下图
在这里插入图片描述

原理解释
在这里插入图片描述
u , v u,v 都单位化,然后用 σ \sigma 来进行缩放,所有的结果求和就是A的值,所以省略掉那些 σ \sigma 很小的内容,对A也没什么影响, A s u m ||A-sum|| 的值很小

使用
看喜欢Matrix的喜欢哪一concept

在这里插入图片描述
这是从people到电影种类,就是concept,但是如果用列数据,好像得不出什么?

在这里插入图片描述


实现

官方API
这个API已经讲的很详细了,建议用matplotlib可视化,opencv的imshow需要uint8的数据格式,会掉精度
试了三种写法:

  1. 对每个通道分别做SVD,然后对每个通道分别取定量特征值,然后再把通道合并
  2. 对整个图片做SVD,API有提供batch功能,然后分别对每个通道取一定比例的特征值
  3. 对整个图片做SVD,然后对全部通道一起取一定比例的特征值

在这里插入图片描述
50 S V D S V D 前50个特征值,单独SVD和全部SVD

在这里插入图片描述
85 % 13 % 85\%的特征值,只占了特征总数的13\%,通道单独计算和整体计算

import numpy as np
import matplotlib.pyplot as plt

image = plt.imread('G:\\hanjia_code\\mx-DeepIM-master\\mx-DeepIM-master\\jian.png')

num = 0.85

def get_infor(num,u,s,v):
    if isinstance(num,int):
        S = np.diag(s)
        new_channel = np.dot(u[:,:num],np.dot(S[:num,:num],v[:num,:]))

    elif isinstance(num,float):
        S = np.diag(s)
        sum_s = np.sum(s)
        num_s = 0
        num_s_index = 0
        flag =True
        while (num_s < num * sum_s) & flag:
            num_s += s[num_s_index]
            num_s_index +=1
            if num_s_index==np.shape(u)[0] or num_s_index==np.shape(v)[0]:
                flag = False

        new_channel = np.dot(u[:,:num_s_index],np.dot(S[:num_s_index,:num_s_index],v[:num_s_index,:]))

    return new_channel


channel = []
for i in range(3):
    u,s,v = np.linalg.svd(image[:,:,i])
    channel.append(get_infor(num,u,s,v))

image_sep = np.stack((channel[0],channel[1],channel[2]),axis=2)






def get_infor_all(num,u,s,S,v):
    if isinstance(num,int):
        new_channel = np.matmul(u[:,:,:num],np.matmul(S[:,:num,:num],v[:,:num,:]))
        return new_channel
    elif isinstance(num,float):
        sum_s = np.sum(s)
        num_s = 0
        num_s_index = 0
        flag =True
        while (num_s < num * sum_s) & flag:
            num_s += np.sum(s[:,num_s_index])
            num_s_index +=1
            if num_s_index==np.shape(u)[1] or num_s_index==np.shape(v)[1]:
                flag = False

        new_channel = np.matmul(u[:,:,:num_s_index],np.matmul(S[:,:num_s_index,:num_s_index],v[:,:num_s_index,:]))

        return new_channel,num_s_index/np.shape(S)[1]

image_2 = np.rollaxis(image,axis=2)
u, s, vh = np.linalg.svd(image_2, full_matrices=True)
S_1 = np.diag(s[0])
S_2 = np.diag(s[1])
S_3 = np.diag(s[2])
S = np.stack((S_1,S_2,S_3),axis=0)


image_seq_3,index = get_infor_all(num,u,s,S,vh)
image_seq_3 = np.rollaxis(image_seq_3,axis=2)
image_seq_3 = np.rollaxis(image_seq_3,axis=2)

if isinstance(num,float):
    number = 20
elif isinstance(num,int):
    number = num
image_all = np.matmul(np.matmul(u[:,:,:number],S[:,:number,:number]), vh[:,:number,:])
image_all = np.rollaxis(image_all,axis=2)
image_all = np.rollaxis(image_all,axis=2)



fig,ax = plt.subplots(1,2)
ax[0].imshow(image_sep)
ax[1].imshow(image_seq_3)
plt.show()
print(index)


应用

SVD拟合平面

平面方程:
A x + B y + C z + D = 0 Ax+By+Cz+D=0
算法步骤如下:

  1. 求点云的平均值 ( x 0 , y 0 , z 0 ) (x_0,y_0,z_0)
  2. 所有点减去平均值,构建矩阵 A A ;
  3. 对矩阵 A A 做SVD分解, A = U S V T A = U * S * V^T
  4. V V 最后一列对应为 ( A , B , C ) (A,B,C) ;
  5. D = ( A x 0 + B y 0 + C z 0 ) D=-(A*x_0+B*y_0+C*z_0)

在这里插入图片描述
效果图
来源


参考

SVD推理,应用

SVD小强,主要讲了公式、方法,作用,优点

PPT图片来源

博客园

发布了63 篇原创文章 · 获赞 2 · 访问量 8014

猜你喜欢

转载自blog.csdn.net/McEason/article/details/104424881
SVD