Skip to content

第八章:科研工作流


万事俱备

你已经可以从任何地方 SSH 连接服务器(第二章)。你有 tmux 让进程在断开连接后依然存活(第三章)。你有代理隧道让服务器能访问外网(第四章)。你有 Claude Code 在持久会话中运行(第五章)。你已经教会了它你的服务器、GPU、conda 环境和各种惯例(第六章)。你已经设置好了 hook、watchdog 监控和定时健康检查,让它能自主行动(第七章)。

七章的基础设施。每个工具单独拿出来都有用,但到目前为止它们是各自独立介绍的。SSH config 只是个便利。tmux 只是个会话管理器。Watchdog 只是个监控脚本。你可以只用其中任何一个,不用其他的。

但这套系统的力量不在于单个组件——而在于它们之间的连接方式。SSH config 让 Claude Code 一条命令就能连上服务器。tmux 让训练在断连后继续存活。代理让服务器能下载模型和上报 WandB。Watchdog 让 Claude Code 能检测到崩溃。CronCreate 让 Claude Code 无需你过问就能定时查看 watchdog。每一层赋能下一层。

这一章是地图。它展示所有组件如何拼合成一条完整的流水线——从你脑中的研究想法到服务器上的训练结果——全程由 Claude Code 协调。下一章是实战:你将真正走完这条流水线,跑一个真实实验。


流水线

每个研究实验,无论多复杂,都遵循相同的五阶段模式:

┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
│ 1. 想法   │───▶│ 2. 代码  │───▶│ 3. 同步  │───▶│ 4. 训练  │───▶│ 5. 结果  │
│   & 计划  │    │          │    │  到服务器 │    │          │    │          │
└──────────┘    └──────────┘    └──────────┘    └──────────┘    └──────────┘
    本地            本地           rsync           服务器          本地

第 1、2、5 阶段在本地机器上完成。第 3 阶段是桥梁。第 4 阶段在 GPU 服务器上进行。这种分离是刻意的——本地机器负责智能(规划、编码、分析),服务器负责计算(训练)。它们通过 SSH 和 rsync 通信,Claude Code 坐镇本地,协调整个流程。

让我们逐一详解每个阶段。


阶段 1:想法与规划(本地机器)

科研从这里开始。你有一个问题、一个假设、或者一篇想要复现的论文。你坐在 Claude Code 面前——或者更常见的场景是,你窝在沙发上,通过 Termius 用手机和 Claude Code 对话。

读论文。 你可以把一篇 PDF 交给 Claude Code,让它总结核心贡献、提取训练配置、或找出用了哪些数据集。它读完论文,给你一份结构化摘要。你不需要翻遍 12 页密密麻麻的公式才发现他们用的是 3e-4 的学习率配 cosine annealing —— Claude Code 直接帮你提取出来。它还能对比多篇论文,指出各自方法和实验配置的差异。

搜文献。 Claude Code 可以调用 arXiv 搜索、HuggingFace 论文搜索和网页搜索等工具。你说一句"找最近关于 domain generalization 的 test-time training 论文",它就返回一份相关工作列表,每篇附一行摘要。这不是替代深度阅读——而是分诊工具。它帮你从某个话题下 50 篇论文中快速识别哪些值得精读、哪些是真正的 baseline、哪些可以跳过。

头脑风暴。 向 Claude Code 描述一个问题,它给你提方案。"我想提升 CLIP 零样本分类在 corrupted images 上的鲁棒性——有哪些可行的方法?"它会列出 prompt 策略、微调方法、test-time adaptation 技术等等。你来选方向,Claude Code 填充细节。它也会戳你想法里的漏洞——"这个方法假设训练时能接触到目标域数据,但你的设置是零样本的"——这比无脑附和有用得多。

规划实验。 确定方向后,Claude Code 帮你把计划写下来。假设是什么?Baseline 是什么?用哪些数据集?看哪些指标?成功的标准是什么?超参数怎么设?这份计划会被写入项目级 CLAUDE.md,作为实验配置的参考——Claude Code 在后续每个阶段都会查阅它。它也是你意图的记录:三周后分析结果时,你清楚地知道当初到底在测什么。

阶段 1 的关键点:你的 GPU 服务器完全没有参与。没在烧算力,没在占用实验室同学需要的硬件。你在思考、阅读、规划——这是科研中杠杆率最高的活动。GPU 后面才上场,而因为你先做了规划,它们的使用效率会高得多。


