浅理解
1.定义
将矩阵拆解为数个矩阵的乘积
2.常用方法
三角分解,QR分解,SVD(奇异值)分解,还有满秩分解、QR分解、Jordan分解等
本次主要介绍SVD分解
SVD分解
[U,S,V]=svd(A),U和V分别代表两个(正交矩阵),而S代表一(对角矩阵]), 原[矩阵]A不必为正方矩阵。
SVD分解法的用途是解最小平方误差法和数据压缩。
3.常用来解决的问题
(1)物品间的相关性问题
(2)稀疏的矩阵元素
(常用来解决评分预测问题)
矩阵分解就是把原来的大矩阵,近似的分解成小矩阵的乘积
深度理解
1.SVD损失函数
image.png
2.预测评分的公式
image.png
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()
按照先前给的样本对分数进行预测吧
输出结果
image.png
拓展
三角分解法
将原正方 (矩阵)分解成一个上三角形矩阵或是排列的上三角形矩阵和一个 下三角形矩阵,这样的分解法又称为LU分解法。它的用途主要在简化一个大矩阵的(行列式)值的计算过程,求逆矩阵,和求解联立(方程组)。
QR分解法
QR(分解法)是将矩阵分解成一个正规(正交矩阵)与上三角形矩阵,所以称为QR分解法,与此正规正交矩阵的通用符号Q有关。












网友评论