import torch import torch.nn as nn class HausdorffDistanceLoss(nn.Module): def __init__(self): super(HausdorffDistanceLoss, self).__init__() def forward(self, pred, target): # 扩展为 (B, N, 1, D) 和 (B, 1, M, D) pred = pred.unsqueeze(1) # (N, D) -> (N, 1, D) target = target.unsqueeze(0) # (M, D) -> (1, M, D) # 计算两组点之间的 pairwise 距离 distances = torch.norm(pred - target, dim=2) # (N, M) # Hausdorff 距离的两个方向 h_a_to_b = distances.min(dim=1)[0].max() # a -> b 距离 h_b_to_a = distances.min(dim=0)[0].max() # b -> a 距离 return (h_a_to_b + h_b_to_a) / 2 # 返回 Hausdorff 距离 class OptimizedHausdorffDistanceLoss(nn.Module): def __init__(self): super(OptimizedHausdorffDistanceLoss, self).__init__() def forward(self, pred, target): """ pred: (B, N, D) - 预测点集 target: (B, M, D) - 目标点集 B: 批量大小 N: 每个预测点集的点数 M: 每个目标点集的点数 D: 点的维度 """ # 确保两个张量的数据类型一致 if pred.dtype != target.dtype: target = target.to(pred.dtype) # 使用torch.cdist计算距离矩阵 distances = torch.cdist(pred, target) # (B, N, M) # 从pred到target的最大最小距离 h_a_to_b = distances.min(dim=1)[0].max(dim=0)[0] # (B,) # 从target到pred的最大最小距离 h_b_to_a = distances.min(dim=1)[0].max(dim=0)[0] # (B,) # 返回Hausdorff距离作为损失值 return ((h_a_to_b + h_b_to_a) / 2).mean() # 返回批量的平均损失 def euclidean_distance_mean(pred, target): """ 计算两个点集之间的欧氏距离,并返回平均值。 参数: pred: Tensor (N, D) - 预测点集 target: Tensor (M, D) - 目标点集 返回: mean_distance: float - 欧氏距离的平均值 """ # 计算两个点集之间的 pairwise 欧氏距离 distances = torch.cdist(pred, target, p=2) # 使用 p=2 计算欧氏距离 # 计算 pairwise 距离的平均值 mean_distance = distances.mean() return mean_distance # 测试部分 if __name__ == "__main__": # 创建两个点集,每个点集只有两个点 pred = torch.tensor([[1.0, 2.0, 3.0], [3.0, 4.0, 5.0]]) target = torch.tensor([[2.0, 3.0, 3.0], [3.0, 4.0, 5.0]]) # 初始化损失函数 loss_fn = HausdorffDistanceLoss() loss_fn2 = OptimizedHausdorffDistanceLoss() # 计算损失值 loss = loss_fn(pred, target) loss2 = loss_fn2(pred, target) print("Hausdorff Distance Loss:", loss.item()) print("Optimized Hausdorff Distance Loss:", loss2.item()) # 计算欧氏距离的平均值 mean_distance = euclidean_distance_mean(pred, target) print("Euclidean Distance Mean:", mean_distance.item())
D:\ProgramData\Anaconda3\envs\torch38\python.exe D:\Desktop\Aidyna\test2.py Hausdorff Distance Loss: 1.4142135381698608 Optimized Hausdorff Distance Loss: 1.4142135381698608 Euclidean Distance Mean: 1.8319511413574219 进程已结束,退出代码为 0
区别解释:
-
Hausdorff Distance:
- Hausdorff 距离用于衡量两个点集之间最远的最近点的距离。
- 它首先计算从一个点集到另一个点集的最短距离,然后在这些最短距离中选择最大的那个值。这通常用于比较两个几何形状的相似性。
h_a_to_b
计算的是pred
到target
的最大最小距离,h_b_to_a
计算的是target
到pred
的最大最小距离,最终 Hausdorff 距离是这两个距离的平均值。
由于 Hausdorff 距离只关心两个点集中最远的最近点,因此它的值通常较小,尤其是在两个点集较为相似的情况下。
-
Euclidean Distance Mean:
- 欧氏距离的均值则是两个点集中所有点之间的 pairwise 距离的均值。
- 它计算所有点对之间的欧氏距离,然后取这些距离的平均值。
因为它考虑了所有点对的距离,因此它会产生一个相对较大的值,尤其是当点集中的所有点距离都不近时。
为什么结果不同?
- Hausdorff 距离 专注于找到两个点集中最不相似的部分,因此它的值反映的是最远的最近距离,这在你例子中是
1.4142135381698608
(即sqrt(2)
,与点(1, 2, 3)
到(2, 3, 3)
的距离一致)。 - 欧氏距离均值 则计算了所有点对的距离,包括一些距离较大的点对(如
(1, 2, 3)
和(3, 4, 5)
),因此它得出了较大的平均值1.8319511413574219
。
这就是为什么 Hausdorff 距离和欧氏距离的平均值会不同,它们度量的东西不同:
- Hausdorff 距离:更关注最坏情况的点对。
- 欧氏距离均值:关注所有点对的整体距离。
标签:Distance,target,Euclidean,pred,距离,点集,Hausdorff From: https://www.cnblogs.com/arwen-xu/p/18390510