Keras ResNet50分类网络,训练大量图像方法

Keras框架常用的两种训练函数

Keras框架常用两种训练函数model.fit()和model.fit_generator()函数。

model.fit()

fit( x, y, batch_size=32, epochs=10, verbose=1, callbacks=None,
validation_split=0.0, validation_data=None, shuffle=True,
class_weight=None, sample_weight=None, initial_epoch=0)

  • x:输入数据。如果模型只有一个输入,那么x的类型是numpy
    array,如果模型有多个输入,那么x的类型应当为list,list的元素是对应于各个输入的numpy array
  • y:标签,numpy array
  • batch_size:整数,指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步。
  • epochs:整数,训练终止时的epoch值,训练将在达到该epoch值时停止。
  • verbose:日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录
  • callbacks:list,其中的元素是keras.callbacks.Callback的对象。这个list中的回调函数将会在训练过程中的适当时机被调用,参考回调函数
  • validation_split:0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等。注意,validation_split的划分在shuffle之前,因此如果你的数据本身是有序的,需要先手工打乱再指定validation_split,否则可能会出现验证集样本不均匀。
  • validation_data:形式为(x,y)的tuple,是指定的验证集。此参数将覆盖validation_spilt。
  • shuffle:布尔值或字符串,一般为布尔值,表示是否在训练过程中随机打乱输入样本的顺序。若为字符串“batch”,则是用来处理HDF5数据的特殊情况,它将在batch内部将数据打乱。

优点:

  1. 将数据集全部读入内存,简单方便
  2. 可执行多次epoch

缺点:

  1. 图像数量多无法全部读入内存时,不能使用
  2. 无法使用数据扩增

model.fit_generator()

fit_generator(generator, steps_per_epoch=None, epochs=1, verbose=1,
callbacks=None, validation_data=None, validation_steps=None,
class_weight=None, max_queue_size=10, workers=1,
use_multiprocessing=False, shuffle=True, initial_epoch=0)

  • generator: 一个生成器,或者一个 Sequence (keras.utils.Sequence) 对象的实例,
    以在使用多进程时避免数据的重复。 生成器的输出应该为以下之一:

    • 一个 (inputs, targets) 元组

    • 一个 (inputs, targets, sample_weights) 元组。

这个元组(生成器的单个输出)组成了单个的 batch。 因此,这个元组中的所有数组长度必须相同(与这一个 batch 的大小相等)。不同的 batch 可能大小不同。 例如,一个 epoch 的最后一个 batch 往往比其他 batch 要小, 如果数据集的尺寸不能被batch size 整除。 生成器将无限地在数据集上循环。当运行到第 steps_per_epoch 时,记一个 epoch 结束。

  • steps_per_epoch: 在声明一个 epoch 完成并开始下一个 epoch 之前从 generator 产生的总步数(批次样本)。 它通常应该等于你的数据集的样本数量除以批量大小。 对于 Sequence,它是可选的:如果未指定,将使用len(generator) 作为步数。
  • epochs: 整数。训练模型的迭代总轮数。一个 epoch 是对所提供的整个数据的一轮迭代,如 steps_per_epoch所定义。注意,与 initial_epoch 一起使用,epoch 应被理解为「最后一轮」。模型没有经历由 epochs给出的多次迭代的训练,而仅仅是直到达到索引 epoch 的轮次。
  • verbose: 0, 1 或 2。日志显示模式。 0 = 安静模式, 1 = 进度条, 2 = 每轮一行。
  • callbacks: keras.callbacks.Callback 实例的列表。在训练时调用的一系列回调函数。
  • shuffle: 是否在每轮迭代之前打乱 batch 的顺序。 只能与 Sequence (keras.utils.Sequence)
    实例同用。
  • initial_epoch: 开始训练的轮次(有助于恢复之前的训练)。

优点:

  1. 可以训练大量图像
  2. 图像数据可扩增

缺点:

  1. epoch固定,为图像总数量/每个epoch训练的图像数
  2. 使用生成器,较为复杂

代码实现

model.fit()

