pytorch和Numpy 的广播机制高效计算矩阵之间两两距离

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import torch
 
def pairwise_distance_broadcast(X, Y=None):
    """
    使用广播机制计算两两欧几里得距离。
    参数:
        X: 第一个张量,形状为 (m, d),表示 m 个 d 维向量。
        Y: 第二个张量(可选),形状为 (n, d)。如果为 None,则计算 X 内部的两两距离。
    返回:
        距离矩阵,形状为 (m, n)。
    """
    if Y is None:
        Y = X
 
    # 扩展维度以支持广播
    X_expanded = X.unsqueeze(1# 形状为 (m, 1, d)
    Y_expanded = Y.unsqueeze(0# 形状为 (1, n, d)
 
    # 计算两两距离
    distance_matrix = torch.sqrt(torch.sum((X_expanded - Y_expanded) ** 2, dim=2))  # 形状为 (m, n)
    return distance_matrix
 
# 示例
X = torch.tensor([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], dtype=torch.float32)
Y = torch.tensor([[7.0, 8.0], [9.0, 10.0]], dtype=torch.float32)
 
# 计算 X 和 Y 之间的两两距离
distances = pairwise_distance_broadcast(X, Y)
print("X 和 Y 之间的两两距离:")
print(distances)
 
# 计算 X 内部的两两距离
internal_distances = pairwise_distance_broadcast(X)
print("X 内部的两两距离:")
print(internal_distances)

 

 

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
'''求三维空间中两组点之间的两两距离'''
import numpy as np
 
# 第一组点,假设有四个点,位置如下
a = np.array([[ 0, 0, 0],
                [10,10,10],
                [20,20,20],
                [30,30,30]])
# 第二组点,假设有两个点,位置如下
b = np.array([[ 0, 0, 0],
                [10,10,10]])
 
# 计算距离
c = a[:, None, :] - b  
# 用None扩展维度,使其shape变为(4, 1, 3),b的shape是(2, 3),
# 然后两个数组相减,此时会用到广播机制。 c的shape:(4, 2, 3)
dist = np.sqrt(np.sum(c * c, axis=-1))
print(dist)
# 输出如下:
# [[ 0.         17.32050808]
#  [17.32050808  0.        ]
#  [34.64101615 17.32050808]
#  [51.96152423 34.64101615]]

广播机制的规则可参考:nupmy broadcast (广播) 

 

======================================================================

以下是旧内容:

利用numpy可以很方便的计算两个二维数组之间的距离。二维数组之间的距离定义为:X的维度为(m, c),Y的维度为(n,c),Z为X到Y的距离数组,维度为(m,n)。且Z[0,0]是X[0]到Y[0]的距离。Z(a,b)为X[a]到Y[b]的距离。

例如: 计算 m*2 的矩阵与 n * 2 的矩阵中,m*2 的每一行到 n*2 的两两之间欧氏距离。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
'''
L2 = sqrt((x1-x2)^2 + (y1-y2)^2 + (z1-z2)^2)
'''
 
import numpy as np
 
# ============= 方法一:不用循环 ====================
def L2_dist_1(cloud1, cloud2):
    m, n = len(cloud1), len(cloud2)
    cloud1 = np.repeat(cloud1, n, axis=0)
    cloud1 = np.reshape(cloud1, (m, n, -1))
    dist = np.sqrt(np.sum((cloud1 - cloud2)**2, axis=2))
    return dist
 
 
# ============= 方法二:用一重循环 ==================
def L2_dist_2(cloud1, cloud2):
    m, n = len(cloud1), len(cloud2)
    dist = np.zeros((m, n), dtype=np.float)
    for i in range(m):
        dist[i, :] = np.sqrt(np.sum((cloud1[i, :] - cloud2)**2, axis=1))
    return dist
 
 
# ============= 方法二:用两重循环 ==================
def L2_dist_3(cloud1, cloud2):
    m, n = len(cloud1), len(cloud2)
    dist = np.zeros((m, n), dtype=np.float)
    for i in range(m):
        for j in range(n):
            dist[i, j] = np.sqrt(np.sum((cloud1[i, :] - cloud2[j, :])**2, axis=0))
    return dist
 
 
if __name__ == '__main__':
    a = np.array([[ 0, 0, 0],
                  [10,10,10],
                  [20,20,20],
                  [30,30,30]])
 
    b = np.array([[ 0, 0, 0],
                  [10,10,10]])
 
    print('不用循环:\n', L2_dist_1(a, b))
    print('用一重循环:\n', L2_dist_2(a, b))
    print('用两重循环:\n', L2_dist_3(a, b))

程序运行结果:

 

参考:Numpy 的广播机制高效计算矩阵之间两两距离

 

posted @   Picassooo  阅读(829)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示