科研论文复现,Python多线程实现方式及并发与同步

1.5 保持学习动力


如果你从来没有复现过一篇论文的算法,或者你对该论文的领域非常陌生,那么论文的阅读就会非常困难。无论发生什么,不要让大量的复杂的数学方程使你气馁。此外,欲速则不达,尽管你的理解速度比你想象的要慢,只要你继续努力,你就会慢慢地、稳步地理解论文所提出的概念,并一个接一个地克服所有困难。

2 三种论文分类

========

随机选择一篇论文,然后立刻开始代码复现并不是一个好主意。从知识库里可以找到大量的论文,这也意味着其中不乏有许多垃圾论文,就我而言,我认为论文可以分为三类:

2.1 开创性论文


一写论文非常有趣,也写的很出色,代表了作者的原创研究。大部分这类论文来自顶尖大学,或者出自那些那些已经在该领域做了大约6到10年的不知名大学的研究团队。这样的研究团队很容易识别出来:他们通常在论文中引用自己的文献资料,表明他们已经在这个问题上研究有一段时间了,并且他们的新工作是建立在之前有可靠记录的文献资料上。此外,一些开创性的论文也通常发表在该领域最好的期刊上。

2.2 抄袭论文


一些研究团队一直关注开创性团队的工作,并对其成果提出改进意见然后发表他们的改进结果。这些论文中,许多论文缺乏适当的统计分析,并常常会得到错误的结论,认为这些改进确实优于原来的算法。大多数时候,除了带来了额外的复杂工作以外,他们实际上没有提出任何创新或更好的东西。但并不是所有的模仿者都是不好的,有些也能给出新的见解,但是很少。

2.3 垃圾论文


有些研究员并不知道他们在做什么,或者他们本身目的就是邪恶的。他们只是试图在自己所属的学术机构或者他们任教的领域保持地位和特权。为此他们需要通过发表一些论文来获得必要的资金资助,他们中有些诚实的人会告诉你实验失败了,并且在只有N%的时间内是准确的(N是一个糟糕的值)。但是也不乏其中邪恶的人会撒谎说取得了巨大的成功。当你读了一段时间的文献资料后,你就很容易区分出垃圾论文,并扔掉他们了。

3 如何阅读科学论文

==========

关于这个主题已经有很多文章了,所以我只是简单提一提。一个好的学习起点是: Srinivasan Keshav的论文如何阅读一篇论文。下面是我在阅读文献时发现的一些有用的观点:

3.1 找到正确的论文


你想要代码复现的应该是是开创了一个全新的领域原创论文,但有有时候,如果你觉得抄袭论文也带来了真正的改进并也算的上一篇不成熟的但却具有创新性的论文,那么选择一篇抄袭的论文也是可以的。

假设你现在找到了一篇论文作为起点。首先,你需要围绕它做一些背景研究,方法是查阅相关文献,以及在这些论文末尾的“参考文献”部分列出的文献资料,去谷歌学术搜索标题和作者。是否在你找到的论文中有比你原来的论文做得更好论文?如果答案是肯定的,那就把你正在看的论文搁在一旁,以你新找到的那篇为新起点。谷歌学术的另一个很酷的特性是,你可以找到引用给定论文的论文。这真的很棒,因为你所要做的就是沿着从一篇论文到下一篇论文的引用链发现该领域最新的论文。从一个起点找到一篇好的论文简单来说就是寻找被当前论文引用的论文,以及引用当前论文的论文。沿着引用链并随着时间的推移,你应该会找到既高质量又符合你需要的论文。

重要提示:注意这个简单探索和计算的阶段,你不必阅读和完全理解这些论文。寻找正确的论文应该通过略读论文并且利用你的直觉来发现垃圾论文(基于你的阅读论文经验而言)。

3.2 不要在屏幕上阅读


打印文献资料并阅读纸质版本。另外,不要为了在每页上打印更多的内容而降低字体大小。虽然这样做你可以节省三张纸,但是你会浪费时间,因为你会因为更快地阅读这些小字体而感到疲倦。适合阅读的字体大小在11到13字号之间。

3.3 良好的时间和地点


不要在半夜看论文,要在白天你的大脑还清醒的时候看。此外,找一个安静的地方,使用良好的照明。当我阅读时,我会在桌面上放置台灯,并且光线对准我的文件。

3.4 标记和注释


用记号笔标出重要信息,并在空白处写下你阅读时脑海中闪现的任何想法。

3.5 了解所有术语的定义


当你习惯主要阅读新的文章和小说时,你的大脑会训练你用上下文作为推理工具,为你不认识的单词填入意义。阅读科文献却是一种不同的方法,最大的错误之一就是推测出一个单词的错误意思。例如这句话:“The results of this segmentation approach still suffer from blurring artifacts”。在这里,“segmentation”和“artifacts”这两个词在英语中具有一般意义,但在计算机视觉领域中又具有特殊意义。如果你不知道这些词在这篇文章中有一个特定的意思,那么当你不刻意注意这些术语时,你的大脑就会填入一般的解释,为此,你可能会错过一些非常重要的信息。因此你必须:

  • 避免推测单词的意思,每当有疑问查找这些术语的专业解释,通常是通过该领域的主要论文文献;
  • 在一张纸上写下所有你不认识的相关文献资料概念和词汇的术语表。如果你第一次遇到诸如“fiducial points”和“piece-wise affine transform”之类的概念,那么你应该查找它们的精确定义并将其记录在术语表中。概念是语言支持的大脑捷径,可以让你更快地理解作者的意图。

