1.前言
本項(xiàng)目適用于Python3.6,GPU>=NVIDIA GTX1050Ti,原master分支已經(jīng)正式切換為CNN+LSTM+CTC的版本了,是時(shí)候?qū)懸黄碌奈恼铝恕?/p>
長話短說,開門見山,網(wǎng)絡(luò)上現(xiàn)有的代碼以教學(xué)研究為主,本項(xiàng)目是為實(shí)用主義者定制的,只要基本的環(huán)境安裝常識(shí),便可很好的訓(xùn)練出期望的模型,重定義幾個(gè)簡單的參數(shù)任何人都能使用機(jī)器學(xué)習(xí)技術(shù)訓(xùn)練一個(gè)商業(yè)化成品。
如果對(duì)于DLL調(diào)用感興趣或是其他語言的TensorFlow API感興趣的移步以下兩個(gè)項(xiàng)目:
https://github.com/kerlomz/captcha_library_c
https://github.com/kerlomz/captcha_demo_csharp
筆者選用的時(shí)下最為流行的CNN+BLSTM+CTC進(jìn)行端到端的不定長驗(yàn)證碼識(shí)別,代碼中預(yù)留了DenseNet+BLSTM+CTC的選項(xiàng),可以在配置中直接選用。首先,介紹個(gè)大概吧。
H16/H64指的是Bi-LSTM的隱藏神經(jīng)元個(gè)數(shù)num_units,這里注意,你沒有看錯(cuò),也沒有寫反,LSTM有時(shí)序依賴,tf.contrib.rnn.LSTMCell的實(shí)現(xiàn)沒能很充分的利用GPU的計(jì)算資源,底層kernel函數(shù)之間的間隙非常大,不利于充分的利用 GPU 的并行性來進(jìn)行計(jì)算。所以本項(xiàng)目使用GPU訓(xùn)練,使用CPU進(jìn)行預(yù)測。預(yù)測服務(wù)部署項(xiàng)目源碼請移步此處:
https://github.com/kerlomz/captcha_platform
2.環(huán)境依賴
關(guān)于CUDA和cuDNN版本的問題,不少人很糾結(jié),這里就列出官方通過pip安裝的TensorFlow的版本對(duì)應(yīng)表:
Windows
如果希望使用上面對(duì)應(yīng)之外的搭配的CUDA和cuDNN,可以自行編譯TensorFlow,或者去Github上搜索TensorFlow Wheel找到第三方編譯的對(duì)應(yīng)版本的whl安裝包。提前預(yù)警,若是自己編譯將會(huì)苦難重重,坑很多,這里就不展開了。
2.1 本項(xiàng)目環(huán)境依賴
目前在以下主流操作系統(tǒng)平臺(tái)均測試通過:
本訓(xùn)練項(xiàng)目主要的環(huán)境依賴清單如下
2.1.1 Ubuntu 16.04 下的 Python 3.6
1)先安裝Python環(huán)境
sudo apt-get install opensslsudo apt-get install libssl-devsudo apt-get install libc6-dev gccsudo apt-get install -y make build-essential zlib1g-dev libbz2-dev libreadline-dev $ libsqlite3-dev wget curl llvm tk-devwget https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tgztar -vxf Python-3.6.6.tar.xzcd Python-3.6.6./configure --prefix=/usr/local --enable-sharedmake -j8sudo make install -j8
經(jīng)過上面指令就安裝好Python3.6環(huán)境了,如果提示找不到libpython3.6m.so.1.0就到/usr/local/lib路徑下將該文件復(fù)制一份到/usr/lib和/usr/lib64路徑下。
2)安裝相關(guān)依賴(這一步Windows和Linux通用)
可以直接在項(xiàng)目路徑下執(zhí)行pip3 install -r requirements.txt安裝所有依賴,注意這一步是安裝在全局Python環(huán)境下的,強(qiáng)烈建議使用虛擬環(huán)境進(jìn)行項(xiàng)目間的環(huán)境隔離,如Virtualenv或Anaconda等等。
我一般使用的是Virtualenv,有修改代碼需要的,建議安裝PyCharm作為Python IDE
virtualenv -p /usr/bin/python3 venv # venv is the name of the virtual environment.cd venv/ # venv is the name of the virtual environment.source bin/activate # to activate the current virtual environment.cd captcha_trainer # captcha_trainer is the project path.pip3 install -r requirements.txt
2.1.2 Ubuntu 16.04 下的 CUDA/cuDNN
網(wǎng)上看到過很多教程,我自己也部署過很多次,Ubuntu 16.04遇到的坑還是比較少的。14.04支持就沒那么好,如果主板不支持關(guān)閉SecureBoot的話千萬不要安裝Desktop版,因?yàn)榘惭b好之后一定會(huì)無限循環(huán)在登陸界面無法進(jìn)入桌面。
網(wǎng)上教程說要加驅(qū)動(dòng)黑名單什么的我直接跳過了,親測沒那個(gè)必要。就簡單的幾步:
1. 下載好安裝包
注意下載runfile類型的安裝包,deb安裝會(huì)自動(dòng)安裝默認(rèn)驅(qū)動(dòng),極有可能導(dǎo)致登陸循環(huán)。
NVIDIA 驅(qū)動(dòng)下載:
https://www.geforce.cn/drivers
CUDA 下載地址:
https://developer.nvidia.com/cuda-downloads
cuDNN 下載地址:
https://developer.nvidia.com/cudnn
(需要注冊NVIDIA賬號(hào)且登陸,下載deb安裝包)
2. 關(guān)閉圖形界面
Ctrl+alt+F1進(jìn)入字符界面,關(guān)閉圖形界面
sudo service lightdm stop
3. 安裝Nvidia Driver
命令中的版本自己對(duì)應(yīng)下載的版本改,在上面的下載地址根據(jù)自己的顯卡型號(hào)下載最新版,切記是runfile格式的安裝包。
sudo chmod a+x NVIDIA-Linux-x86_64-384.90.run //獲取執(zhí)行權(quán)限sudo ./NVIDIA-Linux-x86_64-384.90.run –no-x-check –no-nouveau-check –no-opengl-files //安裝驅(qū)動(dòng)
安裝成功以后使用以下命令驗(yàn)證,如果顯示顯卡信息則表示安裝成功
nvidia-smi
4. 安裝CUDA
先安裝一些系統(tǒng)依賴庫
sudo apt-get install freeglut3-dev build-essential libx11-dev libxmu-dev libxi-dev libgl1-mesa-glx libglu1-mesa libglu1-mesa-dev
執(zhí)行安裝程序,按指示無腦繼續(xù)就好了,如果提示是否安裝驅(qū)動(dòng)選不安裝。
sudo sh cuda_9.0.176_384.81_linux.run
安裝完如果環(huán)境變量沒配上去,就寫到 ~/.bashrc 文件的尾部
export PATH=/usr/local/cuda-9.0/bin${PATH:+:${PATH}}export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
然后在終端執(zhí)行 sudo ldconfig更新,安裝完畢就可以重啟機(jī)器重啟圖形界面了。
sudo service lightdm start
2.1.3 Windows 系統(tǒng)
在Windows其實(shí)簡單很多,只要到官網(wǎng)下載安裝包無腦安裝就可以了,下載連接同Ubuntu,先安裝Python,顯卡驅(qū)動(dòng),CUDA,然后下載對(duì)應(yīng)的cuDNN替換到對(duì)應(yīng)路徑即可。
花了超長篇幅介紹了訓(xùn)練環(huán)境的基本搭建,主要是給尚未入門的讀者看的,老鳥們隨便跳過。
3.使用
入手的第一步環(huán)境搭建好了,那就是準(zhǔn)備跑代碼了,還是有幾個(gè)必要的條件,巧婦難為無米之炊,首先,既然是訓(xùn)練,要先有訓(xùn)練集,有一個(gè)新手嘗鮮的訓(xùn)練集,是mnist手寫識(shí)別的例子,可以在騰訊云下載:https://share.weiyun.com/5pzGF4V,現(xiàn)在萬事俱備,只欠東風(fēng)。
3.1 定義一個(gè)模型
本項(xiàng)目采用的是參數(shù)化配置,不需要改動(dòng)任何代碼,可以訓(xùn)練幾乎任何字符型圖片驗(yàn)證碼,下面從兩個(gè)配置文件說起:
# - requirement.txt - GPU: tensorflow-gpu, CPU: tensorflow# - If you use the GPU version, you need to install some additional applications.# TrainRegex and TestRegex: Default matching apple_20181010121212.jpg file.# - The Default is .*?(?=_.*.)# TrainsPath and TestPath: The local absolute path of your training and testing set.# TestSetNum: This is an optional parameter that is used when you want to extract some of the test set# - from the training set when you are not preparing the test set separately.System: DeviceUsage: 0.7 TrainsPath: 'E:TaskTrainsYourModelName' TrainRegex: '.*?(?=_)' TestPath: 'E:TaskTestGroupYourModelName' TestRegex: '.*?(?=_)' TestSetNum: 1000# CNNNetwork: [CNN5, DenseNet]# RecurrentNetwork: [BLSTM, LSTM]# - The recommended configuration is CNN5+BLSTM / DenseNet+BLSTM# HiddenNum: [64, 128, 256]# - This parameter indicates the number of nodes used to remember and store past states.NeuralNet: CNNNetwork: CNN5 RecurrentNetwork: BLSTM HiddenNum: 64 KeepProb: 0.98# SavedSteps: A Session.run() execution is called a Steps,# - Used to save training progress, Default value is 100.# ValidationSteps: Used to calculate accuracy, Default value is 100.# TestNum: The number of samples for each test batch.# - A test for every saved steps.# EndAcc: Finish the training when the accuracy reaches [EndAcc*100]%.# EndEpochs: Finish the training when the epoch is greater than the defined epoch.Trains: SavedSteps: 100 ValidationSteps: 500 EndAcc: 0.975 EndEpochs: 1 BatchSize: 64 TestBatchSize: 400 LearningRate: 0.01 DecayRate: 0.98 DecaySteps: 10000
上面看起來好多好多參數(shù),其實(shí)大部分可以不用改動(dòng),你需要修改的僅僅是訓(xùn)練集路徑就可以了,注意:如果訓(xùn)練集的命名格式和我提供的新手訓(xùn)練集不一樣,請根據(jù)實(shí)際情況修改TrainRegex和TestRegex的正則表達(dá)式。
TrainsPath和TestPath路徑支持list參數(shù),允許多個(gè)路徑,這種操作適用于需要將多種樣本訓(xùn)練為一個(gè)模型,或者希望訓(xùn)練一套通用模型的人。為了加快訓(xùn)練速度,提高訓(xùn)練集讀取效率,特別提供了make_dataset.py來支持將訓(xùn)練集打包為tfrecords格式輸入,經(jīng)過make_dataset.py打包之后的訓(xùn)練集將輸出到本項(xiàng)目的dataset路徑下,只需修改TrainsPath鍵的配置如下即可。
TrainsPath: './dataset/xxx.tfrecords'
TestPath是允許為空的,如果TestPath為空將會(huì)使用TestSetNum參數(shù)自動(dòng)劃分出對(duì)應(yīng)個(gè)數(shù)的測試集。如果使用自動(dòng)劃分機(jī)制,那么TestSetNum測試集總數(shù)參數(shù)必須大于等于TestBatchSize測試集每次讀取的批次大小。
神經(jīng)網(wǎng)絡(luò)這塊可以講一講,默認(rèn)提供的組合是CNN5(CNN5層模型)+BLSTM(Bidirectional LSTM)+CTC,親測收斂最快,但是訓(xùn)練集過小,實(shí)際圖片變化很大特征很多的情況下容易發(fā)生過擬合。DenseNet可以碰運(yùn)氣在樣本量很小的情況下很好的訓(xùn)練出高精度的模型,為什么是碰運(yùn)氣呢,因?yàn)槭諗靠觳豢祀S機(jī)的初始權(quán)重很重要,運(yùn)氣好前500步可能對(duì)測試集就有40-60%準(zhǔn)確率,運(yùn)氣不好2000步之后還是0,收斂快慢是有一定的運(yùn)氣成分的。
NeuralNet: CNNNetwork: CNN5 RecurrentNetwork: BLSTM HiddenNum: 64 KeepProb: 0.99
隱藏層HiddenNum筆者嘗試過8~64,都能控制在很小的模型大小之內(nèi),如果想使用DenseNet代替CNN5直接修改如上配置中的CNNNetwork參數(shù)替換為:
NeuralNet: CNNNetwork: DenseNet ......
model.yaml # 模型配置
# ModelName: Corresponding to the model file in the model directory,# - such as YourModelName.pb, fill in YourModelName here.# CharSet: Provides a default optional built-in solution:# - [ALPHANUMERIC, ALPHANUMERIC_LOWER, ALPHANUMERIC_UPPER,# -- NUMERIC, ALPHABET_LOWER, ALPHABET_UPPER, ALPHABET]# - Or you can use your own customized character set like: ['a', '1', '2'].# CharExclude: CharExclude should be a list, like: ['a', '1', '2']# - which is convenient for users to freely combine character sets.# - If you don't want to manually define the character set manually,# - you can choose a built-in character set# - and set the characters to be excluded by CharExclude parameter.Model: Sites: [] ModelName: YourModelName-CNN5-H64-150x50 ModelType: 150x50 CharSet: ALPHANUMERIC_LOWER CharExclude: [] CharReplace: {} ImageWidth: 150 ImageHeight: 50# Binaryzation: [-1: Off, >0 and < 255: On].# Smoothing: [-1: Off, >0: On].# Blur: [-1: Off, >0: On].# Resize: [WIDTH, HEIGHT]# - If the image size is too small, the training effect will be poor and you need to zoom in.# - ctc_loss error "No valid path found." happenedPretreatment: Binaryzation: -1 Smoothing: -1 Blur: -1
上述的配置只要關(guān)注ModelName、CharSet、ImageWidth、ImageHeight。
首先給模型取一個(gè)好名字是成功的第一步,字符集CharSet其實(shí)大多數(shù)情況下不需要修改,一般的圖形驗(yàn)證碼離不開數(shù)字和英文,而且一般來說是大小寫不敏感的,不區(qū)分大小寫,因?yàn)榇虼a平臺(tái)收集的訓(xùn)練集質(zhì)量參差不齊,有些大寫有些小寫,不如全部統(tǒng)一為小寫,默認(rèn)ALPHANUMERIC_LOWER則會(huì)自動(dòng)將大寫的轉(zhuǎn)為小寫,字符集可定制化很靈活,除了配置備注上提供的幾種類型,還可以訓(xùn)練中文,自定義字符集用list表示,示例如下:
CharSet: ['常', '世', '寧', '慢', '南', '制', '根', '難']
可以自己根據(jù)收集訓(xùn)練集的實(shí)際字符集使用率來定義,也可以無腦網(wǎng)上找3500常用字來訓(xùn)練,注意:中文字符集一般比數(shù)字英文大很多,剛開始收斂比較慢,需要更久的訓(xùn)練時(shí)間,也需要更多的樣本量,請量力而行。
形如上圖的圖片能輕松訓(xùn)練到95%以上的識(shí)別率。
ImageWidth、ImageHeight只要和當(dāng)前圖片尺寸匹配即可,其實(shí)這里的配置主要是為了方便后面的部署智能策略。
其他的如Pretreatment之下的參數(shù)是用來做圖片預(yù)處理的,因?yàn)楣P者致力于做一套通用模型,模型只使用了灰度做預(yù)處理。其中可選的二值化、均值濾波、高斯模糊均未開啟,即使不進(jìn)行那些預(yù)處理該框架已經(jīng)能夠達(dá)到很理想的識(shí)別效果了,筆者自用的大多數(shù)模型都是98%以上的識(shí)別率。
3.2 開始訓(xùn)練
按照上面的介紹,配置只要修改極少數(shù)的參數(shù)對(duì)應(yīng)的值,就可以開啟正式的訓(xùn)練之旅了,具體操作如下:
可以直接使用PyCharm的Run,執(zhí)行trains.py,也可以在激活Virtualenv下使用終端亦或在安裝依賴的全局環(huán)境下執(zhí)行。
python3 trains.py
剩下的就是等了,看過程,等結(jié)果。正常開始訓(xùn)練的模樣應(yīng)該是這樣的:
訓(xùn)練結(jié)束會(huì)在項(xiàng)目的out路徑下生成一個(gè)pb和yaml文件,下面該到部署環(huán)節(jié)了。
3.3 部署
真的很有必要認(rèn)真的介紹一下部署項(xiàng)目,比起訓(xùn)練,這個(gè)部署項(xiàng)目傾注了筆者更多的心血,為什么呢?
項(xiàng)目地址:
https://github.com/kerlomz/captcha_platform
真的值得了解的幾點(diǎn):
同時(shí)管理多個(gè)模型,支持模型熱拔插
靈活的版本控制
支持批量識(shí)別
服務(wù)智能路由策略
首先筆者重寫了Tensor Flow的Graph會(huì)話管理,設(shè)計(jì)會(huì)話池,允許同時(shí)管理多模型,實(shí)現(xiàn)多模型動(dòng)態(tài)部署方案。
1)訓(xùn)練好的pb模型只要放在部署項(xiàng)目的graph路徑下,yaml模型配置文件放在model,即可被服務(wù)發(fā)現(xiàn)并加載;2)如果需要卸載一個(gè)正在服務(wù)的模型,只需要在model中刪除該模型的yaml配置文件,在graph中刪除對(duì)應(yīng)的pb模型即可;3)如果需要更新一個(gè)已經(jīng)服務(wù)中的模型,只需修改新版的模型yaml配置文件的版本號(hào)高于原模型的版本號(hào),按先放pb后放yaml的順序,服務(wù)便會(huì)自動(dòng)發(fā)現(xiàn)新版的模型并加載使用,舊的模型將因版本低于新版模型不會(huì)被調(diào)用,可以按照上述的卸載方法卸載已被棄用的模型釋放內(nèi)存。
上面的操作中無需重啟服務(wù),完全的無縫切換。
Linux:
Tornado:
# 端口 19952python3 tornado_server.py
Flask
# 方案1,裸啟動(dòng), 端口 19951python flask_server.py# 方案2,使用gunicorn,端口 5000pip install gunicorngunicorn -c deploy.conf.py flask_server:app
Sanic:
# 端口 19953python3 sanic_server.py
gRPC:
# 端口 50054python3 grpc_server.py
Windows:
Windows平臺(tái)下都是通過python3 xxx_server.py啟動(dòng)對(duì)應(yīng)的服務(wù),注意,Tornado、Flask、Sanic的性能在Windows平臺(tái)都大打折扣,gRPC是Google開源的RPC服務(wù),有較為優(yōu)越的性能。
3.4 調(diào)用/測試
1. Flask服務(wù):
具體參數(shù):
請求為JSON格式,形如:{"image": "base64編碼后的圖像二進(jìn)制流"}
返回結(jié)果:
該返回為JSON格式,形如:{"message": "xxxx", "code": 0, "success": true}
2. Tornado服務(wù):
請求參數(shù)和返回格式同上
3. Sanic服務(wù):
請求參數(shù)和返回格式同上
4. gRPC服務(wù):
需要安裝依賴,grpcio、grpcio_tools和對(duì)應(yīng)的grpc.proto文件,可以直接從項(xiàng)目中的示例代碼demo.py中提取。
class GoogleRPC(object): def __init__(self, host: str): self._url = '{}:50054'.format(host) self.true_count = 0 self.total_count = 0 def request(self, image, model_type=None, model_site=None): import grpc import grpc_pb2 import grpc_pb2_grpc channel = grpc.insecure_channel(self._url) stub = grpc_pb2_grpc.PredictStub(channel) response = stub.predict(grpc_pb2.PredictRequest( image=image, split_char=',', model_type=model_type, model_site=model_site )) return {"message": response.result, "code": response.code, "success": response.success}if __name__ == '__main__': result = GoogleRPC().request("base64編碼后的圖片二進(jìn)制流") print(result)
3.5 奇技淫巧
該項(xiàng)目還可以直接用于識(shí)別帶顏色的圖片,本質(zhì)是不同的顏色分別訓(xùn)練,調(diào)用的時(shí)候通過傳參區(qū)分,如果希望獲得圖片中紅色的文字,就直接通過參數(shù)定位到訓(xùn)練紅色的模型,希望獲取圖片中藍(lán)色的圖片就通過參數(shù)定位到藍(lán)色模型,如:
不過這種操作對(duì)樣本量要求較高,且效率不高,當(dāng)顏色參數(shù)越來越多時(shí)就不適用,可以采用顏色提取的方式,這樣所需要的樣本量將大大減少,但對(duì)于顏色提取算法效果要求高了。
還有一種方案是同時(shí)預(yù)測驗(yàn)證碼和每個(gè)字符對(duì)應(yīng)的顏色,不過這需要修改現(xiàn)有的神經(jīng)網(wǎng)絡(luò)進(jìn)行支持,在最后一層修改為雙輸出,一個(gè)輸出顏色,一個(gè)輸出對(duì)應(yīng)字符,這對(duì)于樣本標(biāo)注的要求較高,也提高的成本,所以如果能用無限生成樣本,那問題就迎刃而解了,比如上圖,筆者就寫了樣本生成代碼,感興趣的可以移步:
https://www.jianshu.com/p/da1b972e24f2
其實(shí)還有很多很多技巧,例如,用生成的樣本代替訓(xùn)練集,其實(shí)網(wǎng)上的圖片驗(yàn)證碼大多是采用開源的,稍作修改而已,大多數(shù)情況都能被近似生成出來,上述展示的驗(yàn)證碼圖片不代表任何實(shí)際的網(wǎng)站,如有雷同,純屬巧合,該項(xiàng)目只能用于學(xué)習(xí)和交流用途,不得用于非法用途。
-
代碼
+關(guān)注
關(guān)注
30文章
4808瀏覽量
68812 -
機(jī)器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8428瀏覽量
132835 -
cnn
+關(guān)注
關(guān)注
3文章
353瀏覽量
22265
原文標(biāo)題:實(shí)戰(zhàn):CNN+BLSTM+CTC的驗(yàn)證碼識(shí)別從訓(xùn)練到部署 | 技術(shù)頭條
文章出處:【微信號(hào):rgznai100,微信公眾號(hào):rgznai100】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評(píng)論請先 登錄
相關(guān)推薦
評(píng)論