447. Google Smartphone Decimeter Challenge | google-smartphone-decimeter-challenge
首先,我要感谢主办方组织了这样一场独特的比赛!
在这次比赛中,我成功晋升为 Grand Master(特级大师),我的队友 @fuumin621 也成功晋升为 Master(大师)!
以下是我们简短方案中我负责部分的介绍。
对我们来说,正确使用 AccumulatedDeltaRange(累积距离变化量)并仔细观察数据是非常重要的。
我使用 LightGBM 根据 IMU 数据和基线数据预测了异常值(与真实值的距离)和速度。
然后,我将高于阈值的异常值替换为 NULL,并在它们之间进行线性插值。
我应用了两种模式的线性卡尔曼平滑。
一种考虑了速度,另一种考虑了加速度(即 4D 和 6D)。
此外,由于观测值的时间间隔不是恒定的,我在每次更新步骤中替换了状态转移矩阵中的 delta_t。
我尝试过在市区增大观测噪声、预测横摆角速度以及使用非线性卡尔曼滤波,但都没有效果。
我知道相位观测很重要,所以我尝试利用卫星数据中的 AccumulatedDeltaRange 来改进基线,但由于缺乏相关知识,没有成功……
所以我决定使用 Google 的 GNSS 分析应用。
通过使用这个工具,我能够获得部分数据的 AccumulatedDeltaRange 观测值。
观测数据本身因为包含偏差很难直接使用,但通过取它们之间的差值获得的相对距离非常准确,如下图所示。(delta_adr = ADR(t) - ADR(t-1))
我利用这一点实现了前向 Hatch 滤波器和后向 Hatch 滤波器,并在应用卡尔曼平滑后对它们进行了平均。
prev_smooth = lat_lngs[0]
res = [prev_smooth]
for raw, delta_adr, delta_t in zip(
lat_lngs[1:, :], delta_adrs[1:, :], delta_ts[1:]
):
if not all(np.isnan(delta_adr)):
smooth = 1 / M * raw + (M - 1) / M * (
prev_smooth + delta_adr * delta_t
)
else:
smooth = raw
prev_smooth = smooth
res.append(prev_smooth)
res = np.array(res)
有一个名为 M 的参数,我使用 GroupKFold 针对每个区域对其进行了优化。(在训练数据中找到最小的参数,并在验证数据中进行验证。)
使用这种 Hatch 滤波器进行平滑非常有效。
某些手机的 delta_adr 值有很多缺失,因此我们用其他手机的值填充了它们。
在应用 Hatch 滤波器后,我使用通过 GroupKFold 优化的手机权重对经度和纬度进行加权平均,就像优化参数 M 一样。
部分 millisSinceGpsEpoch 根据手机的不同有轻微差距,因此我使用线性插值来填充它。
在市区,我使用线性插值的真实值执行了离散优化。
为了防止过拟合,真实值本身不包含在吸附目标中。
目标函数如下,我使用贪婪搜索来寻找最佳路径。
cost = distance2cur + distance2prev * alpha
使用 LightGBM 预测的速度值,我对低于阈值的点取了平均值。
使用各种参数,我对结果取平均,CV 大约为 2.149。
最后,在加入其他成员的模型和后处理后,我们的 CV 达到了 2.0569,LB 达到了 2.285。
在 Private 排行榜阶段,我知道高速公路和树木区域有很大的权重,所以我在决定集成权重