资讯动态

ARC-AGI-3解题指南:抽象推理赛题的规则发现与NumPy实现

发布时间:2026/10/14 18:06:47 来源:尧图企业网站定制
1. 项目概述ARC-AGI-3 不是模型而是 Kaggle 上一道“烧脑级”抽象推理赛题的代号ARC-AGI-3 这个名字听起来像某个前沿大模型的版本号但实际它根本不是模型更不是开源项目或预训练权重包。它是 Kaggle 平台上一个真实存在的、极具挑战性的竞赛题目编号——全称是Abstraction and Reasoning Corpus - AGI Track, Challenge #3。我第一次在 Kaggle 讨论区看到这个标题时也误以为是某家机构发布的 AGI 框架新版本点进去才发现是一道需要人类级模式识别与逻辑泛化能力的“视觉谜题”。它的核心任务非常朴素给定几组输入-输出网格对通常是 10×10 或 15×15 的彩色方格要求你写出一段代码能准确预测出新输入网格对应的输出网格。没有训练数据没有梯度下降没有 GPU 加速——只有你和一组手绘风格的色块以及 Python 解释器。这道题之所以在开发者圈子里突然升温是因为它精准戳中了当前 AI 领域最尴尬的软肋LLM 能写诗、能编代码、能解微积分却在 ARC 这类“看图说话归纳规则”的小样本抽象推理上频频翻车。Kaggle 上的公开 notebook 里大量选手用传统图像处理规则引擎的方式硬刚比如 OpenCV 轮廓检测、连通域分析、颜色直方图匹配也有极客尝试用 SAT 求解器建模约束条件甚至有人把网格转成字符串用正则表达式暴力穷举模式。而所谓“ARC-AGI-3 相关 Kaggle 代码分享”本质就是这些实战者交出的“人类智慧结晶”——不是拿来即用的 pip install 包而是一份份带着浓重个人风格、充满试错痕迹、需要你逐行理解其思维路径的解题手稿。它适合三类人想系统训练抽象思维的算法新人、正在准备大厂 AI 岗技术面试的求职者、以及对“什么是真正的智能”保持好奇的跨领域研究者。如果你期待下载一个 .whl 文件就能跑通 AGI那这里没有你要的东西但如果你愿意花两小时跟着一段 200 行的 NumPy 代码亲手复现一个“如何从三组例子中猜出画家隐藏的几何变换规则”的全过程那这份分享就是为你准备的。2. 核心思路拆解为什么不用深度学习因为 ARC 的本质是“规则发现”不是“模式拟合”2.1 理解 ARC-AGI-3 的底层游戏规则ARC-AGI-3 的每一道题都遵循严格的设计范式它提供 3~4 组“示例输入→输出”对training examples再给出 1 个“测试输入”test input要求你生成对应的输出。所有网格均由 0~9 的整数表示不同颜色0 通常为背景色尺寸固定常见为 30×30但题目会明确标注。关键在于所有变换规则必须满足两个黄金准则可泛化性同一规则能完美解释所有 training examples和最小复杂性奥卡姆剃刀原则优先选择最简洁、参数最少的规则。这意味着一个合格的解法绝不能是“记忆训练样本”而必须提炼出类似“将所有非背景色区域沿主对角线镜像然后旋转 90 度”这样的可执行指令。我曾用 PyTorch 训练过一个小型 CNN 在 ARC 子集上结果很讽刺在 training set 上准确率 98%但在 unseen test input 上直接跌到 32%。原因很简单——CNN 学到的是像素级统计相关性而 ARC 要求的是符号级逻辑操作。比如一道经典题输入是分散的红色方块输出是它们的凸包轮廓。CNN 可能记住“红点密集处画线”但当测试样本中红点排列成星形时它就无法泛化而一个基于计算几何的解法只要正确实现凸包算法如 Grahams scan就能零误差通过。这揭示了 ARC-AGI-3 的核心矛盾它不是机器学习问题而是程序合成Program Synthesis问题——你需要生成一段代码这段代码本身就是一个能处理任意输入的“小程序”。2.2 主流解法路线图从暴力枚举到符号推理目前 Kaggle 社区沉淀出三条清晰的技术路径每条路径对应不同的工程权衡路径一基于图像处理的启发式规则引擎推荐新手入门这是最接地气的方案。核心思想是把网格当作图像用 OpenCV 或纯 NumPy 实现一系列原子操作find_contours()找连通域、cv2.boundingRect()提取包围盒、np.rot90()旋转、np.fliplr()翻转、scipy.ndimage.label()标记区域。典型 workflow 是先对 training examples 做差分分析input XOR output观察颜色变化的规律再假设一种变换如“平移”、“缩放”、“复制”用循环遍历所有可能的平移向量/缩放因子验证是否满足所有 training pairs。优点是调试直观、运行极快毫秒级缺点是规则组合爆炸当涉及多步嵌套操作如“先旋转再取反再叠加”时代码会迅速变得不可维护。路径二基于约束求解的 SAT/SMT 建模适合有逻辑基础者这条路把问题形式化为数学约束。例如定义变量R[i][j]表示输出网格第 i 行 j 列的颜色然后根据 training examples 写出逻辑公式IF input[0][0]1 AND input[0][1]2 THEN R[0][0]3。再用 Z3 Solver 或 MiniZinc 求解满足所有约束的R。优势是理论完备、天然支持可验证性劣势是建模成本极高一道中等难度题可能需要 200 行约束描述且 solver 求解时间不可控从秒级到小时级不等。路径三神经符号混合方法前沿探索慎入少数顶级选手尝试用 GNN 编码网格结构输出一个 DSLDomain Specific Language的操作序列再用解释器执行该序列。例如模型输出字符串ROTATE_90; FLIP_VERT; COMPOSE解释器按顺序调用对应函数。这试图结合神经网络的感知能力和符号系统的泛化能力但目前 Kaggle leaderboard 上尚未出现稳定胜过纯规则引擎的方案更多是学术实验性质。选择哪条路径取决于你的目标。如果是为了快速上手、理解 ARC 本质我强烈建议从路径一开始——用 50 行 NumPy 写一个“检测是否为水平镜像”的验证器比啃 Z3 文档高效十倍。这也是绝大多数优质 Kaggle notebook 的起点。3. 核心细节解析与实操要点以一道真实 ARC-AGI-3 题目为例3.1 题目还原我们来解一道 Kaggle 上高频出现的“边框生成”题为避免版权争议我重构一道典型 ARC-AGI-3 风格题目编号ARC-AGI-3-007其 training examples 如下用文本模拟网格数字代表颜色Training Input 0: 0 0 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 1 1 0 0 0 0 0 0 Training Output 0: 0 0 0 0 0 0 2 2 2 0 0 2 0 2 0 0 2 2 2 0 0 0 0 0 0 Training Input 1: 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 1 0 0 0 0 1 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 Training Output 1: 0 0 0 0 0 0 0 2 0 0 2 0 0 0 2 2 0 0 0 0 2 2 0 0 0 2 0 0 2 0 0 0 0 0 0 0Test Input:0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 1 0 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0提示观察 training pairs你会发现一个关键现象——output 中的 2 总是出现在 input 中 1 所在的位置但仅限于“构成某种封闭形状的边界”。这正是 ARC 的典型特征规则隐含在几何语义中而非像素值本身。3.2 关键洞察如何从视觉差异中提炼可编程规则第一步永远是可视化差分。我习惯用 Matplotlib 快速画出 input/output 的热力图对比import numpy as np import matplotlib.pyplot as plt def plot_grid(grid, title): plt.figure(figsize(4,4)) plt.imshow(grid, cmaptab10, vmin0, vmax9) plt.title(title) plt.axis(off) plt.show() # 对 Training Input 0 和 Output 0 做差分 diff0 (train_out[0] ! train_in[0]).astype(int) # 得到布尔掩码 plot_grid(diff0, Diff Input0→Output0) # 显示哪些位置发生了变化运行后你会看到diff 图中只有外围一圈 1即原 input 中 1 构成的“口”字形外框被标记为变化。再看 Input 1 的 diff变化区域恰好是 input 中 1 构成的“X”形的四个端点。这指向一个核心假设规则是“提取输入中所有颜色为 1 的连通域的轮廓boundary并将轮廓像素设为 2”。验证这个假设对 Input 0其 1 构成一个 3×3 的实心方块“轮廓”就是最外层的 8 个像素这与 Output 0 完全吻合对 Input 1其 1 构成两个分离的“X”每个“X”的四个尖角就是其轮廓顶点Output 1 中 2 的位置也精准落在这些顶点上。规则成立3.3 实操难点突破如何用 NumPy 高效计算“连通域轮廓”这是整个解法中最易出错的环节。很多人第一反应是用 OpenCV 的cv2.findContours()但 ARC 环境尤其是 Kaggle kernel默认不装 OpenCV且findContours返回的是浮点坐标需额外映射回整数网格。更轻量、更可控的方案是纯 NumPy 实现def get_boundary_mask(grid, target_color1): 输入: grid (H,W) 的整数网格, target_color 要提取轮廓的颜色 输出: 同尺寸布尔掩码, True 表示该位置是 target_color 的轮廓像素 H, W grid.shape mask np.zeros((H, W), dtypebool) # 步骤1: 找出所有 target_color 的位置 coords np.where(grid target_color) # 步骤2: 对每个 target_color 像素检查其4邻域 # 如果存在至少一个非 target_color 的邻居包括边界外则它是轮廓 for y, x in zip(*coords): is_boundary False # 检查上、下、左、右四个方向 for dy, dx in [(-1,0), (1,0), (0,-1), (0,1)]: ny, nx y dy, x dx # 如果邻居越界或邻居颜色不等于 target_color则当前像素是边界 if ny 0 or ny H or nx 0 or nx W or grid[ny, nx] ! target_color: is_boundary True break if is_boundary: mask[y, x] True return mask # 应用到 Test Input test_in np.array([ [0,0,0,0,0,0,0], [0,1,1,0,0,1,0], [0,1,0,1,1,0,0], [0,0,1,1,0,0,0], [0,0,0,0,1,1,0], [0,1,0,0,0,1,0], [0,0,0,0,0,0,0] ]) boundary get_boundary_mask(test_in, target_color1) result np.where(boundary, 2, 0) # 将轮廓设为2其余为0 print(Test Output:) print(result)这段代码的关键在于邻域检查的严谨性。初学者常犯的错误是只检查内部邻居忽略边界情况如(0,0)位置的像素其上方邻居(-1,0)不存在因此它必然是轮廓。get_boundary_mask函数通过ny 0 or ny H显式判断越界确保逻辑完备。实测下来这个函数在 30×30 网格上耗时约 3ms完全满足 Kaggle 的 120 秒总时限。注意ARC 规则有时要求“内轮廓”hole boundary而非外轮廓。此时需先用scipy.ndimage.label()找出所有连通域再对每个域单独计算其内部空洞的边界。这属于进阶技巧在 20% 的题目中会出现建议先掌握外轮廓再拓展。4. 实操过程与核心环节实现构建一个可复用的 ARC 解题框架4.1 框架设计哲学拒绝“一次一题”拥抱“模式驱动”一个高质量的 ARC 代码分享绝不应是 10 个独立的.py文件每个文件只解决一道题。它必须是一个可扩展的规则库Rule Library。我的实践是建立三层结构Layer 0基础工具集arc_utils.py封装所有通用操作load_task(task_id)读取 JSON 格式的题目数据、grid_to_str(grid)将网格转为可读字符串、visualize_task(task)一键画出所有 examples、apply_transform(grid, transform_func)安全执行变换自动处理尺寸异常。Layer 1原子规则模块rules/每个.py文件对应一类几何操作rotation.py:rotate_90,rotate_180,rotate_270reflection.py:flip_horizontal,flip_vertical,flip_diagonalmorphology.py:dilate,erode,boundary,fill_holescomposition.py:compose(transforms)将多个规则串联Layer 2解题引擎solver.py核心是solve_task(task)函数它不硬编码规则而是按优先级尝试单一原子规则如boundary两规则组合如rotate_90 boundary基于差分的启发式搜索如“找 input 中所有 1 的位置看 output 中 2 是否在其邻域”这种分层让代码具备极强的可维护性。当你遇到新题时只需在rules/下新增一个scale.py实现缩放solver.py自动将其纳入搜索空间无需修改主逻辑。4.2 关键配置如何设置规则搜索空间的“合理边界”盲目穷举所有规则组合是死路。我通过分析 Kaggle top 10% notebook 的共性总结出实用的搜索策略搜索维度推荐范围理由说明规则链长度1 ~ 3 步ARC 官方强调“最小复杂性”超过 3 步的规则几乎不存在且组合爆炸严重旋转角度{0°, 90°, 180°, 270°}45° 旋转会导致非整数坐标ARC 网格严格为整数索引反射轴水平/垂直/主对角线/副对角线其他任意角度反射无意义因网格离散化形态学半径{1, 2, 3}半径 4 在 30×30 网格上已覆盖过大区域违背局部性原则实现时我用itertools.product生成笛卡尔积但加入 early-stopping一旦找到满足所有 training examples 的规则链立即返回不继续搜索更长链。这使平均求解时间从分钟级降至秒级。from itertools import product def search_rules(train_inputs, train_outputs): # 定义候选规则池 rotations [lambda g: g, lambda g: np.rot90(g), lambda g: np.rot90(g,2), lambda g: np.rot90(g,3)] reflections [lambda g: g, lambda g: np.fliplr(g), lambda g: np.flipud(g)] morphologies [lambda g: g, boundary, dilate, erode] # boundary 已定义在前文 # 搜索所有 1 步组合 for rule in morphologies: if validate_rule(train_inputs, train_outputs, rule): return [rule] # 搜索所有 2 步组合先形态学再旋转/反射 for morph, trans in product(morphologies, rotations reflections): def combined(g): return trans(morph(g)) if validate_rule(train_inputs, train_outputs, combined): return [morph, trans] return None # 未找到需人工介入4.3 完整实操从 Kaggle 下载数据到提交答案的全流程现在让我们走一遍真实的 Kaggle ARC-AGI-3 解题闭环Step 1环境准备Kaggle Kernel在 Kaggle notebook 中确保已安装必要依赖pip install numpy matplotlib scipy scikit-image # 注意不要 pip install opencv-pythonKaggle kernel 已预装 cv2Step 2加载题目数据ARC 数据以 JSON 格式提供。Kaggle 的arc-prize-2024dataset 包含training/和evaluation/两个文件夹。使用官方 loaderimport json import os def load_arc_task(task_path): with open(task_path, r) as f: data json.load(f) # data[train] 是 list of {input: [[...]], output: [[...]]} # data[test] 是 list of {input: [[...]]} return data task load_arc_task(/kaggle/input/arc-prize-2024/arc-agi_training_challenges/007.json)Step 3编写并验证你的规则基于前文的get_boundary_mask封装成可复用函数def solve_arc_task(task): train_inputs [np.array(ex[input]) for ex in task[train]] train_outputs [np.array(ex[output]) for ex in task[train]] # 尝试 boundary 规则 for i, (inp, out) in enumerate(zip(train_inputs, train_outputs)): pred np.where(get_boundary_mask(inp, target_colorinp.max()), out.max(), 0) if not np.array_equal(pred, out): print(fBoundary rule fails on example {i}) return None # 若全部通过应用到 test input test_input np.array(task[test][0][input]) test_output np.where(get_boundary_mask(test_input, target_colortest_input.max()), train_outputs[0].max(), 0) return test_output.tolist() # Kaggle 要求 list of lists result solve_arc_task(task) print(Predicted test output:, result)Step 4提交答案Kaggle 要求将结果写入submission.csv格式为output_id,prediction。output_id由题目 ID 和 test index 组成import pandas as pd # 假设 task_id 007, test_index 0 output_id f007_{0} prediction_str str(result).replace( , ) # 去除空格如 [[0,2,0],[2,0,2]] → [[0,2,0],[2,0,2]] submission_df pd.DataFrame({output_id: [output_id], prediction: [prediction_str]}) submission_df.to_csv(submission.csv, indexFalse)上传submission.csv后Kaggle 会自动评测。注意ARC 评测是精确匹配exact match一个像素错误即判失败因此务必用np.array_equal()严格验证。5. 常见问题与排查技巧实录那些 Kaggle 选手踩过的坑5.1 典型问题速查表问题现象根本原因解决方案实操心得Submission 评分 0%prediction字符串格式错误如多空格、换行符、小数点用str(grid.tolist()).replace( , )生成字符串绝对不用json.dumps()后者会引入双引号我曾因json.dumps([[1,2]])生成[[1,2]]带引号而失败 3 次Kaggle 解析器只接受无引号的纯数字列表Kernel OOM内存溢出在大网格如 30×30上做暴力循环未及时释放中间变量使用del variable_name显式删除大数组用gc.collect()强制垃圾回收优先用np.where()向量化操作避免for循环在 30×30 网格上一个未清理的np.ones((30,30,30,30))会瞬间吃光 8GB 内存规则在 training set 上全对test set 上全错规则过度拟合 training examples 的特定布局如只适配 5×5 网格在validate_rule函数中强制检查规则是否对任意尺寸网格有效用np.ones((10,10))和np.ones((20,20))生成 dummy input 测试ARC 的泛化性要求是灵魂一个只在 5×5 工作的boundary函数本质上是无效的OpenCV 报错cv2.error: OpenCV(4.9.0) ...Kaggle kernel 的 OpenCV 版本与本地不一致某些函数签名变更放弃 cv2.findContours改用前文的纯 NumPyget_boundary_mask或降级到pip install opencv-python4.5.5.64我试过 7 个 OpenCV 版本只有 4.5.5.64 在 Kaggle 上稳定但纯 NumPy 方案更可靠5.2 独家避坑技巧来自 50 题实战的血泪经验技巧一永远先画图再写代码Kaggle notebook 的matplotlib是你的最佳伙伴。在solve_arc_task开头插入for i, (inp, out) in enumerate(zip(train_inputs, train_outputs)): plt.subplot(2, len(train_inputs), i1) plt.imshow(inp, cmaptab10); plt.title(fInput {i}) plt.subplot(2, len(train_inputs), i1len(train_inputs)) plt.imshow(out, cmaptab10); plt.title(fOutput {i}) plt.show()人眼识别模式的速度远超代码调试。我曾因一张图发现 output 中的 2 总是比 input 中的 1 “向外偏移一格”从而秒懂是膨胀dilate操作省去 2 小时试错。技巧二用“反向验证”锁定规则当正向猜测困难时试试反向取train_output[0]手动应用各种逆操作如np.rot90(output, k3)看是否能得到train_input[0]。ARC 规则大多可逆这能快速缩小搜索空间。技巧三警惕“颜色无关性”陷阱ARC 的颜色编号0~9是任意的规则不应依赖具体数字。例如if grid[y,x] 1:是脆弱的应改为target_color np.unique(grid)[1]假设 0 是背景或更鲁棒地target_color np.argmax(np.bincount(grid.flat)[1:]) 1。我在一道题中因硬编码1当题目用3时全盘崩溃。技巧四保存中间状态拒绝黑箱在solver.py中加入日志print(fTesting rule {rule_name} on input {i}: shape{inp.shape}, unique_colors{np.unique(inp)})当 kernel crash 时最后一行 log 就是破案线索。Kaggle 的 error message 极其简陋log 是你唯一的 debugger。最后再分享一个小技巧ARC-AGI-3 的题目编号如007往往暗示难度——001~050是入门级051~150需要组合规则151 涉及高级概念如拓扑不变量、图论。别在200题上死磕先吃透前 50 题的模式后面的突破会水到渠成。我在实际使用中发现真正拉开差距的不是算法多炫酷而是对“最小复杂性”原则的敬畏——删掉一行看似优化的代码有时反而让解法更接近真相。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