[comment]: # Machine Learning: 学习心得 - 14 - 利用SVD简化数据

前言

最近在看Peter Harrington写的“机器学习实战”,这是我的学习心得,这次是第14章 - 利用SVD简化数据。

这里介绍,机器学习中的降维技术,可简化样品数据。

基本概念

  • 降维(dimensionality reduction)。

    如果样本数据的特征维度很大,会使得难以分析和理解。我们可以通过降维技术减少维度。

    降维技术并不是将影响少的特征去掉,而是将样本数据集转换成一个低维度的数据集。

降维技术的用途

  • 使得数据集更易使用;
  • 降低很多算法的计算开销;
  • 去除噪声;
  • 使得结果易懂。

问题:如何向用户推荐他喜欢的商品

推荐系统的应用场景

一个系统里有很多商品,也有用户信息,以及用户对商品的打分情况。例如:

表1

用户 商品1 商品2 商品3 商品4 商品5 ... 商品d
user 1 0 0 2 5 3 ... 0
user 2 0 0 3 4 2 ... 0
user 3 0 0 2 5 4 ... 0
user 4 5 4 0 0 0 ... 0
user 5 3 5 0 0 0 ... 0
... ... ... ... ... ... ... ...
user n 0 0 4 5 3 ... 0

这些数据有以下特点:

  1. 商品很多
  2. 用户很多,一般情况下比商品多。
  3. 用户不会对所有商品打分,没有打分的记为0,打分的记为1~5。

解决问题的思路

如果要对一个用户U推荐一个U没有买过的商品:

对于当前用户U的每个没有买过的商品A:
对于系统中每个商品B,并且U给B打过分:
根据A和B的打分数据,获取一个降维数据集。*1
在降维数据集上,计算A和B的相似度Similarity。*2
Rating = U给B的打分
TotalSimilarity += Similarity
TotalRating += Similarity * Rating
A.Rating = TotalRating / TotalSimilarity
按照A.Rating从大到小排序。
打分高的商品作为推荐商品。

注:比如电影,一般用户不会看已经看过的电影,所以"没有买过的商品"在这是有特殊的意义。

也可以将这个条件根据实际的情况换成其它过滤条件。

根据上面的思路,我们还需要解决2个关键问题:

  1. 如何降维。
  2. 如何计算两个矢量(也可以看成2个点)的相似度。

如何计算2个矢量的相似度(Similarity)

先解决简单的问题。相似度是一个0到1的值。可以选择下面的方法来计算。

方法1:计算欧氏距离相似度。

两个点离得越近,越相似。

求两个点的距离D
Similarity = 1 / (1 + D)

方法2:计算皮尔逊相关系数(Pearson correlation)的相似度。

统计方法中求两组数据的相关度,

这两个点的correlationValue
Similarity = correlationValue / 2 + 0.5

方法3:计算角度的相似度。

计算两个点的角度,求余弦值([-1, 1]), 角度越接近0,越相似。

求两个点的角度的余弦值cosineValue.
Similarity = cosineValue / 2 + 0.5

如何降维

方法1: 只看对商品A和商品B都有打分的数据。

对于商品A和商品B,可以看作为两列数据,我们在这两列中,找出两个数据都不为0的行。

比如:表1中商品1和商品2,只要看4,5两行数据就可以。

  • 这个方法的问题是

    • 每次计算都需要寻找相关数据。对性能的优化不够。

方法2: 奇异值分解(Singular Value Decomposition,SVD)

矩阵\(Data_{{m} \times {n}}\),假设m < n。

奇异性分解可以将一个矩阵\(Data_{{m} \times {n}}\)分解成3个矩阵\(U_{{m} \times {m}}\), \(\Sigma_{{m} \times {n}}\), \(V^T_{{n} \times {n}}\)。

\(U\),\(V^T\)都是单式矩阵(unitary matrix),\(\Sigma\)是一个对角矩阵(rectangular diagonal matrix),也就是说只有在对角线上才有值。

比如:

\[\begin{bmatrix}
15 & 0 & 0 \\
0 & 11 & 0 \\
0 & 0 & 0.2 \\
0 & 0 & 0 \\
\end{bmatrix}
\]

这里主要介绍\(\Sigma\),我们只关心它的对角线上的数据。

首先这个对角线上的数据最多有m个(假设m < n)。

而且这个数组是按照从大到小的顺序排列的。

\(\Sigma\)的对角线上的数据被称为奇异数(Singular Values)。

奇异数的一个特点是可以用来计算一个降维的\(SmallData_{{m} \times {k} (k < m)}\)来代替原数据集\(Data_{{m} \times {n}}\)。

一个计算\(k\)的方法是:

在\(Sigma\)中找到前\(k\)的数据,使得其\(\textstyle \sum_{i=1}^k s_i^2\) 刚好大于 \(0.9 \times \textstyle \sum_{i=1}^m s_i^2\)

这时:

\[SmallData_{{m} \times {k}} = Data^T U_{{m} \times {k}} \Sigma_{{k} \times {k}}^I \\
where \\
\qquad k < m \\
\qquad W^I : 矩阵W的逆矩阵
\]

总结

  • 我们可以使用\(SmallData_{{m} \times {k}}\)作为降维后的数据集。
  • SVD降维技术的应用可以是离线的。(也就是说可以事先做好。)

将SVD降维技术应用到数据近似压缩上

求近似数据集:

\[NewData_{{m} \times {n}} = U_{{m} \times {k}} \Sigma_{{k} \times {k}} V^T_{{k} \times {n}} \\
where \\
\qquad NewData_{{m} \times {n}} \approx Data_{{m} \times {n}} \\
\qquad k < m
\]

由于\(NewData_{{m} \times {n}}\)是计算出来的,

所以可以只保存\(U_{{m} \times {k}}\), \(\Sigma_{{k} \times {k}}\)的奇异值, \(V^T_{{k} \times {n}}\)做为压缩数据。

核心公式

  • 相似度计算 - 欧氏距离
from numpy import *
def distanceSimilarity(A, B):
return 1.0 / (1.0 + linalg.norm(A - B))

\[\frac{1}{1 + \lVert A - B \rVert} \\
where \\
\qquad \lVert w \rVert = \sqrt {\textstyle \sum_{i=1}^n w_i^2}
\]

  • 相似度计算 - 皮尔逊相关系数(Pearson correlation)
from numpy import *
def correlationSimilarity(A, B):
if len(A) < 3 : return 1.0
return 0.5 + 0.5 * corrcoef(A, B, rowvar = 0)[0][1]
  • 相似度计算 - 余弦相似度

\[\cos \theta = \frac{A^TB}{\lVert A \rVert \lVert B \rVert} \\
f(A, B) = 0.5 + 0.5 * \cos \theta \\
where \\
\qquad \lVert w \rVert = \sqrt {\textstyle \sum_{i=1}^n w_i^2}
\]

参考

机器学习实战 - 读书笔记(14) - 利用SVD简化数据的更多相关文章

  1. 机器学习实战 - 读书笔记(13) - 利用PCA来简化数据

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第13章 - 利用PCA来简化数据. 这里介绍,机器学习中的降维技术,可简化样品数据. ...

  2. 机器学习实战 - 读书笔记(07) - 利用AdaBoost元算法提高分类性能

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习笔记,这次是第7章 - 利用AdaBoost元算法提高分类性能. 核心思想 在使用某个特定的算法是, ...

  3. 【转载】 机器学习实战 - 读书笔记(07) - 利用AdaBoost元算法提高分类性能

    原文地址: https://www.cnblogs.com/steven-yang/p/5686473.html ------------------------------------------- ...

  4. 【机器学习实战】第14章 利用SVD简化数据

    第14章 利用SVD简化数据 SVD 概述 奇异值分解(SVD, Singular Value Decomposition): 提取信息的一种方法,可以把 SVD 看成是从噪声数据中抽取相关特征.从生 ...

  5. 机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据

    机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据 关键字:PCA.主成分分析.降维作者:米仓山下时间:2018-11-15机器学习实战(Ma ...

  6. 机器学习实战 - 读书笔记(11) - 使用Apriori算法进行关联分析

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第11章 - 使用Apriori算法进行关联分析. 基本概念 关联分析(associat ...

  7. 机器学习实战 - 读书笔记(12) - 使用FP-growth算法来高效发现频繁项集

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第12章 - 使用FP-growth算法来高效发现频繁项集. 基本概念 FP-growt ...

  8. 机器学习——利用SVD简化数据

    奇异值分解(Singular Value Decompositon,SVD),可以实现用小得多的数据集来表示原始数据集. 优点:简化数据,取出噪声,提高算法的结果 缺点:数据的转换可能难以理解 适用数 ...

  9. 《机器学习实战》学习笔记——第14章 利用SVD简化数据

    一. SVD 1. 基本概念: (1)定义:提取信息的方法:奇异值分解Singular Value Decomposition(SVD) (2)优点:简化数据, 去除噪声,提高算法的结果 (3)缺点: ...

随机推荐

  1. Spring3系列4-多个配置文件的整合

    Spring3系列4-多个配置文件的整合 在大型的Spring3项目中,所有的Bean配置在一个配置文件中不易管理,也不利于团队开发,通常在开发过程中,我们会按照功能模块的不同,或者开发人员的不同,将 ...

  2. Spark源码系列(一)spark-submit提交作业过程

    前言 折腾了很久,终于开始学习Spark的源码了,第一篇我打算讲一下Spark作业的提交过程. 这个是Spark的App运行图,它通过一个Driver来和集群通信,集群负责作业的分配.今天我要讲的是如 ...

  3. React Native ——实现一个简单的抓取github上的项目数据列表

    /** * Sample React Native App * https://github.com/facebook/react-native */ 'use strict'; var React ...

  4. swift 附属脚本

    附属脚本是访问对象,集合或序列的快捷方式 struct STest{ let constValue:Int subscript(count:Int)->Int{ return count*con ...

  5. 【Android】Handler、Looper源码分析

    一.前言 源码分析使用的版本是 4.4.2_r1. Handler和Looper的入门知识以及讲解可以参考我的另外一篇博客:Android Handler机制 简单而言:Handler和Looper是 ...

  6. 实现无锁的栈与队列(5):Hazard Pointer

    两年多以前随手写了点与 lock free 相关的笔记:1,2,3,4,质量都不是很高其实(读者见谅),但两年来陆陆续续竟也有些阅读量了(可见剑走偏锋的技巧是多容易吸引眼球).笔记当中在解决内存释放和 ...

  7. notepad++批量头尾追加

    每行首添加 在“查找目标”里输入上尖号“^”,上尖号代表每行的开头 每行尾追加

  8. 在redhat上搭建redmine

    搞个项目管理的东西 找了下还是redmine比较合适,行动action: 1.ruby 额 是的你没有看错 需要先安装一个ruby的环境.话说这个安装起来很是纠结,本来想用yum 结果咩有成功,于是乎 ...

  9. webgame设计之功能模块的代理模式

    原文地址:http://chengduyi.com/blog/?post=27 在游戏设计中,通常会将一些实现了具体功能的模块进行封装,达到重用的目的.这些功能模块包括:1.网络通信模块(实现连接,断 ...

  10. Unity 3D 一个简单的角色控制脚本

    之所以写这个脚本,是因为我想起了我还是新手的时候,那时为了一个角色控制脚本百度了半天还是一无所获,因为看不懂啊,都写的太高级了 希望这个脚本能够帮助那些 像曾经的我一样迷失于代码中的新手们能够清晰的理 ...