前面的文章都在讲”怎么做”,这篇讲”怎么研究”——面对一个开放问题,从”我不知道”到”我有证据支持的结论”的完整路径。这套方法既适用于读研做课题,也适用于工作里的技术调研和方案选型:本质上它们是同一件事——在不确定中用证据做决策。
我自己做技术调研时最大的教训是:研究方法的价值不在于”严谨”,而在于防止自欺。没有方法约束的探索,很容易变成”找支持自己直觉的证据”。这篇把我用的流程和工具整理出来。
前置阅读:无硬性要求。配合 数据采集 和 Pandas 数据分析 阅读,能覆盖研究中的数据环节。
第一步:选题——好问题是研究的一半
新手选题最常见的错误是太大:“研究大模型在教育中的应用”——这够写一百篇论文。可研究的问题要满足三个条件:
- 具体:能在一张实验台上回答。“RAG 系统中 chunk 大小对中文问答准确率的影响”就比上面那个好。
- 有抓手:你能拿到数据、能跑实验、或能找到足够的已有证据。
- 有张力:答案是未知的且有人关心。已知答案的问题是查资料,不是研究。
工作场景的等价物是技术选型:“我们该不该把向量库从 pgvector 迁到 Milvus”——同样适用:先定义清楚评价什么(延迟?召回率?运维成本?),再谈实验。
一个实用技巧:把选题写成可证伪的假设。“方案 A 比方案 B 好”不可证伪(“好”没定义);“在 1000 QPS 下方案 A 的 P99 延迟低于方案 B”可以证伪,可以设计实验。
第二步:文献调研——站在前人肩膀上,而不是旁边
调研的目的不是”读很多论文”,而是回答三个问题:这个问题被解决过吗?解决到什么程度?公认的难点和空白在哪?
我的调研流程:
- 种子论文:从一篇高被引综述(survey)或最近的高质量工作入手。arXiv、Google Scholar、Semantic Scholar 是主战场。
- 双向滚雪球:向前看它的参考文献(这项工作从哪来),向后看它被谁引用(这项工作往哪去)。Semantic Scholar 的引用图谱特别适合干这个。
- 结构化笔记:每篇论文记四行——问题是什么、方法核心一句、关键结果数字、我能借用什么。不记笔记的泛读,一周后等于没读。
- 停止条件:当新读到的论文引用的都是你读过的文献,说明圈子闭合了,调研可以收尾。
工具链推荐:Zotero 管文献(浏览器插件一键抓取 arXiv 页面),Obsidian/Notion 做笔记,论文 PDF 用 Zotero 云同步多设备。
第三步:实验设计——让结果可信
实验的核心目标只有一个:让结论的差异只能归因于你要研究的那个变量。围绕它有几个基本功:
控制变量。对比两个模型时,数据、训练轮数、超参搜索预算都要一致。我见过”新模型吊打基线”的实验,仔细一看基线用的是默认超参、新模型调了一周——这种对比没有任何信息量。
基线要强。基线是研究的”对照组”。选一个弱基线赢它,什么都证明不了。诚实的做法:基线选当前已知最强且你能复现的方案,并且同样认真调参。
重复与方差。深度学习实验有随机性(种子、数据顺序、初始化),单次结果不能下结论。至少跑 3-5 个种子,报告均值 ± 标准差。两个方法差 0.3% 但标准差 0.5%,结论是”分不出胜负”,而不是”A 更好”。
消融实验(Ablation)。你的方法有三个组件,分别去掉再测,才能说明每个组件的贡献。审稿人最爱问的就是”这个提升到底来自哪”。
用代码固化实验纪律:
# 实验记录模板:每次运行自动落盘
import json, time, hashlib
from pathlib import Path
def log_run(config: dict, metrics: dict, out_dir="runs"):
record = {
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"config": config,
"metrics": metrics,
# 配置的哈希当实验 ID,同配置可复现可对账
"run_id": hashlib.md5(json.dumps(config, sort_keys=True).encode()).hexdigest()[:8],
}
path = Path(out_dir) / f"{record['run_id']}_{int(time.time())}.json"
path.write_text(json.dumps(record, ensure_ascii=False, indent=2))
return record
三个月后你(或你的审稿人/同事)问”这个数字当时怎么跑出来的”,这些记录就是答案。靠记忆回答实验细节,是研究事故的头号来源。
第四步:读结果——数字背后的陷阱
先写出什么证据会让你放弃当前解释。若无论结果高低都能被解释成方案有效,这个结论就没有真正接受检验。负结果也应保留配置与观察范围,避免下一次探索重复走同一条路。
实验出数字了,但数字不等于结论。几个最常见的误读:
相关不等于因果。“使用工具 X 的团队交付更快”可能是反过来——本来就强的团队才用得起 X。要因果结论,需要随机分组或至少控制混淆变量。
均值掩盖分布。P99 延迟恶化但均值改善的”优化”真实存在。看分位数、看直方图,别只看一个平均数。Pandas 一篇 里的分布分析工具在这直接用得上。
测试集过拟合。在同一批测试集上反复实验、挑最好的报告,等于对测试集过拟合。学术界的对策是留一个”封存测试集”只在最后评一次;工程上的对策是线上 A/B 验证。
显著性检验。样本少时,两个均值的差异可能只是噪声。简单的 t 检验或 bootstrap 置信区间能回答”这个差异站得住吗”。
第五步:写作与表达——结论要可检验
研究报告/技术文档的结构,其实就是研究过程的重放:
- 问题:要解决什么,为什么重要。
- 假设:你的预期答案是什么(可证伪的版本)。
- 方法:实验怎么设计的,为什么这样设计能让结论可信。
- 结果:数字和图表,包括负面的结果。
- 结论与局限:证据支持什么、不支持什么、下一步是什么。
特别强调两点:
- 写负面结果。“这条路走不通”是有价值的结论,能省下别人三个月。只报成功实验的报告,是在污染团队的知识库。
- 区分事实、推测和观点。“准确率提升了 2.3%(5 种子均值)“是事实;“可能是因为注意力机制捕捉了长距离依赖”是推测;“我认为这个方向值得继续”是观点。三者混着写,读者就无法评估证据强度。我的博客审计规则里也专门有”数据可信度”这一条,原理相同。
把研究做成流水线
研究活动也可以工程化,复用前面文章的工具:
- 文献采集自动化:arXiv 关键词订阅,每天自动拉新论文进库(爬虫 + 自动化工作流)。
- 实验追踪:MLflow / Weights & Biases 管训练实验,比手写 JSON 模板更规范;小项目用上面的模板也够。
- 结果看板:实验记录进 DuckDB,随时 SQL 查”所有 lr=1e-4 的实验结果分布”。
踩坑排查清单
| 症状 | 原因 | 处理 |
|---|---|---|
| 调研一个月还在读论文 | 没有停止条件 | 用”引用闭合”标准;先写调研小结再继续 |
| 实验结果无法复现 | 没记种子/配置/数据版本 | 每次运行自动落盘完整配置 |
| 对比实验总被质疑 | 变量没控制住 | 列一张”两实验唯一差异”清单自查 |
| 结论被一个新数据推翻 | 在单一测试集上反复调 | 封存测试集 + 交叉验证 |
| 报告被问”依据是什么” | 事实与推测混写 | 每个论断标注证据类型 |
| 负面结果不敢写 | 心态问题 | 负面结果是最被低估的研究产出 |
练习
- 选一个你关心的技术问题,把它改写成一个可证伪的假设(包含量化指标和条件)。
- 围绕这个假设做一轮”滚雪球”调研:1 篇种子论文 → 双向各找 5 篇 → 每篇写四行结构化笔记。
- 设计一个对比实验并列出”控制变量清单”:明确哪些因素必须一致,哪些是你要研究的变量。
- 找一篇你最近读过的技术文章或报告,把其中的论断分成”事实 / 推测 / 观点”三类,评估它的证据质量。
面试常问
Q:你怎么做技术选型调研? 先定义评价维度和约束(性能指标、成本、团队能力、合规),再找候选方案的证据(官方基准、第三方测评、可复现的小实验),最后用自己的数据做小规模验证。关键原则:别人的 benchmark 是参考,自己场景的数字才是依据。
Q:怎么保证实验结果可信? 控制变量、强基线、多种子报告方差、消融实验、封存测试集。一句话:让所有能解释结果差异的因素,除了你要研究的那个,都被固定或量化。
Q:实验结果和预期相反怎么办? 这是研究最有价值的时刻。先怀疑实验(bug、数据泄漏、配置错),逐一排除后如果结果依然稳定,它就是真发现——修正假设,写清楚,这就是新结论。千万别反向挑选数据去凑预期。
Q:你怎么读一篇论文? 三遍法:一遍读标题摘要结论定价值(5 分钟);二遍读方法和图表抓核心(30 分钟);需要复现或深挖时三遍精读。不是每篇都值得三遍,调研期的主要动作是高效地”判死刑”。
Q:研究项目和工程项目最大的区别是什么? 工程项目的目标已知(把功能做出来),研究项目的路径和终点都未知(问题可能无解)。所以研究更需要阶段性收敛(定期回答”目前证据支持什么”)、更需要止损纪律(设定探索的时间盒)、更需要诚实记录负结果。
至此这个系列的 13 篇全部完成:从 Linux + Python 环境 起步,经过 Pandas、数据采集、机器学习四课(基础、线性回归、决策树、K-Means)、语音识别、NLP、人脸识别、大数据管理、AI 自动化,到本篇研究方法收官。研究方法是所有技术的元能力——愿你既能动手做,也能想清楚为什么做。
💬 评论
这套方案在哪一步卡住了?也欢迎补充你的实现方式或踩坑经验。