阶段 2:代码实现(本地机器)

有了计划,Claude Code 开始写代码。

项目结构。 Claude Code 创建目录布局:训练脚本、评估脚本、配置文件、requirements.txtenvironment.yml。它遵循你在 CLAUDE.md 中定义的惯例——也许你总是把配置放在 configs/ 目录,也许你用特定的参数解析器,也许你有一套标准的 WandB 日志模板。Claude Code 知道你的偏好,因为你在第六章教过它。

训练脚本。 Claude Code 写实际的训练循环,或者基于现有代码库进行适配。它处理数据加载、模型构建、优化器配置、学习率调度、checkpoint 保存和 WandB 日志记录。如果你在 HuggingFace Transformers 或 PyTorch Lightning 等框架上开发,它修改正确的文件而不破坏其他部分。如果从头写,它遵循标准模式,便于调试。

版本控制。 一切都纳入 git。每个逻辑改动单独一个 commit——不是一个巨大的"初始提交"包含 50 个文件,而是一系列小的、可审查的 commit:"add data loading pipeline"、"add model architecture"、"add training loop with WandB logging"、"add evaluation script"。这不只是好习惯——是安全网。后面出了问题可以 bisect。需要回滚评估代码的改动但保留训练代码?可以。Git 纪律零成本,却能救命。

项目级 CLAUDE.md。 这是把实现和基础设施连接起来的关键。Claude Code 在项目根目录写一份 CLAUDE.md,记录 AI 需要知道的关于这个项目的一切:用哪台服务器、激活哪个 conda 环境、训练命令长什么样、预期的 baseline 指标是多少、数据集在服务器的哪个路径。下周 Claude Code 再打开这个项目——或者在 context compact 之后,或者在一个全新的会话中——它读这个文件就立刻了解全貌。没有热身时间,没有"等等,我们做到哪了?"

阶段 2 仍然完全在本地。不涉及服务器,不依赖网络(除了 Claude Code 自身的 API)。在飞机上也能干。代码存在你的本地机器上,有版本控制,需要的话可以用小数据做快速验证,随时可以部署。


阶段 3:同步到服务器(本地 → 服务器)

这是本地开发环境和远程算力之间的桥梁。代码准备好了,现在需要到 GPU 所在的地方。

一条命令:

bash
rsync -avz --delete \
  --filter=':- .gitignore' \
  --exclude='.git/' --exclude='wandb/' --exclude='outputs/' \
  --exclude='*.pyc' --exclude='__pycache__/' \
  ~/projects/your-project/ your-server:/work/your-project/

把代码推送到服务器。来看几个关键决策:

只同步代码。 注意排除了什么:.git/(服务器上不需要 git 历史——版本控制在本地做)、wandb/(WandB 日志上传到云端,不在机器间同步)、outputs/(结果留在服务器上,等你显式拉回来)。你同步的是源代码、配置文件和小型工具脚本。仅此而已。

--delete 让远程和本地保持一致。 你在本地删了一个文件,--delete 也会在服务器上删掉它。这防止了遗留文件导致的诡异 bug——比如一个旧配置文件覆盖了新配置,或者一个已删除的模块因为 .py 文件还在而被误导入。但 --delete 有个严重的警告:如果训练正在服务器上运行并往项目目录写输出文件,--delete 会把那些文件删掉。同步前务必确认没有正在运行的训练。

--filter=':- .gitignore' 复用你的 .gitignore 规则来做 rsync 排除。只维护一套忽略规则,不需要两套。

模型和数据集不同步。 这是新手常犯的错误。训练数据可能有 100GB,模型权重可能有 10GB,你绝对不要通过家庭网络从笔记本 rsync 过去。它们就待在服务器上——要么在实验室维护的共享数据目录里,要么用 huggingface-cli download 直接在服务器上下载。还记得第四章吗?你配了代理隧道让服务器能上网。这就是主要原因之一:让服务器以数据中心级的速度自行下载权重和数据。

首次同步需要建目录。 第一次往新项目 rsync 之前,先建远程目录:

bash
ssh your-server "mkdir -p /work/your-project"

后续同步是增量的——只传输变化的文件。纯代码同步通常只需 2-5 秒,快到足以支持快速迭代。

