tf_ImageDataGenerator

ImageDataGenerator

本文章介绍了,直接通过Tensorflow 的ImageDataGenerator 来直接根据相应文件所在的标签目录 进行加载数据,并自动根据文件夹名字 进行自动分类,避免了人工进行标注。

对文件进行读取,并通过zip 进行解压,解压到指定文件夹。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import os
import zipfile

# 指定训练集zip的位置
local_zip = '/tmp/horse-or-human.zip'
# 对zip压缩包进行读取
zip_ref = zipfile.ZipFile(local_zip, 'r')
# 解压到指定目录
zip_ref.extractall('/tmp/horse-or-human')
# 指定 验证集zip的位置
local_zip = '/tmp/validation-horse-or-human.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')
zip_ref.extractall('/tmp/validation-horse-or-human')
# 关闭zip进程流 释放资源
zip_ref.close()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Directory with our training horse pictures
# horse 训练集目录
train_horse_dir = os.path.join('/tmp/horse-or-human/horses')

# Directory with our training human pictures
# human 训练集目录
train_human_dir = os.path.join('/tmp/horse-or-human/humans')

# Directory with our training horse pictures
# 设置验证集目录
validation_horse_dir = os.path.join('/tmp/validation-horse-or-human/horses')

# Directory with our training human pictures
validation_human_dir = os.path.join('/tmp/validation-horse-or-human/humans')
1
2
3
4
5
6
7
8
9
10
11
train_horse_names = os.listdir(train_horse_dir)
print(train_horse_names[:10])

train_human_names = os.listdir(train_human_dir)
print(train_human_names[:10])

validation_horse_hames = os.listdir(validation_horse_dir)
print(validation_horse_hames[:10])

validation_human_names = os.listdir(validation_human_dir)
print(validation_human_names[:10])
1
2
3
4
5
6
7
8
9
10
11
train_horse_names = os.listdir(train_horse_dir)
print(train_horse_names[:10])

train_human_names = os.listdir(train_human_dir)
print(train_human_names[:10])

validation_horse_hames = os.listdir(validation_horse_dir)
print(validation_horse_hames[:10])

validation_human_names = os.listdir(validation_human_dir)
print(validation_human_names[:10])

列出各目录下的 文件名称

[‘horse34-7.png’, ‘horse21-9.png’, ‘horse02-5.png’, ‘horse01-8.png’, ‘horse36-0.png’, ‘horse25-7.png’, ‘horse42-1.png’, ‘horse02-1.png’, ‘horse36-5.png’, ‘horse19-0.png’]
[‘human08-12.png’, ‘human14-08.png’, ‘human04-04.png’, ‘human03-27.png’, ‘human15-17.png’, ‘human02-00.png’, ‘human17-06.png’, ‘human04-29.png’, ‘human13-19.png’, ‘human05-00.png’]

1
2
3
4
5
6
7
8
9
10
11
%matplotlib inline

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

# Parameters for our graph; we'll output images in a 4x4 configuration
nrows = 4 # 设置plt幕布 行
ncols = 4 # 设置plt幕布 列

# Index for iterating over images
pic_index = 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Set up matplotlib fig, and size it to fit 4x4 pics
fig = plt.gcf()
fig.set_size_inches(ncols * 4, nrows * 4)

pic_index += 8
next_horse_pix = [os.path.join(train_horse_dir, fname)
for fname in train_horse_names[pic_index-8:pic_index]]
next_human_pix = [os.path.join(train_human_dir, fname)
for fname in train_human_names[pic_index-8:pic_index]]

for i, img_path in enumerate(next_horse_pix+next_human_pix):
# Set up subplot; subplot indices start at 1
sp = plt.subplot(nrows, ncols, i + 1)
sp.axis('Off') # Don't show axes (or gridlines)

img = mpimg.imread(img_path)
plt.imshow(img)

plt.show()

模型架构的搭建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import tensorflow as tf

model = tf.keras.models.Sequential([
# Note the input shape is the desired size of the image 300x300 with 3 bytes color
# This is the first convolution
tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(300, 300, 3)),
tf.keras.layers.MaxPooling2D(2, 2),
# The second convolution
tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# The third convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# The fourth convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# The fifth convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# Flatten the results to feed into a DNN
tf.keras.layers.Flatten(),
# 512 neuron hidden layer
tf.keras.layers.Dense(512, activation='relu'),
# Only 1 output neuron. It will contain a value from 0-1 where 0 for 1 class ('horses') and 1 for the other ('humans')
tf.keras.layers.Dense(1, activation='sigmoid')
])

