1.SVD降维的基本原理
SVD降维的基本原理,可以详见以前文章:https://blog.youkuaiyun.com/u012421852/article/details/80433463
2.降维示例展示
降维的理论以及和意义不再赘述,此处仅仅给出SVD分解降维的一个应用示例。
Step1:准备要降维的数据矩阵M,以及奇异值开方和占比阈值percentage
data = np.array([[5, 5, 0, 5],
[5, 0, 3, 4],
[3, 4, 0, 3],
[0, 0, 5, 3],
[5, 4, 4, 5],
[5, 4, 5, 5]])
percentage = 0.9
Step2:对数据矩阵M进行奇异值分解
(U, S, VT) = np.linalg.svd(M)
解释np.linalg.svd(M)的返回值U,S,VT依次对应于下面SVD公式中的U,∑,V.T,
注意:svd()方法返回的第三个值是SVD中的V.T,而不是V,后面降维时直接使用VT[:K, :len(VT)]作为降维后的SVD公式中的VT
注意:S是M的所有奇异值的数组
求得的U,S,VT如下所示:
降维前的U,S,VT依次为:
(6, 6) U:
[[-0.44721867 0.53728743 0.00643789 -0.50369332 -0.38572204 -0.32982993]
[-0.35861531 -0.24605053 -0.86223083 -0.14584826 0.07797125 0.20015231]
[-0.29246336 0.40329582 0.22754042 -0.10376096 0.4360044 0.70652449]
[-0.20779151 -0.67004393 0.3950621 -0.58878098 0.02599042 0.06671744]
[-0.50993331 -0.05969518 0.10968053 0.28687443 0.59460659 -0.53714128]
[-0.53164501 -0.18870999 0.19141061 0.53413013 -0.54845844 0.24290419]]
(4,) S:
[ 17.71392084 6.39167145 3.09796097 1.32897797]
(4, 4) VT:
[[-0.57098887 -0.4274751 -0.38459931 -0.58593526]
[ 0.22279713 0.51723555 -0.82462029 -0.05319973]
[-0.67492385 0.69294472 0.2531966 -0.01403201]
[ 0.41086611 0.26374238 0.32859738 -0.80848795]]
Step3:根据percentage求k值
def _calc_k(self, percentge):
'''确定k值:前k个奇异值的平方和占比 >=percentage, 求满足此条件的最小k值
:param percentage, 奇异值平方和的占比的阈值
:return 满足阈值percentage的最小k值
'''
self.k = 0
#用户数据矩阵的奇异值序列的平方和
total = sum(np.square(self.S))
svss = 0 #奇异值平方和 singular values square sum
for i in range(np.shape(self.S)[0]):
svss += np.square(self.S[i])
if (svss/total) >= percentge:
self.k = i+1
break
return self.k
求得的k值为:2
即成立:前2个奇异值平方和 / 所有奇异值平方和 >= 0.9
Step4:根据求得的k构造k阶奇异值对角阵
def _buildSD(self, k):
'''构建由奇异值组成的对角矩阵
:param k,根据奇异值开放和的占比阈值计算出来的k值
:return 由k个前奇异值组成的对角矩阵
'''
#方法1:用数组乘方法
self.SD = np.eye(self.k) * self.S[:self.k]
#方法2:用自定义方法
e = np.eye(self.k)
for i in range(self.k):
e[i,i] = self.S[i]
return self.SD
Step5:根据求得的k求降维后的U和VT
new_U = U[:len(U), :k]
new_VT = VT[:k, :len(VT)]
k=2时,降维后的U和VT为:
降维后的U, VT依次为:
(6,) new_U=U[:6,:2]:
[[-0.44721867 0.53728743]
[-0.35861531 -0.24605053]
[-0.29246336 0.40329582]
[-0.20779151 -0.67004393]
[-0.50993331 -0.05969518]
[-0.53164501 -0.18870999]]
(2, 4) new_VT=VT[:2, :4]:
[[-0.57098887 -0.4274751 -0.3845