KDD 2025 | 科研小白的初体验
- 2025.02.03 AoE时间 Abstract截稿
- 2025.02.10 AoE时间 正文截稿
- 2025.04.04-2025.04.18 Rebuttal
Summary:寒假期间,在学长的带领下,投了人生中一篇论文(NLP领域),经历了最忙(熬了好几个大夜)但也最有意义的寒假,在此记录一些科研的心得
说明:
笔者是个大二小登/老登(自由心证),最开始写和LeetCode刷题相关的笔记,是因为觉得自己或许不太适合科研,考虑着毕业之后就业搞钱(狗头)
作为一个方向未定、善变且迷茫的人,这次投稿经历让我重新审视了自己。当论文提交的那一刻,我激动得差点哭出来,very very proud of our work(中不中稿已经不在考虑范围内了)投稿结束之后,花了几天时间整理代码仓库,反思了一下自己的工作
今后这个号会更多涉及科研内容,LeetCode刷题基本停更,关注我的uu们请及时取关,以免浪费各位宝贵的时间
Setup
工欲善其事,必先利其器
搞ML这个领域,和我最初的规划并不相同。本来我是打算做网络安全方向的,但因为一些机缘巧合,进了现在的组。更意外的是,就在我认定自己不适合搞科研,准备放弃、转向找工的时候,写了人生中第一篇论文,结果又让我重新燃起了对科研的兴趣。所以,其实我的准备并不算充分,这点我会在[Future Work](## Future Work)部分反思。接下来,我会根据自己的科研经历,总结一些实操中对我帮助比较大的准备工作
学习
入门ML领域,我主要做了三件事:
- 2倍速刷李宏毅的机器学习课程,顺便做了些Lab(当时觉得ML特别玄学,明明代码一样,改个参数结果就不同)
- 看了Stanford CS224的PPT,但没有写代码
- 读了一些经典论文,比如Transformer、BERT,还读了实验室学长学姐的一些论文
对于像我一样,方向未定,想要快速上手某个领域科研的同学,或许我的经验能有点参考价值:
网课学到什么程度?
- 网课要学到怎么样的程度:(仅适用于快速上手)
去看几篇学长学姐的paper,或者他们用的Baseline的paper(通常是基于经典架构的改良),如果能看懂Method部分,说明我们已经对常用模型有了基本理解,至少知道怎么用。达到这一点,就具备了初步的科研能力,可以不再学习网课,跳到下一步,之后遇到不懂的模型,再回头找论文补。至于课程的Lab,我个人觉得帮助不大,和实际复现Baseline的代码差距太大
网课/教材的作用主要是两点:一是帮你建立领域宏观框架,二是让你能看懂论文。毕竟最新的知识往往来自论文,能看懂论文,说明你具备了在该领域“自学习”的能力 - 读论文:
入门做的三件事里,对我帮助最大的是读论文。只有见过好论文,才能写出好论文,一开始科研,我们都是在玩模仿游戏,模仿高质量的工作。同时对比学长学姐的论文,思考它们和高水平论文的差距在哪。这个过程既能学习领域知识,也能培养对科研的敏感度,为之后的写作打基础
工具
服务器环境配置
刚开始学姐给了我一个服务器账号,但我连“服务器”是啥都不知道。查资料后才知道可以用ssh连接,但每次都要输密码,还得连学校VPN,动不动就断联。直到后来才发现,服务器可以配置免密登录,还能用tmux管理会话
写下这些是因为,我觉得这些工具本身能大大提高科研的效率,但是一般不会有学长学姐教我们这些,需要我们自己去发掘。如果完全没听说过,小白可能根本想不到它们的存在
免密登陆
-
生成SSH密钥对
打开终端,输入以下指令,把最后的字段替换成自己的邮箱(注释部分)ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
-t rsa
表示密钥使用RSA加密算法
-b 4096
表示密钥的长度
最后会保存在C:\Users\Username\.ssh\id_rsa
这是私钥文件,C:\Users\YourUsername\.ssh\id_rsa.pub
这是公钥文件,我个人选择在wsl的linux系统里面操作 -
把公钥复制到服务器
在终端输入以下指令(linux based)ssh-copy-id -p 233 user@remote_host
user
需要替换成自己的服务器账号名,remote_host
是服务器IP地址,-p 233
是端口号
如果不是linux-based,需要自己手动把公钥复制到服务器的~/.ssh/authorized_keys
目录下 -
配置vsCode连接服务器
创建配置文件vim ~/.ssh/config
在config文件中配置SSH
Host <hostname> HostName <ip> User <username> Port 233 IdentityFile ~/.ssh/id_rsa #本机对应的ssh私钥地址
tmux会话管理
*参考资料
常用的命令
tmux list-session #查看目前的会话
tmux new -s <session_name> #新建会话
tmux attach -t <session_name> #重联会话
detach我一般用Ctrl+B+D
实现,tmux
可以保持会话在后台运行,之后可以重新连接,这样即使服务器断联了,程序运行也不会因此中断
VS Code python debug配置
*参考资料
-
下载VS Code python debugger插件
-
打开需要调试的文件夹,点击VS Code左侧的
create a launch.json file
-
选择python debugger(ML领域的话,一般错不了)
-
初始json文件大概如下:
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "Python Debugger: Current File with Arguments", // name是这个debugger配置的名称 // 可以自定义,用于区分不同的配置 // 个人一般喜欢用模型的名称和对应的文件命名 // e.g "name": "BERT: main.py" "type": "debugpy", "request": "launch", "program": "${file}", //进行调试的python文件 "python": "/path/to/conda/envs/myenv/bin/python", // 指定 Conda 环境的 Python 解释器 // 这样可以保证用对应的python环境调试 "justMyCode": false, // 会进入导入的函数内部的代码进行调试 // e.g import torch 调试会进入torch的代码 "console": "integratedTerminal", "args": [ "${command:pickArgs}" // 用来添加运行时传递给函数的参数 // 如不加debugger是 python main.py --model_name llama --dataset c4 // 可以在此配置: // "--model_name": "llama", // "--dataset": "c4" ] //设置环境变量 "env": { "CUDA_VISIBLE_DEVICES":"1" //使用哪个GPU }, // 指定VS Code调试的根目录 // ${workspaceFolder}表示以当前VSCode打开的文件夹为根目录 "cwd": "${workspaceFolder}" }, { // 第二个debugger配置,可以选择与第一个不同的参数 // 方便调试不同的文件 "name": "Python Debugger: Current File with Arguments", "type": "debugpy", "request": "launch", "program": "${file}", "console": "integratedTerminal", "args": [ "${command:pickArgs}" ] } ] }
-
选择
Python Debugger: Debug using launch.json
进行调试,之后出现下图2界面,其中Debugger1
和Debugger2
是之前的name
字段指定的不同配置的名称
- 在调试过程中,可以打断点,一步步step运行,可以在
DEBUG CONSOLE
输入各个变量的名称,查看变量的值
查看GPU情况
经典命令nvidia-smi
可以提供基本信息,但其输出格式不够直观,不利于人类阅读。推荐使用nvitop
,可以更清晰地显示 GPU 的使用率(util)和显存(memory)情况
- 显存(Memory):在加载模型/数据,处理数据,以及训练和推理的时候需要较多显存
- 使用率(Utilization):计算负载,高使用率表示GPU被较高效地使用
AI工具
LLM的问题当然要交给LLM自己解决
这个时代,用AI,用好AI,以此来提升自己的生产力是必须的。后面每个模块会说到,我自己喜欢用不同“品种”的AI负责不同的部分
前期调研
我的科研之旅始于帮学长调研文献,我个人认为猜测,文献调研可分为三种:
- 构思idea时大量阅读 —— 构建研究领域的roadmap,确定方向;找出现有方法的不足,构思如何创新改进
- 有了idea后大量阅读 —— 确认idea未被他人实施,自己研究的问题尚无优秀简洁的解决方案;寻找合适的baseline。这部分文献会反映在论文的related work中
- 有了idea后精读论文 —— 研究baseline(为复现结果和实验做准备),进一步细化想法(构思论文的methods部分)
小白如我只参与了2 3两个部分的文献调研,并不清楚学长是如何想出这样一个idea的,因此对1部分的文献调研不具有发言权
检索网站
-
arXiv https://arxiv.org/ 高级检索如图
-
Google Scholar https://scholar.google.com/ 高级检索如图
-
Semantic Scholar https://www.semanticscholar.org/ 高级检索如图
-
dblp https://dblp.org/search 高级检索如图
判断论文质量
在2阶段,需要大量阅读论文,但是每一篇都精读既不可能,也太过低效。质量不高的论文,不适合拿来作为参考,或者放在我们自己的论文里引用。快速判断一篇论文是否优质,我选择采用两个指标:
- 是否在顶会上发表?与ML领域相关的顶会有 NeurIPS、ICML、ICLR、AAAI、CVPR、ICCV、EMNLP、ACL、KDD 等
- 是否有较高的引用量?引用量代表了业界同行对这篇工作的认可
至于如何判断一篇论文是不是我们想要的(是否切题),我一般:
- 看标题,过滤掉大部分文章
- 看摘要
- 让AI概括,并向AI提问
- 结合摘要和AI的回答,判断论文与我们主题的相关系数,系数高则去粗读论文的结论和method
关键词
我在文献调研时做得不够好,没能为学长找到足够有用的资料。反思后,我总结了两点:
- 利用AI:当我对领域完全陌生,甚至不知道我们研究方向的英文专有名词是什么时,第一步就是把问题清晰地描述给AI,让Al生成10个检索关键词。然后观察这些关键词的共性,以此为起点去搜索
- 动态调整:我们可以从宽泛的关键词开始,阅读部分文献后逐步优化。细化关键词时,要特别注意检索结果的数量:如果论文太少,就放宽关键词范围(因为很多相关论文的标题可能并不直接包含你的关键词,比如我们的baseline文章标题就和我的关键词相差甚远,这时可以尝试内容检索);如果论文太多,就进一步细化关键词
从一到多
秦人不暇自哀,而后人哀之;后人哀之而不鉴之,亦使后人而复哀后人也
论文之间往往存在内在的逻辑联系(试想,我们的研究不也是基于前人工作展开的嘛?)在查找相关文献时,可以从文献综述入手,阅读一两篇高质量的综述文章。这不仅能帮你快速定位学长的创新点在领域中的位置,还能提供大量相关文献的线索
如果找到一篇强相关的论文:
- 仔细阅读它的参考文献和Related Work,梳理它引用了哪些工作,理清研究脉络
- 查看引用这篇论文的其他文献,看看是否有人基于此做出了改进或创新,以及这些改进是否与我们的方向有重合
AI工具
个人感觉豆包和kimi会在论文阅读方面强一点
中期实验
吾尝终日而思矣,不如须臾之所学也
我负责了实验设计和baseline模型的运行(即在自定义的setting下运跑baseline,结果作为与自己模型对比的基准)
作为小白,代码能力有限,修改代码和运行实验对我来说是一个比较的有难度的模块
看懂
修改baseline的前提是看懂代码,常见的修改分为:
- 参数/配置调整
相对简单,需要搞清楚模型接受哪些参数、每个参数的含义,然后在运行时修改输入参数 - 数据集调整
对理解的要求相对低,主要掌握数据的输入输出流,知道数据怎么输入模型、处理成什么形式、输出格式是啥。不需要深入模型内部实现,相当于把baseline当黑箱用,只要知道怎么往里塞数据、怎么取结果就行 - 任务变更
需要较深入的理解,可能会涉及到模型内部的一些调整(在不改baseline实现方法的前提下,让它适应新任务,比如从分类任务改成生成任务)
我个人理解baseline最高效的方式是debugger+AI。由于我缺乏大型项目的经验,面对封装良好的代码库时常常感到迷茫,不太习惯在不同文件之间跳转查看。直接阅读代码对我来说效果不佳,理解起来也比较困难,因此我采用了“运行法”——用VS Code的debugger一步步运行代码,边运行边分析
具体来说,我会:
- 逐步运行:通过debugger一步步step,观察代码的执行流程,理解每个语句的含义
- AI辅助:如果某个模块的作用不明确,我会询问AI并结合运行结果进行推测
- 查看函数调用堆栈:了解不同文件之间的代码是如何关联的,了解每个类的实例化位置和作用
- print:如果某个变量的含义不清楚,我会在DEBUG CONSOLE中打印出来,根据结果推测其作用,如果推测不出来,再查看函数调用堆栈
- 善用搜索:通过Ctrl+F快速定位代码中的关键部分,以及在VS Code中使用全局查找
根据任务的类型,我会调整debug的运行范围:
- 任务1:基本不需要运行,只需查看参数定义即可
- 任务2:运行到数据输入模型的部分,打断点跳过模型的forward/inference过程
- 任务3:完整地step过整个流程,确保对模型内部处理有清晰的理解
这种方法虽然看起来有点笨,但对我来说非常有效,能帮助我逐步理清代码的逻辑和结构
修改
首先,要按照作者提供的README配置好环境,把源代码跑通。期间可能会经历一系列痛不欲生的debug过程。只有确保baseline能正常运行,才能开始修改,否则出了问题都不知道是谁的锅(狗头)
个人觉得,看懂代码之后,修改其实相对简单?或者说,一旦看懂了代码,你就能判断自己能不能改、有没有修改的思路。如果没思路,赶紧找学长学姐或coauthor沟通,听听他们的想法。有了思路又懂代码,修改本身并不难
我总结三点:
- 拆解问题:
在修改之前,先对问题有一个清晰的认知,能不能把问题拆解成1、2、3、4…个子问题?然后思考每个子问题是否有解决的可能性和方案。其实,我觉得这是AI时代最重要的能力,如果你能把大问题拆解成小问题,并把需求和问题描述清楚,AI完全可以搞定,甚至不需要自己写代码 - 改动幅度小,迭代快:
不建议一口气按照自己的思路把代码全改完再运行debug。最好是一小块一小块地改,每改完一块就运行一下。如果报错,你马上就知道是哪里出了问题,然后根据报错信息快速迭代。在对代码有理解的前提下,不需要每次都瞻前顾后,深思熟虑,可以一有想法就马上改,根据报错快速调整方案 - 与人交流:
这一点真的太太太重要了!
第一是和学长学姐coauthor沟通,TA们可能会快速指出我的问题,或者为我提供更简单的思路和解决方案;第二,对于我来说,是和我妈沟通,虽然我妈咪是学计算机的,但她已经脱离行业多年,提不出具体的建议,不过,当我把问题描述给她听,或者向她抱怨我的bug时,我往往会在这种“输出”过程中理清思路,自己找到问题的症结
工具:
- VS Code Debugger
- cursor:AI辅助代码生成工具 *参考资料|Cursor使用文档
- 其他AI:个人觉得DeepSeek代码能力 > ChatGPT,DS似乎更能利用之前对话中给的信息
后期论文
理科生容易对论文这种看似文绉绉的东西产生轻视情绪,尤其是科研小白初次接触时,往往意识不到论文的重要性。然而,论文本质上是所有工作的集大成者,Reviewer并不关心你debug的过程有多痛苦,也不关心你提出的idea有多创新(除非你能证明这个idea能高效解决问题),一切的一切最后都浓缩在那8页纸中
先分享一个非常好的论文写作讲解,虽然是针对CVPR的,其中的内容我觉得对于论文是普适的 How to write a good research paper
由于我主要负责论文的Experiment部分,而Abstract、Introduction、Related Work、Methods和Conclusion主要由学长完成,我则充当了一回“菜鸟Reviewer”,给学长的部分挑挑毛病。因此,我会更多分享自己写作Experiment的感受,以及阅读学长部分的心得
Experiment 写作
在实验部分,我们首先提出了Research Questions (RQ),然后每个实验都针对性地回答一个RQ,每个实验又分为Setting和Result两部分
- Setting:核心是读者能否根据我们的描述复现实验,写作时要避免啰嗦,但必须解释清楚可能引起误解或疑问的地方,需要保持读者意识,即站在读者的角度思考:TA们关心什么?可能会有哪些误解?
- Result:核心是言之有物 毕竟,能写到论文里的结果基本都是好的(狗头)Result部分很容易陷入“黄婆卖瓜自卖自夸”的境地,但实际上,它必须让读者从中读出一些乍一看数据难以得出的结论。在写Result之前,我通常会花一个小时左右的时间深入研究实验数据。研究时,保持主题意识,思考数据结果与模型本身的关系。特别关注那些“意料之外”的数据,它们往往隐藏着一些有意义的结论
Abstraction & Introduction
这两个部分是reviewer重点阅读的内容
- 逻辑结构:写作时心中要有一条清晰的逻辑主线,比如说我们要解决什么问题->现在解决该问题的方法有哪些->这些方法的缺陷是什么->我们如何基于这些缺陷做出改进。只有通过这种逻辑链条,读者才能清晰地理解我们研究的价值(why should they care about our research)
- 环环相扣:作为作者,我们容易主观地认为自己的逻辑是合理的,而忽视潜在的跳步。举个例子,我说“学校要开学,我要多吃东西”,我自认为这是一个合理的逻辑,因为我潜意识里的隐含逻辑是“学校食堂不好吃,所以要在家里多吃点好东西”,但是读者就会觉得我莫名其妙。introduction要做到环环相扣,把隐藏的逻辑都写出来,引导读者步步深入
- 画好图:一个好的模型框架图或是引入时的toy example图,能让读者快速直观地理解内容。我个人非常喜欢将图和文字结合起来阅读,看懂了图,基本就能把整个模型装在心里了
Methods
- 感性理性两个维度:
在阅读学长写的Methods部分时,我发现了一个公式的错误。能发现这个错误,我觉得主要是因为我喜欢从两个维度上去理解东西:- 理性维度:理解每个符号的含义、公式在计算什么、使用了哪些定理或原理
- 感性维度:从宏观上理解这个公式在做什么。我认为数学是“you don’t feel it, you don’t prove it” 如果缺少感性维度的理解,就像模型缺少了toy model,会导致抽象与具体之间存在gap
- “费曼学习法”:
无论是自己写的部分,还是我们模型的Methods,我都会尝试用“自然语言”向领域外的妈咪描述一遍。如果她能听懂,那么看论文的人一定也能懂(狗头);如果她听不懂,那很可能是这个部分我自己也没有理解清楚,论文也很可能写得不够清楚。我会特别重视她提出的疑问和意见(所谓的读者意识hhh)我总是在与我娘交流的过程中理清思路
工具
- Overleaf:LaTeX多人协同编辑平台,不会LaTex也不怕,丢给AI让TA帮你生成
- diagrams:论文绘图,可导出为矢量图
- AI工具:DeepL翻译,ChatGPT polish,我更习惯直接写小学生英文然后直接丢给GPT polish
Rebuttal
TBA.
Future Work
非曰能之,愿学焉
我个人未来的计划写在这里,与大家共勉:
- 代码能力提升:
目前我的代码能力还比较弱。我负责的是baseline的代码,而我们模型的实现是由学长完成的。我计划在完全理解我们method的基础上,尝试仅根据论文内容独立实现我们的模型代码,然后与学长的代码进行比对和学习 - 经验学习:
君子生非异也,善假于物也
在这次科研经历之前,我对别人的经验贴要么看不懂,看不进去,要么看了也没感触,转眼就忘。这次经历是一个很好的开端,让我能够基于自己的背景去学习和吸收他人的经验 - 构建road map,找寻方向:
基于这段科研经历,我调整了未来的规划,决定读PhD,大概率是ML领域。我计划多读一些各个方向的论文,逐步建立对ML领域的整体轮廓和road map,慢慢思考并找到自己的研究方向 - 构思idea能力:
我个人更倾向于采用Goal-driven research的方式来思考问题,同时辅以Idea-driven research的形式,要培养自己在实验中闭环中完善idea的能力(名词解释详见*参考资料|Slide of Learning Research )
分享一个很好的repo Leanring Research,我要多多学习呀~