3.6 在结论中寻找统计分析


如果作者只给出了他们算法结果的一条曲线和另一条曲线,并说“看,它比另一条精确20%”,那么你就知道你读的是垃圾论文。你想读的论文结果是:“通过N个实例的测试,我们的算法表现出了显著的改进,使用两个样本T检验,p值为5%。统计分析的使用表明,在论文复现时与作者的结果差异最小,这很好地证明了,这些结果在推广时是可信的(除非作者为了让自己的结果看起来更真实而说谎,然而这种情况也经常发生)。

3.7 确保论文结果满足你的需求


假设你想要可以在一张图片中找到任何一张脸的算法,论文的作者说他们的模型是通过训练使用80不同的人的10套姿势(10 x 80 = 800张照片)得到的,并且训练出的模型用于面部检测的准确性为98%,但是用于测试时准确的只有70%(用于测试的图片不是从训练图片中选出来的)。这意味着,该算法还需要解决一些问题才能得到适当地推广。它在训练时的表现很好(但这是无用的),在实际情况下使用表现却很差。因此,你应该得出的结论是,这篇论文可能不够好,不能满足你的需求。

3.8 注意作者使用的输入数据


如果你想使用网络摄像头进行人脸检测,而作者使用的是高清相机拍摄的照片,那么算法在你的情况下可能不会像在作者的情况下那样出色。确保算法在类似于你的情况下进行了测试,否则你得到一个并不适合你的情况的论文复现。

3.9 作者也是人


作者也是人,因此他们会犯错误。不要假设作者是绝对正确的,如果一个方程真的很难理解,你应该问问自己,作者是否犯了错误。这可能只是论文中的一个错字,或者是数学公式上的一个错误。无论哪种情况,找出答案的最好方法是自己推出方程,并尝试验证它们的结果。

3.10 理解变量和操作符


论文复现过程中的主要任务是将文章中的数学方程转化为代码和数据,这意味着在开始编写代码之前,你必须100%理解这些方程和推导这些方程的过程。例如,“C = A . B可能有不同的意思,A和B可以是简单的数字,还有".“操作可能只是一个数量积,在这种情况下,C是两个数字A和B的数乘积。但是也许A和B是矩阵,而“.”操作表示矩阵点乘,在这种情况下,C就是矩阵A和B点乘结果。另一种可能性是,A和B是矩阵,“.”是逐项积算子,在这种情况下,每个元素C(i,j)都是A(i,j)和B(i,j)的乘积。变量和运算符的符号可以从一种数学规定更变为另一种数学规定,也可以从一个研究小组规定更改为另一个研究小组的规定。确保你知道每个变量是什么(标量、向量、矩阵或其他东西),以及每个操作符对这些变量所做的操作。

3.11 了解数据流程


一篇论文由一连串的方程式构成。在开始编码之前,你必须知道如何将方程N的输出插入方程N+1的输入。

4 原型

====

一旦你阅读并理解了这篇论文,接下来就该创建一个原型了,这是非常重要的一步,避免了浪费时间和资源。用C、C++或Java等语言实现复杂算法可能非常耗时,即使你对这篇论文复现有一定的信心并且认为这个算法会成功,它仍然有可能完全失败。所以你想要以偷懒的方式,尽可能快地编码,只是为了检查它是否正常工作。

4.1 原型解决方案


最好的解决方案是使用更高级语言或环境,如Matlab、R、Octave或SciPy/NumPy。用C++表示一个数学方程,然后打印结果来手动检查并不容易。相反,在Matlab中编写方程,然后打印出来却是非常简单的。在C++中需要两到三周的东西在Matlab中可能只需要两天。

4.2 原型有助于调试过程


拥有原型的一个优点是,将来编写C++版本时,你将能够比较Matlab原型和C++实现的结果。这将在下面的“调试”小节中进一步开发。

4.3 从原型中获得改进


你肯定会在原型中犯程序设计错误,这是一件好事,因为你将能够确定流程或数据处理的困难所在。当你编写C++版本的代码时,你将知道如何更好地构建代码,并且你将生成比没有原型化步骤时更简洁、更稳定的代码(这是Frederick Brooks在《The Mythical Man-Month》中提出的“抛弃系统”思想)。

4.4 验证论文给出的结果


仔细阅读论文的“实验”部分,尽可能使用与作者相似的测试数据,以达到接近重现的实验条件,这增加了你再现作者所获得结果的可能性。不使用相似的实验条件可能会导致你误判自己的复现代码可能出现问题,而不是判断为错误的数据而导致的失败。只要你能够基于相似的数据再现实验结果,那么你就可以开始在不同类型的数据上进行测试。

