Data - The data analysed in the present work is present here
Some information about the clouds
Clouds are classified according to their height above and appearance (texture) from the ground.
The following cloud roots and translations summarize the components of this classification system
- Cirro-:curl of hair, high; > - Alto-:mid; > - Strato-:layer;> - Nimbo-:rain, precipitation;> - Cumulo-:heap.
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import os
input_dir = "/kaggle/input/"
dirs = ["howard-cloudx", "clouds", "cloudtest"]
for d in dirs:
for dirname, _, filenames in os.walk(input_dir + d):
counter = 0
for filename in filenames:
counter = counter + 1
print(f"Number of files loaded:{counter}")
! pip install timm
from fastai.vision.all import *
from fastai import *
from fastai.vision import *
from fastai.vision.widgets import *
import timm
path = Path('../input/howard-cloudx/Howard-Cloud-X/')
path.ls()
train = (path/"train")
valid = (path/"test")
len(train.ls())
fnames = get_image_files(path)
fnames
dblock = DataBlock()
dsets = dblock.datasets(fnames)
dsets.train[0]
len(dsets.train), len(dsets.valid)
dblock = DataBlock(blocks = (ImageBlock, CategoryBlock),
get_items = get_image_files, get_y = parent_label, splitter = RandomSplitter(), item_tfms = Resize(300, method = ResizeMethod.Squish),
batch_tfms=aug_transforms(size= 224))
dsets = dblock.datasets(path)
dsets.vocab
dls = dblock.dataloaders(path)
dls.show_batch()
learn = vision_learner(dls, resnet34, metrics=error_rate)
learn.lr_find()
learn.fine_tune(5, 3e-3)
import gc
_ = gc.collect()
dls_2 = ImageDataLoaders.from_folder(path, train = "train", valid = "test",vocab = dsets.vocab, bs = 64, item_tfms = Resize(300, method = ResizeMethod.Squish),
batch_tfms=aug_transforms(size= 224))
#batch_tfms=[*aug_transforms(size=224),Normalize.from_stats(*imagenet_stats)])
dls_2.show_batch()
learn_2 = vision_learner(dls_2, "convnext_small_in22k", model_dir="/tmp/model/", metrics=accuracy)
learn_2.fine_tune(10, 3e-3)
learn_2.fine_tune(10, 3e-3)
learn_2.fine_tune(5, 3e-3)
learn_2.show_results()
dls_3 = ImageDataLoaders.from_folder(path, train = "train", valid = "test",vocab = dsets.vocab, bs = 32, item_tfms = Resize(400, method = ResizeMethod.Squish),
batch_tfms=aug_transforms(size= 300))
#batch_tfms=[*aug_transforms(size=224),Normalize.from_stats(*imagenet_stats)])
learn_3 = vision_learner(dls_3, "convnext_tiny_hnf", model_dir="/tmp/model/", metrics=accuracy)
learn_3.fine_tune(10, 3e-3)
learn_3.fine_tune(5, 3e-3)
learn_3.show_results()
interp.most_confused(min_val =3)
dls_4 = ImageDataLoaders.from_folder(path, train = "train", valid = "test",vocab = dsets.vocab, bs = 32, item_tfms = Resize(128),
batch_tfms=aug_transforms())
#batch_tfms=[*aug_transforms(size=224),Normalize.from_stats(*imagenet_stats)])
learn_4 = vision_learner(dls_4, "convnext_base", model_dir="/tmp/model/", metrics=accuracy)
learn_4.fine_tune(10, 3e-3)
turns = 2
for i in range(turns):
learn_4.fine_tune(10, 3e-3)
learn_4.show_results()
interp = ClassificationInterpretation.from_learner(learn_4)
interp.plot_confusion_matrix()
torch.cuda.empty_cache()
dls_5 = ImageDataLoaders.from_folder(path, train = "train", valid = "test",vocab = dsets.vocab, bs = 64, item_tfms = Resize(300, method = ResizeMethod.Squish),
#batch_tfms=aug_transforms(size= 224))
batch_tfms=[*aug_transforms(size=224),Normalize.from_stats(*imagenet_stats)])
learn_5 = vision_learner(dls_5, "convnext_small_in22k", model_dir="/tmp/model/", metrics=[accuracy])
turns = 2
for i in range(turns):
learn_5.fine_tune(10, 3e-3)
learn_5.show_results()
interp = ClassificationInterpretation.from_learner(learn_5)
interp.plot_confusion_matrix()
interp.most_confused(min_val =4)
I am no cloud expert, so googling to see the difference between these clouds.
This primer provides a quick overview.
There are other misclassifications too but for now, let's see how the model behaves when we remove two noisy classes out of the three. I choose Altocumulus and Cirrostratus randomly and would see the result.
There should be better methods to improve the efficiency:> - Remove noisy class> - Balance the classes
- Get more samples per class
- Data preprocessing
for dirname, _, filenames in os.walk('/kaggle/input/clouds/Clouds'):
counter = 0
for filename in filenames:
counter = counter + 1
#print(os.path.join(dirname, filename))
print(f"Number of files loaded:{counter}")
path_n = Path('../input/clouds/Clouds')
path_n.ls()
dblock_n = DataBlock(blocks = (ImageBlock, CategoryBlock),
get_items = get_image_files, get_y = parent_label, splitter = RandomSplitter(), item_tfms = Resize(300, method = ResizeMethod.Squish),
batch_tfms=aug_transforms(size= 224))
dsets_n = dblock_n.datasets(path_n)
dsets_n.vocab
dls_6 = ImageDataLoaders.from_folder(path_n, train = "train", valid = "test",vocab = dsets_n.vocab, bs = 32, item_tfms = Resize(128),
batch_tfms=aug_transforms())
learn_6 = vision_learner(dls_6, "convnext_small_in22k", model_dir="/tmp/model/", metrics=accuracy)
learn_6.fit_one_cycle(3, 3e-3)
learn_6.unfreeze()
learn_6.fit_one_cycle(10)
learn_6.fine_tune(10, 3e-3)
learn_6.fine_tune(10, 3e-3)
learn_6.recorder.plot_loss()
learn_6.show_results()
interp = ClassificationInterpretation.from_learner(learn_6)
interp.plot_confusion_matrix()
dls_7 = ImageDataLoaders.from_folder(path_n, train = "train", valid = "test",vocab = dsets_n.vocab, bs = 32, item_tfms = Resize(224),
batch_tfms=aug_transforms())
learn_7 = vision_learner(dls_7, "convnext_small", model_dir="/tmp/model/", metrics=accuracy)
learn_7.lr_find()
lr = [2e-2, 3e-3]
for i in range(len(lr)):
learn_7.fine_tune(10, lr[i])
learn_7.recorder.plot_loss()
learn_7.show_results()
interp = ClassificationInterpretation.from_learner(learn_7)
interp.plot_confusion_matrix()
learn_7.loss_func
learn_7.opt
dls_8 = ImageDataLoaders.from_folder(path_n, train = "train", valid = "test",vocab = dsets_n.vocab, bs = 32, item_tfms = Resize(224),
batch_tfms=aug_transforms(size= 128))
Focal loss disccussed in this paper https://arxiv.org/pdf/1708.02002.pdf provides more control over the penalisation with the help of a gamma parameter. Gamma = 0 behaves similar to Cross Entropy Loss but higher values of gamma (0 to 2) change this behaviour.
learn_8 = vision_learner(dls_8, "convnext_tiny", model_dir="/tmp/model/", loss_func= FocalLossFlat(gamma = 1.5),metrics=accuracy)
learn_8.loss_func
learn_8.lr_find()
lr = [2e-2, 3e-3, 4e-4]
epoch_lst = [10, 8, 7]
for i in range(len(lr)):
learn_8.fine_tune(epoch_lst[i], lr[i])
learn_8.show_results()
interp = ClassificationInterpretation.from_learner(learn_8)
interp.plot_confusion_matrix()
interp.most_confused(min_val =4)
img_2 = PILImage.create("../input/cloudtest/Screenshot 2022-09-02 at 10.44.33 PM.png")
img_2
learn_8.predict(img_2)
img_3 = PILImage.create("../input/cloudtest/Screenshot 2022-09-02 at 11.35.30 PM.png")
img_3
learn_8.predict(img_3)
img_4 = PILImage.create("../input/cloudtest/Screenshot 2022-09-02 at 11.36.15 PM.png")
img_4
learn_8.predict(img_4)
learn_8.recorder.plot_loss()
learn_8.recorder.losses
data = {'Epochs': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
'train_loss': [1.365729,
1.218585,
1.123894,
1.093431,
0.954352,
0.795425,
0.675656,
0.543923,
0.431559,
0.366880,
0.168368,
0.161951,
0.163574,
0.162362,
0.164124
],
'valid_loss': [1.222900,
0.952413,
1.245164,
1.219178,
1.016823,
0.980452,
0.715877,
0.732847,
0.700989,
0.680698,
0.690924,
0.702923,
0.694562,
0.700117,
0.698838],
'accuracy' : [0.505000,
0.570000,
0.545000,
0.585000,
0.605000,
0.615000,
0.660000,
0.685000,
0.705000,
0.700000,
0.710000,
0.710000,
0.710000,
0.705000,
0.715000]
}
df = pd.DataFrame(data)
df
plt.figure(figsize=(10, 10))
plt.xlabel("Epochs")
plt.ylabel("Loss and Accuracy")
plt.plot(df['train_loss'], label = "train_loss")
plt.plot(df['valid_loss'], label = "valid_loss")
plt.plot(df['accuracy'], label = "accuracy")
plt.legend()
plt.show()
learn_8.recorder.metric_names
cm = interp.confusion_matrix()
interp.plot_confusion_matrix()
cm
tp = cm.diagonal()
fn = cm.sum(1) - tp
fp = cm.sum(0) - tp
precision = tp / (tp + fp)
recall = tp / (tp + fn)
recall
precision
np.sum(precision), np.sum(recall)
print("Precision for the Model : ", 0.715)
print("Recall for the Model :", 0.715)
f1 = (2* precision * recall)/(precision+recall)
f1
np.mean(f1)