返回列表

2nd Place Solution: GPU-Accelerated Random Search

524. G2Net Detecting Continuous Gravitational Waves | g2net-detecting-continuous-gravitational-waves

开始: 2022-10-04 结束: 2023-01-03 物理与天文 数据算法赛
第二名方案:GPU加速的随机搜索

第二名方案:GPU加速的随机搜索

作者: knshnb (Grandmaster) | 团队成员: charmq, yoichi7yamakawa
发布时间: 2023-01-06 | 比赛排名: 第2名

感谢主办方和Kaggle工作人员举办这次比赛,并祝贺获奖者!我也非常感谢我的队友( @charmq@yoichi7yamakawa)。

在比赛结束前八小时,我们意识到在相近频率范围内的真实数据可能具有完全相同的噪声,通过实际识别其中的一些,我们将性能提升到了 0.855/0.849(公榜第一名!)。在这篇文章中,我们将重点介绍不包含这种“泄露技巧”的主要解决方案,该方案仍然可以获得第二名(0.835/0.826)。

基本算法

在经历了训练神经网络模型的挣扎后,在最后两周我们发现一个非常简单的解决方案可以奏效:信号的随机搜索。利用 PyFstat 计算出的每个时间戳的速度,波的形状由四个参数决定:f0, f1, alpha, 和 delta。我们搜索这些参数的组合,以最大化每个数据中对应部分的平均功率(=绝对值的平方)。我们算法的核心部分如下所示(类NumPy伪代码):

stft_sq: (360, n_timestamp)
frequency_Hz: (360)
velocity: (3, n_timestamp)

for _ in range(n_random_search):
    f0, f1, alpha, delta = random_sample_params()
    signal = calc_signal_shape(f0, f1, alpha, delta, velocity)  # (n_timestamp): 每个时间戳的频率
    frequency_idx = np.round((signal - frequency_Hz[0]) / (frequency_Hz[1] - frequency_Hz[0]))  # (n_timestamp)
    signal_part = stft_sq[frequency_idx, np.arange(n_timestamp)]  # (n_timestamp): 数据中对应部分的功率
    score = np.sqrt(signal_part.mean())

作为预测,我们简单地输出了每个数据的两个探测器(L1 和 H1)的平均分数。

我们使用 Cupy 实现了该算法的批量执行,以在 GPU 上加速。这使得在 NVIDIA V100 上大约 20 秒内搜索 3276800 个点成为可能。因此,分别执行所有训练数据和测试数据大约需要 3 个 GPU 小时和 2 个 GPU 天。

细节

我们尝试了信号周围的几种频率宽度(在上面的伪代码中我们只取最近的一个)和加权方法。最好的方法是取最近的两个,并根据与信号频率的差异进行线性插值。

在计算信号形状时,我们将整个数据的 tref 固定为某个值,因为这可以通过改变 f0 和 f1 来覆盖。

选择正确的参数分布很重要。通过对训练数据的分析,我们意识到分数高于某个阈值(约 1.541)的数据几乎肯定是正样本。在测试数据中高分样本的参数分布如下(右图是按每个数据的频率范围缩放的 f0):

参数分布图 F0比例图

由此,我们决定从以下分布中采样每个参数,这大大提高了性能:

alpha: Uniform([0, 2 \pi])
delta: arcsine(Uniform([-1, 1]))
f0: Beta(2, 2) 在向两侧扩展 20% 的频率范围内
f1: 1/3 来自 -2 * 10^(Uniform([-11, -9])), 2/3 来自 2 * 10^(Uniform([-11, -