最近了解了几个类似度分析相关的算法,整理一下。html
曼哈顿距离又叫城市街区距离,形象的理解一下就是你要从城市的一个地方到另外一个地方,怎么计算你行驶的距离。以下图,想象一下,两个点之间是无数的高楼大厦。。。算法
那么怎么计算这两个点的距离呢?segmentfault
放在坐标系里,咱们很快就能算出这两个点的曼哈顿距离:(如下代码均为 Haskell 风格的伪代码)ide
-- 假设:A (x1, y1), B (x2, y2) d = abs(x1 - x2) + abs(y1 - y2)
这是二维平面上两个点的计算方式,咱们再扩展一下到 N 维世界:idea
-- 假设:A (x1, x2, ..., xn), B (y1, y2, ..., yn), A/B 的坐标集用列表表示 d = sum $ zipWith (\x y -> abs(x - y)) A B
这个距离若是放在二维世界来看的话,说的就是两点之间的直线距离:spa
至于这个距离的计算,都已经算是常识了:code
-- A (x1, y1), B (x2, y2) d = sqrt ((x1 - x2)^2 + (y1 - y2)^2)
脱离二维到 N 维:htm
-- A (x1, x2, ..., xn), B (y1, y2, ..., yn), A/B 的坐标集用列表表示 d = sqrt $ sum $ zipWith (\x y -> (x - y)^2) A B
余弦类似度,是指经过夹角的余弦大小来判断两个数据集的差别程度blog
(41, 43), B (82, 86) -> 向量 l (x1, y1)ip
(43, 41), D (86, 82) -> 向量 m (x2, y2)
-- l 和 m 的夹角余弦计算 cosLM = (x1 * x2 + y1 * y2) / (sqrt (x1^2 + y1^2) * sqrt (x2^2 + y2^2))
升级到 N 维空间后:
-- l (x1, x2, ..., xn), m (y1, y2, ..., yn), l/m 用列表表示 cosLM = (sum $ zipWith (*) l m) / ((sqrt $ sum $ zipWith (*) l l) * (sqrt $ sum $ zipWith (*) m m))
余弦值的取值范围是 [-1, 1],该值越大,表示两个向量的夹角越小,数据越类似。两个向量方向重合时,值为1,相反时值为 -1。
不少人用余弦类似度来比较文本是否类似,好比:
http://www.ruanyifeng.com/blo...
https://segmentfault.com/q/10...
https://www.zhihu.com/questio...
看完上面两个连接里面的回答,我再说说个人理解。
皮尔逊相关系数,是要在作余弦类似度计算以前,先把数据进行一次“中心化”
与上面的余弦类似度的计算对比一下,发现分子分母都多剪了一个平均值。
为何要减这个平均值呢?
当咱们在大量数据中挖掘信息时,不少数据可能在不一样维度上会有不一样状况的缺失,那咱们在计算类似度时怎么处理这些缺失呢?皮尔逊相关系数的方式是,把这些缺失都当作 0 ,而后让全部其余维度减去该向量个维度的平均值
pearson xs ys = (n * sumXY - sumX * sumY) / sqrt ( (n * sumX2 - sumX * sumX) * (n * sumY2 - sumY * sumY) ) where n = fromIntegral (length xs) sumX = sum xs sumY = sum ys sumX2 = sum $ zipWith (*) xs xs sumY2 = sum $ zipWith (*) ys ys sumXY = sum $ zipWith (*) xs ys
类似度算法太多了,先简单介绍一下这几个。如今有了这几个锤子,我要去项目里找找有没有合适的钉子了 ? ? ?