from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all'
from fastai.vision import *
base_path = Path('/home/rahul/datasets/Synopsis_Model_All_Concepts/')
def get_label_dirs(path, diagnostic=True):
label_dirs = [f for f in os.listdir(path) if f.startswith(f'{path.name}_')]
label_dirs.sort()
if diagnostic:
num = [len((Path(path/label_dir)).ls()) for label_dir in label_dirs]
file_count = pd.DataFrame({
'LABEL': label_dirs,
'NUM_FILES': num
})
print(file_count.to_string(index=False))
print()
print(f"===== TOTAL NO. OF FILES = {file_count['NUM_FILES'].sum()} =====")
return label_dirs
category = 'shot_lighting'
path = base_path/category
label_dirs = get_label_dirs(path)
LABEL NUM_FILES shot_lighting_hard 623 shot_lighting_key_high 318 shot_lighting_key_low 792 shot_lighting_neutral 271 shot_lighting_silhouette 332 shot_lighting_soft 427 ===== TOTAL NO. OF FILES = 2763 =====
For label
s that have < 350 images, take 50 into the validation set, and put the rest into the training set
train_fnames, valid_fnames = {}, {}
for label in label_dirs:
files = get_files(path/label, presort=True)
np.random.seed(42)
np.random.shuffle(files)
if len(files) < 350:
valid_fnames[label] = files[:50]
train_fnames[label] = files[50:]
else:
valid_fnames[label] = files[:100]
train_fnames[label] = files[100:]
fnames_train = sum(train_fnames.values(),[])
fnames_valid = sum(valid_fnames.values(),[])
len(fnames_train)
len(fnames_valid)
2310
450
Add NAs from textures
textures_dir = base_path/'texture'
textures_subdirs = get_label_dirs(textures_dir)
LABEL NUM_FILES texture_banded 120 texture_blotchy 120 texture_braided 120 texture_bubbly 120 texture_bumpy 120 texture_chequered 120 texture_cobwebbed 120 texture_cracked 120 texture_crosshatched 120 texture_crystalline 120 texture_dotted 240 texture_fibrous 120 texture_flecked 120 texture_frilly 120 texture_gauzy 120 texture_grid 120 texture_grooved 120 texture_honeycombed 120 texture_interlaced 120 texture_knitted 120 texture_lacelike 120 texture_lined 120 texture_marbled 120 texture_matted 120 texture_meshed 120 texture_paisley 120 texture_perforated 120 texture_pitted 120 texture_pleated 120 texture_porous 120 texture_potholed 120 texture_scaly 120 texture_smeared 120 texture_spiralled 120 texture_sprinkled 120 texture_stained 120 texture_stratified 120 texture_striped 120 texture_studded 120 texture_swirly 120 texture_veined 120 texture_waffled 121 texture_woven 120 texture_wrinkled 119 texture_zigzagged 120 ===== TOTAL NO. OF FILES = 5520 =====
5520 is way too many files for the number of samples we have in lighting.
So, we take 10 from each texture
label in the validation set, and 30 for the training set
textures_train_fnames, textures_valid_fnames = {}, {}
for label in textures_subdirs:
files = get_files(textures_dir/label, presort=True)
np.random.seed(42)
np.random.shuffle(files)
# grab 30 train, 10 valid images from each label
textures_valid_fnames[label] = files[:10]
textures_train_fnames[label] = files[10:40]
fnames_textures_train = sum(textures_train_fnames.values(),[])
fnames_textures_valid = sum(textures_valid_fnames.values(),[])
print(f'No. of training samples from `textures` --> {len(fnames_textures_train)}')
print(f'No. of validation samples from `textures` --> {len(fnames_textures_valid)}')
No. of training samples from `textures` --> 1350 No. of validation samples from `textures` --> 450
fnames_valid = fnames_valid + fnames_textures_valid
fnames_train = fnames_train + fnames_textures_train
shuffle_df = lambda df: df.reindex(np.random.permutation(df.index)).reset_index(drop=True)
def get_data_df(fnames:list, regex:str, na_label:str) -> pd.DataFrame:
row_list = []
for i,f in enumerate(fnames):
rowdict = {}
rowdict['filepath'] = str(f)
label = re.search(regex, str(f))
if label:
label = label.group(0).split('/')[:-1][0] # remove '/'; get str, not list
rowdict['label'] = label
else:
rowdict['label'] = na_label
#rowdict['filepath'] = re.search('(?<=shot_location/).*', str(f)).group(0)
row_list.append(rowdict)
df = pd.DataFrame(row_list)
return shuffle_df(df)
df_valid.head(5)
filepath | label | |
---|---|---|
0 | /home/rahul/datasets/Synopsis_Model_All_Concep... | shot_lighting_neutral |
1 | /home/rahul/datasets/Synopsis_Model_All_Concep... | shot_lighting_hard |
2 | /home/rahul/datasets/Synopsis_Model_All_Concep... | NA |
3 | /home/rahul/datasets/Synopsis_Model_All_Concep... | NA |
4 | /home/rahul/datasets/Synopsis_Model_All_Concep... | NA |
img_size = (224,224)
batch_size = 64
tfms = get_transforms()
tfms = tfms[0], [] # remove cropping tfm from validation-transforms
# remove Lighting transforms since we're trying to model lighting...
train_tfms = [t for t in get_transforms()[0] if not isinstance(t.tfm, TfmLighting)]
tfms = train_tfms, []
datagrab_lighting = partial(get_data_df, regex='(?<=shot_lighting/).*/', na_label = 'NA')
df_train = datagrab_lighting(fnames_train)
df_valid = datagrab_lighting(fnames_valid)
lls = LabelLists(path = '/',
train = ImageList.from_df(df_train, path='/'),
valid = ImageList.from_df(df_valid, path='/'))
data_lighting_single = (lls
.label_from_df()
.transform(tfms=tfms,
size=img_size,
resize_method=ResizeMethod.SQUISH)
.databunch(bs=batch_size)
.normalize(imagenet_stats))
data_lighting_single.c
data_lighting_single.classes
7
['NA', 'shot_lighting_hard', 'shot_lighting_key_high', 'shot_lighting_key_low', 'shot_lighting_neutral', 'shot_lighting_silhouette', 'shot_lighting_soft']
data_lighting_single.train_ds
LabelList (3660 items) x: ImageList Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224) y: CategoryList shot_lighting_soft,NA,NA,shot_lighting_key_high,shot_lighting_key_low Path: /
data_lighting_single.valid_ds
LabelList (900 items) x: ImageList Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224) y: CategoryList shot_lighting_key_high,NA,NA,shot_lighting_key_high,NA Path: /
data_lighting_single.show_batch()
datagrab_lighting = partial(get_data_df, regex='(?<=shot_lighting/shot_lighting_).*/', na_label = 'NA')
df_train = datagrab_lighting(fnames_train)
df_valid = datagrab_lighting(fnames_valid)
lls = LabelLists(path = '/',
train = ImageList.from_df(df_train, path='/'),
valid = ImageList.from_df(df_valid, path='/'))
data_lighting_multi = (lls
.label_from_df(label_delim = '_')
.transform(tfms=tfms,
size=img_size,
resize_method=ResizeMethod.SQUISH)
.databunch(bs=batch_size)
.normalize(imagenet_stats))
data_lighting_multi.c
data_lighting_multi.classes
8
['NA', 'hard', 'high', 'key', 'low', 'neutral', 'silhouette', 'soft']
data_lighting_multi.train_ds
LabelList (3660 items) x: ImageList Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224) y: MultiCategoryList NA,NA,NA,hard,NA Path: /
data_lighting_multi.valid_ds
LabelList (900 items) x: ImageList Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224) y: MultiCategoryList NA,NA,NA,NA,NA Path: /
data_lighting_multi.show_batch()
acc_02 = partial(accuracy_thresh, thresh=0.2)
f_score = partial(fbeta, thresh=0.2)
metrics_multi = [acc_02, f_score]
learn_multi = cnn_learner(data_lighting_multi, models.mobilenet_v2,
metrics = metrics_multi,
path = '/home/rahul/tmp/')
learn_multi.lr_find()
learn_multi.recorder.plot()
epoch | train_loss | valid_loss | accuracy_thresh | fbeta | time |
---|---|---|---|---|---|
0 | 0.947226 | #na# | 00:12 |
LR Finder is complete, type {learner_name}.recorder.plot() to see the graph.
learn_multi.fit_one_cycle(3, slice(1e-2))
epoch | train_loss | valid_loss | accuracy_thresh | fbeta | time |
---|---|---|---|---|---|
0 | 0.511877 | 0.210009 | 0.866250 | 0.746908 | 00:17 |
1 | 0.302235 | 0.171378 | 0.895139 | 0.775029 | 00:17 |
2 | 0.228212 | 0.169257 | 0.895417 | 0.798650 | 00:16 |
interp = ClassificationInterpretation.from_learner(learn_multi)
interp.plot_confusion_matrix(dpi=100)
learn_single = cnn_learner(data_lighting_single, models.mobilenet_v2,
metrics = [accuracy, FBeta()],
path = '/home/rahul/tmp/')
learn_single.lr_find()
learn_single.recorder.plot()
epoch | train_loss | valid_loss | accuracy | f_beta | time |
---|---|---|---|---|---|
0 | 2.524050 | #na# | 00:12 |
LR Finder is complete, type {learner_name}.recorder.plot() to see the graph.
learn_single.fit_one_cycle(4, slice(1e-3))
epoch | train_loss | valid_loss | accuracy | f_beta | time |
---|---|---|---|---|---|
0 | 1.702342 | 0.893077 | 0.708889 | 0.539959 | 00:15 |
1 | 1.244825 | 0.795209 | 0.711111 | 0.549682 | 00:16 |
2 | 0.987185 | 0.738248 | 0.703333 | 0.538014 | 00:16 |
3 | 0.815473 | 0.720294 | 0.707778 | 0.538561 | 00:18 |
/home/rahul/fastai/fastai/metrics.py:191: UserWarning: average=`binary` was selected for a non binary case. Value for average has now been set to `macro` instead. warn("average=`binary` was selected for a non binary case. Value for average has now been set to `macro` instead.")
interp = ClassificationInterpretation.from_learner(learn_single)
interp.plot_confusion_matrix(dpi=100)