该项目旨在教会机器识别马和人的图像
获取数据
训练数据集:horse-or-human
测试数据集:validation-horse-or-human
图片预处理
当图片数据过大,且图片的尺寸不一致时,就需要对图片进行预处理操作,将其裁剪成规定大小的图片,然后再生成器中要指定每个批次中要训练的图片的数量。代码如下:
from tensorflow.keras.preprocessing.image import ImageDataGenerator
#创建两个数据生成器,指定scaling范围0-1
train_datagen = ImageDataGenerator(rescale=1/255)
validation_datagen = ImageDataGenerator(rescale=1/255)
#指定训练数据文件夹
train_generator = train_datagen.flow_from_directory(
'F:\\ML_Data\\horse-or-human\\train', #训练数据所在文件夹
target_size=(300,300), #指定输出尺寸
batch_size=32, #单次传递给程序用以训练的参数个数
class_mode='binary') #指定二分类
#指定测试数据文件夹
validation_generator = validation_datagen.flow_from_directory(
'F:\\ML_Data\\horse-or-human\\validation', #训练数据所在文件夹
target_size=(300,300), #指定输出尺寸
batch_size=32, #单次传递给程序用以训练的参数个数
class_mode='binary') #指定二分类
构建神经网络
import tensorflow as tf
from tensorflow.keras.optimizers import RMSprop
model = tf.keras.models.Sequential([
#第一个卷积
tf.keras.layers.Conv2D(16,(3,3),activation='relu',input_shape=(300,300,3)), #300x300和三字节颜色
tf.keras.layers.MaxPooling2D(2,2),
#第二个卷积
tf.keras.layers.Conv2D(32,(3,3),activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
#第三个卷积
tf.keras.layers.Conv2D(64,(3,3),activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
#展开输入神经网络
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(512,activation='relu'), #512个神经元
tf.keras.layers.Dense(1,activation='sigmoid') #1个神经元输出,0代表马,1代表人
])
model.compile(loss='binary_crossentropy',optimizer=RMSprop(lr=0.001),metrics=['acc'])
输入神经网络
history = model.fit(
train_generator, #输入数据
epochs = 15, #训练轮数
verbose = 1, #日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录
validation_data = validation_generator, #指定的验证集
validation_steps = 8 #表示将一个epoch的训练集数据分为多少个batch
)
运行结果:
模型参数的优化
这里相信大家跟我都有一个问题,我们怎么知道设定多少个过滤器、卷积层重复循环多少遍、定义多少个神经元?如何确定这些参数才能达到最好的效果。
这里我们可以调用Hyperband库和HyperParameters库来让机器自己判断如何定义这些参数合适。其实就是在一个区间内循环跑好几遍,选结果最优的参数然后将其保存下来。
# 人马识别项目参数优化
from tensorflow.keras.preprocessing.image import ImageDataGenerator
#创建两个数据生成器,指定scaling范围0-1
train_datagen = ImageDataGenerator(rescale=1/255)
validation_datagen = ImageDataGenerator(rescale=1/255)
#指定训练数据文件夹
train_generator = train_datagen.flow_from_directory(
'F:\\ML_Data\\horse-or-human\\train', #训练数据所在文件夹
target_size=(150,150), #指定输出尺寸
batch_size=32, #单次传递给程序用以训练的参数个数
class_mode='binary') #指定二分类
#指定测试数据文件夹
validation_generator = validation_datagen.flow_from_directory(
'F:\\ML_Data\\horse-or-human\\validation', #训练数据所在文件夹
target_size=(150,150), #指定输出尺寸
batch_size=32, #单次传递给程序用以训练的参数个数
class_mode='binary') #指定二分类
import tensorflow as tf
from tensorflow.keras.optimizers import RMSprop
#调用调参库
from kerastuner.tuners import Hyperband
from kerastuner.engine.hyperparameters import HyperParameters
hp = HyperParameters()
def build_model(hp):
model = tf.keras.models.Sequential()
# 寻找最优过滤器个数
model.add(tf.keras.layers.Conv2D(hp.Choice('num_filters_layer0',values=[16,64],default=16),(3,3),activation='relu',input_shape=(150,150,3)))
model.add(tf.keras.layers.MaxPooling2D(2,2))
# 寻找最优卷积层处理遍数
for i in range (hp.Int("num_conv_layers",1,3)):
# 寻找每一层最优过滤器个数
model.add(tf.keras.layers.Conv2D(hp.Choice(f'num_filters_layer{i+1}',values=[16,64],default=16),(3,3),activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(2,2))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(hp.Int("hidden_units",128,512,step=32),activation='relu')) # 在[128,512]区间中每次递增32,寻找最优神经元个数
model.add(tf.keras.layers.Dense(1,activation='sigmoid'))
model.compile(loss='binary_crossentropy',optimizer=RMSprop(lr=0.001),metrics=['acc'])
return model
tuner = Hyperband(
build_model,
objective='val_acc',
max_epochs=15,
directory='horse_human_params',
hyperparameters=hp,
project_name='my_horse_human_project'
)
tuner.search(train_generator,epochs=10,validation_data=validation_generator)
#model.fit(train_generator,epochs=10,validation_data=validation_generator)
best_hps = tuner.get_best_hyperparameters(1)[0]
print(best_hps.values) #查看最优参数
运行结果:
由此可见,第一个卷积层设置16个过滤器,之后再重复3次。每次过滤器个数分别为16,64,64.神经元个数为384。但缺点是运行时间太长了,这里花了59m19s才跑出循环。
呜呜呜,运行上面结果时f’num_filters_layer{i+1}'忘了+1。这导致两个layer0重合了,所以在运行结果里大家只看见三层layer,最开始那层被覆盖了。跑一次太久了运行结果图就不做更正了。
我们运用算出的最优参数构建模型看看。
model = tuner.hypermodel.build(best_hps) # 按照算出的最优参数构建模型
model.summary() # 查看模型详情
运行结果: