【Tensorflow】训练keras模型+keras的数据生成器ImageDataGenerator+jpg图像数据格式的MNIST数据集+对比flow和flow_from_directory

1.数据集

jpg图像数据格式的MNIST数据集:(放在database1文件夹下面)

 

2.利用tkeras的数据生成器ImageDataGenerator去训练keras模型(MobileNet)

通过tf.io.file读取图像文件,然后用tf.image.decode_jpeg转文件格式,保存为np.array(list(float,int))格式

这样子的话,图像数据集就是全部被读取到内存中,这是非常占内存的!!!

接下来可以有两种方法训练keras模型:

  1. np.array(list(float,int))直接用model.fit
  2. np.array(list(float,int))转ImageDataGenerator,然后用model.fit_generator

这里面的区别就在于:

第1种方法则只能在保存为np.array(list(float,int))之前做一些数据增强或者图像处理,处理完之后就会固定下来不变,不能在训练过程中处理图像数据。

第2种方法中ImageDataGenerator可以在训练过程随机的进行数据增强或者图像处理。

 

训练过程如下:

  1. 通过tf.io.file读取图像文件,然后用tf.image.decode_jpeg转文件格式,保存为np.array(list(float,int))格式
  2. np.array(list(float,int))转ImageDataGenerator(或者不转也可以)
  3. 构建keras网络模型(MobileNet):from tensorflow_core.python.keras.applications.mobilenet import MobileNet
  4. keras训练:model.fit或者model.fit_generator

 

1)np.array(list(float,int))直接用model.fit

完整代码:

train_keras_from_nparraydata.py

import tensorflow as tf
import random
import pathlib
from tensorflow import keras
import os
import numpy as np
from my_input_data import input_data_list
import gc



im_w=128
im_h=128
# im_channels=3

train_image_list,train_label_list,test_image_list,test_label_list,label_names=input_data_list('../database1/')

classes=len(label_names)
nums_for_training=len(train_image_list)
batch_size=32
steps_per_epoch=int(nums_for_training/batch_size) 
epochs=10
print(nums_for_training)
print(steps_per_epoch)


def train_preprocess_image(path):
    image = tf.io.read_file(path)  # 读取图片
    image = tf.image.decode_jpeg(image, channels=3)
    # image = tf.image.grayscale_to_rgb(image)
    
    image = tf.image.resize(image, [im_w, im_h])  # 原始图片大小为(100, 100, 3),重设为(192, 192)
    
    #随机调整图像的亮度
    image = tf.image.random_brightness(image,max_delta=30)
    
    #随机设置图片的对比度
    image = tf.image.random_contrast(image,lower=0.2,upper=1.8)
    
    #随机设置图片的色度
    image = tf.image.random_hue(image,max_delta=0.3)
    
    #随机设置图片的饱和度
    image = tf.image.random_saturation(image,lower=0.2,upper=1.8)
    
    image = tf.cast(image, dtype=tf.float32) / 255.0
    return image

def test_preprocess_image(path):
    image = tf.io.read_file(path)  # 读取图片
    image = tf.image.decode_jpeg(image, channels=3)
    # image = tf.image.grayscale_to_rgb(image)
    image = tf.image.resize(image, [im_w, im_h])  # 原始图片大小为(100, 100, 3),重设为(192, 192)
    image = tf.cast(image, dtype=tf.float32) / 255.0
    return image

def preprocess_label(label):
    label = tf.cast(label, dtype=tf.int32)
    label = tf.one_hot(label, depth=classes)
    return label

train_image = []
train_label = []
for image, label in zip(train_image_list, train_label_list):
    r_image = train_preprocess_image(image)
    r_label = preprocess_label(label)
    train_image.append(r_image)
    train_label.append(r_label)
    
train_images = np.array(train_image)
train_labels = np.array(train_label)
print(train_images.shape)


test_image = []
test_label = []
for image, label in zip(test_image_list, test_label_list):
    r_image = train_preprocess_image(image)
    r_label = preprocess_label(label)
    test_image.append(r_image)
    test_label.append(r_label)
    
test_images = np.array(test_image)
test_labels = np.array(test_label)




from tensorflow_core.python.keras.applications.mobilenet import MobileNet
model=MobileNet(input_shape=(im_w, im_h,3),weights=None,include_top=True,classes=classes)
model.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])


model.fit(train_images, train_labels,batch_size=batch_size,steps_per_epoch=steps_per_epoch, epochs=epochs)

