有关海华AI比赛6

06.1.Observe hidden layers

Code by karbon
This notebook is a modified version of 04.2.MNIST and CNN.ipynb in order to observe the hidden layers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from __future__ import absolute_import, division, print_function, unicode_literals

# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import backend as K
from tensorflow.keras.models import Model

# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
import random

print(tf.__version__)

Import MNIST dataset and preprocess the dataset

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mnist = keras.datasets.mnist

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# grayscale image has only 1 channal
if K.image_data_format() == 'channels_first':
train_images = train_images.reshape(train_images.shape[0], 1, 28, 28)
test_images = test_images.reshape(test_images.shape[0], 1, 28, 28)
input_shape = (1, 28, 28)
else:
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1)
test_images = test_images.reshape(test_images.shape[0], 28, 28, 1)
input_shape = (28, 28, 1)

train_images_normed = train_images / 255.0
test_images_normed = test_images / 255.0
train_labels_onehot = keras.utils.to_categorical(train_labels, 10)
test_labels_onehot = keras.utils.to_categorical(test_labels, 10)

Build the model and train

This example is LeNet-5.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
model = keras.Sequential([
keras.layers.Conv2D(6, kernel_size=(5, 5),
activation='relu',
input_shape=input_shape),
keras.layers.MaxPooling2D(pool_size=(2, 2)),
keras.layers.Conv2D(16, kernel_size=(5, 5), activation='relu'),
keras.layers.MaxPooling2D(pool_size=(2, 2)),
keras.layers.Flatten(),
keras.layers.Dense(120, activation='relu'),
keras.layers.Dense(84, activation='relu'),
keras.layers.Dense(10, activation='softmax')
])

model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adam(),
metrics=['accuracy'])

model.fit(train_images_normed, train_labels_onehot, batch_size=100, epochs=6)
# It may need more than one minute

Make prediction and observe the hidden layers

1
model.summary()
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
num = random.randint(0, len(test_images))
inputImg = test_images[num]
inputImg = np.expand_dims(inputImg, axis=0)

predictions = model.predict(test_images_normed)

layer1 = Model(inputs=model.input, outputs=model.get_layer(index=0).output)
layer1_output = layer1.predict(inputImg)
layer2 = Model(inputs=model.input, outputs=model.get_layer(index=1).output)
layer2_output = layer2.predict(inputImg)
layer3 = Model(inputs=model.input, outputs=model.get_layer(index=2).output)
layer3_output = layer3.predict(inputImg)
layer4 = Model(inputs=model.input, outputs=model.get_layer(index=3).output)
layer4_output = layer4.predict(inputImg)


plt.figure(figsize=(18,18))
plt.subplot(5,3,2)
plt.imshow(inputImg[0,:,:,0])
for i in range(6):
img = layer1_output[0, :, :, i]
plt.subplot(5,6,i+7)
plt.imshow(img)
for i in range(6):
img = layer2_output[0, :, :, i]
plt.subplot(5,6,i+13)
plt.imshow(img)
for i in range(16):
img = layer3_output[0, :, :, i]
plt.subplot(10,8,i+49)
plt.imshow(img)
for i in range(16):
img = layer4_output[0, :, :, i]
plt.subplot(10,8,i+65)
plt.imshow(img)

GKN4aV.png

06.2.Better training methods

Attention! Before running this notebook, you need to run 05.1.ReadAnnotationsFromJSON.ipynb before

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from __future__ import absolute_import, division, print_function, unicode_literals

# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import backend as K
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import LearningRateScheduler
from tensorflow.keras.preprocessing import image
from tensorflow.keras.models import Model

# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
import random
import pandas as pd
import cv2

print(tf.__version__)

Import dataset and preprocessing

Because our dataset is a bit large, RAM may not be enough to directly load all images. We can use flow_from_dataframe to load our dataset. (click here to read more about this function)
First, load labels from our .csv file. We use pandas.read_csv, it loads csv file to DataFrame format.

1
2
3
df = pd.read_csv("./dataset/resizedFullGarbageDataset/train.csv", encoding='gbk', dtype=str)
df = df.sample(frac=1).reset_index(drop=True) # shuffle the datadrame
df

Then, use keras.preprocessing.image.ImageDataGenerator to load trainset.
You can add data augumentation settings in this function. Read more about this function.

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
batch_size = 32 #number one time
sizeX, sizeY = 112, 112 #size
apply_DataAugumentation = True #数据增强 change the picture in different way to increase the database

if apply_DataAugumentation:
datagen=ImageDataGenerator(rescale=1./255,
validation_split=0.1,
rotation_range=15, #旋转角度 rotation angle
width_shift_range=0.2, #大小 size
height_shift_range=0.2,
horizontal_flip=True, #水平镜像 reflection
vertical_flip=False, #垂直镜像
zoom_range=[0.8, 1], #缩放 zoom
fill_mode='reflect'
)
else:
datagen=ImageDataGenerator(rescale=1./255, validation_split=0.1) #10% is test group


trainset = datagen.flow_from_dataframe(dataframe=df, directory='./dataset/resizedFullGarbageDataset/train_resized',
x_col='filename', y_col='name', class_mode='categorical', target_size=(sizeX,sizeY),
batch_size=batch_size, shuffle=True, seed=42, subset='training')
testset = datagen.flow_from_dataframe(dataframe=df, directory='./dataset/resizedFullGarbageDataset/train_resized',
x_col='filename', y_col='name', class_mode='categorical', target_size=(sizeX,sizeY),
batch_size=batch_size, shuffle=True, seed=42, subset='validation')
1
2
3
4
5
6
names = trainset.class_indices

def getname(index):
return list(names)[index] #ues numbers to replace the names of different objects

names

trainset[i] has two parts. trainset[i][0] is the i-th batch of image, while trainset[i][1] is one-hot encodings which represents classes.

1
2
3
4
5
6
7
plt.figure(figsize=(16,8))
n = 123 # index of the batch you want to observe
for i in range(8):
plt.subplot(2,4,i+1)
plt.imshow(trainset[n][0][i])
index = np.argmax(trainset[n][1][i])
plt.xlabel(str(index) + ':' + getname(index))

example:

GKB2MF.png

Import a pre-trained model without prediction layers as feature extractor

1
2
3
4
5
6
7
8
9
10
input_shape = (sizeX, sizeY, 3)

from tensorflow.keras.applications.inception_v3 import InceptionV3 # use InceptionV3 as example
#we can change the model(from Keras documentation)
from tensorflow.keras.applications.inception_v3 import preprocess_input, decode_predictions #the function in the model
from tensorflow.keras.regularizers import l2

base_model = InceptionV3(weights='imagenet', include_top=False, input_shape=input_shape)
#the setting is according to the Keras Documentation
base_model.summary()

Add prediction layers

1
2
3
4
5
6
7
8
9
x = base_model.output
x = keras.layers.AveragePooling2D(pool_size=(2, 2))(x)
x = keras.layers.Dropout(.4)(x)
x = keras.layers.Flatten()(x)
x = keras.layers.Dense(198, kernel_initializer='glorot_uniform', kernel_regularizer=l2(.0005), activation='softmax')(x)

model_finetune = Model(inputs=base_model.input, outputs=x)

model_finetune.summary()

Define optimizer and compile the model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def schedule(epoch):   #change the length of every step according to the epoch
if epoch <= 3:
return .01
elif epoch <= 7:
return .002
else:
return .0004 #change the step as the epoch change
lr_scheduler = LearningRateScheduler(schedule)

sgd = keras.optimizers.SGD(lr=.01, momentum=.9)

model_finetune.compile(loss=keras.losses.categorical_crossentropy,
optimizer=sgd,
metrics=["accuracy"])

Start learning

Because the dataset is large, it may take a very long time.

1
2
3
4
5
6
7
8
9
10
11
STEP_SIZE_TRAIN=trainset.n//trainset.batch_size
STEP_SIZE_VALID=testset.n//testset.batch_size
print(STEP_SIZE_TRAIN, STEP_SIZE_VALID)

model_finetune.fit_generator(generator=trainset,
steps_per_epoch=STEP_SIZE_TRAIN,
validation_data=testset,
validation_steps=STEP_SIZE_VALID,
epochs=10, #this control the times it runs, the more the more accurate,but it have a top value
callbacks=[lr_scheduler]
)

Evaluate the model

1
model_finetune.evaluate_generator(testset,verbose=1) #add more layer

Save the trained model

1
2
modelname = 'finetuneExample0-9964' 
model_finetune.save('./trainedModels/' + modelname + '.h5')