【keras實戰】用Inceptionv3實現五種花的分類
阿新 • • 發佈:2018-12-14
一、資料集準備
訓練資料花朵圖片下載:地址
圖片下載好後劃分資料集,分為訓練集和驗證集,訓練集每類圖片500張,驗證集每類圖片100張。
這是我資料集的樹圖:
二、訓練模型
環境:Ubuntu,Anaconda2,python2.7,tensorflow,keras
# --coding:utf-8-- import os import sys import glob import argparse import matplotlib.pyplot as plt from keras import __version__ from keras.applications.inception_v3 import InceptionV3, preprocess_input #from keras.applications.inception_v3_matt import InceptionV3, preprocess_input from keras.models import Model from keras.layers import Dense, GlobalAveragePooling2D from keras.preprocessing.image import ImageDataGenerator from keras.optimizers import SGD def get_nb_files(directory): """Get number of files by searching directory recursively""" if not os.path.exists(directory): return 0 cnt = 0 for r, dirs, files in os.walk(directory): for dr in dirs: cnt += len(glob.glob(os.path.join(r, dr + "/*"))) return cnt #train_num = get_nb_files('/home/pandafish/AnacondaProjects/Inceptionv3/dataset_my/train') 2500 #print(train_num) #input('wait...') # 資料準備 IM_WIDTH, IM_HEIGHT = 299, 299 #InceptionV3指定的圖片尺寸 FC_SIZE = 1024 # 全連線層的節點個數 NB_IV3_LAYERS_TO_FREEZE = 172 # 凍結層的數量 train_dir = '/home/pandafish/AnacondaProjects/Inceptionv3/dataset_my/train' # 訓練集資料 val_dir = '/home/pandafish/AnacondaProjects/Inceptionv3/dataset_my/validate' # 驗證集資料 output_model_file = '/home/pandafish/AnacondaProjects/Inceptionv3/weight/InceptionV3.model' nb_classes= 5 nb_epoch = 3 batch_size = 16 nb_train_samples = get_nb_files(train_dir) # 訓練樣本個數 nb_classes = len(glob.glob(train_dir + "/*")) # 分類數 nb_val_samples = get_nb_files(val_dir) #驗證集樣本個數 nb_epoch = int(nb_epoch) # epoch數量 batch_size = int(batch_size) # 圖片生成器 train_datagen = ImageDataGenerator( preprocessing_function=preprocess_input, rotation_range=30, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2, zoom_range=0.2, horizontal_flip=True ) test_datagen = ImageDataGenerator( preprocessing_function=preprocess_input, rotation_range=30, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2, zoom_range=0.2, horizontal_flip=True ) # 訓練資料與測試資料 train_generator = train_datagen.flow_from_directory( train_dir, target_size=(IM_WIDTH, IM_HEIGHT), batch_size=batch_size,class_mode='categorical') validation_generator = test_datagen.flow_from_directory( val_dir, target_size=(IM_WIDTH, IM_HEIGHT), batch_size=batch_size,class_mode='categorical') # 新增新層 def add_new_last_layer(base_model, nb_classes): """ 新增最後的層 輸入 base_model和分類數量 輸出 新的keras的model """ x = base_model.output x = GlobalAveragePooling2D()(x) x = Dense(FC_SIZE, activation='relu')(x) #new FC layer, random init predictions = Dense(nb_classes, activation='softmax')(x) #new softmax layer model = Model(input=base_model.input, output=predictions) return model # 凍上NB_IV3_LAYERS之前的層 def setup_to_finetune(model): """Freeze the bottom NB_IV3_LAYERS and retrain the remaining top layers. note: NB_IV3_LAYERS corresponds to the top 2 inception blocks in the inceptionv3 arch Args: model: keras model """ for layer in model.layers[:NB_IV3_LAYERS_TO_FREEZE]: layer.trainable = False for layer in model.layers[NB_IV3_LAYERS_TO_FREEZE:]: layer.trainable = True model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), loss='categorical_crossentropy', metrics=['accuracy']) # 設定網路結構 model = InceptionV3(weights='imagenet', include_top=False) model = add_new_last_layer(model, nb_classes) setup_to_finetune(model) # 模式二訓練 history_ft = model.fit_generator( train_generator, samples_per_epoch=nb_train_samples, nb_epoch=nb_epoch, validation_data=validation_generator, nb_val_samples=nb_val_samples, class_weight='auto1') # 模型儲存 model.save(output_model_file) # 畫圖 def plot_training(history): acc = history.history['acc'] val_acc = history.history['val_acc'] loss = history.history['loss'] val_loss = history.history['val_loss'] epochs = range(len(acc)) plt.plot(epochs, acc, 'r.') plt.plot(epochs, val_acc, 'r') plt.title('Training and validation accuracy') plt.figure() plt.plot(epochs, loss, 'r.') plt.plot(epochs, val_loss, 'r-') plt.title('Training and validation loss') plt.show() # 訓練的acc_loss圖 plot_training(history_ft)
三、測試圖片
模型我只訓練了一個epoch,肯定是欠擬合的,主要是看看程式能否跑通。
# --coding:utf-8-- # 定義層 import sys import argparse import numpy as np from PIL import Image from io import BytesIO import matplotlib.pyplot as plt from keras.preprocessing import image from keras.models import load_model from keras.applications.inception_v3 import preprocess_input # 狂階圖片指定尺寸 target_size = (229, 229) #fixed size for InceptionV3 architecture # 預測函式 # 輸入:model,圖片,目標尺寸 # 輸出:預測predict def predict(model, img, target_size): """Run model prediction on image Args: model: keras model img: PIL format image target_size: (w,h) tuple Returns: list of predicted labels and their probabilities """ if img.size != target_size: img = img.resize(target_size) x = image.img_to_array(img) x = np.expand_dims(x, axis=0) x = preprocess_input(x) preds = model.predict(x) return preds[0] # 畫圖函式 # 預測之後畫圖,這裡預設是貓狗,當然可以修改label labels = ("daisy", "dandelion","roses","sunflowers","tulips") def plot_preds(image, preds,labels): """Displays image and the top-n predicted probabilities in a bar graph Args: image: PIL image preds: list of predicted labels and their probabilities """ plt.imshow(image) plt.axis('off') plt.figure() plt.barh([0, 1,2,3,4], preds, alpha=0.5) plt.yticks([0, 1,2,3,4], labels) plt.xlabel('Probability') plt.xlim(0,1.01) plt.tight_layout() plt.show() # 載入模型 model = load_model('weight.model') # 本地圖片 img = Image.open('sunflower.jpg') preds = predict(model, img, target_size) plot_preds(img, preds,labels)
測試結果