1. 为什么要使用 fit_generator
- 我们都知道我们在进行神经网络训练的时候如果使用
model.fit的方式训练,

那么我们需要把整个x_train加载到内存中,而 keras 自带的一些 datasets 又很小,在训练的时候完全可以这么做,所以如果是 keras 的小白,可能觉得 fit 是一个很好用的训练方法,而且也习惯了这种方式。 - 但是,如果我现在想用
ImageNet数据集(1000000张图片,1000个类别)来进行训练,直接加载到内存,内存会爆掉,所以我们要批量地把他们放到内存里。那么这就产生了一个问题,我们使用fit来训练的时候,在接口中封装了batch_size的参数,我们只需要输入一个数字,他就能够按照我们输入的尺寸对数据集进行分割,方便又快捷,那么如果我们手动地让他们一批批地送入内存中进行训练,该如何实现呢?接下来进入第二部分,创建一个generator来替你完成原来fit中batch_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_))
代码不复杂,希望大家深刻理解,也希望这篇文章能够帮助到你~~

本文介绍如何在Keras中使用fit_generator处理大型ImageNet数据集,通过创建自定义生成器避免内存溢出,同时详细讲解了生成器的创建、fit_generator的使用以及完整代码示例。
1万+

被折叠的 条评论
为什么被折叠?



