HOWTO · NumPy
使用 NumPy 計算歐幾里得距離
本教學說明如何使用 Python 與 NumPy 計算歐幾里得距離。
本頁內容
對於表示具有相同座標數量之點的兩個 NumPy 陣列,請使用 np.linalg.norm(point_a - point_b) 計算歐幾里得距離。減法會產生座標差,而向量的 L2 範數會將這些差縮減為一個非負距離。
理解歐幾里得距離公式
對於點 (a=(a_1,\ldots,a_n)) 和 (b=(b_1,\ldots,b_n)),歐幾里得距離是座標差平方和的平方根:
在 NumPy 中,np.linalg.norm(a - b) 直接表達此定義。對一維差值陣列且未指定 ord 引數時,np.linalg.norm 會計算其 2-範數。兩個輸入都必須描述維度相容的點,減法才有預期的意義。
準備輸入座標
座標位置必須以相同順序描述相同軸:將一個點的第一個座標與另一個點的第一個座標比較,依此類推。請將一個點表示為形狀為 (coordinates,) 的一維陣列。例如,兩個形狀為 (3,) 的陣列表示同一三維座標系中的兩個點,而不是三個獨立距離。
元組和串列可在減法前使用 np.asarray(values, dtype=float) 轉換。浮點類型接受整數或小數座標,並在一個座標小於對應座標時避免無號整數回繞。若輸入已是合適的浮點 NumPy 陣列,則無須轉換。不要只是為了讓形狀相符而壓平任意多維資料,因為這可能掩蓋而非修正輸入結構錯誤。
以下範例使用 Python 3.14.7、NumPy 2.5.3 與 SciPy 1.18.1 執行。展示的 API 是既有介面,但應用程式仍應使用與其支援 Python 環境相容的版本。除非使用 SciPy 方法或成對距離工具,否則 SciPy 為選用項目。
計算兩點之間的距離
下列已驗證的範例比較建議的範數運算式、明確公式、點積形式、標準程式庫 math.dist 以及 SciPy 的 scipy.spatial.distance.euclidean。五種計算對此點對產生相同結果。
"""Verify equivalent Euclidean-distance APIs for one pair of points."""
import math
import numpy as np
from scipy.spatial import distance
point_a = np.array([1.0, 2.0, 3.0])
point_b = np.array([4.0, 5.0, 6.0])
print(f"np.linalg.norm: {np.linalg.norm(point_a - point_b)}")
print(f"formula: {np.sqrt(np.sum((point_a - point_b) ** 2))}")
delta = point_a - point_b
print(f"dot product: {np.sqrt(np.dot(delta, delta))}")
print(f"math.dist: {math.dist(point_a, point_b)}")
print(f"distance.euclidean: {distance.euclidean(point_a, point_b)}")
np.linalg.norm: 5.196152422706632
formula: 5.196152422706632
dot product: 5.196152422706632
math.dist: 5.196152422706632
distance.euclidean: 5.196152422706632
明確公式在概念上使用 NumPy 的逐元素平方,接著求和並取 平方根。範例中的指數形式會將完整計算保留於一個運算式中。點積變體也會計算相同平方和,因為 np.dot(delta, delta) 會將相對應的差相乘再相加。
當點已是陣列或屬於較大 NumPy 計算的一部分時,請使用 np.linalg.norm。它無須詳列歸約即可清楚傳達向量運算。
使用 axis=1 計算逐列距離
對儲存為二維陣列各列的多個點,請減去一個參考點並設定 axis=1。NumPy 會將參考陣列廣播到各列,而 axis=1 會要求 np.linalg.norm 每列傳回一個範數,而不是整個矩陣的一個範數。
"""Verify row-wise distances from several points to one reference point."""
import numpy as np
points = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
reference = np.array([1.0, 2.0, 3.0])
print(np.linalg.norm(points - reference, axis=1))
[0. 5.19615242]
第一列等於參考點,因此其距離為零。第二個結果是單一點對範例所計算的距離。此模式涵蓋一對多距離;對兩個集合間所有成對距離,請使用 scipy.spatial.distance.cdist 等專用常式,而不是在未考量記憶體用量時建立大型廣播中介陣列。
在 NumPy、math.dist 與 SciPy 間選擇
最佳方法取決於周邊程式碼,而非通用的速度宣稱:
- 對 NumPy 陣列、向量化工作流程及含
axis的逐列計算,使用np.linalg.norm(a - b)。 - 當其他地方不需要 NumPy 時,對一對一般 Python 座標可迭代物件使用
math.dist(a, b)。 - 當 SciPy 已是相依項或計算屬於 SciPy 較廣泛的距離工具時,使用
scipy.spatial.distance.euclidean(a, b)。 - 在教學、稽核或調整基礎計算時,使用明確平方和公式或點積。它們不會讓結果比範數運算式更具歐幾里得性。
Python 串列不支援逐元素減法,因此在 NumPy 減法前以 np.asarray(..., dtype=float) 轉換很有用。math.dist 可直接接受等長座標可迭代物件,而 NumPy 和 SciPy 選項需要安裝各自套件。
處理不相容形狀與數值資料類型
兩個個別點必須有相同數目的座標。不相容的一維形狀無法一起廣播,因此 NumPy 會在計算距離前引發 ValueError。
"""Capture the diagnostic for points with incompatible dimensions."""
import numpy as np
point_a = np.array([1.0, 2.0])
point_b = np.array([3.0, 4.0, 5.0])
try:
np.linalg.norm(point_a - point_b)
except ValueError as error:
print(f"ValueError: {error}".rstrip())
ValueError: operands could not be broadcast together with shapes (2,) (3,)
當維度來自使用者輸入或外部資料時,請在減法前檢查形狀。對逐列距離,形狀為 (rows, coordinates) 的點陣列與形狀為 (coordinates,) 的參考點相容;其他形狀可能以非預期方式廣播或失敗。
也請在減法前將無號整數座標轉型為有號或浮點類型。無號減法可能回繞而非表示負座標差,導致後續範數不正確。範例中的浮點陣列可避免此問題並支援非整數座標。
對一對維度相等的 NumPy 點,np.linalg.norm(point_a - point_b) 是簡潔的預設選擇。逐列距離請加入 axis=1,並在輸入結構尚未保證時驗證形狀與資料類型。