numpy和scipy计算向量欧氏距离性能对比

本文通过实测对比了使用NumPy和SciPy库计算大规模数据集欧氏距离的效率,结果显示SciPy在计算速度上显著优于NumPy。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

# coding:utf-8

from scipy import spatial
from functools import wraps
import datetime
import numpy as np


def print_execution_time(func, iter=100):
    @wraps(func)
    def warpper(*args, **kwargs):
        total_time = 0
        for i in range(iter):
            start_time = datetime.datetime.now()
            res = func(*args, **kwargs)
            end_time = datetime.datetime.now()
            duration_time = (end_time - start_time).microseconds // 1000
            total_time += duration_time
        avg_time = total_time / iter
        print("function name -> %s, elapse time -> %s ms" % (func.__name__, avg_time))
        return res

    return warpper


@print_execution_time
def distance_euclidean_numpy(vec1, vec2):
    return np.sqrt(np.sum(np.power(vec1 - vec2, 2), axis=1))


@print_execution_time
def distance_euclidean_scipy(vec1, vec2, distance="euclidean"):
    return spatial.distance.cdist(vec1, vec2, distance)


x = np.random.rand(1000000).reshape((-1, 2)) * 100
x = x.astype(np.int16)

# print(x.dtype, x.shape)
y = np.array([[1, 2]])

print("starting")

distance_numpy = distance_euclidean_numpy(x, y)
distance_scipy = distance_euclidean_scipy(x, y, "euclidean")
print(distance_numpy[500:510])
print(distance_scipy[500:510])

输出结果:

starting
function name -> distance_euclidean_numpy, elapse time -> 24.62 ms
function name -> distance_euclidean_scipy, elapse time -> 10.21 ms
[ 53.60037313  50.28916384  77.62087348  52.63078947  47.38143096
  75.16648189 113.27841807 101.67103816 118.1058847   65.8559033 ]
[[ 53.60037313]
 [ 50.28916384]
 [ 77.62087348]
 [ 52.63078947]
 [ 47.38143096]
 [ 75.16648189]
 [113.27841807]
 [101.67103816]
 [118.1058847 ]
 [ 65.8559033 ]]


结论:scipy计算性能更高

https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.cdist.html

计算两个数组之间的欧氏距离,可以通过以下几种方法实现。以下是详细的说明代码示例: ### 方法 1:基于 NumPy 的手动实现 通过直接运用欧氏距离公式 \(d = \sqrt{\sum_{i=1}^{n}(a_i - b_i)^2}\),可以使用 NumPy 进行高效的矩阵运算。 ```python import numpy as np def euclidean_distance_numpy(arr1, arr2): if len(arr1) != len(arr2): raise ValueError("两个数组的长度必须相同") squared_diffs = np.square(np.subtract(arr1, arr2)) # 计算对应元素差值的平方 sum_squared_diffs = np.sum(squared_diffs) # 求平方项之 distance = np.sqrt(sum_squared_diffs) # 开根号得到最终结果 return distance[^1] # 示例数组 arr1 = np.array([1, 2, 3]) arr2 = np.array([4, 5, 6]) distance = euclidean_distance_numpy(arr1, arr2) print(f"使用 NumPy 手动实现的欧氏距离: {distance}") ``` ### 方法 2:利用 `numpy.linalg.norm` NumPy 提供了内置函数 `numpy.linalg.norm` 来快速计算向量范数,默认情况下它会计算 L2 范数(即欧氏距离),这使得代码更加简洁明了。 ```python import numpy as np def euclidean_distance_linalg(arr1, arr2): if len(arr1) != len(arr2): raise ValueError("两个数组的长度必须相同") diff_vector = np.subtract(arr1, arr2) # 向量差 norm_value = np.linalg.norm(diff_vector) # 使用 linalg.norm 计算 L2 范数 return norm_value[^2] # 示例数组 arr1 = np.array([1, 2, 3]) arr2 = np.array([4, 5, 6]) distance = euclidean_distance_linalg(arr1, arr2) print(f"使用 numpy.linalg.norm 的欧氏距离: {distance}") ``` ### 方法 3:借助 SciPy 的 `pdist` 函数 SciPy 库提供了更为强大的工具来处理各种距离度量问题。对于简单的两数组间欧氏距离计算,也可以调用 `scipy.spatial.distance.pdist` 函数完成此任务。 ```python from scipy.spatial.distance import pdist import numpy as np def euclidean_distance_pdist(arr1, arr2): combined_array = np.vstack([arr1, arr2]) # 将两个数组堆叠成二维形式 pairwise_distances = pdist(combined_array, metric='euclidean') # 计算配对距离 return pairwise_distances[0] # 取第一个也是唯一的一个值作为结果 # 示例数组 arr1 = np.array([1, 2, 3]) arr2 = np.array([4, 5, 6]) distance = euclidean_distance_pdist(arr1, arr2) print(f"使用 scipy.spatial.distance.pdist 的欧氏距离: {distance}" ) ``` --- ### 注意事项 - 上述三种方法均假设输入为一维等长数组;如果遇到不匹配情况,则抛出异常提示错误。 - 在实际项目中可根据具体需求选择合适的方法。当仅需简单操作时可选用前两种方式之一;而面对复杂场景比如批量计算大量点对间的距离时,推荐采用第三种方法或其他高级解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值