В этом руководстве мы рассмотрим, как рассчитать евклидово расстояние между двумя точками в Python с помощью Numpy.

Что такое евклидово расстояние?

Евклидово расстояние - это фундаментальная метрика расстояния, относящаяся к системам в евклидовом пространстве.

  • Евклидово пространство - это классическое геометрическое пространство, с которым вы знакомитесь на уроке математики, обычно связанное с 3 измерениями. Хотя его также можно приписать к любой неотрицательной целочисленной размерности.

  • Евклидово расстояние — кратчайшая прямая между двумя точками в евклидовом пространстве.

Название происходит от Евклида, который широко известен как «отец геометрии», так как это было единственное пространство, которое люди в то время обычно задумывали. Со временем в физике и математике наблюдались различные типы пространства, такие как пространство Аффин.

  • В 3-мерном евклидовом пространстве кратчайшая прямая между двумя точками всегда будет прямой линией между ними.

Учитывая этот факт, евклидово расстояние не всегда является наиболее полезной метрикой для отслеживания при работе со многими размерностями, мы сосредоточимся на 2D и 3D евклидовом пространстве для расчета евклидова расстояния.

Вообще говоря, евклидова расстояние широко используется в разработке 3D-миров, а также алгоритмов машинного обучения, которые включают в себя метрики расстояния, такие как K-ближайшие соседи. Как правило, евклидово расстояние будет представлять, насколько похожи две точки данных, предполагая, что некоторая кластеризация на основе других данных уже была выполнена.

Математическая формула

Математическая формула расчета евклидова расстояния между 2 точками в 2D пространстве:

d(p,q) = \sqrt[2]{(q_1-p_1)^2 + (q_2-p_2)^2 }

Формула легко адаптируется к 3D-пространство, а также к любому размеру:

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^2d(p,q)^2 = (q_1-p_1)^2 + (q_2-p_2)^2

На самом деле существует связь между ними - евклидовое расстояние рассчитывается с помощью теоремы Пифагора, учитывая декартовы координаты двух точек.

Из-за этого евклидова расстояние иногда называют расстоянием Пифагора, хотя прежнее название гораздо более известно.

Примечание: Две точки являются векторами, но выход должен быть скалярным.

Мы будем использовать NumPy для расчета этого расстояния для двух точек, и один и тот же подход используется для 2D и 3D пространств:

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()

Расчет евклидова расстояния в Python с помощью NumPy

Во-первых, нам нужно будет установить библиотеку NumPy:

$ pip install numpy

Теперь давайте импортируем его и настроим две наши точки с декартовыми координатами (0, 0, 0) и (3, 3, 3):

import numpy as np
# Initializing the points
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

В истинном питоновом духе это можно сократить до одной строки:

И вы даже можете вместо этого использовать встроенные методы pow() и sum() математического модуля Python, хотя они требуют, чтобы вы немного поработали с вводом, который удобно абстрагируется с помощью 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/евклида:

5.196152422706632

Нормализация L2 и нормализация L1 широко используются в машинном обучении для нормализации входных данных.

np.dot()

Мы также можем использовать точечное произведение для расчета евклидова расстояния. В математике точечное произведение является результатом умножения двух векторов равной длины, а результатом является единственное число - скалярное значение. Из-за возвращаемого типа его иногда также называют «скалярным продуктом». Эту операцию часто называют внутренним произведением для двух векторов.

Для расчета точечного произведения между 2 векторами вы можете использовать следующую формулу:

\vec{p} \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 есть встроенный метод в математическом модуле, который вычисляет расстояние между 2 точками в трехмерном пространстве. Однако это работает только с Python 3.8 или более поздней версии.

math.dist()принимает два параметра, которые являются двумя точками, и возвращает евклидово расстояние между этими точками.

Примечание: Обратите внимание, что две точки должны иметь одинаковые размеры (т.е. оба в 2d или 3d пространстве).

Теперь, чтобы вычислить Евклидово расстояние между этими двумя точками, мы просто заправляем их в метод thedistdist():

import math
distance = math.dist(point_1, point_2)
print(distance)
5.196152422706632

Заключение

Данная метрика используется во многих контекстах в интеллектуальном анализе данных, машинном обучении и ряде других областей и является одной из фундаментальных метрик расстояния.

Комментарии (7)


  1. Serge78rus
    25.09.2021 12:01
    +2

    Почему на картинке в начале статьи JavaScript, если далее речь идет о Python?


    1. masai
      25.09.2021 12:02
      +5

      Боюсь, что это меньшая из проблем этой статьи. :(


  1. masai
    25.09.2021 12:19
    +3

    метрика расстояния

    Это тавтология. Метрика — это функция, позволяющая вычислять расстояние, так что не бывает метрик не расстояния.

    Евклидово расстояние — кратчайшая прямая между двумя точками в евклидовом пространстве.

    Расстояние — это всё же число.

    Со временем в физике и математике наблюдались различные типы пространства, такие как пространство Аффин.

    Слово аффинный лучше писать с маленькой буквы, так как происходит оно не от названия города в Греции, а от латинского слова affinis.

    В 3-мерном евклидовом пространстве кратчайшая прямая между двумя точками всегда будет прямой линией между ними.

    Наверное, всё же кратчайшая линия, а то получается утверждение, что кратчайшая прямая — это прямая. Но это, кстати, не какое-то свойство евклидовых пространств, а просто по определению. В метрических пространствах кратчайшая линия называется прямой.


  1. MentalBlood
    25.09.2021 12:51
    +1

    ... расстояние кратчайшая прямая ...

    Две ошибки в одном коротком определении


  1. GreySS
    25.09.2021 14:13
    +2

    Хорошая статья, спасибо! Хорошо бы развить серию и написать про вычисление косинуса через чистый Python, через Numpy, через Scipy, а также через собственноручное разложение в ряд Тейлора, с замерами точности и скорости. Так как статья получится слишком насыщенная, то синус предлагается разобрать через неделю, после косинуса.


    1. unibasil
      26.09.2021 13:55

      При такой же содержательности, как здесь, одной статьёй про косинус не обойтись, минимум штук пять понадобится.


  1. jorikdima
    25.09.2021 14:37
    +2

    Всегда поражался умению из воздуха статью наделать.