%reload_ext autoreload
%autoreload 2
%matplotlib inline

from fastai.imports import *
from fastai.transforms import *
from fastai.conv_learner import *
from fastai.model import *
from fastai.dataset import *
from fastai.sgdr import *

PATH = "data/planet/"

!ls {PATH}

"""
Explanation: Replicating: https://github.com/fastai/fastai/blob/master/courses/dl1/lesson2-image_models.ipynb
Multi-label Classification
End of explanation
"""


from fastai.plots import *

def get_1st(path): return glob(f'{path}/*.*')[0]

dc_path = "data/dogscats/valid/"
list_paths = [get_1st(f"{dc_path}cats"), get_1st(f"{dc_path}dogs")]
plots_from_files(list_paths, titles=["cat", "dog"], maintitle="Single-label Classification")

"""
Explanation: 2 Multi-Label versus Single-Label Classification
End of explanation
"""


list_paths = [f"{PATH}train-jpg/train_0.jpg", f"{PATH}train-jpg/train_1.jpg"]
titles = ["haze primary", "agriculture clear primary water"]
plots_from_files(list_paths, titles=titles, maintitle="Multi-label Classification")

"""
Explanation: In single-label classification each sample belongs to one class. In the previous example, each image is either a dog or a cat.
End of explanation
"""


from planet import f2

metrics = [f2]
f_model = resnet34

label_csv = f'{PATH}train_v2.csv'
n = len(list(open(label_csv)))-1
val_idxs = get_cv_idxs(n)

"""
Explanation: Softmax wouldn't be good because it wants to "pick a thing". Instead, we'll use the Sigmoid. In multi-label clsfn, each sample can belong to one or more classes. In the previous example, the 1st images belong to two classes: haze and primary. The 2nd belongs to four classes: agriculture, clear, primary, and water.
3 Multi-Label Models for Planet Dataset
fastai is baller AF bc it'll look at the labels in the CSV, and if there're &gt; 1 labels ever, for any item, it'll automatically switch to multi-label mode.
End of explanation
"""


def get_data(sz,bs=64):
    tfms = tfms_from_model(f_model, sz, aug_tfms=transforms_top_down, max_zoom=1.05)
    return ImageClassifierData.from_csv(PATH, 'train-jpg', label_csv, tfms=tfms, bs=bs,
                                        suffix='.jpg', val_idxs=val_idxs, test_name='test-jpg')

data = get_data(256) # the planet images are 256x256

# turning a dataloader into an iterator:
x,y = next(iter(data.val_dl)) # note: .._ds: dataset; .._dl: dataloader | PyTorch concepts
# idea: dataset gives you a single image or object back
#       dataloader gives you back a single (transformed) mini-batch (next mini-batch only)

y    # 64x17: batch size x number of classes

# zip, basically zips two lists together into an iterator
list(zip(data.classes, y[0])) # getting the 0th image's labels -- from validation set

"""
Explanation: We use a different set of DAs for this dataset -- we also allow vertical flips, since we don't expect the vertical orientation of satellite images to change our classifications.
End of explanation
"""


data.val_ds.fnames[:15]

plt.imshow(data.val_ds.get_x(0))

plt.imshow(data.val_ds.denorm(to_np(x))[0]*1.4);

"""
Explanation: Behind the scenes, FastAI & PyTorch are turning our labels into 1-Hot Encoded Labels.
Storing 1H-Encs as separate arrays is v.inefficient, instead the index values of positive-encodings are used, although the actual 1H-Enc vectors are dealt w/ deep in PyTorch.
End of explanation
"""


