|||
此处仅列直观性图,具体见一下博客:
(1)闵可夫斯基距离定义为:
图1. (左)欧氏距离与曼哈顿距离:绿色的斜线表示欧几里得距离,在现实中是不可能的。其他三条折线表示了曼哈顿距离,这三条折线的长度是相等的。(右)p取值与距离。
图2. p的其他取值所成图
(2)马氏距离
假设x,y是从均值向量为μ,协方差矩阵为Σ的总体G中随机抽取的两个样本,定义x,y两点之间的马氏距离为:
定义x与总体G的马氏距离为:
其中,如果协方差矩阵是单位向量,也就是各维度独立同分布,马氏距离就变成了欧氏距离。
注:上面的两个表达式其实是马氏距离的平方
考虑下面这张图,椭圆表示等高线,从欧几里得的距离来算,绿黑距离大于红黑距离,但是从马氏距离,结果恰好相反:
马氏距离实际上是利用 Cholesky transformation 来消除不同维度之间的相关性和尺度不同的性质。
假设样本点(列向量)之间的协方差对称矩阵是 $\Sigma" alt="" style="border: 0px; height: auto; color: rgb(51, 51, 51); font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13.3333px; white-space: normal; background-color: rgb(214, 211, 214);$ , 通过 Cholesky Decomposition(实际上是对称矩阵 LU 分解的一种特殊形式,可参考之前的博客)可以转化为下三角矩阵和上三角矩阵的乘积: $\Sigma = LL^T" alt="" style="border: 0px; height: auto; color: rgb(51, 51, 51); font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13.3333px; white-space: normal; background-color: rgb(214, 211, 214);$ 。消除不同维度之间的相关性和尺度不同,只需要对样本点 x 做如下处理: $z = L^{-1}(x - \mu )" alt="" style="border: 0px; height: auto; color: rgb(51, 51, 51); font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13.3333px; white-space: normal; background-color: rgb(214, 211, 214);$ 。处理之后的欧几里得距离就是原样本的马氏距离:为了书写方便,这里求马氏距离的平方):
下图蓝色表示原样本点的分布,两颗红星坐标分别是(3, 3),(2, -2):
由于 x, y 方向的尺度不同,不能单纯用欧几里得的方法测量它们到原点的距离。并且,由于 x 和 y 是相关的(大致可以看出斜向右上),也不能简单地在 x 和 y 方向上分别减去均值,除以标准差。最恰当的方法是对原始数据进行 Cholesky 变换,即求马氏距离(可以看到,右边的红星离原点较近):
将上面两个图的绘制代码和求马氏距离的代码贴在这里,以备查阅:
# -*- coding=utf-8 -*-
# code related at: http://www.cnblogs.com/daniel-D/
import numpy as np
import pylab as pl
import scipy.spatial.distance as dist
def plotSamples(x, y, z=None):
stars = np.matrix([[3., -2., 0.], [3., 2., 0.]])
if z is not None:
x, y = z * np.matrix([x, y])
stars = z * stars
pl.scatter(x, y, s=10) # 画 gaussian 随机点
pl.scatter(np.array(stars[0]), np.array(stars[1]), s=200, marker='*', color='r') # 画三个指定点
pl.axhline(linewidth=2, color='g') # 画 x 轴
pl.axvline(linewidth=2, color='g') # 画 y 轴
pl.axis('equal')
pl.axis([-5, 5, -5, 5])
pl.show()
# 产生高斯分布的随机点
mean = [0, 0] # 平均值
cov = [[2, 1], [1, 2]] # 协方差
x, y = np.random.multivariate_normal(mean, cov, 1000).T
plotSamples(x, y)
covMat = np.matrix(np.cov(x, y)) # 求 x 与 y 的协方差矩阵
Z = np.linalg.cholesky(covMat).I # 仿射矩阵
plotSamples(x, y, Z)
# 求马氏距离
print('\n到原点的马氏距离分别是:')
print(dist.mahalanobis([0,0], [3,3], covMat.I), dist.mahalanobis([0,0], [-2,2], covMat.I))
# 求变换后的欧几里得距离
dots = (Z * np.matrix([[3, -2, 0], [3, 2, 0]])).T
print('\n变换后到原点的欧几里得距离分别是:')
print(dist.minkowski([0, 0], np.array(dots[0]), 2), dist.minkowski([0, 0], np.array(dots[1]), 2))
点滴分享,福泽你我!Add oil!
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-11-10 07:12
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社