这篇文章主要介绍了keras中的图像生成器ImageDataGenerator的用法,详细介绍了每个参数什么意思,哪些参数 比较常用,另外在介绍一下keras中常用的四种模型保存和加载,包括h5(常用)、json和yaml、pb(这种模式我知道的在tensorflow和 opencv中可以直接读取)。
ImageDataGenerator
位于from tensorflow.keras.preprocessing.image import ImageDataGenerator
参数介绍:
- featurewise_center:使输入的均值为0,这个是以整个数据集的分布来处理的,所以变换后整体变化不大
- samplewise_center:使每个样本的均值为0,这个是针对每幅图片进行的,处理后的图像与原图差别很大
- featurewise_std_normalization:输入除以自身标准差
- samplewise_std_normalization:每个样本除以自身标准差
- zca_epsilon:ZCA白化中的epsilon参数,默认为1e-6
- zca_whitening:是否开启ZCA白化,取出图像颜色的冗余信息
- rotation_range:随机旋转的角度范围,整型,范围为[0,target]
- width_shift_range:图像水平偏移的范围
- height_shift_range:图像垂直偏移的范围,这两个一般不用
- brightness_range:亮度变化范围,包含两个浮点型的tuple或者list#旋转
- shear_range:错切变换,保持所有点的x坐标(或者y坐标)保持不变,而对应的y坐标(或者x坐标)则按比例发生平移,且平移的大小和该点到x轴(或y轴)的垂直距离成正比,效果像是图像被拉伸
- zoom_range:让图片在长或宽的方向进行放大,可以理解为某方向的resize,参数大于0小于1时,执行的是放大操作,当参数大于1时,执行的是缩小操作
- channel_shift_range:随机的通道偏移
- fill_mode:填充模式,"constant", "nearest", "reflect" or "wrap",默认是"nearest",比如在旋转时,超出尺寸的部分会怎么处理
- cval:填充的值,只有在fill_mode = "constant"时才有作用
- horizontal_flip:随机水平翻转
- vertical_flip:随机垂直翻转
- rescale:缩放因子,会乘在像素值上,默认是None
- preprocessing_function:自定义的处理函数,在其它预处理方法之后运行
- data_format:这个设置的是通道的模式,有channels_first和channels_last两种
- validation_split:生成验证集的比例(在0和1之间)
- dtype:制定生成的数据格式
flow_from_directory,只介绍一般情况下用到的参数
- directory:数据的路径,要求:将数据分为train和test两个文件夹,每个文件夹下每一类别再存放进一个子文件夹
- target_size:读取的每个图片都会resize到这个尺寸
- color_mode:默认rgb,一般不改变
- classes:识别的类别名称,类似于["dog","cat","fish"],训练和测试要一致
- class_mode:分类模式,默认是categorical,表示多分类
- batch_size:一批的大小
- shuffle:是否打乱数据,这个是必须的,默认为True
- seed:随机操作的随机种子
例子
train_generator = ImageDataGenerator(rotation_range=5, #旋转 horizontal_flip=True, #翻转 vertical_flip=True) test_generator = ImageDataGenerator()#一般情况下,测试图像不做增强 train_generator = ('./re/train/', target_size=(144,144), batch_size=32, classes=['bus','dinosaurs','elephants','flowers','horse']) #注意这里的classes貌似必须要声明,但是源码里说的是,不声明时,安装目录下的文件夹名来当做class。就我测试而言,同样的程序,不显式定义classes的话,准确率在80,显然是不正常的,显式声明的话,就达到99,所以我猜测是train_generator和test_generator都是读取子文件夹的名称为类别名,估计是按照读取的顺序来确定类别顺序,这样的话,上下两个flow_from_directory得到的类别列表就有可能不一样 test_generator = ('./re/test/', target_size=(144,144), batch_size=32, classes=['bus', 'dinosaurs', 'elephants', 'flowers', 'horse']) #此处是在网络中使用数据,fit_generator是将数据一批一批的送往GPU history_tl = model.fit_generator(train_generator, epochs=10, steps_per_epoch=400/32, validation_data=test_generator)keras可以保存的模型种类
- h5:此格式需要python提前安装h5py库,sudo pip install h5py
- json
- yaml
- pb
几种文件格式的区别
h5
我们可以将网络结构和权重一起保存为.h5文件,另外还包括模型训练时的配置(包括损失函数、优化器等),以及优化器的状态,比如优化器中变化的参数的状态等,优点是:操作非常方便,代码很少,缺点是:占用空间较大
model.save('my_model.h5') #用于保存模型 model = load_model('my_model.h5') #用于加载模型当然,我们也可以单独将网络的权重保存为.h5文件,并不保存结构。
#只保存了网络的权重 model.save_weights('my_model_weig;) #将网络初始化 ... #加载权重到搭建的网络 model.load_weights('my_model_weig;)json和yaml
一般只保存网络的结构,并不保存权重,配合save_weights和load_weights使用
import json import yaml json_model = model.to_json() #将网络结构保存为json字符串 open('model.json', 'w').write(json_model) #写入json文件 # yaml_model = model.to_yaml() #将网络结构保存为yaml字符串 # open('model.yaml', 'w').write(yaml_model) #写入yaml文件 model.save_weights('my_model_weig;) #单独保存权重参数 from keras.models import model_from_json,model_from_yaml #从文件中加载网络结构 json_model = model_from_json(open('model.json').read()) # yaml_model = model_from_yaml(open('model.yaml').read()) #单独加载权重参数 model.load_weights('my_model_weig;)pb
pb格式的文件里是保存了网络的结构和权重的,方便tensorflow和opencv调用。
#1、定义网络结构 model = ... #2、输出节点名称,用于查看output_node_names for layer in model.layers: prin) #3、生成pb格式的模型 sess = K.get_session() #获得当前的sess #这个是将模型的结构和权重固化,注意第二步输出的节点名称形式为dense_1/Softmax:0,但是这里传入时需要将:0删除,不然会提示找不到tensor,不太清楚原因,之前用tensorflow时是需要写全的 frozen_def = (sess,(),output_node_names=['dense_1/Softmax']) (frozen_def, './', ';, as_text=False) #将网络的结构和权重写进pb文件中 #4、在tensorflow中使用pb模型 with ().as_default(): output_graph_def = Def() with open(';, "rb") as f: #打开pb模型文件 ou()) #进行解析 _ = (output_graph_def, name="") with () as sess: #下面就是使用模型 ()) #下面的input_1:0和dense_1/Softmax:0都是通过步骤2查看的 #然而这里节点名称却带了:0,我猜测是keras的graph中保存的节点名是不包含:0的,当你选择保存为pb格式时,此时注意我们是使用tensorflow的形式进行保存的,所以又都被加上了:0,当你读取的时候自然也要加上:0 input_x = ("input_1:0") output = ("dense_1/Softmax:0") print((output, feed_dict={input_x: img}))