Keras实例:generator生成器(多输入/ImageDataGenerator)

当我们在训练模型的时候,有时会因为数据太大造成OOM或者影响效率,generator是Keras的一种解决方案,不仅如此,generator还能在训练时根据需要实时进行数据增强,这次我们继续使用Keras多输入模型实例的代码。

生成器的关键是yield,它能在循环中不停的返回数据,每次返回之前,我们都可以对数据进行操作,比如增加噪音。善用此功能可以增加模型的鲁棒性。首先我们用一个while循环无限跑,因为我们并不知道一共要训练多少次数据。然后每次循环都返回下一组batch_size个数据。与之前不同的是,我们这次使用了dict而不是数组来产生input,dict的key必须与模型中Input的name参数一致。

def data_generator(x1, x2, y, batch_size):
	size = len(y)
	while 1:
		for i in range(int(size / batch_size)):
			in1 = x1[i*batch_size: (i+1)*batch_size]
			in2 = x2[i*batch_size: (i+1)*batch_size]
			out = y[i*batch_size: (i+1)*batch_size]

			in1 = in1.reshape(in1.shape[0], -1)
			in2 = in2.reshape(in2.shape[0], -1)

			yield {'in1' : in1, 'in2' : in2}, out

接下来就是如何使用这个generator了,传统的fit方法并不支持使用generator的方法,这个时候我们就需要使用fit_generator了。fit_generator并不支持validation_split的方法,因为数据不是一次全部读进来的,所以我们需要手动把训练集和验证集分开。并且我们需要设定一个参数:steps_per_epoch。这个参数决定了我们获取多少次数据来完成一次epoch。一般来说,我们设定 steps_per_epoch = data_size / batch_size,这样一个epoch正好跑完全部的数据。这里我们取80%做训练集,20%做验证集。

def train_model():
	x1,x2,y = load_data()
	data_size = int(0.8 * len(y))
	batch_size = 10
	
	train_datagen = data_generator(x1[:data_size], x2[:data_size], y[:data_size], batch_size)
	val_data = ({'in1':x1[data_size:], 'in2':x2[data_size:]}, y[data_size:]) #使用与generator相同格式的dict

	x1 = x1.reshape(x1.shape[0], -1)
	x2 = x2.reshape(x2.shape[0], -1)
	model = load_model(x1, x2)

	model.summary()
	reduce_lr = LearningRateScheduler(step_decay)
	model.fit_generator(train_datagen, epochs=500, steps_per_epoch=int(data_size/batch_size), validation_data=val_data, callbacks=[reduce_lr])
	model.save('linear.model')

查看一下结果,发现精度很高。

Epoch 500/500
8/8 [==============================] - 0s 4ms/step - loss: 3.7366e-07 - mae: 1.6553e-04 - val_loss: 4.9633e-09 - val_mae: 6.0201e-05

在做CNN或者图像相关的模型时,Keras提供了一个强大好用的图片生成器:ImageDataGenerator。具体的使用方法本文不讨论。但是ImageDataGenerator是只能生成单个输入的,当我们的模型是多输入时,便需要自定义我们自己设定generator了。假设我们的输入图片有face和body两种,去预测一个人的性别,并且我们要分开做不同的图片数据增强,这样我们可以分别定义两个ImageDataGenerator,然后给予相同的seed,这样生成的图片顺序也是对应的,要注意的是,如果不给相同的seed,或者不给seed的话,结果会出错,因为ImageDataGenerator给予的数据顺序是随机的,face和body的数据会对不上。每次循环可以使用next函数调取ImageDataGenerator,因为ImageDataGenerator内部也是一个yield生成数据。

def train_generator(face_img, body_img, y, batch_size, seed = 1000):
	face_gen = ImageDataGenerator(brightness_range=[0,100])
	body_gen = ImageDataGenerator()

	face_flow = face_gen.flow(face_img, y, batch_size=batch_size, seed=seed) # 给予数据
	body_flow = body_gen.flow(body_img, y, batch_size=batch_size, seed=seed)

	while 1:
		facein,out = next(face_flow)
		bodyin,_ = next(body_flow)
		yield {'face' : facein, 'body' : bodyin}, out

以上就是Keras的generator的使用方法了。

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值