Keras学习之:如何使用 fit_generator进行训练,如何创建 generator

1. 为什么要使用 fit_generator

  • 我们都知道我们在进行神经网络训练的时候如果使用 model.fit 的方式训练,
    在这里插入图片描述
    那么我们需要把整个 x_train 加载到内存中,而 keras 自带的一些 datasets 又很小,在训练的时候完全可以这么做,所以如果是 keras 的小白,可能觉得 fit 是一个很好用的训练方法,而且也习惯了这种方式。
  • 但是,如果我现在想用 ImageNet 数据集(1000000张图片,1000个类别)来进行训练,直接加载到内存,内存会爆掉,所以我们要批量地把他们放到内存里。那么这就产生了一个问题,我们使用 fit 来训练的时候,在接口中封装了 batch_size 的参数,我们只需要输入一个数字,他就能够按照我们输入的尺寸对数据集进行分割,方便又快捷,那么如果我们手动地让他们一批批地送入内存中进行训练,该如何实现呢?接下来进入第二部分,创建一个 generator 来替你完成原来 fitbatch_size 所做的工作

2. 如何创建 generator

  • 这里拿最简单的数据集 mnist 来做个展示

from keras.datasets import mnist
from keras.layers import Conv2D,MaxPool2D,Dropout,Flatten,Dense
from keras.models import Sequential
from keras.utils import to_categorical
import numpy as np
import keras 

#### 分导入数据集 #####
(x_train,y_train),(x_test,y_test)= mnist.load_data()

#### 对数据维度进行调整 ####
x_train_ = np.expand_dims(x_train,3)	# (60000,28,28,1)
y_train_ = to_categorical(y_train)		# (60000,10)
x_test_ = np.expand_dims(x_test,3)		# (10000,28,28,1)
y_test_ = to_categorical(y_test)		# (10000,10)

##### 定义 cnn 网络 #####
def cnn():
    model = Sequential()
    model.add(Conv2D(input_shape=(28,28,1),filters=25,kernel_size=(3,3),padding='same',activation='relu')) 
    model.add(MaxPool2D())
    model.add(Dropout(rate=0.3))
    model.add(Flatten())
    model.add(Dense(32,activation='relu'))
    model.add((Dense(10,activation='softmax')))
    return model


#### 规定 generator 每一次产生的数据量 64 个
#### 数据从 x_train_ 数据集中产生,x_train_数据集的尺寸是 dataset_size=60000
batchsize = 64
dataset_size = x_train_.shape[0]

def generator(x_train_,y_train_,batchsize=batchsize,shuffle=True):
    dataset_size = x_train_.shape[0]
    while True:
        i = 0 
        if shuffle:		# 对数据集洗牌的话,就每次随机抽取 batchsize 个数作为抽取的索引
            img_index = np.random.randint(0,dataset_size,batchsize)
            img = x_train_[img_index]
            label = y_train_[img_index]
        else:			# 不对数据集洗牌的话,就每次顺序抽取 batchsize 个数作为抽取的索引
            img = x_train_[i:((i+batchsize)% dataset_size)]		# (i+batchsize % dataset_size) 是为了防止索引数超出数据集的最大索引,以便于可以循环训练
            label = y_train_[i:((i+batchsize)% dataset_size)]
            i = (i+batchsize)% dataset_size
        yield (img,label)
        
        
        

3. 如何使用 fit_generator

  • 首先让我们先测试一下我们的 generator 是否能够按照要求来产生我们想要的数据格式:
gen = generator(x_train_,y_train_,shuffle=True)

data_batch = x.__next__()

print(data_batch[0].shape)
print(data_batch[0])

在这里插入图片描述

  • 可以看见产生的数据格式是非常标准啦~

  • 接下来,把 generator 加载到 fit_generator 接口中:

net = cnn()			## 创建 cnn 网络
net.compile(loss=keras.losses.categorical_crossentropy,optimizer=keras.optimizers.Adam(0.001),metrics=['accuracy'])		
net.fit_generator(generator=gen,steps_per_epoch=dataset_size/batchsize,epochs=5,validation_data=(x_test_,y_test_))

在这里插入图片描述

  • 这里的 gen 就是我们刚才的 generator
  • steps_per_epoch 顾名思义,就是每一个 epoch 进行多少步:steps * steps_per_epoch = epoch 比如我们 generator 中定义了每一批产生 64 个数据,这对于 fit_generator 来说就是一个 step 的数据,所以每个 epoch=60000个数据的话: steps_per_epoch = 60000 / 64\
  • 为什么要用 step_per_epoch 呢, 因为 fit_generator 由于生成器 generator 的缘故,会一直进行循环数据的产生,从而一直不停下来,这时候我们需要人为设定每个 epoch 中有多少个 step,否则训练永远不会停止。想试验一下的小伙伴可以在训练的时候不写 step_per_epoch的参数试一下。

4. 完整代码

from keras.datasets import mnist
from keras.layers import Conv2D,MaxPool2D,Dropout,Flatten,Dense
from keras.models import Sequential
from keras.utils import to_categorical
import numpy as np
import keras 

(x_train,y_train),(x_test,y_test)= mnist.load_data()

x_train_ = np.expand_dims(x_train,3)
y_train_ = to_categorical(y_train)
x_test_ = np.expand_dims(x_test,3)
y_test_ = to_categorical(y_test)

def cnn():
    model = Sequential()
    model.add(Conv2D(input_shape=(28,28,1),filters=25,kernel_size=(3,3),padding='same',activation='relu')) 
    model.add(MaxPool2D())
    model.add(Dropout(rate=0.3))
    model.add(Flatten())
    model.add(Dense(32,activation='relu'))
    model.add((Dense(10,activation='softmax')))
    return model



batchsize = 64
dataset_size = x_train_.shape[0]

def generator(x_train_,y_train_,batchsize=batchsize,shuffle=True):
    dataset_size = x_train_.shape[0]
    while True:
        i = 0 
        if shuffle:
            img_index = np.random.randint(0,dataset_size,batchsize)
            img = x_train_[img_index]
            label = y_train_[img_index]
        else:
            img = x_train_[i:((i+batchsize)% dataset_size)]
            label = y_train_[i:((i+batchsize)% dataset_size)]
            i = (i+batchsize)% dataset_size
        yield (img,label)
        
net = cnn()
net.compile(loss=keras.losses.categorical_crossentropy,optimizer=keras.optimizers.Adam(0.001),metrics=['accuracy'])
net.fit_generator(generator=x,steps_per_epoch=dataset_size/batchsize,epochs=5,validation_data=(x_test_,y_test_))        
        

代码不复杂,希望大家深刻理解,也希望这篇文章能够帮助到你~~

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暖仔会飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值