# 输出 模型各层参数的大概
model.summary()
1
2
3
4
5
from tensorflow.keras.optimizers import RMSprop
# 模型编译,指定loss损失函数,metrics评估标准 以及optimizer优化器
model.compile(loss='binary_crossentropy',
optimizer=RMSprop(lr=0.001),
metrics=['acc'])

创建ImageDataGenerator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# All images will be rescaled by 1./255
# 利用ImageDataGenerator rescale 对读取图像进行正则化 归1
train_datagen = ImageDataGenerator(rescale=1/255)
validation_datagen = ImageDataGenerator(rescale=1/255)

# Flow training images in batches of 128 using train_datagen generator
# 创建训练样本生成器 ,指定训练目录,目录下不同image存放在 不同的 指定文件夹,并更具指定文件夹 自动设置label。
# 并通过设置target_size,在读取文件时 自动将image的shape 进行转换
train_generator = train_datagen.flow_from_directory(
'/tmp/horse-or-human/', # This is the source directory for training images
target_size=(300, 300), # All images will be resized to 150x150
batch_size=128,
# Since we use binary_crossentropy loss, we need binary labels
class_mode='binary')

# Flow training images in batches of 128 using train_datagen generator
validation_generator = validation_datagen.flow_from_directory(
'/tmp/validation-horse-or-human/', # This is the source directory for training images
target_size=(300, 300), # All images will be resized to 150x150
batch_size=32,
# Since we use binary_crossentropy loss, we need binary labels
class_mode='binary')

若使用Generator,则应使用model.fit_generator 进行训练

1
2
3
4
5
6
7
history = model.fit_generator(
train_generator,
steps_per_epoch=8,
epochs=15,
verbose=1,
validation_data = validation_generator,
validation_steps=8)

steps_per_epoch 根据样本数n,batch_size 来确定,告诉模型经过多少step 才代表一个batch为结束。

steps_per_epoch = n / batch_size

verbose = 0 时 模型训练时 只输出结果

verbose = 1 时 模型训练时 控制台不会出现进度条

verbose = 2 时 模型训练时 控制台出现进度条

图片特征提取处理

展示 卷积层Cov,最大池化层MaxPooling,各filter所提取的图片特征

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import numpy as np
import random
from tensorflow.keras.preprocessing.image import img_to_array, load_img

# Let's define a new Model that will take an image as input, and will output
# intermediate representations for all layers in the previous model after
# the first.
successive_outputs = [layer.output for layer in model.layers[1:]]
#visualization_model = Model(img_input, successive_outputs)
visualization_model = tf.keras.models.Model(inputs = model.input, outputs = successive_outputs)
# Let's prepare a random input image from the training set.
horse_img_files = [os.path.join(train_horse_dir, f) for f in train_horse_names]
human_img_files = [os.path.join(train_human_dir, f) for f in train_human_names]
img_path = random.choice(horse_img_files + human_img_files)

img = load_img(img_path, target_size=(300, 300)) # this is a PIL image
x = img_to_array(img) # Numpy array with shape (150, 150, 3)
x = x.reshape((1,) + x.shape) # Numpy array with shape (1, 150, 150, 3)

# Rescale by 1/255
x /= 255

# Let's run our image through our network, thus obtaining all
# intermediate representations for this image.
successive_feature_maps = visualization_model.predict(x)

# These are the names of the layers, so can have them as part of our plot
layer_names = [layer.name for layer in model.layers]

# Now let's display our representations
for layer_name, feature_map in zip(layer_names, successive_feature_maps):
if len(feature_map.shape) == 4:
# Just do this for the conv / maxpool layers, not the fully-connected layers
n_features = feature_map.shape[-1] # number of features in feature map
# The feature map has shape (1, size, size, n_features)
size = feature_map.shape[1]
# We will tile our images in this matrix
display_grid = np.zeros((size, size * n_features))
for i in range(n_features):
# Postprocess the feature to make it visually palatable
x = feature_map[0, :, :, i]
x -= x.mean()
x /= x.std()
x *= 64
x += 128
x = np.clip(x, 0, 255).astype('uint8')
# We'll tile each filter into this big horizontal grid
display_grid[:, i * size : (i + 1) * size] = x
# Display the grid
scale = 20. / n_features
plt.figure(figsize=(scale * n_features, scale))
plt.title(layer_name)
plt.grid(False)
plt.imshow(display_grid, aspect='auto', cmap='viridis')![download](/Users/lollipop/Desktop/download.png)

特征filter 只展示顶上两个

cov2d

max_pooling