《机器学习实战》笔记之十四——利用SVD简化数据

2024-05-15 05:48

本文主要是介绍《机器学习实战》笔记之十四——利用SVD简化数据,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第十四章 利用SVD简化数据


14.1 SVD的应用

特点:

利用SVD能够用小得多的数据集来表示原始数据集。

优点:简化数据,去除噪声,提高算法的结果。

缺点:数据的转换可能难以理解。

隐性语义索引(LSI)

利用SVD的方法为隐性语义索引(Latent Semantic Indexing, LSI)或隐性语义分析(Latent Semantic Analysis, LSA)。在LSI中,一个矩阵是由文档和词语组成的,应用SVD时,会构建出多个奇异值,其代表了文档中的概念或主题。

推荐系统

上述矩阵由餐馆的菜和品菜师对这些菜的意见构成的。品菜师采用1到5之间的任意一个整数来对菜评级,如果品菜师没有尝过某道菜,则评级为0。对上述矩阵进行SVD分解,会得到两个奇异值(注意其特征值位2),也即仿佛有两个概念或主题与此数据集相关联。


14.2 矩阵分解

在很多情况下,数据中的一小段携带了数据集中的大部分信息,其他信息则要么是噪声,要么就是毫不相关的信息。在线性代数中还有很多矩阵分解技术。 矩阵分解可以将原始矩阵表示成新的易于处理的形式。

SVD将原始数据集矩阵Data分解成三个矩阵U,sigma,V.T。


Figure 14-1: SVD矩阵分解公式

分解出来的sigma矩阵为对角阵,对角元素从大到小排列,称之为奇异值(Singular Value),这些奇异值为Data*Data.T特征值的平方根。且若是Data的秩为r,则奇异值的个数为r个,也即数据集中仅有r个重要特征。


14.3 利用python实现SVD

python numpy包里有linalg的线性代数工具箱,其有包括处理求范式、逆、行列式、伪逆、秩、qr分解、svd分解等等函数。


Figure 14-2: numpy linalg工具包

代码:

#!/usr/bin/env python
# coding=utf-8
from numpy import *
from numpy import linalg as la
def loadExData():return [[1,1,1,0,0],[2,2,2,0,0],[5,5,5,0,0],[1,1,0,2,2],[0,0,0,3,3],[0,0,0,1,1]]Data = loadExData()
U,Sigma,VT = la.svd(Data)
Sig3 = mat([[Sigma[0],0,0],[0,Sigma[1],0],[0,0,Sigma[2]]])#由于Sigma是以向量的形式存储,故需要将其转为矩阵,
#利用numpy的diag函数,直接Sig3 = np.diag(Sigma)[:3,:3]即可,diag将行向量转为矩阵,值放在对角线上,并取前面3行3列
print Sigma
print U[:,:3]*Sig3*VT[:3,:]#重构原始矩阵

结果:


Figure 14-3: sigma及重构后的矩阵

保留奇异值的数目:

  1. 保留矩阵中90%的能量信息。将所有的奇异值求平方和,将奇异值平方和累加到总值的90%为止。
  2. 保留上万奇异值中的前面2000到3000个。

14.4 基于协同过滤的推荐引擎

协同过滤通过将用户和其他用户的数据进行对比来实现推荐的。

当知道了两个用户或者两个物品之间的相似度,我们就可以利用已有的数据来预测未知的用户喜好。

唯一所需要的数学方法就是相似度的计算。

相似度计算:


Figure 14-4: 用于展示相似度计算的简单矩阵

手撕猪肉与鳗鱼饭的欧式距离:


相似度化为0到1之间:相似度=1/(1+距离)。

皮尔逊相关系数(Pearson correlation):

由numpy包中corrcoef()函数计算,化为0到1之间:0.5+0.5*corrcoef()。

余弦相似度(cosine similarity):

coding:

#!/usr/bin/env python
# coding=utf-8
from numpy import *
from numpy import linalg as la
def loadExData():return [[1,1,1,0,0],[2,2,2,0,0],[5,5,5,0,0],[1,1,0,2,2],[0,0,0,3,3],[0,0,0,1,1]]def eulidSim(inA, inB):return 1.0/(1.0+la.norm(inA - inB))#根据欧式距离计算相似度def pearsSim(inA, inB):if len(inA)<3:return 1.0else:return 0.5+0.5*corrcoef(inA, inB, rowvar = 0)[0][1]def cosSim(inA, inB):num   = float(inA.T*inB)            #向量inA和向量inB点乘,得cos分子denom = la.norm(inA)*la.norm(inB)   #向量inA,inB各自范式相乘,得cos分母return 0.5+0.5*(num/denom)          #从-1到+1归一化到[0,1]myMat = mat(loadExData())
print eulidSim(myMat[:,0], myMat[:,4])#第一行和第五行欧式距离
print eulidSim(myMat[:,0], myMat[:,0])#第一行和第一行欧式距离
print cosSim(myMat[:,0], myMat[:,4])#第一行和第五行cos距离
print cosSim(myMat[:,0], myMat[:,0])#第一行和第一行cos距离
print pearsSim(myMat[:,0], myMat[:,4])#第一行和第五行皮尔逊距离
print pearsSim(myMat[:,0], myMat[:,0])#第一行和第一行皮尔逊距离

Figure 14-5: 三种距离度量的结果

基于物品的相似度还是基于用户的相似度

行与行之间比较的是基于用户的相似度,列与列之间比较的则是基于物品的相似度。基于物品相似度计算的时间会随物品数量的增加而增加,基于用户的相似度计算的时间则会随用户数量的增加而增加。如果用户的数目很多,那么我们可能倾向于使用基于物品相似度的计算方法。对于大部分产品导向的推荐系统而言,用户的数量往往大于物品的数量,即购买商品的用户数会多于出售的商品种类。

推荐系统的评价

我们将某些已知的评分值去掉,然后对它们进行预测,最后计算预测值与真实值之间的差异。通常使用的指标为最小均方根误差(Root Mean Squared Error, RMSE)。

14.5 示例:餐馆菜肴推荐引擎

推荐未尝过的菜肴

过程:给定一个用户,系统会为此用户返回N个最好的推荐菜。需要:

  1. 寻找用户没有评级的菜肴,即在用户-物品矩阵中的0值。
  2. 在用户没有评级的所有物品中,对每个物品预计一个可能的评级分数。
  3. 对这些物品的评分从高到低进行排序,返回前N个物品。
coding:

#===============基于物品相似度的推荐系统===============================
def standEst(dataMat, user, simMeas, item):     #数据矩阵,用户编号,相似度计算方法,物品编号n = shape(dataMat)[1]                       #行为用户,列为物品,n即物品数目simTotal    = 0.0ratSimTotal = 0.0for j in range(n):userRating = dataMat[user, j]           #j为某个物品编号if userRating == 0:continueelse:#寻找两个用户都评级的物品overLap = nonzero(logical_and(dataMat[:, item].A>0, dataMat[:,j].A>0))[0]#为向量if len(overLap)== 0:similarity = 0else:similarity = simMeas(dataMat[overLap, item], dataMat[overLap, j])simTotal += similarityratSimTotal += similarity * userRatingif simTotal == 0:return 0else:return ratSimTotal/simTotaldef recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=standEst):#输入用户编号,返回用户对前N个未评级物品预测评分值unratedItems = nonzero(dataMat[user, :].A==0)[1]                    #寻找未评级的物品,nonzero()[1]返回参数的某些为0的列的编号,dataMat中用户user对某个商品评价为0的列if len(unratedItems) == 0:return "you rated everything"else:itemScores = []for item in unratedItems:estimatedScore = estMethod(dataMat, user, simMeas, item)#对未评价的物品item进行进行预测评分,传入函数standEstitemScores.append((item,estimatedScore))return sorted(itemScores, key=lambda e:e[1], reverse = True)[:N]#前N个未评级物品myMat = mat(loadExData())
myMat[0,3] = myMat[0,4] = myMat[1,4] = myMat[2,3] = 4
myMat[4,1] = 2
print myMat
print recommend(myMat, 4)
print recommend(myMat, 4,simMeas = eulidSim)
print recommend(myMat, 4,simMeas = pearsSim)

效果:


Figure 14-6: 对用户4未评分的物品用不同的具体推荐的结果

利用SVD进提高推荐的效果

计算在奇异值的总能量,了解其到底需要多少维特征。

def loadExData2():return [[0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5],[0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 3],[0, 0, 0, 0, 4, 0, 0, 1, 0, 4, 0],[3, 3, 4, 0, 0, 0, 0, 2, 2, 0, 0],[5, 4, 5, 0, 0, 0, 0, 5, 5, 0, 0],[0, 0, 0, 0, 5, 0, 1, 0, 0, 5, 0],[4, 3, 4, 0, 0, 0, 0, 5, 5, 0, 1],[0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 4],[0, 0, 0, 2, 0, 2, 5, 0, 0, 1, 2],[0, 0, 0, 0, 5, 0, 0, 0, 0, 4, 0],[1, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0]]U,Sigma,VT = la.svd(mat(loadExData2()))
print Sigma
Sig2 =  Sigma**2
print Sig2
print sum(Sig2)*0.9
print sum(Sig2[:2])
print sum(Sig2[:3])

Figure 14-7: 奇异值的能量计算
前3个元素所包含的能量超过总能量的90%,故可以将这个11维的矩阵转换为3维矩阵。
对转换后的三维空间构造出一个相似度计算函数。利用SVD将所有的菜肴映射到一个低维空间。
#======================基于SVD的评分估计==========================
def SVDEst(dataMat, user, simMeas, item):n = shape(dataMat)[1]simTotal = 0.0ratSimTotal = 0.0U, Sigma, VT = la.svd(dataMat)Sig4 = mat(eye(4)*Sigma[:4]) #化为对角阵,或者用linalg.diag()函数可破xformedItems = dataMat.T*U[:,:4]*Sig4.I#构造转换后的物品for j in range(n):userRating = dataMat[user,j]if userRating == 0 or j == item:continueelse:similarity = simMeas(xformedItems[item,:].T, xformedItems[j, :].T)print "the %d and %d similarity is: %f" %(item,j,similarity)simTotal += similarityratSimTotal += similarity*userRatingif simTotal ==0 :return 0else:return ratSimTotal/simTotalmyMat = mat(loadExData2())
print recommend(myMat, 1, estMethod = SVDEst)
print recommend(myMat, 1, estMethod = SVDEst, simMeas = pearsSim)
Figure 14-8: 使用SVD评分估计

14.6 示例:基于SVD的图像压缩

原始图像为32×32=1024像素的图像,用SVD对其进行压缩,以节省空间或带宽开销。

coding:


def printMat(inMat, thresh=0.8):for i in range(32):for k in range(32):if float(inMat[i,k]) > thresh:print 1,else:print 0,print ""def imgCompress(numSV=3, thresh=0.8):myl = []for line in open("0_5.txt").readlines():newRow = []for i in range(32):newRow.append(int(line[i]))myl.append(newRow)myMat = mat(myl)print "****original matrix****"printMat(myMat,thresh)U, Sigma, VT = la.svd(myMat)SigRecon = mat(zeros((numSV, numSV)))for k in range(numSV):SigRecon[k,k] = Sigma[k]reconMat = U[:,:numSV]*SigRecon*VT[:numSV,:]#重构矩阵print "****reconstructed matrix using %d singular values****" % numSVprintMat(reconMat, thresh)print imgCompress(2)

效果:

Figure 14-9: 数字0的原始矩阵