import os
import numpy as np
from keras.applications.resnet50 import ResNet50
from keras.preprocessing.image import ImageDataGenerator
import keras
import cv2
import random
from tqdm import tqdm

# 读取图像数据和标签数据
def data_set(img_path, xml_path):
	imgSet = []  # 图像数据集合
    labelSet = []  # 标签数据集合
    imgfiles = os.listdir(img_path)
    # 读取数据
    for index in tqdm(range(len(imgfiles))):
        img = cv2.imread(os.path.join(img_path,imgfiles[index]), 1)
        img = cv2.resize(img, (224, 224)) / 255.0
        imgSet.append(img)
        xmlfile = os.path.splitext(imgfiles[index])[0] + '.xml'
        # 此处可改为自己的获取标签的函数
        label = get_label(os.path.join(xml_path, xmlfile))	
        labelSet.append(label)
    imgTrain = np.asarray(imgSet,dtype=np.float32)
    labelTrain = np.asarray(labelSet,dtype=np.int32)
    index = [i for i in range(len(imgfiles))]
    random.shuffle(index)
    imgTrain = imgTrain[index]
    labelTrain = labelTrain[index]
    return imgTrain, labelTrain

if __name__ == '__main__':  
	# 启动网络
    model = ResNet50(
        weights=None,
        classes=4
    )
    # 设计优化器
    model.compile(optimizer=keras.optimizers.Adam(0.001),loss='categorical_crossentropy',metrics=['accuracy'])
    # train
    filepath = 'weight/resnet50_epoch-{epoch:02d}_loss-{loss:.4f}.h5'
    checkpoint = keras.callbacks.ModelCheckpoint(filepath, monitor='loss', verbose=1, save_best_only=True,mode='auto', save_weights_only=True)
    callbacks_list = [checkpoint]
    model.fit(x=img, y=label, epochs=200, batch_size=4, validation_split=0.1, verbose=1, shuffle=True)
    

model.fit_generator()

import os
import numpy as np
from keras.applications.resnet50 import ResNet50
from keras.preprocessing.image import ImageDataGenerator
import keras
import cv2
import random
from tqdm import tqdm

# 读取图像数据和标签数据
def data_set(img_path, xml_path):
	imgfiles = os.listdir(img_path)	# 从图像文件夹读取图像集合
	aug = ImageDataGenerator(rotation_range=10,
							 zoom_range=0.15,
                             width_shift_range=0.2,
                             height_shift_range=0.2,
                             shear_range=0.15,
                             horizontal_flip=True,
                             vertical_flip=Tru
                             fill_mode="nearest")
	# 读取数据 生成器模式
	for index in tqdm(range(len(imgfiles))):
		img = cv2.imread(os.path.join(img_path, imgfiles[index]), 1)
		img = cv2.resize(img, (224, 224)) / 255.0
		imgEX = np.expand_dims(img, axis=0)
		xmlfile = os.path.splitext(imgfiles[index])[0] + '.xml'
		label = get_label(os.path.join(xml_path, xmlfile))
        labelEX = np.expand_dims(label, axis=0)
        aug.flow(imgEX,labelEX,batch_size=4)
        yield imgEX, labelEX
        
if __name__ == '__main__':  
	# 启动网络
    model = ResNet50(
        weights=None,
        classes=4
    )
    # 设计优化器
    model.compile(optimizer=keras.optimizers.Adam(0.001),loss='categorical_crossentropy',metrics=['accuracy'])
    # train
    filepath = 'weight/resnet50_epoch-{epoch:02d}_loss-{loss:.4f}.h5'
    checkpoint = keras.callbacks.ModelCheckpoint(filepath, monitor='loss', verbose=1, save_best_only=True,mode='auto', save_weights_only=True)
    callbacks_list = [checkpoint]
    model.fit_generator(data_generate, steps_per_epoch=4000, epochs=2, verbose=1,callbacks=callbacks_list)
    

工作心得

generator生成器,相当于将普通函数中的return关键字,换成yield关键字,并且将输入数据X与标签Y按网络要求设置好即可。

你可能感兴趣的:(深度学习)