记住这条规则:代码去服务器。数据和权重留在服务器。结果回本地。 这种单向流动让一切保持清晰和高效。


阶段 4:训练(服务器)

现在我们在 GPU 服务器上了。代码到位,数据到位,conda 环境就绪。开始训练。

模式:先前台,再后台

这个模式不可跳过。不要省前台那一步。

第一步:前台冒烟测试。 Claude Code SSH 到服务器,直接运行训练脚本——不在 tmux 里,不在后台。直接执行:

bash
ssh your-server 'cd /work/your-project && \
  conda activate your-env && \
  python train.py --epochs 1 --subset 100'

你看着输出滚动。会不会立刻崩?data loader 找到文件了吗?模型塞得进 GPU 显存吗?loss 的初始值合理吗?在下降吗?WandB 连上了吗、开始记录了吗?

这是 90% 的问题会暴露的时刻。数据路径错误、缺少依赖包、张量形状不匹配、OOM 错误、WandB 认证失败——全都在头 30 秒内显现。立即修复。在本地改代码,重新 rsync,再跑一次。反复迭代,直到训练能干净地跑过至少几百步,loss 在下降。

两分钟的前台测试,省下后面在一个跑了一整夜的 tmux session 里发现问题要花的几小时。

第二步:后台长跑。 确认训练稳定后,终止前台进程。现在在服务器上的 tmux 里重新启动:

bash
tmux new-session -d -s train01 "cd /work/your-project && \
  export WANDB_API_KEY=your-key && \
  conda activate your-env && \
  python train.py --config configs/exp1.yaml"

训练现在在 tmux 里运行。你可以断开服务器连接,可以合上笔记本,可以回家。训练继续——因为 tmux 保持了会话(第三章),代理隧道因为 SSH ControlMaster 而不会断(第四章)。

第三步:监控。 第七章的投入在这里产生回报。Watchdog 脚本在服务器上监控 GPU 利用率和进程健康状态。本地机器上的 CronCreate 每 10-15 分钟检查一次 watchdog 的汇总文件。一切正常时,什么都不发生——没有通知,没有打断,没有噪音。训练崩溃时、GPU 利用率跌到零时、watchdog 检测到停滞时,Claude Code 会收到警报并介入:读错误日志,诊断问题,修配置,重启。

WandB:你的远程仪表盘

每个训练脚本都应该向 Weights & Biases 记录日志。这不是可有可无的装饰——它是让整个远程工作流变得实用的关键。

WandB 给你一个 web 仪表盘,显示训练 loss、验证指标、学习率、GPU 利用率,以及你记录的任何自定义指标。你可以在手机浏览器上查看。不需要 SSH,不需要 Termius,不需要命令行。打开网址,看 loss 曲线。

这是你的被动监控通道。主动监控(watchdog + CronCreate)捕获崩溃和错误。被动监控(WandB 仪表盘)告诉你即使没有出错,训练是否进展顺利。Loss 曲线过早平坦、验证准确率停滞——这些不是 watchdog 会捕获的"错误",但它们是信号,提示你下一个实验应该改点什么。

Claude Code 也可以编程方式查询 WandB,自动拉取指标进行对比分析,不需要你去看图表。

出了问题怎么办

训练崩溃会发生。OOM 错误、NaN loss、data loader 异常、多卡训练的 NCCL 超时。问题不是它们会不会发生——而是多快能检测到并修复。

有了这套系统,检测是自动的(watchdog + CronCreate)。修复取决于问题类型:

  • OOM: Claude Code 修改配置减小 batch size,调整梯度累积步数来保持等效 batch size 不变,rsync 改动,从最新 checkpoint 重启。
  • NaN loss: 需要更多调查。Claude Code 读日志,检查是学习率问题(太高)、数据问题(损坏的样本),还是数值不稳定(缺少梯度裁剪)。它提出修复方案,如果涉及实质性的实验决策则征求你的意见,否则自动应用。
  • Data loader 崩溃: 通常是损坏的样本或路径问题。Claude Code 定位问题文件,加入排除列表或修正路径,然后重启。
  • NCCL 超时: 多卡通信失败。通常是偶发的。Claude Code 从最新 checkpoint 重启训练。

