基础
原理推导什么的看大佬的博客就行了,直接往最下面找参考,我这就是个笔记本。
A
A
T
AA^T
AAT的特征向量就是
U
U
U,
A
T
A
A^TA
ATA的特征向量是
V
V
V,中间的就是
A
A
T
AA^T
AAT的特征值的平方根,奇异值的个数=A的秩数
一般使用的时候只取其中的部分:
其中r远小于m or n, 如果r的取值远远小于n,从计算机内存的角度来说,右边三个矩阵的存储内存要远远小于矩阵A的
奇异值的计算:
也可以用这个求奇异值,
u
i
,
v
i
u_i,v_i
ui,vi分别是
U
,
V
U,V
U,V的特征向量:
特征对应关系:
每个特征向量都能代表一个特征,特征值代表该特征的重要程度
概念理解
分析观众和电影的
S矩阵只有三维,是因为 A A A的秩=3,第一个奇异值是科幻,第二个奇异值是romance,第三个不知道是啥
然后左边的U矩阵,每一行都是每个人对各个类别的喜好程度,不同的行代表不同的人,不同的列代表不同的电影种类
中间的S代表权重,分别是某一“concept”的整体重要性
这个V是指每个电影对concept(三个,科幻、浪漫、其他)的匹配度
为啥 A T A A^TA ATA的特征向量有这个功能?A的第一维度是people,第二维度是movies,那 A T A A^TA ATA就是 m o v i e s × m o v i e s movies \times movies movies×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} moviesfeature×moviesnum,就是说有三个concept,而每一行的内容,就是每个电影对这个concept的影响程度
那 U U U就是 p e o p l e × p e o p l e people \times people people×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} peoplenum×peoplefeature,然后这个的特征向量和 A T A A^TA ATA的特征向量又是相似的 ,所有 U U U就是user对不同concept的喜欢程度
根据这个公式可以知道,奇异值是和两种特征向量都关联的,而且也知道
所以说这个特征本来就是藏在A中的,试试拿出来了,然后在不同的维度(people movies)中使用它
获取主要特征:
对应的显示如下图
原理解释:
将
u
,
v
u,v
u,v都单位化,然后用
σ
\sigma
σ来进行缩放,所有的结果求和就是A的值,所以省略掉那些
σ
\sigma
σ很小的内容,对A也没什么影响,
∣
∣
A
−
s
u
m
∣
∣
||A-sum||
∣∣A−sum∣∣的值很小
使用:
看喜欢Matrix的喜欢哪一concept:
这是从people到电影种类,就是concept,但是如果用列数据,好像得不出什么?
实现
官方API
这个API已经讲的很详细了,建议用matplotlib可视化,opencv的imshow需要uint8的数据格式,会掉精度
试了三种写法:
- 对每个通道分别做SVD,然后对每个通道分别取定量特征值,然后再把通道合并
- 对整个图片做SVD,API有提供batch功能,然后分别对每个通道取一定比例的特征值
- 对整个图片做SVD,然后对全部通道一起取一定比例的特征值
前
50
个
特
征
值
,
单
独
S
V
D
和
全
部
S
V
D
前50个特征值,单独SVD和全部SVD
前50个特征值,单独SVD和全部SVD
85
%
的
特
征
值
,
只
占
了
特
征
总
数
的
13
%
,
通
道
单
独
计
算
和
整
体
计
算
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
Ax+By+Cz+D=0
算法步骤如下:
- 求点云的平均值 ( x 0 , y 0 , z 0 ) (x_0,y_0,z_0) (x0,y0,z0);
- 所有点减去平均值,构建矩阵 A A A;
- 对矩阵 A A A做SVD分解, A = U ∗ S ∗ V T A = U * S * V^T A=U∗S∗VT;
- V V V最后一列对应为 ( A , B , C ) (A,B,C) (A,B,C);
- D = − ( A ∗ x 0 + B ∗ y 0 + C ∗ z 0 ) D=-(A*x_0+B*y_0+C*z_0) D=−(A∗x0+B∗y0+C∗z0)
效
果
图
效果图
效果图
来源