在本指南中,我们将看看如何在Python中使用Numpy计算两点之间的欧氏距离。
什么是欧几里得距离?
欧氏距离是一个与欧氏空间中的系统有关的基本距离度量。
欧氏空间是你在数学课上熟悉的经典几何空间,通常被限定为3维。虽然,它也可以适用于任何非负的整数维。
欧几里得距离是欧几里得空间中两点之间最短的直线。
这个名字来自于欧几里德,他被广泛认为是*"几何学之父",因为这是当时人们通常会想到的唯一空间。随着时间的推移,人们在物理学和数学中观察到了不同类型的空间,如Affine空间*,而非欧几里得空间和几何学对于我们的认知是非常不直观的。
在3维欧几里得空间中,两点之间最短的线永远是它们之间的直线,尽管这在更高维度上并不成立。
鉴于这一事实,在处理许多维度时,欧氏距离并不总是最有用的指标,我们将专注于二维和三维欧氏空间来计算欧氏距离。
测量高维数据的距离通常是用其他距离指标,如曼哈顿距离。
一般来说,欧氏距离在三维世界的发展中有着重要的用途,以及包含距离度量的机器学习算法,如K-Nearest Neighbors。通常情况下,欧氏距离将代表两个数据点的相似程度--假设已经根据其他数据进行了一些聚类。
数学公式
计算二维空间中两点之间的欧氏距离的数学公式:
$
d(p,q) = sqrt[2]{(q_1-p_1)^2 + (q_2-p_2)^2 }
该公式很容易适应三维空间,以及任何维度。
d(p,q) = \sqrt[2]{(q_1-p_1)^2 + (q_2-p_2)^2 + (q_3-p_3)^2 }
一般公式可以简化为:
d(p,q) = \sqrt[2]{(q_1-p_1) ^2 + ...+ (q_n-p_n)^2 }
眼尖的人可能会注意到欧氏距离和毕达哥拉斯定理的相似性:
C^2 = A^2 + B^2
$
d(p,q)^2 = (q\_1-p\_1)^2 + (q\_2-p\_2)^2
事实上,这些之间存在着一种关系--欧氏距离是通过毕达哥拉斯定理计算的,给定两点的笛卡尔坐标。
正因为如此,欧氏距离有时也被称为毕达哥拉斯距离,不过,前者的名字更为人所知。
注意:两点是向量,但输出应该是一个标量(也就是距离)。
我们将使用NumPy来计算两点的这个距离,同样的方法也用于二维和三维空间。
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
ax.scatter(0, 0, 0)
ax.scatter(3, 3, 3)
plt.show()

用NumPy在Python中计算欧几里得距离
首先,我们需要安装NumPy库。
$ pip install numpy
现在,让我们导入它并设置我们的两个点,直角坐标为(0,0,0)和(3,3,3)。
import numpy as np
point_1 = np.array((0, 0, 0))
point_2 = np.array((3, 3, 3))
现在,让我们利用NumPy的辅助方法,而不是手动进行计算,使之变得更加简单
np.sqrt()和np.sum()
计算欧氏距离所需的操作和数学函数相当简单:加法、减法以及平方根函数。多次加法也可以用和来代替:
$
d(p,q) = \sqrt[2]{(q_1-p_1)^2 + (q_2-p_2)^2 + (q_3-p_3)^2 }
NumPy为我们提供了一个`np.sqrt()` 函数,代表平方根函数,以及一个`np.sum()` 函数,代表一个和。有了这些,在Python中计算欧几里得距离就简单而直观了。
```
# Get the square of the difference of the 2 vectors
square = np.square(point_1 - point_2)
# Get the sum of the square
sum_square = np.sum(square)
```
这给了我们一个相当简单的结果。
```
(0-3)^2 + (0-3)^2 + (0-3)^2
```
这等于*27*。剩下的就是得到这个数字的平方根。
```
# The last step is to get the square root and print the Euclidean distance
distance = np.sqrt(sum_square)
print(distance)
```
这就得出了。
```
5.196152422706632
```
本着真正的Pythonic精神,这可以缩短到只有一行。
```
distance = np.sqrt(np.sum(np.square(point_1 - point_2)))
```
`math` 你甚至可以用Python的`pow()` 和`sum()` 模块的内置方法来代替,尽管它们需要你对输入进行一些修改,这很方便地用NumPy进行了抽象,因为`pow()` 函数只对标量(数组中的每个元素都是单独的)工作,并且接受一个参数--你要把数字提高到哪个幂。
不过,这种方法在直觉上*看起来*更像我们以前使用的公式。
```
from math import *
distance = np.sqrt(sum(pow(a-b, 2) for a, b in zip(point_1, point_2)))
print(distance)
```
这也导致了。
```
5.196152422706632
```
### *np.linalg.norm()*
`np.linalg.norm()` 函数表示一个*数学规范*。从本质上讲,一个向量的*规范*就是它的*长度*。这个长度不一定是*欧氏距离*,也可以是其他距离。欧氏距离是**一个向量的L2规范**(有时被称为**欧氏规范**),默认情况下,`norm()` 函数使用L2--`ord` 参数被设置为2。
如果你将`ord` 参数设置为其他值*p*,你就会计算其他*p规范*。例如,*一个向量的L1准则是曼哈顿距离*!
考虑到这一点,我们可以使用`np.linalg.norm()` 函数来计算欧氏距离,而且比使用其他函数要简单得多。
```
distance = np.linalg.norm(point_1-point_2)
print(distance)
```
这样,L2/Euclidean距离就会被打印出来。
```
5.196152422706632
```
*L2归一化*和*L1归一化*在机器学习中被大量使用,用于归一化输入数据。
> 如果你想了解更多关于特征缩放的信息--请阅读我们的《[使用Scikit-Learn对数据进行特征缩放指南》](https://stackabuse.com/feature-scaling-data-with-scikit-learn-for-machine-learning-in-python/)!
### *np.dot()*
我们也可以用一个 ***点积***来计算欧几里得距离。在数学中,*点积*是两个等长的向量相乘的结果,其结果是一个单一的数字--标量值。由于返回类型的关系,它有时也被称为a ***"标量乘积"***.这个操作通常被称为两个向量的**内积**。
要计算2个向量之间的点积,可以使用以下公式:
\vec{p}
\cdot
\cdot \vec{q} = {(q_1-p_1) + (q_2-p_2) + (q_3-p_3) }
使用NumPy,我们可以使用`np.dot()` 函数,传入两个向量。
如果我们计算这两个点之间的差值的点积,再加上这个差值--我们会得到一个与这两个向量之间的欧几里得距离有关的数字。提取这个数字的平方根,就可以得到我们要找的距离。
```
# Take the difference between the 2 points
diff = point_1 - point_2
# Perform the dot product on the point with itself to get the sum of the squares
sum_square = np.dot(diff, diff)
# Get the square root of the result
distance = np.sqrt(sum_square)
print(distance)
```
当然,你也可以把它缩短为一个单行代码。
```
distance = np.sqrt(np.dot(point_1-point_2, point_1-point_2))
print(distance)
```
```
5.196152422706632
```
### 使用内置的*math.dist()*
Python 在`math` 模块里有一个内置的方法,可以计算三维空间中两点之间的距离。然而,这只适用于Python 3.8或更高版本。
`math.dist()` dist()接收两个参数,即两个点,并返回这两个点之间的欧几里得距离。
**注意**:请注意,这两个点必须有相同的尺寸(即都在2d或3d空间)。
现在,为了计算这两个点之间的欧几里得距离,我们只需把它们夹在`dist()` 方法中。
```
import math
distance = math.dist(point_1, point_2)
print(distance)
```
```
5.196152422706632
```
### 结论
*欧氏距离*是一个与*欧氏空间*中的系统有关的基本距离度量。
> 欧氏空间是你在数学课上熟悉的*经典几何空间*,通常被限定为3维。虽然,它也可以适用于任何非负的整数维。
> 欧几里得距离是欧几里得空间中两点之间的最短直线。
该指标在数据挖掘、机器学习和其他一些领域的许多情况下使用,是基本距离指标之一。