【机器学习】各种距离度量

在机器学习中,会经常与各种距离打交道。于是,在这篇文章中,我们来简单总结一下常见的距离以及其计算方式。

首先定义两个向量 a ⃗ = ( x 1 , x 2 , … , x n ) , b ⃗ = ( y 1 , y 2 , … , y n ) \vec{a}=(x_1,x_2,\ldots,x_n),\vec{b}=(y_1,y_2,\ldots,y_n) a =(x1,x2,,xn),b =(y1,y2,,yn),然后计算它们之间的距离。

曼哈顿距离

又称“街区距离”。是向量各维度差值的绝对值之和。
d = ∑ i = 1 n ∣ x i − y i ∣ d=\sum_{i=1}^n\vert x_i-y_i\vert d=i=1nxiyi
曼哈顿距离_360百科

欧氏距离

欧氏距离是大家最为熟悉的距离,早在高中甚至初中学习中就学习过。下面来回顾一下:

普通欧氏距离

普通欧氏距离是两个点在空间中的距离,对应向量就是各个分量差值的平方和再开方。
d = ∑ i = 1 n ( x i − y i ) 2 d=\sqrt{\sum_{i=1}^n(x_i-y_i)^2} d=i=1n(xiyi)2

标准化欧氏距离

为什么需要标准化欧氏距离呢?因为原始的欧氏距离有缺点:

  • 数据各维分量的分布不一样
  • 各个维度之间的尺度不一样

方法:先将各个分量都“标准化”到均值、方差相等。标准化后的值=( 标准化前的值-分量的均值) /分量的标准差
d = ∑ i = 1 n ( x i − y i ) S i 2 d=\sqrt{\sum_{i=1}^n\frac{(x_i-y_i)}{S_i}^2} d=i=1nSi(xiyi)2

切比雪夫距离

切比雪夫距离,来源于这样一个问题:国际象棋中的国王,每次可以沿八个方向行动,假设国王从A点到B点,那么国王至少需要移动几步?

对应我们的向量中,问题的答案就是向量各维的差值的最大值。
d = max ⁡ ∣ x i − y i ∣ d=\max\vert x_i-y_i\vert d=maxxiyi
image-20240318181336470

闵可夫斯基距离

闵可夫斯基距离可能大家不太熟悉。其实它不是一个距离,而是一组距离。它的计算公式为:
d = ∑ i = 1 n ( x i − y i ) p p d=\sqrt[p]{\sum_{i=1}^n (x_i-y_i)^p} d=pi=1n(xiyi)p
当p取不同的值时,意义也会有所不同了。

  • p=1,为曼哈顿距离
  • p=2,为欧氏距离
  • p= ∞ \infty 时,为切比雪夫距离

余弦距离

这个就不是度量向量之间的距离了,它是度量向量方向的差异。
d i s t ( a , b ) = 1 − A ⋅ B ∥ A ∥ ⋅ ∥ B ∥ dist(a,b)=1-\frac{A\cdot B}{\Vert A\Vert \cdot\Vert B\Vert} dist(a,b)=1ABAB
它的取值范围[0,2],值越大,说明两个向量方向差异也越大。余弦距离天然实现了归一化,不用考虑各个维度之间的尺度不一样的问题。

字符串距离

在计算机视觉中,是要经常跟字符串打交道的。字符串也有其相应的距离。

汉明距离

汉明距离很常见,它有两种表述:一是两个字符串对应位置的不同字符的个数,二是将其中一个变为另外一个所需要作的最小字符替换次数。

image-20240318185813470

这从编程的角度上来说其实很简单。

例子:

  • 1011111与1001001之间的汉明距离是3

  • happy 与puppy之间的汉明距离是2

int HanMing(const string&a,const string&b){
    //字符串长度不一致时无法计算汉明距离
    if (a.size()!=b.size())
        return -1;
    int ans=0;
    for (int i = 0; i < a.size(); ++i) {
        if (a[i]!=b[i])
            ans++;
    }
    return ans;
}

编辑距离

编辑距离也是一个经典的字符串距离,它指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。

经典算法使用动态规划求解,设字符串A,B,计算它们的编辑距离。

状态转移方程:

image-20240318185537930

下面附上代码实现(C++):

vector<vector<int>>dp;
int Distance(const string&a,const string&b){
    //向量容器初始化(当其中一个字符串为0时的答案)
    dp.assign(a.size()+1,vector<int>(b.size()+1));
    for (int i = 0; i <= a.size(); ++i) {
        dp[i][0]=i;
    }
    for (int i = 0; i <= b.size(); ++i) {
        dp[0][i]=i;
    }
    //状态转移方程(核心部分)
    for (int i = 1; i <= a.size(); ++i) {
        for (int j = 1; j <= b.size(); ++j) {
            if (a[i-1]==b[j-1])
                dp[i][j]=dp[i-1][j-1];
            else
                dp[i][j]= min({dp[i-1][j],dp[i][j-1],dp[i-1][j-1]})+1;
        }
    }
    return dp[a.size()][b.size()];
}
  • 29
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Forgotten Legend

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值