cost = model.evaluate(test_images, test_labels)
print('test loss: ', cost)


del train_image,train_label,test_images,test_labels
gc.collect()

这里补充一下tensorflow-V1和tensorflow-V2的区别:(简单做了验证实验)

在tensorflow-V1中,tf.image的方法返回的变量类型都是<class 'tensorflow.python.framework.ops.Tensor'>也就是tf.Tensor,直接用print打印的话会得到:Tensor("resize_910/Squeeze:0", shape=(128, 128, 3), dtype=float32)

在tensorflow-V2中,tf.image的方法返回的变量类型是<class 'tensorflow.python.framework.ops.EagerTensor'>也就是tf.EagerTensor,直接用print打印的话会得到:tf.Tensor(arraydata, shape=(128, 128, 3), dtype=float32),其中arraydata是指矩阵的原始数据

对比之后可以发现,tf.EagerTensor中是带有arraydata数据的,因此可以通过np.array或者list,转为可以使用的原始float数据,而tf.Tensor只能是用sess.run之后才能得到原始float数据,这也是为什么tensoflow-V1难调试的原因。

以博主的水平难说好坏,就这样用着先吧~

 

2)np.array(list(float,int))转ImageDataGenerator,然后用model.fit_generator


完整代码:

train_keras_from_kerasgenerator.py

# -*- coding: utf-8 -*-
"""
Created on Fri Jan 29 20:36:16 2021

@author: Leon_PC
"""

import tensorflow as tf
import random
import pathlib
from tensorflow import keras
import os
import numpy as np
from my_input_data import input_data_list
import gc



im_w=128
im_h=128
# im_channels=3

train_image_list,train_label_list,test_image_list,test_label_list,label_names=input_data_list('../database1/')

classes=len(label_names)
nums_for_training=len(train_image_list)
batch_size=32
steps_per_epoch=int(nums_for_training/batch_size) 
epochs=10
print(nums_for_training)
print(steps_per_epoch)


def train_preprocess_image(path):
    image = tf.io.read_file(path)  # 读取图片
    image = tf.image.decode_jpeg(image, channels=3)
    # image = tf.image.grayscale_to_rgb(image)
    
    image = tf.image.resize(image, [im_w, im_h])  # 原始图片大小为(100, 100, 3),重设为(192, 192)
    
    # #随机调整图像的亮度
    # image = tf.image.random_brightness(image,max_delta=30)
    
    # #随机设置图片的对比度
    # image = tf.image.random_contrast(image,lower=0.2,upper=1.8)
    
    # #随机设置图片的色度
    # image = tf.image.random_hue(image,max_delta=0.3)
    
    # #随机设置图片的饱和度
    # image = tf.image.random_saturation(image,lower=0.2,upper=1.8)
    
    # image = tf.cast(image, dtype=tf.float32) / 255.0
    return image

def test_preprocess_image(path):
    image = tf.io.read_file(path)  # 读取图片
    image = tf.image.decode_jpeg(image, channels=3)
    # image = tf.image.grayscale_to_rgb(image)
    image = tf.image.resize(image, [im_w, im_h])  # 原始图片大小为(100, 100, 3),重设为(192, 192)
    # image = tf.cast(image, dtype=tf.float32) / 255.0
    return image

def preprocess_label(label):
    label = tf.cast(label, dtype=tf.int32)
    label = tf.one_hot(label, depth=classes)
    return label

train_image = []
train_label = []
for image, label in zip(train_image_list, train_label_list):
    r_image = train_preprocess_image(image)
    r_label = preprocess_label(label)
    train_image.append(r_image)
    train_label.append(r_label)
    
train_images = np.array(train_image)
train_labels = np.array(train_label)
print(train_images.shape)


test_image = []
test_label = []
for image, label in zip(test_image_list, test_label_list):
    r_image = train_preprocess_image(image)
    r_label = preprocess_label(label)
    test_image.append(r_image)
    test_label.append(r_label)
    
test_images = np.array(test_image)
test_labels = np.array(test_label)



# from keras.utils import np_utils
# y_train = np_utils.to_categorical(train_labels, classes)
# y_test = np_utils.to_categorical(test_labels, classes)

# train_datagen = keras.preprocessing.image.ImageDataGenerator()
train_datagen = keras.preprocessing.image.ImageDataGenerator(
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)
test_datagen = keras.preprocessing.image.ImageDataGenerator(rescale=1./255)



