From 0de845d3deea409a2deb66cf12224ed6e0c567dc Mon Sep 17 00:00:00 2001 From: jiangzhonglian Date: Tue, 29 Aug 2017 14:47:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20svd.md=20=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/14.利用SVD简化数据.md | 128 +++++++++++++++++++++++++++--------- src/python/14.SVD/svdRec.py | 27 ++++---- 2 files changed, 110 insertions(+), 45 deletions(-) diff --git a/docs/14.利用SVD简化数据.md b/docs/14.利用SVD简化数据.md index bee9ff86..4171ef13 100644 --- a/docs/14.利用SVD简化数据.md +++ b/docs/14.利用SVD简化数据.md @@ -3,36 +3,38 @@ ![利用SVD简化数据首页](/images/14.SVD/svd_headPage.jpg "利用SVD简化数据首页") +## SVD 概述 + ``` 奇异值分解(SVD, Singular Value Decomposition): - 提取信息的一种方法,可以把SVD看成是从噪声数据中抽取相关特征。从生物信息学到金融学,SVD是提出信息的强大工具。 - -* 优点:简化数据,去除噪声,提高算法的结果 -* 缺点:数据的转换可能难以理解 -* 使用的数据类型:数值型数据 + 提取信息的一种方法,可以把 SVD 看成是从噪声数据中抽取相关特征。从生物信息学到金融学,SVD 是提出信息的强大工具。 ``` -## SVD的应用 +## SVD 场景 > 信息检索-隐形语义检索(Lstent Semantic Indexing, LSI)或 隐形语义分析(Latent Semantic Analysis, LSA) 隐性语义索引:矩阵 = 文档 + 词语 -* 是最早的SVD应用之一。我们称利用SVD的方法为隐性语义索引(LSI)或隐性语义分析(LSA)。 -* ![LSA举例](/images/14.SVD/使用SVD简化数据-LSI举例.png) +* 是最早的 SVD 应用之一,我们称利用 SVD 的方法为隐性语义索引(LSI)或隐性语义分析(LSA)。 + +![LSA举例](/images/14.SVD/使用SVD简化数据-LSI举例.png) > 推荐引擎 -1. 利用SVD从数据中构建一个主题空间。 +1. 利用 SVD 从数据中构建一个主题空间。 2. 再在该空间下计算其相似度。(从高维-低维空间的转化,在低维空间来计算相似度,SVD提升了推荐引擎的效率。) -* ![主题空间案例1](/images/14.SVD/SVD_推荐系统_主题空间案例1.jpg) -* 上图右边标注的为一组共同特征,表示美式BBQ 空间;另一组在上图右边未标注的为日式食品 空间。 +![主题空间案例1](/images/14.SVD/SVD_推荐系统_主题空间案例1.jpg) + +* 上图右边标注的为一组共同特征,表示美式 BBQ 空间;另一组在上图右边未标注的为日式食品 空间。 > 图像压缩 例如:`32*32=1024 => 32*2+2*1+32*2=130`(2*1表示去掉了除对角线的0), 几乎获得了10倍的压缩比。 -## SVD矩阵分解 +## SVD 原理 + +### SVD 工作原理 > 矩阵分解 @@ -40,20 +42,84 @@ * 矩阵分解可以将原始矩阵表示成新的易于处理的形式,这种新形式时两个或多个矩阵的乘积。(类似代数中的因数分解) * 举例:如何将12分解成两个数的乘积?(1,12)、(2,6)、(3,4)都是合理的答案。 -> SVD 是矩阵分解的一种类型,也是矩阵分解最常见的技术。 +> SVD 是矩阵分解的一种类型,也是矩阵分解最常见的技术 * SVD 将原始的数据集矩阵Data分解成三个矩阵U、∑、\\(V^T\\) * 举例:如果原始矩阵 \\(Data_{m*n}\\) 是m行n列, * \\(U_{m*m}\\) 表示m行m列 * \\(∑_{m*n}\\) 表示m行n列 * \\(V^T_{n*n}\\) 表示n行n列。 -* ![SVD公式](/images/14.SVD/使用SVD简化数据-SVD公式.png) -* 上述分解中会构建出一个矩阵∑,该矩阵只有对角元素,其他元素均为0(近似于0)。另一个惯例就是,∑的对角元素是从大到小排列的。这些对角元素称为奇异值,它们对应原始矩阵Data的奇异值。 -* 奇异值与特征值(PCA数据中重要特征)是有关系的。这里的奇异值就是矩阵 \\(Data * Date^T\\) 特征值的平方根。 -* 普遍的事实:在某个奇异值的数目(r个=>奇异值的平方和累加到总值的90%以上)之后,其他的奇异值都置为0(近似于0)。这意味着数据集中仅有r个重要特征,而其余特征则都是噪声或冗余特征。 + +![SVD公式](/images/14.SVD/使用SVD简化数据-SVD公式.png) + +* 上述分解中会构建出一个矩阵∑,该矩阵只有对角元素,其他元素均为0(近似于0)。另一个惯例就是,∑的对角元素是从大到小排列的。这些对角元素称为奇异值,它们对应原始矩阵 Data 的奇异值。 +* 奇异值与特征值(PCA 数据中重要特征)是有关系的。这里的奇异值就是矩阵 \\(Data * Date^T\\) 特征值的平方根。 +* 普遍的事实:在某个奇异值的数目(r 个=>奇异值的平方和累加到总值的90%以上)之后,其他的奇异值都置为0(近似于0)。这意味着数据集中仅有 r 个重要特征,而其余特征则都是噪声或冗余特征。 + +### SVD 算法特点 + +``` +优点:简化数据,去除噪声,提高算法的结果 +缺点:数据的转换可能难以理解 +使用的数据类型:数值型数据 +``` ## 推荐引擎 +### 推荐系统 概述 + +`推荐系统是利用电子商务网站向客户提供商品信息和建议,帮助用户决定应该购买什么产品,模拟销售人员帮助客户完成购买过程。` + +### 推荐系统 场景 + +1. Amazon 会根据顾客的购买历史向他们推荐物品 +2. Netflix 会向其用户推荐电影 +3. 新闻网站会对用户推荐新闻频道 + +### 推荐系统 原理 + +* 推荐系统的工作过程:给定一个用户,系统会为此用户返回N个最好的推荐菜。 +* 实现流程大致如下: + 1. 寻找用户没有评级的菜肴,即在用户-物品矩阵中的0值。 + 2. 在用户没有评级的所有物品中,对每个物品预计一个可能的评级分数。这就是说:我们认为用户可能会对物品的打分(这就是相似度计算的初衷)。 + 3. 对这些物品的评分从高到低进行排序,返回前N个物品。 +* 现在我们来观测代码实现。 + + +### 项目案例: 餐馆菜肴推荐引擎 + +#### 项目概述 + +`假如一个人在家决定外出吃饭,但是他并不知道该到哪儿去吃饭,该点什么菜。推荐系统可以帮他做到这两点。` + + +#### 开发流程 + +> 收集 并 准备数据 + +```python +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]] +``` + +> 分析数据 + +> 使用算法 + + + + > 基于协同过滤(collaborative filtering)的推荐引擎 * 利用Python 实现SVD(Numpy 有一个称为linalg的线性代数工具箱) @@ -80,10 +146,12 @@ > 基于物品的相似度和基于用户的相似度:物品比较少则选择物品相似度,用户比较少则选择用户相似度。【矩阵还是小一点好计算】 * 基于物品的相似度:计算物品之间的距离。【耗时会随物品数量的增加而增加】 -* ![SVD公式](/images/14.SVD/使用SVD简化数据-基于物品相似度.png) + +![SVD公式](/images/14.SVD/使用SVD简化数据-基于物品相似度.png) * 基于用户的相似度:计算用户之间的距离。【耗时会随用户数量的增加而增加】 -* ![SVD公式](/images/14.SVD/使用SVD简化数据-基于用户相似度.png) + +![SVD公式](/images/14.SVD/使用SVD简化数据-基于用户相似度.png) > 推荐引擎的评价 @@ -91,35 +159,33 @@ * 推荐引擎评价的指标: 最小均方根误差(Root mean squared error, RMSE),也称标准误差(Standard error),就是计算均方误差的平均值然后取其平方根。 * 如果RMSE=1, 表示相差1个星级;如果RMSE=2.5, 表示相差2.5个星级。 -> 餐馆菜肴推荐引擎-案例 +### 项目案例: 基于 SVD 的图像压缩 -* 推荐系统的工作过程:给定一个用户,系统会为此用户返回N个最好的推荐菜。 -* 实现流程大致如下: - 1. 寻找用户没有评级的菜肴,即在用户-物品矩阵中的0值。 - 2. 在用户没有评级的所有物品中,对每个物品预计一个可能的评级分数。这就是说:我们认为用户可能会对物品的打分(这就是相似度计算的初衷)。 - 3. 对这些物品的评分从高到低进行排序,返回前N个物品。 -* 现在我们来观测代码实现。 -> 补充:基于内容(content-based)的推荐 +### 要点补充 + +#### 基于内容(content-based)的推荐 1. 通过各种标签来标记菜肴 2. 将这些属性作为相似度计算所需要的数据 3. 这就是:基于内容的推荐。 -> 构建推荐引擎面临的挑战 +#### 构建推荐引擎面临的挑战 + +> 问题 -* 问题 * 1)在大规模的数据集上,SVD分解会降低程序的速度 * 2)存在其他很多规模扩展性的挑战性问题,比如矩阵的表示方法和计算相似度得分消耗资源。 * 3)如何在缺乏数据时给出好的推荐-称为冷启动【简单说:用户不会喜欢一个无效的物品,而用户不喜欢的物品又无效。】 -* 建议 +> 建议 + * 1)在大型系统中,SVD分解(可以在程序调入时运行一次)每天运行一次或者其频率更低,并且还要离线运行。 * 2)在实际中,另一个普遍的做法就是离线计算并保存相似度得分。(物品相似度可能被用户重复的调用) * 3)冷启动问题,解决方案就是将推荐看成是搜索问题,通过各种标签/属性特征进行`基于内容的推荐`。 * * * -* **作者:[片刻](http://www.apache.wiki/display/~jiangzhonglian) [1988](http://www.apache.wiki/display/~lihuisong)** +* **作者:[片刻](http://cwiki.apachecn.org/display/~jiangzhonglian) [1988](http://cwiki.apachecn.org/display/~lihuisong)** * [GitHub地址](https://github.com/apachecn/MachineLearning): * **版权声明:欢迎转载学习 => 请标注信息来源于 [ApacheCN](http://www.apachecn.org/)** diff --git a/src/python/14.SVD/svdRec.py b/src/python/14.SVD/svdRec.py index 9ecfd309..6586a147 100644 --- a/src/python/14.SVD/svdRec.py +++ b/src/python/14.SVD/svdRec.py @@ -1,5 +1,6 @@ #!/usr/bin/python # coding: utf-8 + ''' Created on Mar 8, 2011 Update on 2017-05-18 @@ -73,7 +74,7 @@ def pearsSim(inA, inB): # 如果不存在,该函数返回1.0,此时两个向量完全相关。 if len(inA) < 3: return 1.0 - return 0.5 + 0.5 * corrcoef(inA, inB, rowvar = 0)[0][1] + return 0.5 + 0.5 * corrcoef(inA, inB, rowvar=0)[0][1] # 计算余弦相似度,如果夹角为90度,相似度为0;如果两个向量的方向相同,相似度为1.0 @@ -100,7 +101,7 @@ def standEst(dataMat, user, simMeas, item): continue # 寻找两个用户都评级的物品 # 变量overLap 给出的是两个物品当中已经被评分的那个元素 - overLap = nonzero(logical_and(dataMat[:, item].A>0, dataMat[:, j].A>0))[0] + overLap = nonzero(logical_and(dataMat[:, item].A > 0, dataMat[:, j].A > 0))[0] # 如果相似度为0,则两着没有任何重合元素,终止本次循环 if len(overLap) == 0: similarity = 0 @@ -216,17 +217,17 @@ def imgCompress(numSV=3, thresh=0.8): if __name__ == "__main__": - # 对矩阵进行SVD分解(用python实现SVD) - Data = loadExData() - print Data - U, Sigma, VT = linalg.svd(Data) - # 打印Sigma的结果,因为前3个数值比其他的值大了很多,为9.72140007e+00,5.29397912e+00,6.84226362e-01 - # 后两个值比较小,每台机器输出结果可能有不同可以将这两个值去掉 - print Sigma + # # 对矩阵进行SVD分解(用python实现SVD) + # Data = loadExData() + # print Data + # U, Sigma, VT = linalg.svd(Data) + # # 打印Sigma的结果,因为前3个数值比其他的值大了很多,为9.72140007e+00,5.29397912e+00,6.84226362e-01 + # # 后两个值比较小,每台机器输出结果可能有不同可以将这两个值去掉 + # print Sigma - # 重构一个3x3的矩阵Sig3 - Sig3 = mat([[Sigma[0], 0, 0], [0, Sigma[1], 0], [0, 0, Sigma[2]]]) - print U[:, :3] * Sig3 * VT[:3, :] + # # 重构一个3x3的矩阵Sig3 + # Sig3 = mat([[Sigma[0], 0, 0], [0, Sigma[1], 0], [0, 0, Sigma[2]]]) + # print U[:, :3] * Sig3 * VT[:3, :] """ # 计算欧氏距离 @@ -245,7 +246,6 @@ if __name__ == "__main__": """ - """ # 计算相似度的方法 myMat = mat(loadExData2()) # print myMat @@ -256,7 +256,6 @@ if __name__ == "__main__": # 默认推荐(菜馆菜肴推荐示例) print recommend(myMat, 2) - """ """ # 利用SVD提高推荐效果