In [1]:
%reload_ext autoreload
%autoreload 2
%matplotlib inline
In [2]:
from fastai.imports import *
from fastai.torch_imports import *
from fastai.transforms import *
from fastai.model import *
from fastai.dataset import *
from fastai.sgdr import *
from fastai.plots import *
from fastai.conv_learner import *
In [3]:
PATH = "data/dogbreeds/"
sz = 224
arch = resnext101_64
bs = 64
In [4]:
label_csv = f'{PATH}labels.csv'
n = len(list(open(label_csv)))-1
val_idxs = get_cv_idxs(n)
In [17]:
val_idxs, n, len(val_idxs)
Out[17]:
In [5]:
!ls {PATH}
In [7]:
label_df = pd.read_csv(label_csv)
label_df.head()
Out[7]:
In [10]:
# use Pandas to create pivot table which shows how many of each label:
label_df.pivot_table(index='breed', aggfunc=len).sort_values('id', ascending=False)
Out[10]:
In [5]:
tfms = tfms_from_model(arch, sz, aug_tfms=transforms_side_on, max_zoom=1.1)
data = ImageClassifierData.from_csv(PATH, folder='train', csv_fname=f'{PATH}labels.csv',
test_name='test', val_idxs=val_idxs, suffix='.jpg',
tfms=tfms, bs=bs)
In [26]:
fn = PATH + data.trn_ds.fnames[0]; fn
Out[26]:
In [27]:
img = PIL.Image.open(fn); img
Out[27]:
In [28]:
img.size
Out[28]:
In [30]:
size_d = {k: PIL.Image.open(PATH + k).size for k in data.trn_ds.fnames}
In [31]:
row_sz, col_sz = list(zip(*size_d.values()))
In [36]:
row_sz = np.array(row_sz); col_sz = np.array(col_sz)
In [37]:
row_sz[:5]
Out[37]:
In [41]:
plt.hist(row_sz);
In [42]:
plt.hist(row_sz[row_sz < 1000])
Out[42]:
In [45]:
plt.hist(col_sz);
In [46]:
plt.hist(col_sz[col_sz < 1000])
Out[46]:
In [50]:
len(data.trn_ds), len(data.test_ds)
Out[50]:
In [51]:
len(data.classes), data.classes[:5]
Out[51]:
starting w/ small images, large batch sizes to train model v.fast in beginning; increase image size and decrease batch-size as go along.
In [5]:
def get_data(sz, bs):
tfms = tfms_from_model(arch, sz, aug_tfms=transforms_side_on, max_zoom=1.1)
data = ImageClassifierData.from_csv(PATH, 'train', f'{PATH}labels.csv', test_name='test',
num_workers=4, val_idxs=val_idxs, suffix='.jpg',
tfms=tfms, bs=bs)
return data if sz > 300 else data.resize(340, 'tmp')
In [7]:
data = get_data(sz, bs)
In [57]:
learn = ConvLearner.pretrained(arch, data, precompute=True) # GTX870M;bs=64;sz=224;MEM:2431/3017
In [58]:
learn.fit(1e-2, 5)
In [6]:
from sklearn import metrics
In [ ]:
# data = get_data(sz, bs)
In [8]:
learn = ConvLearner.pretrained(arch, data, precompute=True, ps=0.5)
In [62]:
learn.fit(1e-2, 2)
In [ ]:
lrf = learn.find_lr()
learn.sched.plot()
In [9]:
# turn precompute off then use dataug
learn.precompute = False
In [64]:
learn.fit(1e-2, 5, cycle_len=1)
In [65]:
learn.save('224_pre')
In [10]:
learn.load('224_pre')
If you train smth on a smaller size, you can call
learn.set_data()and pass in a larger sized dataset. That'll take your model, however it's trained so far, and continue to train on larger images.This is another way to get SotA results. Starting training on small images for a few epochs, then switching to larger images and continuing training is an amazing effective way to avoid overfitting.
NOTE: Fully-Convolutional Architectures only.
In [14]:
learn.set_data(get_data(299, bs=32))
learn.freeze() # just making all but last layer already frozen
In [15]:
learn.fit(1e-2, 3, cycle_len=1) # precompute is off so DataAugmentation is back on
In [16]:
learn.fit(1e-2, 3, cycle_len=1, cycle_mult=2)
In [17]:
log_preds, y = learn.TTA()
probs = np.exp(log_preds)
accuracy(log_preds, y), metrics.log_loss(y, probs)
Out[17]:
In [18]:
learn.save('299_pre')
In [ ]:
# learn.load('299_pre')
In [19]:
learn.fit(1e-2, 1, cycle_len=2)
In [20]:
learn.save('299_pre')
In [21]:
log_preds, y = learn.TTA()
probs = np.exp(log_preds)
accuracy(log_preds, y), metrics.log_loss(y, probs)
Out[21]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
SUBM = f'{PATH}subm/'
os.makedirs(SUBM, exist_ok=True)
df.to_csv(f'{SUBM}subm.gz', compression='gzip', index=False)
In [ ]:
FileLink(f'{SUBM}subm.gz')
In [6]:
fn = data.val_ds.fnames[0]
In [7]:
fn
Out[7]:
In [8]:
Image.open(PATH+fn).resize((150,150))
Out[8]:
In [9]:
trn_tfms, val_tfms = tfms_from_model(arch, sz)
In [12]:
learn = ConvLearner.pretrained(arch, data)
learn.load('299_pre')
In [ ]:
# ds = FilesIndexArrayDataset([fn], np.array([0]), val_tfms, PATH)
# dl = DataLoader(ds)
# preds = learn.predict_dl(dl)
# np.argmax(preds)
In [ ]:
im = trn_tfms(Image.open(PATH+fn))
preds = to_np(learn.model(V(T(im[None]).cuda())))
np.argmax(preds)
In [ ]:
trn_tfms, val_tfms = tfms_from_model(arch, sz)
In [ ]:
im = val_tfms(Image.open(PATH+fn)) # or could apply trn_tfms(.)
preds = learn.predict_array(im[None]) # index into image as[None] to create minibatch of 1 img
np.argmax(preds)