本文首先谈自己的源码阅读体验,然后给几个案例解读,选的例子都是比较简单。重在说明我琢磨的点线面源码阅读方法。我不是专业架构师,是从一个深度学习算法工程师的角度来谈的,不专业的地方请大家轻拍。
经常看别人写的代码,然后改别人的代码,然后实现自己的想法,我想这是我们coder常干的事情。看人看代码,代码如人。他代码写的有多清爽简洁,说明他思维是清晰的;代码的结构有多合理,模块化内聚如何,是否低耦合,反应他的宏观把控能力。一个软件系统你可以把他看成是一个简单的企业,各个职能部门如何发挥自己的作用,相当于每个软件的模块如何组织理顺,一段繁冗杂乱的代码和一家管理混乱的公司一样,剪不断理还乱,索性推翻重来。
谈一谈我阅读源码的经验吧。希望能成为大家的垫脚石,大家可以在我的基础上飞的更高,走的更稳。
源码阅读我自己琢磨的经验是:点-线-面立体式逐层深入。
点:点有两个层面的意思,首先你要找到突破点,比如说程序的入口main函数,或者说一个比较容易切入的点,很多时候main函数下面写的很简洁,就几行代码走一个主流程,或调用多进程,你很难看清楚里面的逻辑,这时候找切入点就是一个比较技巧的事情了。找到切入点才能由点到线,开始去摸清楚里面的东西。
点的另一个层面的意思是当通过切入点找到主线后,由线串起来的其它一些点,比如说一些功能性函数utils,一些功能性模块的内容。这些东西你干瘪瘪的去看没有太大趣味,你有可能搞不明白它是干什么的,有一根线来串的话,你就可以调试,你会快速搞清楚里面的功能。
线:线有主线和旁线。深度学习我认为是一个面向过程的,因为它其实就是一个方程,一个函数,面向过程的编程思想就是给一个input,在你软件系统里走一遍后,得到一些输出。主线就是连接输入和输出的线。旁线就是主线的一些分支。给定一个输入后,你可以跟着这根线逐步往后走,每步打印出一些关键变量,你就能基本明白每步做了什么事情。
旁线就是一些分支,从主线上分出一个输入,然后调用一个功能性模块,得到一个结果后,又去走主线的流程。这个调用功能性模块就是一个旁线,只有把这些旁线搞明白,你才能建立一个知识树,你才能立体的对一个系统有深入认识。
面:线跟线交错,线把点串起来,组织成一张网,就是一个面了。讲面这层次主要是希望大家有全局意识。系统的设计者设计系统的时候应该首先想到的是面,是一个立体的东西,然后才抽丝剥缕的码代码。哪个文件放到哪个模块,哪个函数放哪个文件中更合适,都要非常清楚,这样有一个整体感,层次鲜明,逻辑清楚。就像网络工程师搭网线一样,有的高手搭建的网线有层次感,顺手一摸就知道那根线是跟哪个交换机连的。
杂乱无章
有逻辑的代码结构。
Labelimg案例:
实话实说,我之前经常用labelimg打标签,但一直没看过源码。由于要在这个基础上开发一个半自动化标签系统,这周我也是从0开始摸索的。搞了三天才把它摸清楚。
Labelimg是用pyqt写的。姑且说是一个面向对象的编程框架吧。他的主函数很简单。主要逻辑全在mainwindow这个类里面了。
这个mainwindow类东西太多了,一时找不到突破点。本来就对这种获取点击信息然后执行一些action的编程范式不是很熟,摸索了好久,才找到了一个突破口,那就是,画完框后,他会弹出一个对话框,就是这个OK或者cancel的框。
之所以选它作为突破口,是因为1、下面那个列表数据是从txt文件中读取返显出来的,根据这条线,就能摸清楚怎么样把自己想要的数据返显到对话框中;2他是在图片上画框后自动弹出对话框,这有助于你摸清楚他是怎么获取鼠标点击交互的,获取点击交互后怎么打开对话框的。你把这个搞明白了就抓到主线了。
通过摸索,发现这个对话框写在libs下面,代码如下:
然后就是去找一些点了:1、在主mainwindow中是怎么调用这个类的;2、txt中存的数据是怎么读取然后给到labeldialog的。3、这些Qwidget、QlistWidget都是干啥的。大家是不是觉得特别简单?别笑话我为了琢磨这些玩意琢磨了三天哈。哥是比你笨,但哥比你action。
这个系列起了个头,可能大家觉得这些都是工程的事情,算法工程师干这些玩意浪费时间。事实上,鼻祖hinton曾经告诫我们说:要少看论文,不要停止编程。强大的工程能力才是算法的基石,而如何收集数据(包括打标签)和如何定义问题及建模是算法落地的基石。有没有同感的请扣1。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:源码阅读经验谈-slim,darknet,labelimg,caffe(1) - Python技术站