5 选择正确的语言和库

===========

在这个阶段,你必须清楚地理解文献中提出的算法和概念,并且必须有一个运行的原型,以确保算法确实在你输入想要的数据是能够得到正确的结果。现在是进入下一个步骤的时候了,该步骤包括使用你希望在复现中使用的语言和框架。

5.1 现有系统


很多时候,编程语言和库是由现有系统决定的。例如,在用Java编码的库中,你有一组用于图片光照规范化的算法,并且你想要从该文献中添加一个新的算法。在这种情况下,很明显,你不会用C++编写这个新算法,而是用Java编写。

5.2 预测复现代码的未来用途


如果没有现存系统强制你使用一种语言,那么应该根据算法的未来用途来选择该语言。举个例子,如果你相信在四到六个月,可能你的应用程序可以移植到iPhone,那么你应该选择C / C++ / Java,因为它是不需要一切从头开始将代码整合到一个Objective - C应用程序的简便方法。

5.3 完全或部分解决算法的可用库


可用库的差异还可以决定再现代码的编程语言。假设你希望实现的算法使用了注明的代数技术比如如主成分分析(PCA)和奇异值分解(SVD),虽然你也可以重写他们的代码,并花上一周时间调试,但是我建议你用一个已经实现了这些技术的库,并使用这个库的约定和矩阵类编写实现代码。理想情况下,你应该能够将复现代码分解为子任务,并尝试尽可能找到已经实现了这些子任务的库。如果你找到一组只适用于给定语言的合适的库,那么你应该选择该语言。另外,请注意库的选择应该在引用现有代码和最小化依赖关系之间进行权衡,尽管为实现所需的每个子任务的编程代码很好,但是如果这需要创建超过20个不同库的依赖关系,那么它可能不太实用,甚至可能危及实现的复现算法的稳定性。

6 算法复现

======

以下是我在复现论文算法的一些经验。

6.1 正确得选择精度


应该仔细选择你将用于计算的类型。通常使用double而不是float会更好,虽然内存的使用会增大,但计算的精度也会提高。此外,你应该了解32位和64位系统之间的差异,只要可以,就创建自己的类型来封装底层类型(float或double、32位或64位),并在代码中使用这种类型。这可以通过定义为C/ C++或Java中的类来实现。

6.2 归档编程过程


尽管过度文档化确会显著地降低项目的速度,但是对于复杂科学论文的实现,你需要对所有内容进行存档和解释,即使你是这个项目的唯一工作人员,你也应该记录你的文件、类和方法。选择一个像Doxygen或reStructuredText这样的管理,并坚持下去。在开发的后期,你可能会忘记某个类是如何工作的,或者你是如何实现某个算法,你会感谢自己为代码编写了文档!

6.3 在代码中添加对论文的引用


对于你实现的论文中的每个方程式,你都需要添加论文引用(作者和年份)的注释,以及段落号或方程编号。这样,当以后重新阅读代码时,你将能够直接将代码连接到论文中的精确位置。这些引用注释应该如下:

6.4 避免使用数学符号命名变量


假设算法中的某个量是一个矩阵,记作A。接下来,算法要求矩阵在二维上的梯度,记作dA = (dA/dx, dA/dy),那么变量就不该命名为“dA_dx”和“dA_dy”,而应该是“gradient_x”和“gradient_y”。类似地,如果一个方程系统需要收敛判定,那么变量不应该命名为“prev_dA_dx”和“dA_dx”,而应该是“error_previous”和“error_current”。根据它们所表示的物理量来命名,而不是根据论文作者使用的任何字母符号(例如“gradient_x”而不是“dA_dx”),并且从左到右表示更具体的内容(例如“gradient_x”而不是“x_gradient”)。

6.5 第一遍不做优化


把所有的优化留到以后。因为你永远无法绝对确定代码的哪一部分需要优化。每当你看到一个可能的优化,添加一条注释,并用几行代码解释如何实现优化,例如:

这样,以后就可以找到代码中所有可能进行优化的位置,并获得关于如何优化技巧。一旦复现完成,你就可以通过运行诸如Valgrind之类的分析器或你使用的编程语言中的任何可用工具来找到优化的位置。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img



既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Python开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注Python)
img

如果你也是看准了Python,想自学Python,在这里为大家准备了丰厚的免费学习大礼包,带大家一起学习,给大家剖析Python兼职、就业行情前景的这些事儿。

一、Python所有方向的学习路线

Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

二、学习软件

工欲善其必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

三、全套PDF电子书

书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。

四、入门学习视频

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

四、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

五、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

成为一个Python程序员专家或许需要花费数年时间,但是打下坚实的基础只要几周就可以,如果你按照我提供的学习路线以及资料有意识地去实践,你就有很大可能成功!
最后祝你好运!!!

将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

五、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

成为一个Python程序员专家或许需要花费数年时间,但是打下坚实的基础只要几周就可以,如果你按照我提供的学习路线以及资料有意识地去实践,你就有很大可能成功!
最后祝你好运!!!

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值