From Model to Production#

%load_ext autoreload
%autoreload 2

Imports#

from fastai.vision.all import *
from fastai.vision.widgets import *
from aiking.data.external import * #We need to import this after fastai modules
import warnings

warnings.filterwarnings("ignore")

Constructing Dataset#

clstypes = ["Grizzly Bear", 'Black Bear', "Teddy Bear"]
dest = "Bears"
path = construct_image_dataset(clstypes, dest, key=os.getenv("BING_KEY"), loc=None, count=150, engine='bing'); path
Path('/Landmark2/pdo/aiking/data/Bears')
(path/"Teddy_Bear").ls()
(#146) [Path('/Landmark2/pdo/aiking/data/Bears/Teddy_Bear/00000086.png'),Path('/Landmark2/pdo/aiking/data/Bears/Teddy_Bear/00000057.png'),Path('/Landmark2/pdo/aiking/data/Bears/Teddy_Bear/00000146.JPG'),Path('/Landmark2/pdo/aiking/data/Bears/Teddy_Bear/00000076.jpg'),Path('/Landmark2/pdo/aiking/data/Bears/Teddy_Bear/00000004.jpg'),Path('/Landmark2/pdo/aiking/data/Bears/Teddy_Bear/00000129.jpeg'),Path('/Landmark2/pdo/aiking/data/Bears/Teddy_Bear/00000078.jpg'),Path('/Landmark2/pdo/aiking/data/Bears/Teddy_Bear/00000127.jpg'),Path('/Landmark2/pdo/aiking/data/Bears/Teddy_Bear/00000003.jpg'),Path('/Landmark2/pdo/aiking/data/Bears/Teddy_Bear/00000036.jpg')...]

Define DataBlock#

?DataBlock
Init signature:
DataBlock(
    blocks=None,
    dl_type=None,
    getters=None,
    n_inp=None,
    item_tfms=None,
    batch_tfms=None,
    *,
    get_items=None,
    splitter=None,
    get_y=None,
    get_x=None,
)
Docstring:      Generic container to quickly build `Datasets` and `DataLoaders`
File:           ~/anaconda3/envs/aiking/lib/python3.8/site-packages/fastai/data/block.py
Type:           type
Subclasses:     
bears = DataBlock(
    blocks = (ImageBlock, CategoryBlock),
    get_items=get_image_files,
    splitter=RandomSplitter(valid_pct=0.2, seed=42), 
    get_y=parent_label,
    item_tfms=Resize(128)
); bears
<fastai.data.block.DataBlock at 0x7f127cb77970>
dls = bears.dataloaders(path); dls
<fastai.data.core.DataLoaders at 0x7f127cb027c0>
dls.valid.show_batch(max_n=4, nrows=1)
../../_images/production_11_0.png
bears = bears.new(item_tfms=Resize(128, ResizeMethod.Squish))
dls = bears.dataloaders(path)
dls.valid.show_batch(max_n=4, nrows=1)
../../_images/production_12_0.png
bears = bears.new(item_tfms=Resize(128, ResizeMethod.Pad, pad_mode='zeros'))
dls = bears.dataloaders(path)
dls.valid.show_batch(max_n=4, nrows=1)
../../_images/production_13_0.png
bears = bears.new(item_tfms=RandomResizedCrop(300, min_scale=0.1))
dls = bears.dataloaders(path)
dls.valid.show_batch(max_n=4, nrows=1, unique=True)
../../_images/production_14_0.png
bears=bears.new(item_tfms=Resize(128),
                batch_tfms=aug_transforms(mult=2))
dls=bears.dataloaders(path)
dls.train.show_batch(max_n=8,nrows=2,unique=True)
../../_images/production_15_0.png

Data Augmentation#

bears=bears.new(item_tfms=RandomResizedCrop(224,min_scale=0.5),
                batch_tfms=aug_transforms())
dls=bears.dataloaders(path)
dls.train.show_batch(max_n=8,nrows=2,unique=True)
../../_images/production_17_0.png

Training & Fine Tuning#

learn = cnn_learner(dls, resnet18, metrics=accuracy); learn
<fastai.learner.Learner at 0x7f12d7830760>
learn.fine_tune(4)
epoch train_loss valid_loss accuracy time
0 1.376441 0.216977 0.921053 00:12
epoch train_loss valid_loss accuracy time
0 0.221669 0.076347 0.986842 00:11
1 0.164557 0.035963 0.986842 00:11
2 0.114788 0.023873 1.000000 00:12
3 0.102989 0.022870 1.000000 00:11

Interpretation#

interp = ClassificationInterpretation.from_learner(learn); interp
<fastai.interpret.ClassificationInterpretation at 0x7f12ce3cd340>
interp.plot_confusion_matrix()
../../_images/production_23_0.png
interp.plot_top_losses(5, nrows=5)
../../_images/production_24_0.png

Data Cleaning [ML Driven]#

cleaner = ImageClassifierCleaner(learn)
cleaner
for idx in cleaner.delete(): cleaner.fns[idx].unlink()
for idx,cat in cleaner.change():
    shutil.move(str(cleaner.fns[idx]), path/cat)

Retraining#

bears=bears.new(item_tfms=RandomResizedCrop(224,min_scale=0.5),
                batch_tfms=aug_transforms())
dls=bears.dataloaders(path)
dls.train.show_batch(max_n=8,nrows=2,unique=True)
learn = cnn_learner(dls, resnet18, metrics=accuracy); learn
learn.fine_tune(4)
epoch train_loss valid_loss accuracy time
0 1.306404 0.231466 0.934211 00:11
epoch train_loss valid_loss accuracy time
0 0.241304 0.076639 0.973684 00:11
1 0.165573 0.045445 0.986842 00:11
2 0.141758 0.055787 0.986842 00:12
3 0.109832 0.060983 0.986842 00:12
interp = ClassificationInterpretation.from_learner(learn); interp
interp.plot_confusion_matrix()
../../_images/production_32_1.png
interp.plot_top_losses(3, nrows=3)
../../_images/production_33_0.png

Model Export#

c = Config()
# c.model_path.mkdir()
(c.learner_path/'bears.pkl').unlink()
learn.export(c.learner_path/'bears.pkl')
c.model_path.ls()
(#1) [Path('/Landmark2/pdo/aiking/models/bears.pkl')]

Load Model and Run Inference#

learn_inf=load_learner(c.learner_path/'bears.pkl')
learn_inf
<fastai.learner.Learner at 0x7f127c96d550>
uploader = widgets.FileUpload(); uploader
img = PILImage.create(uploader.data[0])
img
../../_images/production_40_0.png
learn_inf.predict(img)
('Grizzly_Bear', tensor(1), tensor([9.8355e-09, 1.0000e+00, 1.5711e-08]))