机器学习中的距离度量(python实现)

最近读《统计学习方法》的时候用到了各种距离,这里做一个小总结,并且用numpy实现一下。
一般的距离度量使用欧氏距离,就是我们生活中最常用的距离概念。但也可以使用其他的度量方式。

  1. 闵可夫斯基距离 L p L_p Lp距离)(Minkowski distance)

    闵可夫斯基距离也叫 L p L_p Lp距离,欧式距离是 L p L_p Lp距离的一种特殊情况。

机器学习中的距离度量(python实现)_第1张图片

在这里 p > = 1 p>=1 p>=1

  • p = 2 p=2 p=2时,称为欧氏距离(Euclidean distance)

    欧氏距离就是我们最常用的距离。相当于棋子和终点在棋盘上的交叉点,棋子只能沿任意直线(不一定是棋盘上的线)走到终点这样的长度

  • p = 1 p=1 p=1时,称为曼哈顿距离(Manhattan distance)

    *曼哈顿距离就是每个维度的差值之和。相当于棋子和终点在棋盘上的交叉点,棋子只能沿着棋盘格子的边边走到终点这样的长度

  • p = ∞ p=\infty p=时,称为切比雪夫距离(Chebyshev Distance)

    切比雪夫距离是各个坐标距离的最大值。相当于棋子和终点在棋盘上的交叉点,棋子每步只能横跳,纵跳或斜跳到邻近的交叉点最终调到终点的步数

下图是在二维空间中取不同的 p p p值时,与原点的 L p L_p Lp距离为1的点组成的图形:
机器学习中的距离度量(python实现)_第2张图片

从上图可以看到,采用不同的距离度量,最近邻的点也会不同。另外,采用闵可夫斯基距离通常需要数据进行标准化,因为不同维度的量纲会影响距离计算。

  1. 余弦距离

    与闵可夫斯基距离不同,余弦距离表征两个向量角度的。表达式为: d i s t ( A , B ) = 1 − c o s ( A , B ) dist(A,B)=1-cos(A,B) dist(A,B)=1cos(A,B).因此取值范围为 [ 0 , 2 ] [0,2] [0,2](非负性)。

    其中 c o s ( A , B ) = ∑ i = 1 N ( A i × B i ) ( ∑ i = 1 N ( A i 2 ) ) 1 2 × ( ∑ i = 1 N ( B i 2 ) ) 1 2 cos(A,B)=\frac{\sum_{i=1}^{N}(A_i\times{B_i})}{(\sum_{i=1}^{N}(A_i^2))^{\frac{1}{2}}\times{(\sum_{i=1}^{N}(B_i^2))^{\frac{1}{2}}}} cos(A,B)=(i=1N(Ai2))21×(i=1N(Bi2))21i=1N(Ai×Bi)

  2. 马氏距离(Mahalanobis distance)

    马氏距离是一种基于样本分布的距离。打比方:有一个集合和一个数据项,通过这个集合的分布来确定这个数据项距离集合总体的远近程度。

    定义:有M个样本向量 { X 1 , . . . , X M } \{X_1,...,X_M\} { X1,...,XM},协方差矩阵记为 S S S,均值记为向量 μ \mu μ,则其中样本向量 x x x μ \mu μ的马氏距离为:

    D ( x ) = ( ( X − μ ) T S − 1 ( X − μ ) ) 1 2 D(x)=((X-\mu)^TS^{-1}(X-\mu))^\frac{1}{2} D(x)=((Xμ)TS1(Xμ))21

    向量 X i X_i Xi X j X_j Xj的马氏距离为:

    D ( x ) = ( ( X i − X j ) T S − 1 ( X i − X j ) ) 1 2 D(x)=((X_i-X_j)^TS^{-1}(X_i-X_j))^\frac{1}{2} D(x)=((XiXj)TS1(XiXj))21

    注意:

    1. 马氏距离与量纲无关,因为每个维度都是互相独立的。
    2. 样本集合中样本数必须大于样本维度,否则没法算协方差矩阵。

    若协方差矩阵是单位矩阵(样本向量独立同分布),则向量 X i X_i Xi X j X_j Xj的马氏距离为他们的欧式距离。

各距离的numpy实现:

import numpy as np

def mks_distance(x1,x2,p=2):
    '''
    闵可夫斯基距离
    '''
    if len(x1) == len(x2):
        ans = sum(abs(x1 - x2) ** p) ** (1./p)
        return ans
    else:
        print('向量维度必须相等!')



def cos_distance(x1,x2):
    '''
    余弦距离
    '''
    if len(x1) == len(x2):
        a = sum(x1*x2)
        b = sum(x1 ** 2)**(0.5) * sum(x2 ** 2)**(0.5)
        return 1-a/b
    else:
        print('向量维度必须相等!')


def cov(x1,x2):
    '''
    向量协方差
    '''
    n = len(x1)
    if len(x2) == n:
        average1 = sum(x1)/len(x1)
        average2 = sum(x2)/len(x2)
        ans = (1/(n-1)) * sum((x1-average1) * (x2-average2))
        return ans
    else:
        print('向量维度必须相等!')


def ma_distance(m,x):
    '''
    马氏距离
    m为行向量组成的集合
    x为一个行向量
    '''
    a,b = np.shape(m)
    mean_m = m.mean(axis=0)
    if a>b:
        if len(x) == b:
            # 计算协方差矩阵
            s = np.zeros((b,b))
            for i in range(b):
                for j in range(b):
                    s[i][j] = cov(m[:,i],m[:,j])
        else:
            print('向量维度必须等于矩阵列数')
    else:
        print('矩阵行数必须大于列数')
    aa = np.dot((x-mean_m).T,s.T)
    print(s)
    ans = np.dot(aa,(x-mean_m))
    return ans

你可能感兴趣的:(统计学习方法,python,机器学习)