train_datagen.fit(train_images) 
test_datagen.fit(test_images) 



from tensorflow_core.python.keras.applications.mobilenet import MobileNet
model=MobileNet(input_shape=(im_w, im_h,3),weights=None,include_top=True,classes=classes)
model.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])


model.fit_generator(train_datagen.flow(train_images, train_labels, batch_size=batch_size),steps_per_epoch=steps_per_epoch, epochs=epochs)

cost = model.evaluate(test_datagen.flow(test_images, test_labels))
print('test loss: ', cost)


del train_image,train_label,test_images,test_labels
gc.collect()

 

3)相关补充代码:my_input_data.py

my_input_data.py

# -*- coding: utf-8 -*-
"""
Created on Sat Jan 30 15:08:38 2021

@author: Leon_PC
"""
import random
import pathlib
import os
def input_data_list(file_dir,train_ratio=4/5):
    # data_path = pathlib.Path('./database1/')
    data_path = pathlib.Path(file_dir)
    print(type(data_path))#<class 'pathlib.WindowsPath'>
    all_image_paths = list(data_path.glob('*/*'))  
    print(type(data_path.glob('*/*')))#<class 'generator'>
    # print(all_image_paths)
    
    # all_image_paths = [str(path) for path in all_image_paths]  # 所有图片的相对路径的列表
    all_image_paths = [os.path.abspath(path) for path in all_image_paths]  # 所有图片的绝对路径的列表
    random.shuffle(all_image_paths)  # 打散
    # print(all_image_paths[0:3])
    
    image_count = len(all_image_paths)
    print('image_count: ',image_count)
    
    
    label_names = sorted(item.name for item in data_path.glob('*/') if item.is_dir())
    # print('label_names: ',label_names)
    label_to_index = dict((name, index) for index, name in enumerate(label_names))
    # print('label_to_index: ',label_to_index)
    all_image_labels = [label_to_index[pathlib.Path(path).parent.name] for path in all_image_paths]
    
    # classes=len(label_names)
    print(label_names)
    
    # train_ratio=4/5
    nums_for_training=int(len(all_image_paths)*train_ratio)
    
    train_image_list = list(all_image_paths[0:nums_for_training])
    train_label_list = list(all_image_labels[0:nums_for_training])
    test_image_list = list(all_image_paths[nums_for_training:len(all_image_paths)])
    test_label_list = list(all_image_labels[nums_for_training:len(all_image_paths)])  
    return train_image_list,train_label_list,test_image_list,test_label_list,label_names



if __name__=='__main__':
    input_data('../database1/')

 

4)对比flow和flow_from_directory

ImageDataGenerator.flow_from_directory方法,可以直接用分好train和test的文件夹读取数据,转化为ImageDataGenerator

所以还是:database1这个数据集了,博主没有分为train和test,直接将‘../database/’输出flow_from_directory

这个方法适合于提前做好train和test的数据集,但是一般来说应该都是train和test放在一起的然后按比例随机分配吧,不过还是蛮适合新手去用的,前提是用python写好批处理程序自动分好train和test文件夹。

官方给出的例子:https://tensorflow.google.cn/versions/r2.1/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator

完整代码:

train_keras_from_kerasgenerator_fromdirectory.py

# -*- coding: utf-8 -*-
"""
Created on Fri Jan 29 20:36:16 2021

@author: Leon_PC
"""

import tensorflow as tf
from tensorflow import keras

im_w=128
im_h=128
# im_channels=3
batch_size=32
classes=10

train_datagen = keras.preprocessing.image.ImageDataGenerator(
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)

image_path='../database1/'
train_data_gen = train_datagen.flow_from_directory(directory=image_path,
                                                           batch_size=batch_size,
                                                           shuffle=True,   #打乱数据
                                                           target_size=(im_h, im_w),
                                                           class_mode='categorical')
print(train_data_gen)#<keras_preprocessing.image.directory_iterator.DirectoryIterator object at 0x00000204624B8550>

nums_for_training=train_data_gen.n

steps_per_epoch=int(nums_for_training/batch_size) 
epochs=10
print(nums_for_training)
print(steps_per_epoch)


from tensorflow_core.python.keras.applications.mobilenet import MobileNet
model=MobileNet(input_shape=(im_w, im_h,3),weights=None,include_top=True,classes=classes)
model.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])


model.fit_generator(train_data_gen,steps_per_epoch=steps_per_epoch, epochs=epochs,max_queue_size=1,workers=1)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值