本文共 3471 字,大约阅读时间需要 11 分钟。
[comment]: # Machine Learning: 学习心得 - 14 - 利用SVD简化数据
最近在看Peter Harrington写的“机器学习实战”,这是我的学习心得,这次是第14章 - 利用SVD简化数据。
这里介绍,机器学习中的降维技术,可简化样品数据。一个系统里有很多商品,也有用户信息,以及用户对商品的打分情况。例如:
用户 | 商品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 |
这些数据有以下特点:
如果要对一个用户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个关键问题:
先解决简单的问题。相似度是一个0到1的值。可以选择下面的方法来计算。
两个点离得越近,越相似。
求两个点的距离DSimilarity = 1 / (1 + D)
统计方法中求两组数据的相关度,
这两个点的correlationValueSimilarity = correlationValue / 2 + 0.5
计算两个点的角度,求余弦值([-1, 1]), 角度越接近0,越相似。
求两个点的角度的余弦值cosineValue.Similarity = cosineValue / 2 + 0.5
对于商品A和商品B,可以看作为两列数据,我们在这两列中,找出两个数据都不为0的行。
比如:中商品1和商品2,只要看4,5两行数据就可以。矩阵\(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),也就是说只有在对角线上才有值。比如:这里主要介绍\(\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\)
这时:
求近似数据集:
由于\(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))
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]
转载地址:http://igxfz.baihongyu.com/