1. 程式人生 > >【Keras篇】---利用keras改寫VGG16經典模型在手寫數字識別體中的應用

【Keras篇】---利用keras改寫VGG16經典模型在手寫數字識別體中的應用

model類 都是 ast 訓練樣本 轉化 一個 h5py 次梯度 窗口

一、前述

VGG16是由16層神經網絡構成的經典模型,包括多層卷積,多層全連接層,一般我們改寫的時候卷積層基本不動,全連接層從後面幾層依次向前改寫,因為先改參數較小的。

二、具體

1、因為本文中代碼需要依賴OpenCV,所以第一步先安裝OpenCV

技術分享圖片

因為VGG要求輸入244*244,而數據集是28*28的,所以需要通過OpenCV在代碼裏去改變。

2、把模型下載後離線放入用戶的管理目錄下面,這樣訓練的時候就不需要從網上再下載了

技術分享圖片

3、我們保留的是除了全連接的所有層。

4、選擇數據生成器,在真正使用的時候才會生成數據,加載到內存,前面yield只是做了一個標記

技術分享圖片

代碼:

# 使用遷移學習的思想,以VGG16作為模板搭建模型,訓練識別手寫字體
# 引入VGG16模塊 from keras.applications.vgg16 import VGG16 # 其次加載其他模塊 from keras.layers import Input from keras.layers import Flatten from keras.layers import Dense from keras.layers import Dropout from keras.models import Model from keras.optimizers import SGD # 加載字體庫作為訓練樣本 from keras.datasets import
mnist # 加載OpenCV(在命令行中窗口中輸入pip install opencv-python),這裏為了後期對圖像的處理, # 大家使用pip install C:\Users\28542\Downloads\opencv_python-3.4.1+contrib-cp35-cp35m-win_amd64.whl # 比如尺寸變化和Channel變化。這些變化是為了使圖像滿足VGG16所需要的輸入格式 import cv2 import h5py as h5py import numpy as np # 建立一個模型,其類型是Keras的Model類對象,我們構建的模型會將VGG16頂層(全連接層)去掉,只保留其余的網絡
# 結構。這裏用include_top = False表明我們遷移除頂層以外的其余網絡結構到自己的模型中 # VGG模型對於輸入圖像數據要求高寬至少為48個像素點,由於硬件配置限制,我們選用48個像素點而不是原來 # VGG16所采用的224個像素點。即使這樣仍然需要24GB以上的內存,或者使用數據生成器 model_vgg = VGG16(include_top=False, weights=imagenet, input_shape=(48, 48, 3))#輸入進來的數據是48*48 3通道 #選擇imagnet,會選擇當年大賽的初始參數 #include_top=False 去掉最後3層的全連接層看源碼可知 for layer in model_vgg.layers: layer.trainable = False#別去調整之前的卷積層的參數 model = Flatten(name=flatten)(model_vgg.output)#去掉全連接層,前面都是卷積層 model = Dense(4096, activation=relu, name=fc1)(model) model = Dense(4096, activation=relu, name=fc2)(model) model = Dropout(0.5)(model) model = Dense(10, activation=softmax)(model)#model就是最後的y model_vgg_mnist = Model(inputs=model_vgg.input, outputs=model, name=vgg16) #把model_vgg.input X傳進來 #把model Y傳進來 就可以訓練模型了 # 打印模型結構,包括所需要的參數 model_vgg_mnist.summary() #以下是原版的模型結構 224*224 model_vgg = VGG16(include_top=False, weights=imagenet, input_shape=(224, 224, 3)) for layer in model_vgg.layers: layer.trainable = False#別去調整之前的卷積層的參數 model = Flatten()(model_vgg.output) model = Dense(4096, activation=relu, name=fc1)(model) model = Dense(4096, activation=relu, name=fc2)(model) model = Dropout(0.5)(model) model = Dense(10, activation=softmax, name=prediction)(model) model_vgg_mnist_pretrain = Model(model_vgg.input, model, name=vgg16_pretrain) model_vgg_mnist_pretrain.summary() # 新的模型不需要訓練原有卷積結構裏面的1471萬個參數,但是註意參數還是來自於最後輸出層前的兩個 # 全連接層,一共有1.2億個參數需要訓練 sgd = SGD(lr=0.05, decay=1e-5)#lr 學習率 decay 梯度的逐漸減小 每叠代一次梯度就下降 0.05*(1-(10的-5))這樣來變 #隨著越來越下降 學習率越來越小 步子越小 model_vgg_mnist.compile(loss=categorical_crossentropy, optimizer=sgd, metrics=[accuracy]) # 因為VGG16對網絡輸入層需要接受3通道的數據的要求,我們用OpenCV把圖像從32*32變成224*224,把黑白圖像轉成RGB圖像 # 並把訓練數據轉化成張量形式,供keras輸入 (X_train, y_train), (X_test, y_test) = mnist.load_data("../test_data_home") X_train, y_train = X_train[:1000], y_train[:1000]#訓練集1000條 X_test, y_test = X_test[:100], y_test[:100]#測試集100條 X_train = [cv2.cvtColor(cv2.resize(i, (48, 48)), cv2.COLOR_GRAY2RGB) for i in X_train]#變成彩色的 #np.concatenate拼接到一起把 X_train = np.concatenate([arr[np.newaxis] for arr in X_train]).astype(float32) X_test = [cv2.cvtColor(cv2.resize(i, (48, 48)), cv2.COLOR_GRAY2RGB) for i in X_test] X_test = np.concatenate([arr[np.newaxis] for arr in X_test]).astype(float32) print(X_train.shape) print(X_test.shape) X_train = X_train / 255 X_test = X_test / 255 def tran_y(y): y_ohe = np.zeros(10) y_ohe[y] = 1 return y_ohe y_train_ohe = np.array([tran_y(y_train[i]) for i in range(len(y_train))]) y_test_ohe = np.array([tran_y(y_test[i]) for i in range(len(y_test))]) model_vgg_mnist.fit(X_train, y_train_ohe, validation_data=(X_test, y_test_ohe), epochs=100, batch_size=50)

結果:

技術分享圖片

自定義的網絡層:

技術分享圖片

【Keras篇】---利用keras改寫VGG16經典模型在手寫數字識別體中的應用