目标:大多数崩溃在不惊醒你的情况下被处理。你早上看 WandB,发现训练在凌晨 3 点有一次 2 分钟的短暂中断后继续了。这就是系统按设计运行的样子。


阶段 5:结果与分析(服务器 → 本地)

训练完成。结果在服务器上。拉回来。

bash
rsync -avz \
  --exclude='checkpoint-*/' --exclude='*.safetensors' --exclude='*.bin' \
  your-server:/work/your-project/outputs/ \
  ~/projects/your-project/outputs/

注意排除项:你拉回的是日志、指标、评估结果和生成的输出。你不拉模型 checkpoint——它们通常每个好几 GB,你在本地机器上用不着。如果需要跑更多评估或生成更多输出,就在 checkpoint 所在的服务器上做。

Claude Code 在本地分析结果。 它读训练日志,解析指标,与 baseline 数字对比,给你一份结构化总结:"实验 A 在 ImageNet 验证集上达到 94.2% 准确率,比 baseline 论文报告的 95.5% 低 1.3 个点。Loss 曲线在前 1000 步有不稳定现象——学习率 warmup 可能太短。实验 B 使用修改后的 schedule 达到 95.1%,更接近目标。"

迭代决策。 基于分析,三种走向之一:

  1. 结果不好。 回到阶段 2。改代码,调超参,换方案。同步,训练,分析。循环重复。
  2. 结果有希望但不最终。 跑更多实验:不同 seed 做统计显著性检验,ablation 研究隔离关键因素,不同数据集测试泛化性。更多 3-4-5 阶段的循环,但代码改动少——主要是配置微调。
  3. 结果好。 写论文,或者跑最终的一整套完整实验,用于论文报告。从探索模式切换到巩固模式。

这个迭代循环——规划、编码、同步、训练、分析、重复——是计算科研的心跳。这套系统让每次迭代更快、更省心。过去需要一整天人工操作的事(写代码、调 SSH 问题、前一小时盯着看、半夜设闹钟、醒来检查、手动重启崩溃的训练),变成了一个你睡着时就自动完成的循环。


日常作息

有了这套系统,日常生活到底是什么样的?以下是典型的一天:

早上。 你醒来,拿起手机,在浏览器里打开 WandB。昨晚训练的 loss 曲线很平滑——跑了一整夜没崩。指标没有异常。不需要 SSH 进去,不需要检查别的什么。你去洗澡、泡咖啡、坐到桌前——知道你的 GPU 在你离开的整整 10 个小时里都在高效工作。

上午晚些。 通宵训练完成了。Claude Code 通过定时的 CronCreate 检查,检测到 tmux 进程已退出。你坐下来让 Claude Code 拉结果。它 rsync 回输出日志和指标,分析一番,呈上总结:"训练完成。50 个 epoch,最佳验证准确率 93.7%(epoch 42)。低于目标 95.5%。学习率调度似乎太激进——验证 loss 在 epoch 35 开始上升,表明后期出现了过拟合。"

下午。 基于分析,你和 Claude Code 决定下一个实验方案。学习率减半,加 cosine annealing,warmup 从 500 步延长到 2000 步。Claude Code 改好配置,你扫一眼 diff 确认合理,它 commit 到 git 然后 rsync 到服务器。快速前台冒烟测试——loss 在降,WandB 在记录,显存占用正常。Claude Code 在 tmux 里启动下一轮训练,watchdog 自动接管,CronCreate 已经在定期检查了。

傍晚。 训练在跑。你下班了。不再每 20 分钟看一次手机。和朋友吃饭,看场电影。如果出了什么严重问题,Claude Code 会做第一时间的分诊处理,你明天早上看 WandB 就能看到处理结果。

深夜。 Claude Code 通过 CronCreate 监控。Watchdog 在盯着。WandB 记录着每个指标。你一觉到天亮。

周末。 同样的模式,但更随意。一天看一两次手机上的 WandB。如果周五晚上启动的训练出了结果,也许周六花 20 分钟在沙发上通过 Termius 和 Claude Code 讨论下一步。或者干脆让实验继续跑,周一再处理。你的 GPU 不休周末,但你可以。

这种日常的核心特征是焦虑的消失。你不担心静默失败,因为 watchdog 会捕获。你不担心 GPU 白白空转,因为 Claude Code 会重启崩溃的训练。你不取消周末计划,因为系统不需要你就能运行。第一章的 GPU 保姆问题被解决了——不是把你训练成更好的保姆,而是把你从这个岗位上彻底撤下来。


