回復「書籍」即可獲贈Python從入門到進階共10本電子書
大家好,我是Snowball。一、前言今天給大家分享的實戰項目是常用驗證碼標註&識別,前面三篇文章講解了文章的創作靈感、需求分析和實現思路、數據採集/預處理/字符圖切割等知識、高效率數據標註等知識,分別是以下文章:
Python項目實戰篇——常用驗證碼標註和識別(需求分析和實現思路)
Python項目實戰篇——常用驗證碼標註&識別(數據採集/預處理/字符圖切割)
Python項目實戰篇——常用驗證碼標註&識別(前端+後端實現高效率數據標註)
這篇文章引入機器學習,給大家講解下基於該項目的CNN神經網絡模型訓練/測試/部署。
二、背景知識按照學習的好習慣,先搜索網上資源,再腦洞一下,先思考啥是神經網絡,啥是卷積,CNN神經網絡為啥能提取圖片特徵,這些問題筆者剛開始全部都遇到過,一臉蒙蔽有沒有。不要急,有問題有時候是好事,說明你知道自己那些不知道,等到自己了解和懂得多了,有些問題就迎刃而解。
筆者剛開始在上面的OpenCV知識學習過程中,就嘗試用過傳統的SIFT算法進行提取圖片特徵可以進行圖片相似度匹配,但是效果都比較差,這裡面用的是多維向量特徵描述。而神經網絡在機器學習的領域為啥這麼牛皮,這裡面是有數學方面的理論支撐,也有現在計算力和數據量的支持,而卷積神經網絡專門用來處理圖片特徵提取。
剛開始,筆者對這方面的理論知識了解甚少,於是充分利用搜索工具和網上資源,這裡分享一下自己學習過程中的文章連結和視頻連結,可以保證讀者看完基本可以加深對神經網絡訓練的實戰了解,可上手進行項目功能調整。好的,讓我們開始學習(卷)起來,以下就是所有內容的連結,沒有基礎的朋友可以補一補,有基礎的可以直接跳過:
**數學基礎**[微積分](https://www.bilibili.com/video/BV1Eb411u7Fw)
[線性代數](https://www.bilibili.com/video/BV1aW411Q7x1)
[概率論](https://www.bilibili.com/video/BV1ot411y7mU)
[計算機數學基礎](https://www.bilibili.com/video/BV1AB4y1K7kM)
**OpenCV**[OpenCV文章專欄](https://blog.csdn.net/yukinoai/category_9283880.html)
[OpenCV-Python視頻](https://www.bilibili.com/video/BV1tb4y1C7j7)
**神經網絡**[理解卷積意義](https://www.bilibili.com/video/BV1VV411478E)
[前饋神經網絡](https://www.bilibili.com/video/BV1Tt411s7fK)
[神經網絡學習理解](https://space.bilibili.com/504715181?spm_id_from=333.788.b_765f7570696e666f.1)
**Python框架使用**[Numpy中文教程](https://www.runoob.com/numpy/numpy-tutorial.html)
[PyTorch中文教程](https://pytorch.panchuang.net/SecondSection/neural_networks/)
[PyTorch視頻](https://www.bilibili.com/video/BV1t64y1t7V8)以上就是筆者這次項目開發幾個月來搜索的優質學習文章和視頻資源了,有基礎的朋友可以選擇性相關知識學習,沒有基礎而時間充裕的可以惡補基礎再動手實戰,所謂磨刀不誤砍柴工。想快速動手的小夥伴可以快速學習,把對應項目需要的知識點看明白即可。筆者建議的學習方式是確定自己的任務主線,然後邊學邊練邊思考,在項目實戰中學習總結是成長最快的方式。
好的,在上面前置知識學習了解的差不多後,相信大家都已經知道CNN神經網絡的理論知識了,接下來我們動手進行CNN模型的實戰訓練過程。
在開始,確定模型訓練基本過程
準備訓練數據集、測試數據集、預測數據集
CNN模型編碼
模型訓練、測試
模型預測、部署
三、CNN神經網絡模型訓練
1.準備數據
通過實現思路第1-2步,可以得到相關圖片驗證碼字符數據,筆者這裡準備訓練集500多張(這裡得感謝我妹子花時間幫我在標註系統上手動標註的初始數據集~~),測試集30多張,預測5張。讀者在python項目拉取下來後,對應的文件夾下面已有全部數據,對應路徑如下:
src_img:訓練數據集
test_src_img:測試數據集
usage_src_img:預測數據集
在準備好圖片驗證碼數據後,本次案例需要先進行字符切割預處理(其他常用驗證碼需要讀者自己調整),對應文件image_split,以下是main方法代碼。
if __name__ == '__main__': split_image_dir(SRC_IMG_DIR) split_test_image()執行字符切割後,對應的訓練集字母分類在letter_template目錄下,測試集字母分類在letter_test目錄下。
數據集類:net_data.py,下面是主要代碼。
labels = []for i in range(8): labels.append(50 + i)for i in range(26): labels.append(65 + i)
class VerCodeDataset(Dataset): def __init__(self, image_dir="./letter_template/"): l = os.listdir(image_dir) self.data = [] self.label = [] for d in l: fs = os.listdir("{}{}".format(image_dir, d)) for f in fs: fup = "{}{}/{}".format(image_dir, d, f) t = torch.from_numpy(io.imread(fup)).float() / 255 norl = transforms.Normalize(t.mean(), t.std()) self.data.append(norl(t.reshape(1, 40, 40))) self.label.append(labels.index(ord(d)))數據集值製作描述可參考該文章連結:
[數據集製作參考文章](https://zhuanlan.zhihu.com/p/358671390)
2.CNN模型編碼
本文驗證碼的識別與MNIST的識別相當類似,模型這塊採用簡單的前饋神經網絡,它接收輸入,讓輸入一個接著一個的通過一些層,最後給出輸出。下面是minst網絡結構圖:
[PyTorch 神經網絡 - PyTorch官方教程中文版](https://link.zhihu.com/?target=http%3A//pytorch.panchuang.net/SecondSection/neural_networks/)一個典型的神經網絡訓練過程包括以下幾點:
1.定義一個包含可訓練參數的神經網絡
2.迭代整個輸入
3.通過神經網絡處理輸入
4.計算損失(loss)
5.反向傳播梯度到神經網絡的參數
6.更新網絡的參數,典型的用一個簡單的更新方法:weight = weight - learning_rate *gradient
定義神經網絡(net_train.py):
class Net(nn.Module): def __init__(self, dropout=0.1): super(Net, self).__init__() self.dropout = nn.Dropout(dropout) self.conv1 = nn.Conv2d(1, 10, 5) self.conv2 = nn.Conv2d(10, 25, 5) self.fc1 = nn.Linear(1 * 25 * 7 * 7, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 34)
def forward(self, x): x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) x = self.dropout(x) x = F.max_pool2d(F.relu(self.conv2(x)), (2, 2)) x = self.dropout(x) x = x.view(-1, self.num_flat_features(x)) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x
def num_flat_features(self, x): size = x.size()[1:] num_features = 1 for s in size: num_features *= s return num_features下方代碼中:
self.fc1 = nn.Linear(1 * 25 * 7 * 7, 120)全連接層第一個參數的大小:
[40,40]經過[5,5]卷積核->[35,35]
[35,35]經過[2,2]池化->[18,18]
[18,18]經過[5,5]卷積核->[13,13]
[13,13]經過[2,2]池化->[7,7]
上層卷積層一共25個卷積核,因此這裡的大小為1(通道數)*25*7*7= 1225,至於後面全連接的84可以隨便改,和下層全連接層保持一致即可。
以上就是模型定義的代碼了,讀者有興趣的也可以自行用其他模型訓練。
四、CNN神經網絡模型測試
net_train.py文件提供的訓練代碼支持GPU訓練,在沒有NVDIA顯卡和安裝pytorch對應版本的CUDA庫,默認是使用CPU訓練,筆者對二種訓練方式都進行了嘗試,下面是訓練對比情況:
數據量:2286張 40*40 單通道字符圖片batch_size: 50epoch: 200
設備 時間GTX 1070TI 25sAMD R7 4750U PRO 4min總結,數據量大,有條件上GTX顯卡就用顯卡訓練,訓練效率高出CPU數量級
[cuda安裝文章連結](https://www.cnblogs.com/yang520ming/p/10677110.html)這裡是cuda安裝注意事項:
1.更新nvida顯卡驅動程序,然後看cuda版本2.找pytorch對應cuda的版本安裝
train方法代碼如下:
def train_gpu(): use_cuda = torch.cuda.is_available() if(use_cuda): print("use gpu cuda") else: print("use cpu")
device = torch.device("cuda:0" if use_cuda else "cpu") net = Net() net.to(device) opt = optim.SGD(net.parameters(), lr=0.01) epoch = 200 batch_size = 50 trainloader = data.trainloader(batch_size) st = datetime.datetime.now() loss = 0
for e in range(epoch): for step, d in enumerate(trainloader): data_cuda = d["data"].to(device) label_cuda = d["label"].to(device) opt.zero_grad() out = net(data_cuda) lf = nn.CrossEntropyLoss() loss = lf(out, label_cuda) loss.backward() opt.step()
if (e % 50 == 0 or step == 1): print("e : {} , step : {}, loss : {}".format(e, step, loss))
print("loss : {}".format(loss)) print("cost time:",datetime.datetime.now() - st) saveModel(net, opt)描述見上面代碼注釋,對概念理解有問題建議可以再看下這個up主的視頻,筆者覺得講得非常不錯:
[神經網絡學習理解](https://space.bilibili.com/504715181?spm_id_from=333.788.b_765f7570696e666f.1)下面給出訓練、測試過程中的效果圖:
GPU模型-訓練集訓練:
CPU模型-訓練集訓練:
可以看到迭代200次,花費4分鐘的訓練,模型趨於擬合效果,次數越往後梯度下降越慢。其實在迭代100次之後就接近穩定來回振蕩,損失值減少越慢,最後的損失值為0.0016,擬合效果還不錯,如果增加訓練數據量、迭代次數、優化部分字符串的切割,可以讓模型效果更好,讀者可自行實踐。
CPU模型-測試集測試:
代碼見net_test.py
可以看到152個字符,97%的準確率,部分字符切割問題會導致準確率下降,不過問題不大,基本達到個人項目可用程度,Nice~~
五、CNN神經網絡模型預測和部署
經過1,2,3步循環過程後,可以用一個相對擬合穩定的模型進行預測集預測,因為過擬合的問題,可能有些模型在測試集表現較好,在測試時效果就不太好,這裡需要對訓練數據,模型參數進行排
CPU模型-預測集測試:
代碼見net_usage.py
上圖可以看到,5張驗證碼的字符全部預測正確。
CPU模型-部署:
使用python的web框架Flask API,編寫圖片驗證碼識別POST接口,傳入文件路徑,啟動web應用,以下是通過本機文件路徑識別接口代碼,詳細代碼見net_flask.py
@app.route('/recognize/path', methods=['POST'])def recognize_path(): filePathList = request.json['filePathList'] code = CODE_SUCCESS msg = MSG_SUCCESS data = [] for filePath in filePathList: if not os.path.exists(filePath): # code = CODE_FAIL # msg = "文件不存在" print("文件不存在:", filePath) data.append("") continue else: labels = usage_model.usage(filePath) data.append(''.join(labels)) result = {'code': code, "msg": msg, "data": data} return jsonify(result)模型-Flask Web App啟動效果:
Postman接口測試效果:
Web頁面批量請求-預測:
好的,以上就是筆者圖片驗證碼識別案例中的卷積神經網絡模型訓練、測試、部署的全部內容了,總的來說,從結果看模型預測效果還是非常不錯的,首先利用標註系統進行人工標註初始數據集、下載數據集,然後再進行數據集的準備,接著進行模型的編碼、訓練和測試,然後利用訓練出來的模型進行數據預測,通過人工判斷修正再把加入到訓練集中,從而低時間成本、高效率增加訓練數據量。
六、總結
大家好,我是Snowball。這幾篇文章,整個過程下來,讀者就會熟悉到CNN神經網絡在圖片特徵提取的魅力之處,其原理還是利用概率論、機器學習知識,在多層CNN模型下,通過多層感知機的激活函數、隨機梯度下降法、損失函數、反向傳播等機制進行複雜非線性模型參數的調節,使得訓練處理的模型概率分布儘可能接近人腦中標註數據的概率模型。
當然,讀者看到這裡覺得這裡面還有很多疑問和問題,請不要氣餒,整個機器學習、神經網絡的知識體系是非常龐大的,從數學理論到計算機算法,再到工程框架,細節一步步被隱藏,請保持好奇心和思考,持續了解和學習,未來可能等知識積累到一定程度,那麼很多問題就會明白和理解。說的東西有點多了,哈哈,總之還是,資訊時代合理利用網際網路上的資源。
接下來講述最後一部分,下一篇文章奉上。就是所有項目模塊的部署部分,這部分內容不會太難,如果讀者不感興趣可以跳過,可以利用筆者部署到線上的系統進行體驗,伺服器帶寬有限,有資源的讀者可以自己部署一套:線上效果體驗地址
小夥伴們,快快用實踐一下吧!如果在學習過程中,有遇到任何問題,歡迎加我好友,我拉你進Python學習交流群共同探討學習。
------------------- End -------------------
往期精彩文章推薦:
歡迎大家點讚,留言,轉發,轉載,感謝大家的相伴與支持
想加入Python學習群請在後臺回復【入群】
萬水千山總是情,點個【在看】行不行
/今日留言主題/
隨便說一兩句吧~~