浅理解
1.定义
将矩阵拆解为数个矩阵的乘积
2.常用方法
三角分解,QR分解,SVD(奇异值)分解,还有满秩分解、QR分解、Jordan分解等
本次主要介绍SVD分解
SVD分解
[U,S,V]=svd(A),U和V分别代表两个(正交矩阵),而S代表一(对角矩阵]), 原[矩阵]A不必为正方矩阵。
SVD分解法的用途是解最小平方误差法和数据压缩。
3.常用来解决的问题
(1)物品间的相关性问题
(2)稀疏的矩阵元素
(常用来解决评分预测问题)
矩阵分解就是把原来的大矩阵,近似的分解成小矩阵的乘积
深度理解
1.SVD损失函数

2.预测评分的公式

3.SVD的学习过程(以评分为例)
(1)准备好用户物品的评分矩阵,每一条评分数据看作是一条训练样本
(2)给分解后的U矩阵和V矩阵随机初始化元素值
(3)用U和V计算预测后的分数
(4) 计算预测的分数和实际的分数误差
(5)按照梯度下降的方向更行U和V中的元素值
(6)重复步骤3到5,直到达到停止条件
4.代码实现
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, 4, 0, 5],
[5, 0, 3, 4],
[3, 4, 0, 3],
[0, 0, 4, 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()
按照先前给的样本对分数进行预测吧
输出结果

拓展
三角分解法
将原正方 (矩阵)分解成一个上三角形矩阵或是排列的上三角形矩阵和一个 下三角形矩阵,这样的分解法又称为LU分解法。它的用途主要在简化一个大矩阵的(行列式)值的计算过程,求逆矩阵,和求解联立(方程组)。
QR分解法
QR(分解法)是将矩阵分解成一个正规(正交矩阵)与上三角形矩阵,所以称为QR分解法,与此正规正交矩阵的通用符号Q有关。
网友评论