运行多个实验

熟悉了单实验工作流后,你自然想要扩展规模。你有多块 GPU,也许有多台服务器——为什么让它们闲着?

一台服务器,多个实验。 如果你的服务器有 8 块 GPU,你可以同时跑两个 4 卡实验,或者一个 6 卡加一个 2 卡实验。每个实验有自己的 tmux session(train01train02)。每个记录到自己的 WandB run。服务器上的单个 watchdog 进程监控所有活跃的 tmux session,在一份汇总文件中报告它们的整体状态。

多台服务器,多个实验。 跨服务器扩展。每台服务器有自己的 tmux session、自己的 watchdog 实例、自己的实验集。在本地机器上,Claude Code 管理所有一切——它知道哪些实验在哪里跑,因为它写了项目 CLAUDE.md 和 CronCreate 任务。每台服务器一个 cron 检查,读那台服务器的汇总文件,覆盖那台机器上的每一个实验。两台服务器意味着两个 cron job,不是十个。

管理开销保持恒定。 这是关键洞察。跑 6 个实验不需要 6 倍的精力。Claude Code 做多路复用。你看到的是一份摘要:"服务器 A:train01 运行中(epoch 34/50),train02 已完成(结果待查看)。服务器 B:train03 运行中(epoch 12/50),train04 在 epoch 8 崩溃并已重启。"看一眼就知道一切的状态。

实际上限。 你可以现实地同时管理 4-6 个实验,分布在 2-3 台服务器上,复杂度不会失控。超过这个数,你会开始搞不清每个实验到底在测什么,理解 10 个并行 run 的结果所需的认知开销会抵消时间节省。从一个实验开始,随着肌肉记忆的养成再增加。


常见模式

Ablation 扫参

你需要测试 5 种不同配置,找出你方法中哪个组件真正起了作用。不用串行一个个跑:

  1. Claude Code 准备好 5 个配置文件(每次只改一个变量)
  2. Claude Code 把它们分配到可用的 GPU 上——也许服务器 A 跑 2 个,服务器 B 跑 3 个
  3. 每个在自己的 tmux session 里运行,WandB 记录
  4. Watchdog 同时监控全部 5 个
  5. 每个跑完,Claude Code 记录结果
  6. 全部完成后,Claude Code 汇总对比表

最后一个跑完时你也许正在吃晚饭。第二天早餐时看结果。

通宵训练

实验要跑 14 小时。现在是下午 6 点。

老做法:启动训练,回家,设半夜的闹钟 SSH 进去查一下,再设早上 6 点的闹钟再查一次。整个晚上半心半意,想着 data loader 是不是碰到坏样本了。

新做法:启动训练。前台冒烟测试通过。放进 tmux。回家。安心入睡。凌晨 2 点崩了,Claude Code 修。凌晨 4 点跑完了,结果等着你。早上端着咖啡看 WandB:loss 曲线干净利落,无中断。开始分析。

投稿截止日冲刺

截止日前三天。你需要 8 组实验结果来填论文里的表格。Claude Code 在 3 台服务器上同时跑实验,全部监控着,修复崩溃,整理结果成结构化格式。你在写论文——introduction、method section、related work。每隔几小时用手机看一下:"实验怎么样了?"Claude Code 给你两行更新。结果陆续到位。表格逐渐填满。你准时提交,每晚都睡了觉。


检查点

你现在应该能描述完整的五阶段流水线:想法、代码、同步、训练、结果。如果有人问"你的自动化科研配置是怎么工作的?",你的回答只需 60 秒:

"Claude Code 在本地机器上写代码,rsync 到 GPU 服务器,先跑个快速冒烟测试,然后在 tmux 里启动正式训练。一个 watchdog 脚本监控 GPU 利用率和进程健康状态。定时 cron 检查自动暴露任何问题。WandB 提供我可以在手机上查看的仪表盘。训练完成后我把结果拉回本地,Claude Code 做分析。凌晨 3 点崩了也不用我管。GPU 从不空闲,我安睡整晚。"

这就是整个系统。五个阶段,三台机器,一条工作流。你已经有了地图。下一章,你将走进实战——从头到尾跑一个真实实验。

Released under the MIT License.