返回列表

20th place solution -- Keypoint-Based Dual-Graph Predictor

653. BYU - Locating Bacterial Flagellar Motors 2025 | byu-locating-bacterial-flagellar-motors-2025

开始: 2025-03-05 结束: 2025-06-04 医学影像分析 数据算法赛
20th place solution -- Keypoint-Based Dual-Graph Predictor

第 20 名解决方案 -- 基于关键点的双图预测器

作者: Tom (tom99763)
排名: 20
发布时间: 2025-06-05

致谢

虽然这次比赛我实际上是单人参赛(除了 @daphne4sg),但我想感谢所有在另一个 LLM 比赛中帮助过我并分享生活美好事物的队友 @goodcoder@bigochampion@cybersimar08。我从你们身上学到了很多。我也想感谢 @andrewjdarley 举办了如此精彩的比赛。这个项目对我的工作面试有很大帮助。由于你们的目标非常有趣,我非常愿意进行进一步的开发。

关于本方案的简短故事

该方案源于我职业生涯中最好的项目,那是我一年前在硕士学位期间完成的。我通过工业合作关系与 Micron Technology 的一位总监合作。该项目极具挑战性——由于数据隐私限制,我们只能使用 88 张 HBM 扫描图像来构建高性能异常检测器。

此外,标签是 AOI 判定结果和人类专家注释的混合体。我们的目标是对人类专家的偏好进行建模。我的 BYU 解决方案的一些部分改编自这个 HBM 项目,例如关键点生成和从图结构中推断标签。

然而,我方法中最具创新性的方面是利用视觉 - 语言模型(VLM)进行少样本预测,而不是像 YOLO 这样的传统物体检测器。本质上,我使用诸如“这个 HBM 是异常的”或"HBM 是正常的”这样的提示来表示目标的存在或不存在,允许模型进行初步分类猜测。

我的解决方案使用基于图的方法校准文本 - 图像嵌入空间,使 VLM 能够有效地执行我们的特定任务。结果,我能够仅用大约 20 张图像训练模型,并且它成功检测到了 HBM 数据集中人类专家识别的几乎所有异常。

解决方案

初步想法

初步想法可以参考我早些时候公开的 notebook。我想生成大量的点,然后通过建立它们与标签的关系来细化它们。我的策略是在细菌周围采样,因为马达存在于它的头部。如果我聚合所有的关键点并总结它们,就可以捕捉到正确的语义并避开噪声标签。然而,最大的问题是如何表示每个点的特征,所以我仅使用从简单 CNN 提取的补丁特征,然后构建 GNN 来预测马达的位置。结果证明这是一个非常糟糕的模型。

进一步改进 -- YOLO 作为特征提取器和关键点生成器

有趣的是,我两个月前差点在 这个帖子 中泄露了我的解决方案。我就此发展与 @hengck23 进行了简短的讨论。在这次讨论之后,我开始实施它,这个想法变成了下面展示的流程。基本上,我使用 YOLO11 的 C3K2 特征图,因为每个空间位置的特征可以代表细化的物体。设置较小的置信度阈值(conf=0.05)可以过滤掉足够多的由 YOLO11 确定的物体位置。这种设计极大地提高了分数,基本方法得到了很大改进。

节点特征 -- C3K2 + RandomWalkPE

特征对马达预测有很大影响。我尝试了几乎每种类型的特征,如 HoG、Daisy、EfficientNet、ResNet 和不同版本的 YOLO,除了 YOLO11 外,它们的效果都不好,但分数仍然不够好。几天后,我在 PYG 文档 上发现了 AddRandomWalkPE。我突然意识到这是 3D 任务中缺失的成分。添加它后分数立即提升。所以节点特征是 C3K2 + RandomWalkPE,其中 walk_length=8。我认为它提高分数的主要原因是因为它可以表示每个点的位置,隐式地建模马达的位置。

创建更多 3D 点

YOLO 通过设置低置信度阈值成功生成了很多点,但在 3D 空间中仍然稀疏,并且很有可能遗漏物体的存在。所以我解决这个问题的策略是使用预测点作为中心,然后在半径内均匀采样其他点。我设置 radiusnum_samples 分别控制范围和密度。我发现使用这种策略训练 GNN 也能提高分数。

标签开发 -- 半径内的相似度

由于将单个点注释为马达不能完全代表实际的语义(这就是为什么主持人在指标中给出了如此大的半径容差),我通过以下条件将点标记为正样本:

  • 当前位置与真实位置之间的特征相似度大于 thr_sim
  • 当前位置在真实位置的 3D 半径 thr 内。
def feat_labeling(points, feat, extract_feat, tomo_id, train_labels, thr = 10, thr_sim=0.5):
    label = train_labels[train_labels.tomo_id == tomo_id]
    print('location:', label[['Motor axis 0', 'Motor axis 1', 'Motor axis 2']].values[0])
    n_motors = label['Number of motors'].item()
    if n_motors == 0:
        return np.zeros(points.shape[0], )
    d, h, w = label[['Array shape (axis 0)', 'Array shape (axis 1)', 'Array shape (axis 2)']].values[0]
    loc = label[['Motor axis 0', 'Motor axis 1', 'Motor axis 2']].values[0]
    tz, ty, tx = loc.astype('int32')
    fd, fh, fw = feat.shape[0], feat.shape[2], feat.shape[3]
    z = tz.astype('int32')
    y = ((ty/h) * fh).astype('int32')
    x = ((tx/w) * fw).astype('int32')
    #sim
    extract_feat = extract_feat / np.linalg.norm(extract_feat, axis=-1, keepdims=True)
    target_feat = feat[z, :, y, x][None, :]
    target_feat = target_feat / np.linalg.norm(target_feat, axis=-1, keepdims=True)
    sim = extract_feat @ target_feat.T
    bool1 = sim[:, 0]>thr_sim

    #dist
    dist = np.linalg.norm(points - loc[None, :], axis=-1) #(N, 3)
    bool2 = dist<thr

    #label
    label = np.array(bool1 & bool2, dtype='float32')
    return label

图结构的选择

我尝试了各种图结构,最终发现结合 k-NN 图和 Delaunay 图 能产生最佳结果。k-NN 图提供高密度,而 Delaunay 图在远距离集群之间建立连接。通过利用这两种属性,结合的方法产生了更通用的模型。下面的实验结果清楚地解释了为什么有人只提交了 16 次就去睡觉了。

公共分数 私有分数 CV
Knn Graph 0.835 0.835 0.968
Radius Graph 0.826 0.830 0.966
Delaunay Graph 0.801 0.806 0.962
Knn + Radius 0.841 0.835 0.966
Knn + Delaunay 0.856 0.843 0.966
Graphs Comparison

流程

首先在竞赛数据集上训练 YOLO。我不使用外部数据集,因为我认为注释者不是同一个人,所以可能会对马达的存在给出不同的判断。然后为每个折叠训练两个 GraphSages,使用 Binary Cross Entropypositive_weight=8。在我选择的提交中,集成函数是最大值,但在某些场景下 HDBSCAN 更好。GNN 的训练数据是从 YOLO 过滤的点中收集的,其中包含正负数据。这里没有使用额外的数据集。

Pipeline Diagram

YOLO 模型大小

不幸的是,我在实验中陷入了困境,无法在截止时间的最后几分钟做出正确的选择。YOLO11L 预测了很多假阳性,这在这场比赛中是好的。但我没有选择它。这意味着我作为数据科学家的心态和经验还需要提高。

公共分数 私有分数 CV 提交时间
YOLO11L 0.856 0.843 0.968 7HR
YOLO11X 0.865 0.831 0.983 11HR

无效的方法

  • 所有的分割模型
  • 纯关键点生成
  • 更大的模型

代码发布

实验记录

我的流程相当复杂,验证这些方法花费了我大量的工程精力。这是过去三个月的所有实验记录:Google Sheet

如果您有任何问题,请在下方评论或使用 email & linkin 联系我!
欢迎您在您的博客上分享我的解决方案——这是我的荣幸!我希望其他人会觉得它有用,并在未来的比赛中参考它。

同比赛其他方案