Figure 14-10: 数字0重构后的矩阵

只需要两个奇异值就能相当精确地对图像实现重构,U和VT都是32×2的矩阵,有两个奇异值,也即只需要32×2+2+32×2=130个0、1进行存储。原来需要1024个0、1,几乎获得10倍的压缩比。

14.7小结

SVD是一种强大的降维工具,可以利用SVD来逼近矩阵并从中提取重要特征,保留矩阵80%-90%的能量,得到重要的特征去掉噪音。推荐系统为SVD的一个成功的应用,协同过滤则是一种基于用户喜好或行为数据的推荐的实现方法。协同过滤的核心是相似度计算方法。


这篇关于《机器学习实战》笔记之十四——利用SVD简化数据的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/990972

相关文章

MySQL 多列 IN 查询之语法、性能与实战技巧(最新整理)

《MySQL多列IN查询之语法、性能与实战技巧(最新整理)》本文详解MySQL多列IN查询,对比传统OR写法,强调其简洁高效,适合批量匹配复合键,通过联合索引、分批次优化提升性能,兼容多种数据库... 目录一、基础语法:多列 IN 的两种写法1. 直接值列表2. 子查询二、对比传统 OR 的写法三、性能分析

Python办公自动化实战之打造智能邮件发送工具

《Python办公自动化实战之打造智能邮件发送工具》在数字化办公场景中,邮件自动化是提升工作效率的关键技能,本文将演示如何使用Python的smtplib和email库构建一个支持图文混排,多附件,多... 目录前言一、基础配置:搭建邮件发送框架1.1 邮箱服务准备1.2 核心库导入1.3 基础发送函数二、

PowerShell中15个提升运维效率关键命令实战指南

《PowerShell中15个提升运维效率关键命令实战指南》作为网络安全专业人员的必备技能,PowerShell在系统管理、日志分析、威胁检测和自动化响应方面展现出强大能力,下面我们就来看看15个提升... 目录一、PowerShell在网络安全中的战略价值二、网络安全关键场景命令实战1. 系统安全基线核查

SQL中如何添加数据(常见方法及示例)

《SQL中如何添加数据(常见方法及示例)》SQL全称为StructuredQueryLanguage,是一种用于管理关系数据库的标准编程语言,下面给大家介绍SQL中如何添加数据,感兴趣的朋友一起看看吧... 目录在mysql中,有多种方法可以添加数据。以下是一些常见的方法及其示例。1. 使用INSERT I

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

MySQL 删除数据详解(最新整理)

《MySQL删除数据详解(最新整理)》:本文主要介绍MySQL删除数据的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、前言二、mysql 中的三种删除方式1.DELETE语句✅ 基本语法: 示例:2.TRUNCATE语句✅ 基本语

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语

Java MQTT实战应用

《JavaMQTT实战应用》本文详解MQTT协议,涵盖其发布/订阅机制、低功耗高效特性、三种服务质量等级(QoS0/1/2),以及客户端、代理、主题的核心概念,最后提供Linux部署教程、Sprin... 目录一、MQTT协议二、MQTT优点三、三种服务质量等级四、客户端、代理、主题1. 客户端(Clien

MyBatisPlus如何优化千万级数据的CRUD

《MyBatisPlus如何优化千万级数据的CRUD》最近负责的一个项目,数据库表量级破千万,每次执行CRUD都像走钢丝,稍有不慎就引起数据库报警,本文就结合这个项目的实战经验,聊聊MyBatisPl... 目录背景一、MyBATis Plus 简介二、千万级数据的挑战三、优化 CRUD 的关键策略1. 查

python实现对数据公钥加密与私钥解密

《python实现对数据公钥加密与私钥解密》这篇文章主要为大家详细介绍了如何使用python实现对数据公钥加密与私钥解密,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录公钥私钥的生成使用公钥加密使用私钥解密公钥私钥的生成这一部分,使用python生成公钥与私钥,然后保存在两个文