import fastbook
fastbook.setup_book()from tqdm import tqdm
from fastbook import *
from fastai.vision.widgets import *
Bear classifier
Using FastAI
Credits: Practical Deep Learning for Coders book by Jeremy Howard and Sylvain Gugger.
See a deployed app here.
There will be two parts to it: - first part generates a model - second part deploys it as an app on HuggingFace (see code)
= search_images_ddg('grizzly bear')
results = results.attrgot('contentUrl')
ims len(ims)
200
= 'bear_images/grizzly.jpg'
dest 0], dest) download_url(ims[
100.99% [704512/697626 00:00<00:00]
Path('bear_images/grizzly.jpg')
= Image.open(dest)
im 128,128) im.to_thumb(
= 'grizzly', 'black', 'teddy'
bear_types = Path('bear_images') path
if not path.exists():
path.mkdir()
for o in tqdm(bear_types):
= (path/o)
dest =True)
dest.mkdir(exist_ok= search_images_ddg(f'{o} bear')
results =results) download_images(dest, urls
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:50<00:00, 25.04s/it]
= get_image_files(path)
fns fns
(#578) [Path('bear_images/grizzly/e1a38b7a-5ad4-4070-b27d-7991e67ffbf1.jpg'),Path('bear_images/grizzly/8af6b4cd-7146-4401-8201-3c69b630bb9c.jpg'),Path('bear_images/grizzly/5afcf7a1-0ff0-4c7f-b012-fa5f2fea5a2c.jpg'),Path('bear_images/grizzly/0d7a2b60-9867-4a6f-a785-1b0877b5949a.jpg'),Path('bear_images/grizzly/7977441d-8f9e-4a87-9fc1-1bdaa54151c5.jpg'),Path('bear_images/grizzly/b2e96643-4ea1-49b6-bd77-dac698a9e333.jpg'),Path('bear_images/grizzly/c6be2eea-8fc4-4678-8b35-ba2b5ca20ea2.jpg'),Path('bear_images/grizzly/83500b29-961d-4273-8249-164e123232c7.jpg'),Path('bear_images/grizzly/96ad8b99-4570-4210-85f1-7a664efabe8a.jpg'),Path('bear_images/grizzly/6e24cf29-dae3-41d4-9152-afc34e622236.jpg')...]
= verify_images(fns)
failed failed
(#9) [Path('bear_images/grizzly/3216c80f-8f83-4bf9-84ff-811da170b8c7.jpg'),Path('bear_images/grizzly/7cd788f0-f6a4-495b-9745-5a4972c1b9de.jpg'),Path('bear_images/black/165f5c5c-d9c9-4113-b863-1e62ef2ce219.jpg'),Path('bear_images/black/7b7e11b1-a71a-4e93-b10f-7b6d72d62330.jpg'),Path('bear_images/black/70d2b973-2b84-464d-b9d9-f077af0f7451.jpg'),Path('bear_images/black/268676a1-dd6c-4cd8-b15c-cb999a38e857.jpg'),Path('bear_images/black/a22e8eee-25c0-4e0f-b954-768d2be32dfb.jpg'),Path('bear_images/black/90d38027-558e-49cd-ba26-934c80b4e593.jpg'),Path('bear_images/teddy/d09b9bcd-728f-429b-9506-06d4b59a5b41.jpg')]
map(Path.unlink); failed.
From Data to DataLoaders
= DataBlock(
bears =(ImageBlock, CategoryBlock),
blocks=get_image_files,
get_items=RandomSplitter(valid_pct=0.2, seed=42),
splitter=parent_label,
get_y=Resize(128)) item_tfms
= bears.dataloaders(path) dls
=4, nrows=1) dls.valid.show_batch(max_n
Training Your Model, and Using It to Clean Your Data
= bears.new(
bears =RandomResizedCrop(224, min_scale=0.5),
item_tfms=aug_transforms())
batch_tfms= bears.dataloaders(path) dls
= vision_learner(dls, resnet18, metrics=error_rate) learn
4) learn.fine_tune(
epoch | train_loss | valid_loss | error_rate | time |
---|---|---|---|---|
0 | 1.027743 | 0.179141 | 0.062500 | 01:22 |
epoch | train_loss | valid_loss | error_rate | time |
---|---|---|---|---|
0 | 0.114028 | 0.170333 | 0.026786 | 01:35 |
1 | 0.096802 | 0.224060 | 0.026786 | 01:28 |
2 | 0.081567 | 0.242517 | 0.026786 | 01:22 |
3 | 0.065939 | 0.244289 | 0.026786 | 01:20 |
= ClassificationInterpretation.from_learner(learn)
interp interp.plot_confusion_matrix()
5, nrows=2, figsize=(10, 10)) interp.plot_top_losses(
= ImageClassifierCleaner(learn)
cleaner cleaner
#hide
for idx in cleaner.delete():
cleaner.fns[idx].unlink()for idx, cat in cleaner.change():
str(cleaner.fns[idx]), path/cat) shutil.move(
Turning Your Model into an Online Application
Using the Model for Inference
'bears.pkl') learn.export(
= Path()
path ='.pkl') path.ls(file_exts
(#1) [Path('bears.pkl')]
= load_learner(path/'bears.pkl') learn_inf
'bear_images/grizzly.jpg') learn_inf.predict(
('grizzly', TensorBase(1), TensorBase([2.1257e-06, 1.0000e+00, 2.7545e-08]))
learn_inf.dls.vocab
['black', 'grizzly', 'teddy']
Creating a Notebook App from the Model
= widgets.FileUpload()
btn_upload btn_upload
#hide
# For the book, we can't actually click an upload button, so we fake it
= SimpleNamespace(data = ['bear_images/grizzly.jpg']) btn_upload
= PILImage.create(btn_upload.data[-1]) img
= widgets.Output()
out_pl
out_pl.clear_output()with out_pl: display(img.to_thumb(128,128))
out_pl
= learn_inf.predict(img) pred,pred_idx,probs
= widgets.Label()
lbl_pred = f'Prediction: {pred}; Probability: {probs[pred_idx]:.04f}'
lbl_pred.value lbl_pred
= widgets.Button(description='Classify')
btn_run btn_run
def on_click_classify(change):
= PILImage.create(btn_upload.data[-1])
img
out_pl.clear_output()with out_pl: display(img.to_thumb(128,128))
= learn_inf.predict(img)
pred,pred_idx,probs = f'Prediction: {pred}; Probability: {probs[pred_idx]:.04f}'
lbl_pred.value
btn_run.on_click(on_click_classify)
#hide
#Putting back btn_upload to a widget for next cell
= widgets.FileUpload() btn_upload
'Select your bear!'),
VBox([widgets.Label( btn_upload, btn_run, out_pl, lbl_pred])
All together:
= Path()
path = load_learner(path/'bears.pkl')
learn_inf
= widgets.Output()
out_pl = widgets.FileUpload()
btn_upload = widgets.Label()
lbl_pred = widgets.Button(description='Classify')
btn_run
def on_click_classify(change):
= PILImage.create(btn_upload.data[-1])
img
out_pl.clear_output()with out_pl: display(img.to_thumb(128,128))
= learn_inf.predict(img)
pred,pred_idx,probs = f'Prediction: {pred}; Probability: {probs[pred_idx]:.04f}'
lbl_pred.value
btn_run.on_click(on_click_classify)
'Select your bear!'),
VBox([widgets.Label( btn_upload, btn_run, out_pl, lbl_pred])