1.数据集
jpg图像数据格式的MNIST数据集:(放在database1文件夹下面)
2.利用tkeras的数据生成器ImageDataGenerator去训练keras模型(MobileNet)
通过tf.io.file读取图像文件,然后用tf.image.decode_jpeg转文件格式,保存为np.array(list(float,int))格式
这样子的话,图像数据集就是全部被读取到内存中,这是非常占内存的!!!
接下来可以有两种方法训练keras模型:
- np.array(list(float,int))直接用model.fit
- np.array(list(float,int))转ImageDataGenerator,然后用model.fit_generator
这里面的区别就在于:
第1种方法则只能在保存为np.array(list(float,int))之前做一些数据增强或者图像处理,处理完之后就会固定下来不变,不能在训练过程中处理图像数据。
第2种方法中ImageDataGenerator可以在训练过程随机的进行数据增强或者图像处理。
训练过程如下:
- 通过tf.io.file读取图像文件,然后用tf.image.decode_jpeg转文件格式,保存为np.array(list(float,int))格式
- np.array(list(float,int))转ImageDataGenerator(或者不转也可以)
- 构建keras网络模型(MobileNet):from tensorflow_core.python.keras.applications.mobilenet import MobileNet
- 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文件夹。
完整代码:
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)