奇異值分解 (Singular Value Decomposition)SVD 簡單手算範例+PYTHON範例

奇異值分解 (Singular Value Decomposition)SVD 簡單手算範例+PYTHON範例

奇異值分解 (Singular Value Decomposition)SVD 簡單手算範例+PYTHON範例



資料來源:

https://www.cnblogs.com/pinard/p/6251584.html
https://www.itread01.com/content/1545298204.html
https://blog.csdn.net/u012421852/article/details/80439403

GUTHUB: https://github.com/jash-git/Singular-Value-Decomposition



# -*- coding: utf-8 -*-
"""
@author: 蔚蓝的天空Tom
Talk is cheap, show me the code
Aim:svd分解降维应用示例的代码实现
CSDN URL:https://mp.csdn.net/postedit/80450590
"""
 
import numpy as np
from numpy import linalg as LA
 
class CSVD(object):
    '''
    实现SVD分解降维应用示例的数学求解过程的Python代码
    '''
    
    def __init__(self, data):
        self.data = data       #用户数据
        self.S = []  #用户数据矩阵的奇异值序列 singular values
        self.U = []  #svd后的单位正交向量
        self.VT = []  #svd后的单位正交向量
        self.k = 0   #满足self.p的最小k值(k表示奇异值的个数)
        self.SD = [] #对角矩阵,对角线上元素是奇异值 singular values diagonal matrix
        
        #svd奇异值分解
        self._svd()
        
    def _svd(self):
        '''
        用户数据矩阵的svd奇异值分解
        '''
        u,s,v = np.linalg.svd(self.data)
        (self.U, self.S, self.VT) = (u, s, v)
        return self.U, self.S, self.VT
        
    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
 
    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
    
    def DimReduce(self, percentage):
        '''
        SVD降维
        :param percentage, 奇异值开方和的占比阈值
        :return 降维后的用户数据矩阵
        '''
        #计算k值
        self._calc_k(percentage)
        print('\n按照奇异值开方和占比阈值percentage=%d, 求得降维的k=%d'%(percentage, self.k))
        #构建由奇异值组成的对角矩阵singular values diagonal
        self._buildSD(self.k)
        k,U,SD,VT = self.k,self.U, self.SD, self.VT
        #按照svd分解公式对用户数据矩阵进行降维,得到降维压缩后的数据矩阵
        print('\n降维前的U,S,VT依次为:')
        print(np.shape(U),      'U:\n', U)
        print(np.shape(self.S), 'S:\n', self.S)
        print(np.shape(VT),     'VT:\n', VT)
        print('\n降维后的U,SD,VT依次为:')
        print(np.shape(U[:len(U),k]), 'U=U[:%d,:%d]:\n'%(len(U),k), U[:len(U), :k])
        print(np.shape(SD), 'SD=SD[:%d, :%d]:\n'%(k,k), SD[:k, :k])
        print(np.shape(VT[:k, :len(VT)]), 'VT=VT[:%d, :%d]:\n'%(k, len(VT)), VT[:k, :len(VT)])
 
        a = U[:len(U), :k]
        b = np.dot(SD, VT[:k, :len(VT)])
        newData = np.dot(a,b)
        return newData
        
def CSVD_manual():
    ##训练数据集,用户对商品的评分矩阵,行为多个用户对单个商品的评分,列为用户对每个商品的评分
    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
    svdor = CSVD(data)
    ret = svdor.DimReduce(percentage)
    print('====================================================')
    print('原始用户数据矩阵:\n', data)
    print('降维后的数据矩阵:\n', ret)
    print('====================================================')
    
if __name__=='__main__':
    CSVD_manual()

2 thoughts on “奇異值分解 (Singular Value Decomposition)SVD 簡單手算範例+PYTHON範例

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *