CNN實戰

需求:判斷手寫ld的指令

訓練模型:

from keras.models import Sequential
from keras import layers
from keras.layers import Dense, Dropout, Conv2D, MaxPooling2D, Flatten
import numpy
from keras import optimizers
from keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
from keras.callbacks import ModelCheckpoint

#image->convolution->pooling->convolution->pooling->full connected->full connected(hidden layer) ->classifier

def defineModelAndGenerateModel():
    model = Sequential()  ## 定義cnn模型
    model.add(Conv2D(32, (3,3), activation='relu',input_shape=(100,200,1))) ## 添加2D卷積層,32個過濾器,用3乘3過濾器,使用relu激活函數,指定輸入圖片尺寸
    ## ken 這裏應該添加更多的層
    model.add(MaxPooling2D(2,2)) ## 添加最大池化層
    model.add(Conv2D(32, (3,3), activation='relu')) ## 添加2D卷積層,32個過濾器,用3乘3過濾器,使用relu激活函數,指定輸入圖片尺寸
    model.add(MaxPooling2D(2,2)) ## 添加最大池化層
    model.add(Conv2D(64, (3,3), activation='relu')) ## 添加2D卷積層,32個過濾器,用3乘3過濾器,使用relu激活函數,指定輸入圖片尺寸
    model.add(MaxPooling2D(2,2)) ## 添加最大池化層

    # drop out of max-pooling layer , drop out rate is 0.25 (0.5??) 
    #model.add(Dropout(0.25))
    model.add(Dropout(0.5))
    # flatten inputs from 2d to 1d
    model.add(Flatten())
    model.add(Dense(8, activation='softmax'))  ## 添加全連結層,使用softmax激活函數,輸出8種分類的可能性

    model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) ## 編譯模型,rmsprop優化函數,分類交叉熵損失函數
    train_datagen = ImageDataGenerator(rescale=1./255) ## 從目錄裏提取圖片

    train_generator = train_datagen.flow_from_directory(
        'C:/hand-imgs', target_size=(100,200),  #(120,205)
        batch_size=10,
        color_mode='grayscale',
        class_mode='categorical'
    )


    #todo:訓練之前應該將一部分訓練中的數據挑選爲validation用,用keras的split方法。
    validation_generator= train_datagen.flow_from_directory(
        'c:/hand-imgs-validate', target_size=(100,200),
        batch_size=10,
        color_mode='grayscale',
        class_mode='categorical'
    )

    checkpoint = ModelCheckpoint('model-{epoch:03d}-{acc:03f}-{val_acc:03f}.h5', verbose=1, monitor='val_loss',save_best_only=True, mode='auto')  

    #調整參數
    history = model.fit_generator(  #開始訓練模型
        train_generator,
        steps_per_epoch=100,
        epochs=10,
        validation_data= validation_generator,
        callbacks=[checkpoint],
        validation_steps=2)
    model.save('hand_ld')  ## 保存訓練的模型(*以後做預測會用到)
    return history

def showresult(history):  ## 生成模型衡量的結果
    plt.figure()
    acc = history.history['acc']
    val_acc = history.history['val_acc']
    loss = history.history['loss']
    val_loss = history.history['val_loss']
    epochs = range(1,len(acc)+1)
    plt.plot(epochs, acc, 'bo', label='Training acc')
    plt.plot(epochs, val_acc, 'b', label='Validation acc')
    plt.title('Training and validation accuracy')
    #plt.legend()
    plt.show()

if __name__ == "__main__":
    history= defineModelAndGenerateModel()
    #showresult(history)
    

注意點:

  • 多個池化層
  • Dropout 0.2太小會產生過擬合,一般採用0.5
  • 增加了checkpoint, 由於梯度下降的參數不同,順着step增加,acc_val會變小。用checkpoint保存最高的acc_val
import os
import numpy as np
import cv2
from keras.models import Model
from keras.preprocessing import image as kimage
from keras.models import load_model
from procImg import procImage, drawImageResult 

#const
#predictFile = "C:/hand-test/20200102170013216-2.jpg"
#predictFile = "C:/hand-backup/training/20191230165257965-6.jpg"
predictFile = "C:/hand-backup/validate/20200102101640083-28.jpg"
modlepath = 'model-008-0.966599-0.950000.h5'

def predict(image, model):
    cv2.imwrite('cv2.jpeg', image)  ##保存當前視頻(圖片)畫面
    kimg = kimage.load_img('cv2.jpeg', target_size=([100,200]), color_mode='grayscale')  ## 轉化爲Keras能讀取的數據格式
    img_tensor = kimage.img_to_array(kimg)
    img_tensor = np.expand_dims(img_tensor, axis=0)
    predict = np.argmax(model.predict(img_tensor))  ## 使用模型預測,結果取8個分類結果中可能性最大的
    return predict
    

def run():
    model = load_model(modlepath)  ## 讀取保存的模型
    image = cv2.imread(predictFile)
    images = procImage(image)
    predicts = []
    for img in images:
        ret = predict(img, model)
        print(ret)
        predicts.append(ret)
    drawImageResult(image, predicts)

    

if __name__ == '__main__':
    run()
    cv2.waitKey()

創建模型的時候,前兩位是訓練產生的loss和acc,後兩位是驗證產生的val_loss和val_acc。

 

 

發佈了57 篇原創文章 · 獲贊 2 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章