%reload_ext autoreload
%autoreload 2
#export
from nb_005a import *
import pandas as pd
from pandas import Series
import csv
from collections import OrderedDict
PATH = Path('data/planet')
TRAIN = 'train-jpg'
label_csv = PATH/'train_v2.csv'
bs = 64
norm,denorm = normalize_funcs(*imagenet_stats)
df = pd.read_csv(label_csv, header=0)
df.head()
df.iloc[:,1] = list(csv.reader(df.iloc[:,1], delimiter=' '))
df.head()
tst = df.iloc[:,1].apply(lambda x: len(x))
tst.head()
(tst != 1).any()
#export
def uniqueify(x:Series) -> List[Any]: return list(OrderedDict.fromkeys(x).keys())
classes = uniqueify(np.concatenate(df.tags))
' '.join(classes)
class FilesMultiDataset(LabelDataset):
def __init__(self, fns, labels, classes=None):
self.classes = ifnone(classes, uniqueify(np.concatenate(labels)))
self.class2idx = {v:k for k,v in enumerate(self.classes)}
self.x = np.array(fns)
self.y = [np.array([self.class2idx[o] for o in l], dtype=np.int64)
for l in labels]
def encode(self, x):
res = np.zeros((self.c,), np.float32)
res[x] = 1.
return res
def get_labels(self, idx): return [self.classes[i] for i in self.y[idx]]
def __getitem__(self,i): return open_image(self.x[i]), self.encode(self.y[i])
@classmethod
def from_random_split(cls, path, folder, fns, labels, valid_pct, classes=None, test_name=None):
train,valid = random_split(valid_pct, f'{path}/{folder}/' + fns, labels)
train_ds = cls(*train, classes=classes)
res = [train_ds,cls(*valid, classes=train_ds.classes)]
if test_name:
test_fns = get_image_files(Path(path)/test_name)
test_labels = [[train_ds.classes[0]]]*len(test_fns)
res.append(cls(test_fns, test_labels, classes=train_ds.classes))
return res
def get_path(x): return x+'.jpg'
tfms = get_transforms(flip_vert=True, max_lighting=0.1, max_zoom=1.05, max_warp=0.)
np.random.seed(42)
datasets = FilesMultiDataset.from_random_split(
PATH, TRAIN, get_path(df.image_name), df.tags, valid_pct=0.2, test_name='test-jpg')
valid_ds = datasets[1]
idx=0
valid_ds[idx][0].brightness(0.7).contrast(1.5).show(
title=valid_ds.get_labels(idx), figsize=(5,5))
valid_ds[1][1]
def get_data(size):
return DataBunch.create(*datasets, path=PATH, ds_tfms=tfms, size=size,
bs=bs, num_workers=12, tfms=norm)
data=get_data(64)
x,y = next(iter(data.valid_dl))
x,y = x.data,y.data
x.shape
#export
def fbeta(y_pred:Tensor, y_true:Tensor, thresh:float=0.5, beta:float=2, eps:float=1e-9, sigmoid:bool=True) -> Rank0Tensor:
"Computes the f_beta between preds and targets"
beta2 = beta**2
if sigmoid: y_pred = y_pred.sigmoid()
y_pred = (y_pred>thresh).float()
y_true = y_true.float()
TP = (y_pred*y_true).sum(dim=1)
prec = TP/(y_pred.sum(dim=1)+eps)
rec = TP/(y_true.sum(dim=1)+eps)
res = (prec*rec)/(prec*beta2+rec+eps)*(1+beta2)
return res.mean()
def accuracy_thresh(y_pred:Tensor, y_true:Tensor, thresh:float=0.5, sigmoid:bool=True) -> Rank0Tensor:
if sigmoid: y_pred = y_pred.sigmoid()
return ((y_pred>thresh)==y_true.byte()).float().mean()
def f2_opt(y_pred, y_true, start=0.15, end=0.25, step=0.01):
return max([fbeta(y_pred, y_true, th)
for th in np.arange(start,end,step)])
metrics = [accuracy_thresh, f2_opt]
learn = ConvLearner(data, tvm.resnet34, metrics=metrics, ps=0.4, loss_fn=nn.BCEWithLogitsLoss())
learn.lr_find()
learn.recorder.plot()
def train_size(size, it_num, lr):
learn.data=get_data(size)
learn.freeze()
learn.fit_one_cycle(5, slice(lr))
learn.save(str(it_num))
learn.unfreeze()
learn.fit_one_cycle(5, slice(lr/20, lr/2), pct_start=0.1)
learn.save(str(it_num+1))
lr=1e-2
train_size(64, 0, lr)
train_size(128, 2, lr/2)
train_size(256, 2, lr/5)
learn.fit_one_cycle(5, slice(lr/100, lr/10), pct_start=0.1)