In [1]:
    
%reload_ext autoreload
%autoreload 2
%matplotlib inline
    
In [2]:
    
from fastai.conv_learner import *
    
In [3]:
    
import torch
torch.cuda.is_available()
    
    Out[3]:
In [4]:
    
PATH = '../data/planet/'
    
In [5]:
    
ls {PATH}
    
    
In [6]:
    
!ls {PATH}train-jpg/ | wc -l
!ls {PATH}test-jpg/ | wc -l
    
    
In [7]:
    
from fastai.plots import *
    
In [8]:
    
def get_1st(path): return glob(f'{path}/*.*')[0]
    
In [9]:
    
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")
    
    
In single-label classification each sample belongs to one class. In the previous example, each image is either a dog or a cat.
In [10]:
    
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")
    
    
In multi-label classification each sample can belong to one or more clases. In the previous example, the first images belongs to two clases: haze and primary. The second image belongs to four clases: agriculture, clear, primary and water.
In [11]:
    
from helper.planet import f2
metrics=[f2]
f_model = resnet34
    
In [12]:
    
label_csv = f'{PATH}train_v2.csv'
n = len(list(open(label_csv)))-1
val_idxs = get_cv_idxs(n)
    
We use a different set of data augmentations for this dataset - we also allow vertical flips, since we don't expect vertical orientation of satellite images to change our classifications.
In [13]:
    
def get_data(sz):
    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,
                    suffix='.jpg', val_idxs=val_idxs, test_name='test-jpg')
    
In [14]:
    
data = get_data(256)
data.classes
    
    Out[14]:
In [15]:
    
x,y = next(iter(data.val_dl))
    
In [16]:
    
x.shape
    
    Out[16]:
In [17]:
    
y.shape
    
    Out[17]:
In [18]:
    
sample = to_np(x[0])
sample_denorm = data.val_ds.denorm(sample)[0]
plt.imshow(sample_denorm)
    
    Out[18]:
    
In [19]:
    
list(zip(data.classes, y[0]))
    
    Out[19]:
In [20]:
    
plt.imshow(data.val_ds.denorm(to_np(x))[0]*1.5);
    
    
    
In [21]:
    
sz=64
    
In [22]:
    
data = get_data(sz)
    
In [23]:
    
data = data.resize(int(sz*1.3), 'tmp')
    
    
 
 
    
In [24]:
    
x,y = next(iter(data.trn_dl))
x.shape, y.shape
    
    Out[24]:
In [27]:
    
sample = to_np(x[0])
plt.imshow(data.val_ds.denorm(sample)[0]*1.2)
    
    Out[27]:
    
In [28]:
    
metrics
    
    Out[28]:
In [29]:
    
learn = ConvLearner.pretrained(f_model, data, metrics=metrics)
    
In [30]:
    
lrf=learn.lr_find()
learn.sched.plot()
    
    
 
 
    
    
In [34]:
    
learn.sched.plot_loss()
    
    
In [31]:
    
def plot_loss_change(sched, sma=1, n_skip=20, y_lim=(-0.01,0.01)):
    """
    Plots rate of change of the loss function.
    Parameters:
        sched - learning rate scheduler, an instance of LR_Finder class.
        sma - number of batches for simple moving average to smooth out the curve.
        n_skip - number of batches to skip on the left.
        y_lim - limits for the y axis.
    """
    derivatives = [0] * (sma + 1)
    for i in range(1 + sma, len(learn.sched.lrs)):
        derivative = (learn.sched.losses[i] - learn.sched.losses[i - sma]) / sma
        derivatives.append(derivative)
        
    plt.ylabel("d/loss")
    plt.xlabel("learning rate (log scale)")
    plt.plot(learn.sched.lrs[n_skip:], derivatives[n_skip:])
    plt.xscale('log')
    plt.ylim(y_lim)
plot_loss_change(learn.sched, sma=20)
    
    
Looking at the above plot, we can see that 0.1 seems the best learning rate.
In [32]:
    
lr = 0.1
    
In [33]:
    
learn.fit(lr, 3, cycle_len=1, cycle_mult=2)
    
    
 
 
    
    Out[33]:
In [36]:
    
lrs = np.array([lr/9,lr/3,lr])
    
In [37]:
    
learn.unfreeze()
learn.fit(lrs, 3, cycle_len=1, cycle_mult=2)
    
    
 
 
    
    Out[37]:
In [38]:
    
learn.save(f'{sz}')
    
In [39]:
    
learn.sched.plot_loss()
    
    
In [41]:
    
learn.sched.plot_lr()
    
    
In [42]:
    
sz=128
    
In [44]:
    
learn.set_data(get_data(sz))
learn.freeze()
    
In [45]:
    
learn.fit(lr, n_cycle=3, cycle_len=1, cycle_mult=2)
    
    
 
 
    
    Out[45]:
F2 Score not improving
In [46]:
    
learn.unfreeze()
learn.fit(lrs, 3, cycle_len=1, cycle_mult=2)
learn.save(f'{sz}')
    
    
 
 
    
TODO
In [ ]:
    
sz=256
    
In [24]:
    
learn.set_data(get_data(sz))
learn.freeze()
learn.fit(lr, 3, cycle_len=1, cycle_mult=2)
    
    
 
 
    
In [25]:
    
learn.unfreeze()
learn.fit(lrs, 3, cycle_len=1, cycle_mult=2)
learn.save(f'{sz}')
    
    
 
 
    
In [47]:
    
learn.models_path
    
    Out[47]:
In [48]:
    
learn.load(f'{sz}')
    
In [49]:
    
multi_preds, y = learn.TTA()
    
    
In [50]:
    
multi_preds.shape, y.shape
    
    Out[50]:
In [51]:
    
multi_preds[:,0,:]
    
    Out[51]:
In [52]:
    
y[0,:]
    
    Out[52]:
In [54]:
    
preds = np.mean(multi_preds, 0)
preds[0,:]
    
    Out[54]:
Sample Predictions
In [55]:
    
plt.plot(y[0,:])
    
    Out[55]:
    
In [56]:
    
plt.plot(preds[0,:])
    
    Out[56]:
    
In [57]:
    
f2(preds,y)
    
    Out[57]: