%reload_ext autoreload
%autoreload 2
%matplotlib inline
from fastai import *
from fastai.vision import *
from tqdm import tqdm_notebook
import PIL
import os
import shutil
img_path = '/home/jupyter/custom_datasets/pasta/'
prepared_path = '/home/jupyter/custom_datasets/pasta_prepared/'
os.makedirs(prepared_path, exist_ok=True)
for pasta_folder in os.listdir(img_path):
pasta_type = pasta_folder.split()[0]
filenames = os.listdir(os.path.join(img_path, pasta_folder))
for filename in tqdm_notebook(filenames):
ext = os.path.splitext(filename)[1]
if ext in ['.jpg', '.jpeg', '.png']:
full_src_path = os.path.join(img_path, pasta_folder, filename)
try:
img = PIL.Image.open(full_src_path)
except:
continue
shutil.copyfile(
os.path.join(img_path, pasta_folder, filename),
os.path.join(prepared_path, f'{pasta_type}_{filename}')
)
path_img = Path(prepared_path)
fnames = get_image_files(path_img)
for fname in fnames:
with PIL.Image.open(fname) as img:
img.save(fname)
path_img = Path(prepared_path)
fnames = get_image_files(path_img)
fnames[:5], len(fnames)
([PosixPath('/home/jupyter/custom_datasets/pasta_prepared/spaghetti_495.jpg'), PosixPath('/home/jupyter/custom_datasets/pasta_prepared/spaghetti_207.jpg'), PosixPath('/home/jupyter/custom_datasets/pasta_prepared/linguine_729.jpg'), PosixPath('/home/jupyter/custom_datasets/pasta_prepared/spaghetti_27.jpg'), PosixPath('/home/jupyter/custom_datasets/pasta_prepared/penne_435.png')], 3682)
pat = r'/([^/]+)_\d+.(?:jpg|png|jpeg)$'
np.random.seed(2)
data = ImageDataBunch.from_name_re(path_img, fnames, pat, ds_tfms=get_transforms(), size=224)
data.normalize(imagenet_stats)
data.show_batch(rows=5, figsize=(10,8))
print(data.classes)
len(data.classes),data.c
['spaghetti', 'linguine', 'penne', 'farfalle', 'fusilli']
(5, 5)
learn = ConvLearner(data, models.resnet34, metrics=error_rate)
learn.fit_one_cycle(4)
VBox(children=(HBox(children=(IntProgress(value=0, max=4), HTML(value='0.00% [0/4 00:00<00:00]'))), HTML(value…
Total time: 03:18 epoch train loss valid loss error_rate 1 1.236885 0.717455 0.286649 (00:49) 2 0.896984 0.600923 0.240838 (00:48) 3 0.691726 0.550127 0.229058 (00:49) 4 0.591316 0.546946 0.222513 (00:50)
learn.recorder.plot_losses()
learn.save('stage-1')
learn.load('stage-1')
interp = ClassificationInterpretation.from_learner(learn)
HBox(children=(IntProgress(value=0, max=6), HTML(value='')))
HBox(children=(IntProgress(value=0, max=6), HTML(value='0.00% [0/6 00:00<00:00]')))
interp.plot_confusion_matrix(figsize=(12,12), dpi=60)
interp.most_confused(min_val=2)
[('spaghetti', 'linguine', 36), ('linguine', 'spaghetti', 34), ('fusilli', 'farfalle', 20), ('farfalle', 'fusilli', 15), ('penne', 'fusilli', 10), ('fusilli', 'penne', 9), ('penne', 'farfalle', 8), ('linguine', 'farfalle', 6), ('linguine', 'penne', 5), ('farfalle', 'spaghetti', 5), ('penne', 'linguine', 4), ('spaghetti', 'penne', 3), ('farfalle', 'penne', 3), ('fusilli', 'spaghetti', 3)]
interp.plot_top_losses(9, figsize=(15,11))
Since our model is working as we expect it to, we will unfreeze our model and train some more.
learn.load('stage-1')
learn.unfreeze()
learn.lr_find(start_lr=1e-9)
VBox(children=(HBox(children=(IntProgress(value=0, max=3), HTML(value='0.00% [0/3 00:00<00:00]'))), HTML(value…
learn.recorder.plot()
learn.unfreeze()
learn.fit_one_cycle(2, max_lr=slice(1e-7,1e-4))
VBox(children=(HBox(children=(IntProgress(value=0, max=2), HTML(value='0.00% [0/2 00:00<00:00]'))), HTML(value…
Total time: 01:36 epoch train loss valid loss error_rate 1 0.501930 0.542925 0.217277 (00:48) 2 0.489032 0.532420 0.210733 (00:47)
learn.save('stage-2')
learn.load('stage-2')
learn.fit_one_cycle(4, max_lr=slice(1e-6,1e-4))
VBox(children=(HBox(children=(IntProgress(value=0, max=4), HTML(value='0.00% [0/4 00:00<00:00]'))), HTML(value…
Total time: 03:15 epoch train loss valid loss error_rate 1 0.454010 0.517948 0.204188 (00:50) 2 0.474383 0.501396 0.197644 (00:48) 3 0.431146 0.492708 0.195026 (00:49) 4 0.419746 0.489169 0.201571 (00:48)
learn.save('stage-3')
interp = ClassificationInterpretation.from_learner(learn)
HBox(children=(IntProgress(value=0, max=6), HTML(value='')))
HBox(children=(IntProgress(value=0, max=6), HTML(value='0.00% [0/6 00:00<00:00]')))
interp.plot_confusion_matrix(figsize=(12,12), dpi=60)
interp.most_confused(min_val=2)
[('spaghetti', 'linguine', 36), ('linguine', 'spaghetti', 32), ('fusilli', 'farfalle', 16), ('farfalle', 'fusilli', 13), ('fusilli', 'penne', 10), ('penne', 'fusilli', 9), ('penne', 'farfalle', 6), ('linguine', 'farfalle', 5), ('linguine', 'penne', 4), ('penne', 'linguine', 4), ('penne', 'spaghetti', 3), ('farfalle', 'spaghetti', 3), ('farfalle', 'penne', 3), ('fusilli', 'spaghetti', 3)]
interp.plot_top_losses(9, figsize=(15,11))
np.random.seed(2)
data = ImageDataBunch.from_name_re(path_img, fnames, pat, ds_tfms=get_transforms(), size=299, bs=26)
data.normalize(imagenet_stats)
learn = ConvLearner(data, models.resnet50, metrics=error_rate)
learn.fit_one_cycle(5)
VBox(children=(HBox(children=(IntProgress(value=0, max=5), HTML(value='0.00% [0/5 00:00<00:00]'))), HTML(value…
Total time: 05:19 epoch train loss valid loss error_rate 1 0.894858 0.569887 0.230563 (01:03) 2 0.613684 0.490064 0.190348 (01:04) 3 0.495972 0.412598 0.163539 (01:04) 4 0.377713 0.345537 0.128686 (01:02) 5 0.319166 0.338292 0.124665 (01:04)
learn.recorder.plot_losses()
learn.save('stage-1-50')
learn.load('stage-1-50')
interp = ClassificationInterpretation.from_learner(learn)
HBox(children=(IntProgress(value=0, max=15), HTML(value='')))
HBox(children=(IntProgress(value=0, max=15), HTML(value='0.00% [0/15 00:00<00:00]')))
interp.plot_confusion_matrix(figsize=(12,12))
interp.most_confused(min_val=2)
[('spaghetti', 'linguine', 27), ('linguine', 'spaghetti', 26), ('fusilli', 'farfalle', 7), ('spaghetti', 'fusilli', 4), ('farfalle', 'fusilli', 3), ('fusilli', 'spaghetti', 3), ('fusilli', 'linguine', 3), ('fusilli', 'penne', 3)]
interp.plot_top_losses(9, largest=True, figsize=(15,11))
learn.unfreeze()
learn.lr_find(start_lr=1e-9)
VBox(children=(HBox(children=(IntProgress(value=0, max=1), HTML(value='0.00% [0/1 00:00<00:00]'))), HTML(value…
learn.recorder.plot()
Lower batch size because of memory error in second epoch
(Also setting the same random sees as the previous databunch to make sure the train and validation sets remain the same)
np.random.seed(2)
data = ImageDataBunch.from_name_re(path_img, fnames, pat, ds_tfms=get_transforms(), size=299, bs=16)
data.normalize(imagenet_stats)
Create new learner object because databunch is part of the learner, and current learning still has a databunch with a higher batch size.
learn = ConvLearner(data, models.resnet50, metrics=error_rate)
learn.load('stage-1-50')
learn.fit_one_cycle(2, max_lr=slice(1e-7,1e-5))
VBox(children=(HBox(children=(IntProgress(value=0, max=2), HTML(value='0.00% [0/2 00:00<00:00]'))), HTML(value…
Total time: 02:12 epoch train loss valid loss error_rate 1 0.325695 0.339867 0.120643 (01:07) 2 0.323032 0.333728 0.134048 (01:04)
Finetuning doesn't seem to help