源碼閱讀經驗談-slim,darknet,labelimg,caffe
本文首先談自己的源碼閱讀體驗,然後給幾個案例解讀,選的例子都是比較簡單。重在說明我琢磨的點線面源碼閱讀方法。我不是專業架構師,是從一個深度學習演算法工程師的角度來談的,不專業的地方請大家輕拍。
經常看別人寫的代碼,然後改別人的代碼,然後實現自己的想法,我想這是我們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。
推薦閱讀: