本文主要是介绍Introduction to Advanced Machine Learning, 第三周,week3_task2_fine_tuning_clean(hse-aml/intro-to-dl 答案),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
这是俄罗斯高等经济学院的系列课程第一门,Introduction to Advanced Machine Learning,第三周编程作业。任务是利用pre-trained InceptionV3架构,使用花朵分类训练集,经过fine tune之后,能够用于花朵的识别。
这个作业一共两个部分,难易程度:容易。
1. prepared images for the model,图片剪裁
2. implemented your own batch generator,分批
3. fine-tuned the pre-trained model,训练
Fine-tuning InceptionV3 for flowers classification
In this task you will fine-tune InceptionV3 architecture for flowers classification task.
InceptionV3 architecture (https://research.googleblog.com/2016/03/train-your-own-image-classifier-with.html):
Flowers classification dataset (http://www.robots.ox.ac.uk/~vgg/data/flowers/102/index.html) consists of 102 flower categories commonly occurring in the United Kingdom. Each class contains between 40 and 258 images:
Import stuff
import sys
sys.path.append("..")
import grading
import download_utils
# !!! remember to clear session/graph if you rebuild your graph to avoid out-of-memory errors !!!
def reset_tf_session():K.clear_session()tf.reset_default_graph()s = K.get_session()return s
download_utils.link_all_keras_resources()
import tensorflow as tf
import keras
from keras import backend as K
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
print(tf.__version__)
print(keras.__version__)
import cv2 # for image processing
from sklearn.model_selection import train_test_split
import scipy.io
import os
import tarfile
import tqdm
import keras_utils
Using TensorFlow backend.1.2.1
2.0.6
Fill in your Coursera token and email
To successfully submit your answers to our grader, please fill in your Coursera submission token and email
grader = grading.Grader(assignment_key="2v-uxpD7EeeMxQ6FWsz5LA", all_parts=["wuwwC", "a4FK1", "qRsZ1"])
# token expires every 30 min
COURSERA_TOKEN = '124YSWW2CF2jlAdd'
COURSERA_EMAIL = 'calmly@yeah.net'
Load dataset
Dataset was downloaded for you, it takes 12 min and 400mb.
Relevant links (just in case):
- http://www.robots.ox.ac.uk/~vgg/data/flowers/102/index.html
- http://www.robots.ox.ac.uk/~vgg/data/flowers/102/102flowers.tgz
- http://www.robots.ox.ac.uk/~vgg/data/flowers/102/imagelabels.mat
# we downloaded them for you, just link them here
download_utils.link_week_3_resources()
Prepare images for model
# we will crop and resize input images to IMG_SIZE x IMG_SIZE
IMG_SIZE = 250
def decode_image_from_raw_bytes(raw_bytes):img = cv2.imdecode(np.asarray(bytearray(raw_bytes), dtype=np.uint8), 1)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)return img
We will take a center crop from each image like this:
def image_center_crop(img):"""Makes a square center crop of an img, which is a [h, w, 3] numpy array.Returns [min(h, w), min(h, w), 3] output with same width and height.For cropping use numpy slicing."""h = img.shape[0]w = img.shape[1]length = min(h,w)h_start = h//2 - length//2h_end = h_start + length w_start = w//2 - length//2w_end = w_start + length cropped_img = img[h_start:h_end, w_start:w_end, ]### YOUR CODE HEREreturn cropped_img
def prepare_raw_bytes_for_model(raw_bytes, normalize_for_model=True):img = decode_image_from_raw_bytes(raw_bytes) # decode image raw bytes to matriximg = image_center_crop(img) # take squared center cropimg = cv2.resize(img, (IMG_SIZE, IMG_SIZE)) # resize for our modelif normalize_for_model:img = img.astype("float32") # prepare for normalizationimg = keras.applications.inception_v3.preprocess_input(img) # normalize for modelreturn img
# reads bytes directly from tar by filename (slow, but ok for testing, takes ~6 sec)
def read_raw_from_tar(tar_fn, fn):with tarfile.open(tar_fn) as f:m = f.getmember(fn)return f.extractfile(m).read()
# test cropping
raw_bytes = read_raw_from_tar("102flowers.tgz", "jpg/image_00001.jpg")img = decode_image_from_raw_bytes(raw_bytes)
print(img.shape)
plt.imshow(img)
plt.show()img = prepare_raw_bytes_for_model(raw_bytes, normalize_for_model=False)
print(img.shape)
plt.imshow(img)
plt.show()
(500, 591, 3)
(250, 250, 3)
## GRADED PART, DO NOT CHANGE!
# Test image preparation for model
prepared_img = prepare_raw_bytes_for_model(read_raw_from_tar("102flowers.tgz", "jpg/image_00001.jpg"))
grader.set_answer("qRsZ1", list(prepared_img.shape) + [np.mean(prepared_img), np.std(prepared_img)])
# you can make submission with answers so far to check yourself at this stage
grader.submit(COURSERA_EMAIL, COURSERA_TOKEN)
Submitted to Coursera platform. See results on assignment page!
Prepare for training
# read all filenames and labels for them# read filenames firectly from tar
def get_all_filenames(tar_fn):with tarfile.open(tar_fn) as f:return [m.name for m in f.getmembers() if m.isfile()]all_files = sorted(get_all_filenames("102flowers.tgz")) # list all files in tar sorted by name
all_labels = scipy.io.loadmat('imagelabels.mat')['labels'][0] - 1 # read class labels (0, 1, 2, ...)
# all_files and all_labels are aligned now
N_CLASSES = len(np.unique(all_labels))
print(N_CLASSES)
102
# split into train/test
tr_files, te_files, tr_labels, te_labels = \train_test_split(all_files, all_labels, test_size=0.2, random_state=42, stratify=all_labels)
# will yield raw image bytes from tar with corresponding label
def raw_generator_with_label_from_tar(tar_fn, files, labels):label_by_fn = dict(zip(files, labels))with tarfile.open(tar_fn) as f:while True:m = f.next()if m is None:breakif m.name in label_by_fn:yield f.extractfile(m).read(), label_by_fn[m.name]
# batch generator
BATCH_SIZE = 32def batch_generator(items, batch_size):"""Implement batch generator that yields items in batches of size batch_size.There's no need to shuffle input items, just chop them into batches.Remember about the last batch that can be smaller than batch_size!Input: any iterable (list, generator, ...). You should do `for item in items: ...`In case of generator you can pass through your items only once!Output: In output yield each batch as a list of items."""return_batch = []cnt = 0for item in items:if cnt != batch_size:return_batch.append(item) else:yield return_batchprint(return_batch) return_batch = []return_batch.append(item)cnt = cnt%batch_size + 1if cnt != 0:yield return_batchprint(return_batch) ### YOUR CODE HERE
## GRADED PART, DO NOT CHANGE!
# Test batch generator
def _test_items_generator():for i in range(10):yield igrader.set_answer("a4FK1", list(map(lambda x: len(x), batch_generator(_test_items_generator(), 3))))
[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9]
# you can make submission with answers so far to check yourself at this stage
grader.submit('calmly@yeah.net', 'WOj4hMjSwhrVRiP7')
Submitted to Coursera platform. See results on assignment page!
def train_generator(files, labels):while True: # so that Keras can loop through this as long as it wantsfor batch in batch_generator(raw_generator_with_label_from_tar("102flowers.tgz", files, labels), BATCH_SIZE):# prepare batch imagesbatch_imgs = []batch_targets = []for raw, label in batch:img = prepare_raw_bytes_for_model(raw)batch_imgs.append(img)batch_targets.append(label)# stack images into 4D tensor [batch_size, img_size, img_size, 3]batch_imgs = np.stack(batch_imgs, axis=0)# convert targets into 2D tensor [batch_size, num_classes]batch_targets = keras.utils.np_utils.to_categorical(batch_targets, N_CLASSES)yield batch_imgs, batch_targets
# test training generator
for _ in train_generator(tr_files, tr_labels):print(_[0].shape, _[1].shape)plt.imshow(np.clip(_[0][0] / 2. + 0.5, 0, 1))break
(32, 250, 250, 3) (32, 102)
Training
You cannot train such a huge architecture from scratch with such a small dataset.
But using fine-tuning of last layers of pre-trained network you can get a pretty good classifier very quickly.
# remember to clear session if you start building graph from scratch!
s = reset_tf_session()
# don't call K.set_learning_phase() !!! (otherwise will enable dropout in train/test simultaneously)
def inception(use_imagenet=True):# load pre-trained model graph, don't add final layermodel = keras.applications.InceptionV3(include_top=False, input_shape=(IMG_SIZE, IMG_SIZE, 3),weights='imagenet' if use_imagenet else None)# add global pooling just like in InceptionV3new_output = keras.layers.GlobalAveragePooling2D()(model.output)# add new dense layer for our labelsnew_output = keras.layers.Dense(N_CLASSES, activation='softmax')(new_output)model = keras.engine.training.Model(model.inputs, new_output)return model
model = inception()
model.summary()
# how many layers our model has
print(len(model.layers))
313
# set all layers trainable by default
for layer in model.layers:layer.trainable = True# fix deep layers (fine-tuning only last 50)
for layer in model.layers[:-50]:layer.trainable = False
# compile new model
model.compile(loss='categorical_crossentropy', # we train 102-way classificationoptimizer=keras.optimizers.adamax(lr=1e-2), # we can take big lr here because we fixed first layersmetrics=['accuracy'] # report accuracy during training
)
# we will save model checkpoints to continue training in case of kernel death
model_filename = 'flowers.{0:03d}.hdf5'
last_finished_epoch = None#### uncomment below to continue training from model checkpoint
#### fill `last_finished_epoch` with your latest finished epoch
from keras.models import load_model
s = reset_tf_session()
last_finished_epoch = 15
model = load_model(model_filename.format(last_finished_epoch))
#print(model_filename)
#print(format(last_finished_epoch))
Training takes 2 hours. You’re aiming for ~0.93 validation accuracy.
# fine tune for 2 epochs (full passes through all training data)
# we make 2*8 epochs, where epoch is 1/8 of our training data to see progress more often
model.fit_generator(train_generator(tr_files, tr_labels), steps_per_epoch=len(tr_files) // BATCH_SIZE // 8,epochs=2 * 8,validation_data=train_generator(te_files, te_labels), validation_steps=len(te_files) // BATCH_SIZE // 4,callbacks=[keras_utils.TqdmProgressCallback(), keras_utils.ModelSaveCallback(model_filename)],verbose=0,initial_epoch=last_finished_epoch or 0
)
Epoch 16/16
## GRADED PART, DO NOT CHANGE!
# Accuracy on validation set
test_accuracy = model.evaluate_generator(train_generator(te_files, te_labels), len(te_files) // BATCH_SIZE // 2
)[1]
grader.set_answer("wuwwC", test_accuracy)
print(test_accuracy)
0.93
That’s it! Congratulations!
What you’ve done:
- prepared images for the model
- implemented your own batch generator
- fine-tuned the pre-trained model
这篇关于Introduction to Advanced Machine Learning, 第三周,week3_task2_fine_tuning_clean(hse-aml/intro-to-dl 答案)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!