如何计算周期为[-180°,180°]的角度相对真值的L1、L2范数
如何计算[-180°,180°]周期角度的L1/L2范数?
角度数据具有周期性(±180°等价于∓180°),直接用常规范数计算会因为跨周期的差值放大导致结果失真。解决核心是先计算每个角度对的周期性最小偏差,再基于该偏差计算范数。
核心思路
对于每个真值gt[i]和预测值ip_data[i],先计算周期内的最小角度差(绝对值≤180°),再用该差值计算L1、L2范数:
- 计算原始差值:
delta = gt[i] - ip_data[i] - 将差值映射到[-180°,180°]范围,得到最小偏差:
该公式的作用是把任意差值调整为周期内的最短距离,例如350°会被转换为-10°(等价于10°的偏差)。min_delta = ((delta + 180) % 360) - 180
修正后的范数计算
- L1范数:所有最小偏差的绝对值之和
L1 norm = sum(abs(min_delta[i])) - L2范数:所有最小偏差平方和的平方根
L2 norm = sqrt(sum(min_delta[i]^2))
示例验证
用测试数据验证:
gt[] = [175, 179, 177] ip_data_b[] = [-175, -171, -173]
对每个角度对计算最小偏差:
- 175 - (-175) = 350 → min_delta = ((350+180)%360)-180 = -10
- 179 - (-171) = 350 → min_delta = -10
- 177 - (-173) = 350 → min_delta = -10
最终计算结果:
L1 = |-10| + |-10| + |-10| = 30 L2 = sqrt((-10)^2 + (-10)^2 + (-10)^2) = sqrt(300) ≈ 17.32
与ip_data_a的结果一致,符合实际角度偏差的评估。
代码实现(Python)
import math def get_min_angle_deltas(gt, ip_data): deltas = [] for g_val, d_val in zip(gt, ip_data): raw_delta = g_val - d_val # 计算周期内的最小偏差 min_delta = ((raw_delta + 180) % 360) - 180 deltas.append(min_delta) return deltas def calculate_angle_L1(gt, ip_data): min_deltas = get_min_angle_deltas(gt, ip_data) return sum(abs(d) for d in min_deltas) def calculate_angle_L2(gt, ip_data): min_deltas = get_min_angle_deltas(gt, ip_data) return math.sqrt(sum(d**2 for d in min_deltas)) # 测试 gt = [175, 179, 177] ip_data_a = [165, 169, 167] ip_data_b = [-175, -171, -173] print(f"ip_data_a L1: {calculate_angle_L1(gt, ip_data_a)}") # 30 print(f"ip_data_a L2: {round(calculate_angle_L2(gt, ip_data_a), 2)}") # 17.32 print(f"ip_data_b L1: {calculate_angle_L1(gt, ip_data_b)}") # 30 print(f"ip_data_b L2: {round(calculate_angle_L2(gt, ip_data_b), 2)}") # 17.32
内容的提问来源于stack exchange,提问作者Milan
相关产品推荐
相关产品推荐

