拓冰建站拓冰建站
首页 / 资讯中心 / 正文

SELF-MM 复现遇到 CUDA 报错?让 Codex 走 TaoToken 对着这几个补丁查

1. 复现现场run.py 55 行和 self-mm.py 132 行卡住了SELF-MM 复现时最耗耐心的环节常常不是模型训练本身而是run.py第 55 行的 CUDA 报错。那句torch.device(cuda:%d % int(args.gpu_ids[0]))换台机器就踩空还没等处理完self-mm.py第 132 行又提示 lengths 张量不在 CPU 上。遇到这种连锁问题我一般直接打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 拿一把 API Key把 Codex 的 Base URL 填成 https://taotoken.net/api然后让 Codex 按原文的四步补丁逐条核对。下面把整个排障过程拆开写省得你一边翻博客一边对照着改。1.1 这两个报错为什么每次环境一变就复现原仓库run.py第 55 行默认读者机器上插了显卡而且args.gpu_ids非空。当你在新的服务器、新的容器或者没有独立显卡的环境复现时args.gpu_ids[0]的取值会踩空。这不是 SELF-MM 特有的问题而是很多论文仓库共用的torch.device写法不健壮。原文给的改法很直接核心是把「从参数列表里拿第一个 GPU 编号」换成「先看机器上有几张卡再说」# device torch.device(cuda:%d % int(args.gpu_ids[0]) if using_cuda else cpu) device torch.device(cuda:0 if torch.cuda.device_count() 0 else cpu)这里有一个容易忽略的细节torch.cuda.device_count() 0判断的是 PyTorch 当前能看到的 GPU 数量。如果你的服务器本身有显卡但 PyTorch 编译的是 CPU 版本torch.cuda.device_count()依然返回 0此时会静默落到 CPU 上。SELF-MM 的 batch size 和序列长度都不算小CPU 上跑会慢很多但不至于报错。至少训练脚本能正常启动比卡在前面强。1.2 self-mm.py 132 行为什么需要 lengths.cpu()self-mm.py第 132 行的报错常见形式是RuntimeError: lengths argument should be a 1D CPU tensor或者AssertionError。原因是lengths这个张量在 CUDA 设备上而后面调用的 RNN 工具函数只接受 CPU 张量。原文补丁就一行lengths lengths.cpu()注意这行代码放在哪个位置很关键。如果lengths是在循环里反复使用的你需要在每次调用工具函数之前执行如果只执行一次放在 132 行原位置即可。更稳妥的做法是让 Codex 看一下 132 行前后 10 行的代码确认后面有没有把lengths重新.to(device)的操作。如果有顺序就变成lengths转 CPU → 传给工具函数 → 用完后再转回 CUDA不能只补一行就以为万事大吉。1.3 复现前先建好 logs 目录原文专门提了「根目录新建一个 logs 文件」很多人第一次复现时会跳过。训练脚本里通常有os.makedirs(logs, exist_okTrue)但也有仓库直接写open(logs/train.log, w)目录不存在时会在更早的位置报FileNotFoundError。这个错和 CUDA 报错混在一起时很容易被误判成环境问题。所以动手改代码前先在 SELF-MM 项目根目录执行mkdir -p logs如果你的运行命令里指定了别的输出目录比如--output_dir ./output也要一并建好。目录这类问题Codex 是看不出来的因为它只能读到贴过去的代码片段读不到你磁盘上的真实目录结构。你需要自己在本地建好再把目录树贴回给 Codex 核对。2. 按原仓库格式放好预训练 bert 和数据集SELF-MM 的数据加载逻辑比较死板它不认你自定义的散装目录只认固定层级。原文说的「按照默认格式 MOSI/Processed/unaligned_50.pkl 新建文件夹」意思是在数据根目录下建数据集名/Processed/unaligned_50.pkl的三层结构。SIMS 和 MOSEI 同理。这一步做不对后面改再多的 CUDA 代码也白搭。2.1 预训练 bert 文件替换的是文件不是整个目录原文强调「区别在于多了一个 model 文件」。不同渠道下载的预训练 bert 打包格式不一样有的是pytorch_model.bin直接放在根目录有的是把config.json、vocab.txt、pytorch_model.bin放在Model子目录里。SELF-MM 代码用AutoModel.from_pretrained去加载它按目录找pytorch_model.bin、config.json和vocab.txt只要这三个文件在同一个目录下就能识别。所以替换时不要整个文件夹扔进去要看原仓库的 bert 目录下预期的是哪几个文件。如果原仓库已经有旧的pytorch_model.bin直接用下载的新文件覆盖同名文件如果下载包多了一个model目录就把里面的pytorch_model.bin拿出来别把多出来的目录层级原样塞进去。这个操作描述起来很啰嗦但让 Codex 处理时你可以直接给它两边的文件列表原仓库 bert 目录 config.json vocab.txt pytorch_model.bin 我下载的文件 Model/config.json Model/vocab.txt Model/pytorch_model.binCodex 会告诉你把Model目录里的三个文件移动到原仓库 bert 目录覆盖同名文件即可。它不会替你执行移动因为它的工作范围限制在对话里但它能帮你把命令写出来。2.2 数据集目录的层级不能省数据集的坑比 bert 文件更隐蔽。很多人下载好unaligned_50.pkl后直接平铺在数据根目录然后 config 里的 path 改来改去都找不到文件。SELF-MM 的dataloader会拼出MOSI/Processed/unaligned_50.pkl这样的相对路径你必须在数据根目录下建MOSI/Processed/两级目录把 pkl 文件放进去。MOSEI 和 SIMS 同理。这里有一个来自实操的细节如果 pkl 文件是你从别处找的旧副本特征维度可能对不上 SELF-MM 要求的输入形状。改好目录结构后第一次加载如果报IndexError或size mismatch优先怀疑 pkl 文件版本而不是数据集路径。这类维度断言错误Codex 可以通过报错信息里的 tensor shape 帮你推算是哪一层输入对不上但前提是你要把完整 traceback 贴给它。2.3 config 里的 path 不要只改一个原文说「下载好之后在 config 文件里修改对应的 path 路径为你自己电脑的路径」。很多复现笔记只会提一句「改 path」但 SELF-MM 的 config 里通常有data_path、bert_path、output_path三个字段而且 MOSI、MOSEI、SIMS 各有一组配置块。你至少要把当前要跑的模态对应的data_path和bert_path都改掉否则训练循环可能读到一半就找不到文件。改完 path 后建议先单独跑一次数据加载脚本确认三个数据集都能正常读出 pkl再进入训练阶段。这一步可以用 Codex 生成一段小脚本读一个样本看看字段是否完整import pickle from pathlib import Path path Path(data/MOSI/Processed/unaligned_50.pkl) with open(path, rb) as f: data pickle.load(f) print(type(data)) if isinstance(data, dict): for k in list(data)[:3]: print(k, type(data[k]))这段脚本在本地执行输出贴回对话Codex 就能根据字段名判断数据格式是否符合 SELF-MM 的预期。不要指望 Codex 直接读你磁盘上的 pkl 文件它只能读到你的输出文本。3. 给 Codex 接上 TaoToken 的 API 通道前面这些准备工作看起来和 API 通道没什么关系但它们是复现 SELF-MM 的底座。底座稳了接下来要让 Codex 能真正跑起来帮你核对补丁。这里的核心配置就两样东西一把 API Key一个 Base URL。Key 从官网控制台创建Base URL 填 https://taotoken.net/api。3.1 拿 Key官网注册后进控制台打开 TaoToken 注册账号进入控制台后找到 API Keys 页面创建一个 Key。生成的 Key 长这样YOUR_API_KEY创建后先复制到本地临时文件里因为有些控制台只显示一次。Codex 配置时会用到这个 Key建议直接设置成环境变量不要写死在代码里。如果你和同事共用一台开发机环境变量方式也能避免 Key 被随意拷贝。3.2 在 ~/.codex/config.toml 里配置 Base URLCodex 的模型通道配置在~/.codex/config.toml。编辑这个文件加一个 model_provider 指向 TaoToken# 模型 ID 以 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 模型广场当时列表为准 model 你的模型ID model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY然后在 shell 里设置环境变量export TAOTOKEN_API_KEYYOUR_API_KEY注意 Base URL 是https://taotoken.net/api末尾不要加/v1也不要给接口地址拼任何 UTM 参数。官网链接是给人点击访问用的接口地址是填进工具用的两者混用时最容易把?utm_source...一长串误粘到配置里导致 Codex 解析失败。模型 ID 不要凭记忆填去 TaoToken 模型广场看当前可用的模型列表再回来填。不同时期的模型上架情况会变写死一个过期 ID 会在后续对话里反复收到 404。3.3 验证 Codex 能正常对话再进入正题配置保存后先别急着处理 SELF-MM跑一条最简单的消息验证通道codex 你好只回复四个字连接正常如果返回正常说明 Key、base_url、model_provider 三个字段都对齐了。这一步出现 401多半是 Key 复制漏了字符或带了空格出现 404先查模型 ID 是否在模型广场列表中出现 405 或 400检查 base_url 是不是多了/v1。验证通过后再把项目代码片段贴给 Codex它的上下文窗口也可以完整留给排障不用浪费在反复试错上。4. 让 Codex 对着原文四步补丁逐条核对你的修改通道通了接下来就是正文战场。SELF-MM 的排障不是让 Codex 凭空生成代码而是把原文的补丁作为已知信息让 Codex 对照你的实际代码逐条检查。这样可以避免照抄补丁时出现的偏移和遗漏。4.1 把 run.py 55 行的原注释和报错一起贴进去原文给的补丁是注释掉torch.device(cuda:%d % int(args.gpu_ids[0]))换成torch.device(cuda:0 if torch.cuda.device_count() 0 else cpu)。但你的仓库版本可能和原文不完全一致直接替换可能丢掉了using_cuda这个变量的控制逻辑。更好的方式是带着上下文问 Codex我在复现 SELF-MMrun.py 第 55 行报 IndexError: list index out of range。 当前代码 device torch.device(cuda:%d % int(args.gpu_ids[0]) if using_cuda else cpu) 已知补丁是改成 device torch.device(cuda:0 if torch.cuda.device_count() 0 else cpu)。 请结合我的报错和我当前代码确认这个补丁是否完整是否有副作用。Codex 会指出torch.cuda.device_count() 0这种写法会把设备固定为 0 号卡如果你的训练命令里用了CUDA_VISIBLE_DEVICES2PyTorch 看到的 0 号卡其实是物理上的 2 号卡语义上没问题但如果你依赖args.gpu_ids指定多卡这个补丁会丢掉多卡逻辑。正确的补丁应该是if using_cuda and len(args.gpu_ids) 0: device torch.device(cuda:%d % int(args.gpu_ids[0])) elif using_cuda and torch.cuda.device_count() 0: device torch.device(cuda:0) else: device torch.device(cpu)让 Codex 做的不只是「替换」而是告诉你为什么替换以及替换后哪些能力丢失了。这是把对话式 AI 工具用出效果的关键。4.2 让 Codex 解释 self-mm.py 132 行为的报错self-mm.py第 132 行的补丁是lengths lengths.cpu()。但你直接把这一行贴进文件可能不知道它为什么能解决报错。更有效的操作是把 132 行前后各 10 行代码贴给 Codexself-mm.py 第 132 行附近代码是 ... 贴你的代码 ... 报错是 RuntimeError: lengths argument should be a 1D CPU tensor。 匹配的补丁是 lengths lengths.cpu()。 请确认我的代码里 lengths 在当前作用域是否可写是否需要在调用前先 copies 一份。如果你在 132 行后面还有.to(device)的操作Codex 会提醒你注意张量设备的流转而不是无脑补一行。某些版本的 PyTorch 对pack_padded_sequence的lengths参数要求必须是 CPU 张量但pack_padded_sequence的输入序列本身可以在 CUDA 上这两个张量的设备不一致就要求你先.cpu()再传参。Codex 能根据报错信息反推调用链把整段因果讲清楚。4.3 让 Codex 核对数据集路径和 bert 文件清单数据集和 bert 文件的问题不会像 CUDA 报错那样亮红色的 traceback更多是训练到一半精度异常或者第一个 epoch 就崩。原文说要在 config 里改 path但改完对不对可以让 Codex 生成一段检查脚本find . -maxdepth 4 -name *.pkl -o -name pytorch_model.bin | sort在项目根目录执行后把输出贴给 Codex。Codex 能对照 SELF-MM 的目录要求直接指出哪个数据集放的层级不对哪个 bert 文件缺失。这个过程比人肉对着 find 结果逐一核验快很多尤其是你还没弄清楚原仓库到底要哪几个文件时。Codex 不会自己去读你的磁盘它只是根据你贴的目录树和已知仓库结构做推断最终改文件名的操作还是你来执行。5. 跑通之后验证、排障、给下一次复现留好配置改完补丁、重跑训练脚本后不急着庆祝。先确认 Codex 走的 TaoToken 通道确实记到了用量里然后把这次排障留下的配置整理好。后面再复现其他论文仓库时同一套 Codex 配置可以直接复用只要改模型 ID 和 Key 即可。5.1 去控制台对一下刚才这次调用登录 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 在用量或日志页面能看到刚才 Codex 对话产生的记录。如果能看到一条对应时间的调用说明 Key、Base URL、模型 ID 这条链路完全打通。看不到记录说明 Codex 实际走的还是默认的 OpenAI 通道你的 config.toml 没生效需要检查model_provider字段是否拼写正确。验证这一步不要省。很多时候对话能正常返回是因为 Codex 自动选择了环境里已有的默认配置你的model_provider根本没被加载。控制台的用量记录是最直接的证据。5.2 如果 CUDA 报错还没消失按这个顺序查补丁改完仍然报 CUDA 相关错误时对照下面几个方向排查run.py55 行改完没有如果args.gpu_ids本身是Noneint(args.gpu_ids[0])会先抛TypeError不是IndexError。这时要检查参数解析逻辑确认gpu_ids的默认值。self-mm.py132 行补进去后后面别的代码又把lengths移回 CUDA 了吗如果loss_fn内部重新.cuda()你的.cpu()补丁就白补了。数据集没加载出来FileNotFoundError经常被误报成 CUDA 错误因为训练脚本在 GPU 初始化之后才加载数据一旦数据路径不对报错位置会出现在设备有关的代码之后。logs 目录存在吗logs忘建时会报FileNotFoundError这个错出现的时机时早时晚容易被漏掉。Codex 在这个阶段的作用是把这些检查点串成一条 checklist你每完成一项就把新的 traceback 贴回去它会根据新信息缩小范围。不要一下贴一堆无关代码Codex 的上下文有限报错信息越完整越好。5.3 剩下的长尾报错怎么继续查原文最后一句是「其他问题请提问」。放到当下提问的对象可以是已经配好的 Codex。跑完 SELF-MM 复现后如果还有别的报错把完整 traceback 贴回对话让 Codex 沿着同一套逻辑继续排查。TaoToken 的模型通道除了给 Codex 用也可以在浏览器里直接对话先验证模型选型是否合适再回到 Codex 处理长尾问题。顺手把这次复现用到的配置记下来后续换机器时按同样方式填 Key 和 Base URL训练脚本相关的问题就能少走几轮弯路。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门