大佬說 | 寫給程序員的TensorFlow教程-準備篇
- 2019 年 10 月 7 日
- 筆記

太多的TensorFlow入門教程上來就是列了一系列國外的文獻,視頻。或者直接扔一堆代碼,實在難以稱之為入門。我們希望針對想學習TensorFlow的程序員來寫一系列教程,聊一聊如何在基本掌握python的情況下,能夠快速的使用TensorFlow這個工具解決實際問題。
首先,這個系列文章是之前的系列-《反爬與反反爬的奇技淫巧》的番外篇,感興趣的可以在網上搜索反爬與反反爬的奇技淫巧》
之所以是反爬系列的番外篇,因為我們主要是討論如果使用TensorFlow解決爬蟲中常見的問題,包括驗證碼,圖片電話號碼識別這類問題(這個系列主要是圖像識別)。不過雖然跟反爬相關,但是這個系列依然可以獨立來看,不做爬蟲的朋友也不會受影響。
作為系列文章第一篇,先說說這個系列的定位,我們希望能給廣大想轉型機器學習(準確說是Tensorflow實現的神經網絡)的程序員帶來一些不一樣的內容,我們不講公式,只調方法,不聊文獻,只說代碼。不求最好,只求有用。正如下面這個自帶bgm的表情:

那麼我認為對於想要轉型的程序員來說,做到以下四點就算基本轉型成功了:
1.了解一定的機器學習原理(類似寫web,我們要知道http的包結構,知道tcp的三次握手即可)
2.大方向上知道遇到什麼問題該用什麼機器學習算法來解決(成熟的大類就幾個,很容易掌握)
3.熟悉主流算法的實現方案和用法,最好自己有一套對主流方案的封裝(做到這一點其實已經很好了)
4.掌握整個從測試環境到生產環境的完整流程(通俗點就是會做能上線的產品,這一點很重要卻最容易被忽略)
好了,扯了這麼多題外話,我們正式開始:
一、準備部分
在我們動手寫代碼之前還是要有一些準備工作:
首先我們要對整個問題和解決方案有一個宏觀的認知,另外為了方便,本文所有的提到機器學習的地方都可以等價為神經網絡實現的監督學習這個領域,關於其他機器學習的領域不在本系列的討論範圍以內。(如果沒入門的朋友可以忽略這句話)
1.知識的準備
先說說問題,我們今天要從一個最簡單的驗證碼識別問題入手,我們看下我們的敵人:

就是這貨,看着不複雜,沒有太多雜點雜線。不過我們說他最簡單,絕對不是說的這些,而是這個驗證碼我們是有生成代碼的(Discuz是開源的)。這就意味着我們有無窮多的標註好的驗證碼圖片(就是自帶識別結果的圖片)。這個對於機器學習來說簡直就是無敵了。
聊完問題,我們再整體聊一聊Tensorflow和機器學習的解題思路。我們上學的時候,無論遇到什麼問題總有一個解題思路,否則絕對是一頭霧水。所謂隔行如隔山,很多時候是因為我們不了解那個行業解決一個常規問題的解題思路,那麼機器學習的解題思路是什麼呢?
當我們拿到一個問題決定用機器學習的方法解決他,我們要做以下幾步:
第一步:將問題分解成輸入(x)到輸出(y)這樣的結構,如Discuz驗證碼的輸入是圖片,輸出是四個字符的字符串
第二步:找到很多同時包含輸入輸出的數據,比如很多有識別結果的驗證碼圖片
第三步:針對不同問題,找到算法大神們的已經定義好的算法並實現成代碼
第四步:嘗試使用這個算法訓練這些數據,如果效果不好,算法中有一些參數可以手動調整,至於怎麼調,可以參考前人經驗,也可以自己瞎調積累經驗。
第五步:寫一個程序載入模型,接受一個新的輸入值,通過模型計算出新的輸出值。
以上應該還算通俗易懂,唯一值得提一下的就是第四步中的效果不好,效果不好主要是指訓練了大半天,準確度還是很低或者忽高忽低(所謂不收斂或者收斂的速度很慢),當然還有些其他效果不好,不過對於入門級來說,其他的效果不好我們甚至可以認為是成功了。
好,咱們了解這麼多,就可以開始寫代碼了。
2.環境搭建:
俗話說萬事開頭難,對於程序員來說,就是搭建環境了。相對於其他環境來說 Tensorflow環境搭建起來應該說中度難度。順利的話,按照官方教程一步步走完就好。不順利就比較糟心了。這裡我們蟄伏了兩個月就是為了給大家提供一個免安裝的實驗環境,大家登陸神箭手,直接創建Tensorflow應用就可以在線寫Tensorflow了,非常方便。我們後面的教程都是基於線上的,不過線上環境和線下環境完全兼容,所以在哪寫都可以。
3.數據準備
前面說了解題思路,第一步,已經把驗證碼識別問題分解成輸入x和輸出y,那麼我們就要進行第二步準備數據了。這步應該也是這一篇文章中唯一涉及代碼的部分。我們首先下載Discuz源碼,找到其中實現生成驗證碼的文件sourcemodulemiscmisc_seccode.php,我們將核心代碼抽取出來,並實現一個我們可以指定字符的邏輯,具體代碼我已經上傳到github上:
https://github.com/ShenJianShou/tensorflow_tutorial
另外我也自己上傳了一份,大家可以通過訪問如下地址獲取生成的驗證碼圖片:
http://www.shujuheiban.com/tutorial/lession-1/captcha-generator.php?label=BCEF
大家可以替換label後面的字符生成自己想要的驗證碼圖片。
雖然我們已經實現了在線生成無窮多的帶結果的驗證碼圖片,但是一般來說,我們還是盡量減少在TensorFlow中對網絡的請求,這樣會降低整個訓練的速度。另外對我們最終上線的時候也會造成不必要的麻煩,所以我們一般都會把圖片和識別結果整理好,這裡我採用神箭手上的爬蟲請求並存儲15萬的數據備用(其實想要多少就多少,15萬我覺得足足夠了)

代碼也在github上:
https://github.com/ShenJianShou/tensorflow_tutorial
這兩份代碼我就不展開講了,因為這不是我們的重點,如果大家不是在我們神箭手上寫TensorFlow的話,第二份爬蟲的代碼完全可以自己本地實現,也可以用神箭手爬取好了之後導出到本地CSV,具體的大家可以自行根據自己的技術棧來完成這些準備工作。
這裡特殊提一下一個小問題,下一篇文章我們也會在講到,就是為什麼我們要在爬蟲里把base64中的一些字符進行替換:
page.raw = page.raw.replace(/+/g,"-").replace(///g,"_").replace(/s+/g,"")
4.算法準備
好了,到了最激動人心的算法準備部分了。這裡先扔出一個觀點(來自fast.ai的創始人):圖像識別基本已經算是一個已解決的問題。也就是說我們以後凡是遇到圖像中的物體識別,都可以考慮用機器學習來搞定,而搞定的方案也非常成熟,就是如日中天的CNN,當然具體也有很多種實現方式和架構,這裡我們不深入討論,既然是入門,我們只需要實現一個最基本的CNN即可,更何況我們的數據集可以是無限大,還能奢求什麼呢。
你們以為我要講CNN了嗎,那這還是入門教程的第一課嗎。其實什麼是NN,什麼是CNN我個人認為剛開始也不用太理解,大家只要知道這就是解決驗證碼識別目前的最佳方案就可以了,具體怎麼實現,我們可以先抄代碼,然後封裝成一個函數,以後每次使用不就可以了(當然了,有人說keras都已經做好了,幹嘛還要在用tensorflow費勁巴拉的實現一遍。這個嘛,咱們雖然現在是入門,但是也不能一直都停留在入門級別,所謂抄碼百遍,其義自見,先混個眼熟)
好了通過以上的準備,我們的解題思路中的第一、二步都搞定了,第三步選中的算法是最基本的CNN,不過還沒有實現,第四、五步還沒有做,那麼我們下一篇文章就詳細討論下最基本的CNN如何使用TensorFlow實現以及過程中一些常見的問題。