本文將介紹:
使用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)