# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# + [markdown] hide_input=false
# # Applying the data_block API

# + hide_input=false
from fastai import *
from fastai.vision import *
# -

path = Path('data/aircrafts')

path.ls()
# (path/'train').ls()
# (path/'test').ls()

# **Transformations**  
# We can get a lot more specific with this. For example, for satellite images you can use  
# `planet_tfms = get_transforms(flip_vert=True, max_lighting=0.1, max_zoom=1.05, max_warp=0.)`

tfms = get_transforms(do_flip=False)

data = (ImageList.from_folder(path) #Where to find the data? -> in path and its subfolders
        .split_by_folder()              #How to split in train/valid? -> use the folders
        .label_from_folder()            #How to label? -> depending on the folder of the filenames
        .add_test_folder()              #Optionally add a test set (here default name is test)
        .transform(tfms, size=64)       #Data augmentation? -> use tfms with a size of 64
        .databunch())                   #Finally? -> use the defaults for conversion to ImageDataBunch

# Alternatively, split by random instead of by folder using split_by_rand_pct()

data = (ImageList.from_folder(path) #Where to find the data? -> in planet 'train' folder
        .split_by_rand_pct() #How to split in train/valid? -> randomly with the default 20% in valid
        .label_from_folder() #How to label?
        .transform(tfms, size=64) #Data augmentation? -> use tfms with a size of 128
        .databunch())             #Finally -> use the defaults for conversion to databunch

# We can also split up the source and the data itself  
# and normalize using these `imagenet_stats`

np.random.seed(42)
src = (ImageList.from_folder(path)
       .split_by_folder()
       .label_from_folder())

data = (src.transform(tfms, size=64)
       .databunch().normalize(imagenet_stats))

# ## View data

# Look at the data from the created databunch

data.show_batch(3, figsize=(6,6), hide_axis=False)

data.c

# Classes are inferred from folder names

data.classes, data.c, len(data.train_ds), len(data.valid_ds)
# data.valid_ds.classes
# data.train_ds.classes

data.classes, data.c, len(data.train_ds), len(data.valid_ds)

# ## Train model

arch = models.resnet50

learn = cnn_learner(data, arch, metrics=accuracy)

learn.lr_find()

lr_find(learn)
learn.recorder.plot()

lr = 0.01

learn.fit_one_cycle(5, slice(lr))

learn.save('stage-1-rn50')

learn.unfreeze()

learn.lr_find()
learn.recorder.plot()

learn.fit_one_cycle(5, slice(1e-3, lr/5))

learn.save('stage-2-rn50')

learn.unfreeze()

learn.lr_find()
learn.recorder.plot()

learn.fit_one_cycle(5, slice(1e-4, lr/5))

learn.show_results(rows=3, figsize=(9,9))

# ## Interpretation

learn.load('stage-2-rn50');

# +
interp = ClassificationInterpretation.from_learner(learn)

losses,idxs = interp.top_losses()

len(data.valid_ds)==len(losses)==len(idxs)
# -

interp.plot_top_losses(9, figsize=(15,11))

interp.most_confused()

# Try with `learn.predict()` using an actual image.  
# Steps taken from https://github.com/npatta01/web-deep-learning-classifier/blob/master/notebooks/1_train.ipynb

plane_url = "https://upload.wikimedia.org/wikipedia/commons/5/5e/ANA_777-300_Taking_off_from_JFK.jpg"

url = plane_url


def fetch_image(url):
    response = requests.get(url)
    img = open_image(BytesIO(response.content))
    return img


img = fetch_image(plane_url)
pred_class, pred_idx, outputs = learn.predict(img)
pred_class, pred_idx, outputs

import pprint
def predict(url):
    img = fetch_image(url)
    pred_class,pred_idx,outputs = learn.predict(img)
    res =  zip (learn.data.classes, outputs.tolist())
    predictions = sorted(res, key=lambda x:x[1], reverse=True)
    top_predictions = predictions[0:5]
    pprint.pprint(top_predictions)
    return img.resize(500)


predict(plane_url)

StarcoderdataJupyterScriptsDedupFiltered