对于人工智能而言,人工智能算法将向量看作一维数组,每个数组或是每个向量都代表着一组数据.
衡量两个向量的相似程度就需要使用到距离算法.和我们现实世界中的距离类似,越相似的两个向量投影在现实空间中自然离得很近.
例如鸢尾花的五个量值:
5.1,3.5,1.4,0.2,Iris-Setosa
转为向量就变成了
[5.1, 3.5, 1.4, 0.2, 1, 0, 0]
这本质上仍然是一个一维数组.对计算机而言没有区别,只是线性代数将其称作为向量.

向量计算

欧氏距离

在外面熟知的笛卡尔坐标系中,两点间的距离为

这个距离公式是用于处理两个点的距离,换言之,就是两个维度,但是我们需要处理的大部分数据都不止两个维度。
例如我们有三个向量,a,b,c;
a和b之间的欧氏距离为10
ac之间的欧氏距离为20,那么a显然距离b更近,我们就认为a和b更相似。
根据上式的推广,我们可以得出对于任意两个向量的欧氏距离d:

能看出,欧式距离和起点无关,不论是qp还剩pq他们的距离是等价的。

  1. #include <iostream>
  2. #include <cmath>
  3. const int N = 3; //length or dimension
  4. double v1[N],v2[N];
  5. double euclidean(double pos1[], double pos2[])
  6. {
  7. double sum = 0.0;
  8. double d = 0.0;
  9. for(int i = 0;i < N;i++)
  10. {
  11. d = pos1[i] - pos2[i];
  12. sum = sum + d * d;
  13. }
  14. return sqrt(sum);
  15. }
  16. int main(){
  17. int n = 3;
  18. while(--n)
  19. {
  20. v1[n] = n; // 2,1,0
  21. v2[n] = n + 10; // 12,11,10
  22. }
  23. std::cout << euclidean(v1,v2);
  24. }

image.png

曼哈顿距离

对于欧氏距离而言,欧式距离更像是两个点之间的直线距离,但是在现实生活中或是计算机中,路径的存在都让直线距离很难处理。例如司机需要根据道路来规划路线,不能点到点直线驾驶。计算机也需要规定特定线路或逻辑距离。
为了解决这个问题,在矩阵中“按照路线”行走的距离便是曼哈顿距离
而对于曼哈顿距离的计算也非常简单,只需要将两点间的维度的绝对距离相加即可。
如下:
第三节 距离度量 - 图2
和欧氏距离一样,传入的参数位置并不影响结果.

  1. #include <iostream>
  2. #include <cmath>
  3. const int N = 3; //length or dimension
  4. double v1[N],v2[N];
  5. double manhattan(double pos1[], double pos2[])
  6. {
  7. double sum = 0.0;
  8. double d = 0.0;
  9. for(int i = 0;i < N;i++)
  10. {
  11. d = abs(pos1[i] - pos2[i]);
  12. sum = sum + d;
  13. }
  14. return sum;
  15. }
  16. int main(){
  17. int n = 3;
  18. while(--n)
  19. {
  20. v1[n] = n;// 2,1,0
  21. v2[n] = n + 10;// 12,11,10
  22. }
  23. std::cout << manhattan(v1,v2);
  24. }

切比雪夫距离

切比雪夫距离标明了该点在各维度中的最大值,例如象棋棋盘中需要移动的步数.
在计算机中,有一个更加适合的模型,就是在广度优先搜索中的层数.
例如在目标点的周围所有点都是BFS中的第一层,那么这些围绕着目标点的点距离目标点就都是1.
如下:
第三节 距离度量 - 图3

  1. #include <iostream>
  2. #include <cmath>
  3. const int N = 3; //length or dimension
  4. double v1[N],v2[N];
  5. double max(double a,double b){return a>b?a:b;}
  6. double chebyshev(double pos1[], double pos2[])
  7. {
  8. double result = 0.0;
  9. double d = 0.0;
  10. for(int i = 0;i < N;i++)
  11. {
  12. d = abs(pos1[i] - pos2[i]);
  13. result = max(result, d);
  14. }
  15. return result;
  16. }
  17. int main(){
  18. int n = 3;
  19. while(--n)
  20. {
  21. v1[n] = n;
  22. v2[n] = n + 10;
  23. }
  24. std::cout << chebyshev(v1,v2) <<std::endl;
  25. }