Keras之 使用keras實現resnet50模型做遷移學習-finetune


  本文將介紹:

  使用keras實現resnet50模型

  實現遷移學習-finetune

  一,下載kaggle-10monkey數據

  下載dataset到本地目錄intput中

  二,使用keras中ImageDataGenerator讀取數據、數據增強

  1,使用keras中ImageDataGenerator讀取數據、數據增強

  #!/usr/bin/env python3

  # -*- coding: utf-8 -*-

  import matplotlib as mpl

  import matplotlib.pyplot as plt

  import numpy as np

  import os

  import pandas as pd

  import sklearn

  import sys

  import tensorflow as tf

  import time

  from tensorflow import keras

  # 打印使用的python庫的版本信息

  print(tf.__version__)

  print(sys.version_info)

  for module in mpl, np, pd, sklearn, tf, keras:

  print(module.__name__, module.__version__)

  # 1,實現tensorflow動態按需分配GPU

  from tensorflow.compat.v1 import ConfigProto

  from tensorflow.compat.v1 import InteractiveSession

  config = ConfigProto()

  config.gpu_options.allow_growth = True

  session = InteractiveSession(config=config)

  # 常量的定義

  train_dir = "./input/training/training"

  valid_dir = "./input/validation/validation"

  label_file = "./input/monkey_labels.txt"

  print(os.path.exists(train_dir))

  print(os.path.exists(valid_dir))

  print(os.path.exists(label_file))

  print(os.listdir(train_dir))

  print(os.listdir(valid_dir))

  # 查看打印出來的label值

  labels = pd.read_csv(label_file, header=0)

  print(labels)

  # 定義常量

  height = 224 # resne50的處理的圖片大小

  width = 224 # resne50的處理的圖片大小

  channels = 3

  batch_size = 24 # 因為處理的圖片變大,batch_size變小一點 32->24

  num_classes = 10

  # 一,使用keras中ImageDataGenerator讀取數據

  # 1,實例化ImageDataGenerator

  # 對於圖片數據,在keras里有更高層的封裝.讀取數據且做數據增強 -> Generator

  train_datagen = keras.preprocessing.image.ImageDataGenerator(

  preprocessing_function = keras.applications.resnet50.preprocess_input,# 此函數是是現在keras中,而非tf.keras中,在tf中,實現數據做歸一化,數據取值在-1~1之間.

  # rescale = 1./255, # 由於preprocessing_function已做了歸一化,此處注釋; 圖像中的每個像素點都是在0~255之間,得到一個0~1之間的數

  rotation_range = 40, # 圖片增強的方法,把圖片隨機旋轉一個角度,旋轉的角度就在-40~40之間

  width_shift_range = 0.2, # 做水平位移 - 增加位移魯棒性(如果0~1之間則位移比例隨機選數做位移;如果大於1,則是具體的像素大小)

  height_shift_range = 0.2, # 做垂直位移 - 增加位移魯棒性(如果0~1之間則位移比例隨機選數做位移;如果大於1,則是具體的像素大小)

  shear_range = 0.2, # 剪切強度

  zoom_range = 0.2, # 縮放強度

  horizontal_flip = True, # 是否隨機做水平翻轉

  fill_mode = 'nearest', # 填充像素規則,用離其最近的像素點做填充

  )

  # 2,使用ImageDataGenerator讀取圖片

  # 從訓練集的文件夾中讀取圖片

  train_generator = train_datagen.flow_from_directory(train_dir,# 圖片的文件夾位置

  target_size = (height, width),# 將圖片縮放到的大小

  batch_size = batch_size, # 多少張為一組

  seed = 7,#隨機數種子

  shuffle = True,# 是否做混插

  class_mode = "categorical") # 控制目標值label的形式-選擇onehot編碼后的形式

  # 從驗證集的文件夾中讀取圖片

  valid_datagen = keras.preprocessing.image.ImageDataGenerator(

  preprocessing_function = keras.applications.resnet50.preprocess_input)

  valid_generator = valid_datagen.flow_from_directory(valid_dir,

  target_size = (height, width),

  batch_size = batch_size,

  seed = 7,

  shuffle = False,

  class_mode = "categorical")

  2,查看訓練家和驗證集分別有多少張數據

  train_num = train_generator.samples

  valid_num = valid_generator.samples

  print(train_num, valid_num)

  3,如何從ImageDataGenerator中讀取數據

  for i in range(1):

  x, y = train_generator.next()

  print(x.shape, y.shape)

  print(y)

  三,定義模型

  1,定義ResNet50中50層初始化參數均不變

  resnet50_fine_tune = keras.models.Sequential()

  resnet50_fine_tune.add(keras.applications.ResNet50(include_top = False, # 網絡結構的最后一層,resnet50有1000類,去掉最后一層

  pooling = 'avg', #resnet50模型倒數第二層的輸出是三維矩陣-卷積層的輸出,做pooling或展平

  weights = 'imagenet')) # 參數有兩種imagenet和None,None為從頭開始訓練,imagenet為從網絡下載已訓練好的模型開始訓練

  resnet50_fine_tune.add(keras.layers.Dense(num_classes, activation = 'softmax')) # 因為include_top = False,所以需要自己定義最后一層

  resnet50_fine_tune.layers[0].trainable = False # 因為參數是從imagenet初始化的,所以我們可以只調整最后一層的參數

  resnet50_fine_tune.compile(loss="categorical_crossentropy",

  optimizer="sgd", metrics=['accuracy']) #對於微調-finetune來說,優化器使用sgd來說更好一些

  resnet50_fine_tune.summary()

  2,定義ResNet50中后5層初始化參數變化

  plot_learning_curves(history, 'accuracy', epochs, 0, 1)

  plot_learning_curves(history, 'loss', epochs, 0, 2)

  #

  resnet50 = keras.applications.ResNet50(include_top = False,

  pooling = 'avg',

  weights = 'imagenet')

  resnet50.summary()

  #

  for layer in resnet50.layers[0:-5]:

  layer.trainable = False

  resnet50_new = keras.models.Sequential([

  resnet50,

  keras.layers.Dense(num_classes, activation = 'softmax'),

  ])

  resnet50_new.compile(loss="categorical_crossentropy",

  optimizer="sgd", metrics=['accuracy'])

  resnet50_new.summary()

  四,訓練模型

  epochs = 10

  # history = resnet50_fine_tune.fit_generator(train_generator,

  history = resnet50_new.fit_generator(train_generator,

  steps_per_epoch = train_num // batch_size,

  epochs = epochs,

  validation_data = valid_generator,

  validation_steps = valid_num // batch_size)

  五,打印模型訓練曲線

  def plot_learning_curves(history, label, epcohs, min_value, max_value):

  data = {}

  data[label] = history.history[label]

  data['val_'+label] = history.history['val_'+label]

  pd.DataFrame(data).plot(figsize=(8, 5))

  plt.grid(True)

  plt.axis([0, epochs, min_value, max_value])

  plt.show()

  plot_learning_curves(history, 'accuracy', epochs, 0, 1)

  plot_learning_curves(history, 'loss', epochs, 0, 2)

  六,總結代碼

  #!/usr/bin/env python3

  # -*- coding: utf-8 -*-

  import matplotlib as mpl

  import matplotlib.pyplot as plt

  import numpy as np

  import os

  import pandas as pd

  import sklearn

  import sys

  import tensorflow as tf

  import time

  from tensorflow import keras

  # 打印使用的python庫的版本信息

  print(tf.__version__)

  print(sys.version_info)

  for module in mpl, np, pd, sklearn, tf, keras:

  print(module.__name__, module.__version__)

  # 1,實現tensorflow動態按需分配GPU

  from tensorflow.compat.v1 import ConfigProto

  from tensorflow.compat.v1 import InteractiveSession

  config = ConfigProto()

  config.gpu_options.allow_growth = True

  session = InteractiveSession(config=config)

  # 常量的定義

  train_dir = "./input/training/training"

  valid_dir = "./input/validation/validation"

  label_file = "./input/monkey_labels.txt"

  print(os.path.exists(train_dir))

  print(os.path.exists(valid_dir))

  print(os.path.exists(label_file))

  print(os.listdir(train_dir))

  print(os.listdir(valid_dir))

  # 查看打印出來的label值

  labels = pd.read_csv(label_file, header=0)

  print(labels)

  # 定義常量

  height = 224 # resne50的處理的圖片大小

  width = 224 # resne50的處理的圖片大小

  channels = 3

  batch_size = 24 # 因為處理的圖片變大,batch_size變小一點 32->24

  num_classes = 10

  # 一,使用keras中ImageDataGenerator讀取數據

  # 1,實例化ImageDataGenerator

  # 對於圖片數據,在keras里有更高層的封裝.讀取數據且做數據增強 -> Generator

  train_datagen = keras.preprocessing.image.ImageDataGenerator(

  preprocessing_function = keras.applications.resnet50.preprocess_input,# 此函數是是現在keras中,而非tf.keras中,在tf中,實現數據做歸一化,數據取值在-1~1之間.

  # rescale = 1./255, # 由於preprocessing_function已做了歸一化,此處注釋; 圖像中的每個像素點都是在0~255之間,得到一個0~1之間的數

  rotation_range = 40, # 圖片增強的方法,把圖片隨機旋轉一個角度,旋轉的角度就在-40~40之間

  width_shift_range = 0.2, # 做水平位移 - 增加位移魯棒性(如果0~1之間則位移比例隨機選數做位移;如果大於1,則是具體的像素大小)

  height_shift_range = 0.2, # 做垂直位移 - 增加位移魯棒性(如果0~1之間則位移比例隨機選數做位移;如果大於1,則是具體的像素大小)

  shear_range = 0.2, # 剪切強度棗庄婦科醫院哪家好 http://mobile.0632dffk.com/

  zoom_range = 0.2, # 縮放強度

  horizontal_flip = True, # 是否隨機做水平翻轉

  fill_mode = 'nearest', # 填充像素規則,用離其最近的像素點做填充

  )

  # 2,使用ImageDataGenerator讀取圖片

  # 從訓練集的文件夾中讀取圖片

  train_generator = train_datagen.flow_from_directory(train_dir,# 圖片的文件夾位置

  target_size = (height, width),# 將圖片縮放到的大小

  batch_size = batch_size, # 多少張為一組

  seed = 7,#隨機數種子

  shuffle = True,# 是否做混插

  class_mode = "categorical") # 控制目標值label的形式-選擇onehot編碼后的形式

  # 從驗證集的文件夾中讀取圖片

  valid_datagen = keras.preprocessing.image.ImageDataGenerator(

  preprocessing_function = keras.applications.resnet50.preprocess_input)

  valid_generator = valid_datagen.flow_from_directory(valid_dir,

  target_size = (height, width),

  batch_size = batch_size,

  seed = 7,

  shuffle = False,

  class_mode = "categorical")

  # 3,查看訓練家和驗證集分別有多少張數據

  train_num = train_generator.samples

  valid_num = valid_generator.samples

  print(train_num, valid_num)

  # 4,如何從ImageDataGenerator中讀取數據

  for i in range(2):

  x, y = train_generator.next()

  print(x.shape, y.shape)

  print(y)

  # 二,構建模型

  # 1,ResNet50中50層參數均不變

  resnet50_fine_tune = keras.models.Sequential()

  resnet50_fine_tune.add(keras.applications.ResNet50(include_top = False, # 網絡結構的最后一層,resnet50有1000類,去掉最后一層

  pooling = 'avg', #resnet50模型倒數第二層的輸出是三維矩陣-卷積層的輸出,做pooling或展平

  weights = 'imagenet')) # 參數有兩種imagenet和None,None為從頭開始訓練,imagenet為從網絡下載已訓練好的模型開始訓練

  resnet50_fine_tune.add(keras.layers.Dense(num_classes, activation = 'softmax')) # 因為include_top = False,所以需要自己定義最后一層

  resnet50_fine_tune.layers[0].trainable = False # 因為參數是從imagenet初始化的,所以我們可以只調整最后一層的參數

  resnet50_fine_tune.compile(loss="categorical_crossentropy",

  optimizer="sgd", metrics=['accuracy']) #對於微調-finetune來說,優化器使用sgd來說更好一些

  resnet50_fine_tune.summary()

  # 2,ResNet50中后5層參數均變化

  resnet50 = keras.applications.ResNet50(include_top = False,

  pooling = 'avg',

  weights = 'imagenet')

  resnet50.summary()

  for layer in resnet50.layers[0:-5]:

  layer.trainable = False

  resnet50_new = keras.models.Sequential([

  resnet50,

  keras.layers.Dense(num_classes, activation = 'softmax'),

  ])

  resnet50_new.compile(loss="categorical_crossentropy",

  optimizer="sgd", metrics=['accuracy'])

  resnet50_new.summary()

  # 三,訓練模型(兩種模型可選擇訓練)

  epochs = 10

  # history = resnet50_fine_tune.fit_generator(train_generator,

  history = resnet50_new.fit_generator(train_generator,

  steps_per_epoch = train_num // batch_size,

  epochs = epochs,

  validation_data = valid_generator,

  validation_steps = valid_num // batch_size)

  # 四,打印模型訓練曲線

  def plot_learning_curves(history, label, epcohs, min_value, max_value):

  data = {}

  data[label] = history.history[label]

  data['val_'+label] = history.history['val_'+label]

  pd.DataFrame(data).plot(figsize=(8, 5))

  plt.grid(True)

  plt.axis([0, epochs, min_value, max_value])

  plt.show()

  plot_learning_curves(history, 'accuracy', epochs, 0, 1)

  plot_learning_curves(history, 'loss', epochs, 0, 2)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM