Kaggle competition: Cassava Leaf Disease Classification
<SOS> metric: CategorizationAccuracy Kaggle data source: cassava-leaf-disease-classification<init_hyperparams>
!pip install /kaggle/input/kerasapplications -q
!pip install /kaggle/input/efficientnet-keras-source-code/ -q --no-deps
datagen = ImageDataGenerator(
 featurewise_center=False,
samplewise_center=False,
featurewise_std_normalization=False,
samplewise_std_normalization=False,
zca_whitening=False,
rotation_range=15,
zoom_range = 0.1,
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=False,
vertical_flip=False )<train_model>
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
warnings.simplefilter('ignore' )
datagen.fit(X_train)
 model.fit_generator(datagen.flow(X_train,Y_train, batch_size=batch_size),
epochs = epochs, validation_data =(X_val,Y_val),
verbose = 1,
steps_per_epoch = X_train.shape[0] // batch_size
)<predict_on_test>
MIXED_PRECISION = True
XLA_ACCELERATE = False
GPUS = tf.config.experimental.list_physical_devices('GPU')
 if GPUS:
try:
for GPU in GPUS:
tf.config.experimental.set_memory_growth(GPU, True)
 logical_gpus = tf.config.experimental.list_logical_devices('GPU')
 print(len(GPUS), "Physical GPUs,", len(logical_gpus), "Logical GPUs")
 except RuntimeError as RE:
print(RE)
 if MIXED_PRECISION:
policy = tf.keras.mixed_precision.experimental.Policy('mixed_float16')
 tf.keras.mixed_precision.experimental.set_policy(policy)
 print('Mixed precision enabled')
 if XLA_ACCELERATE:
tf.config.optimizer.set_jit(True)
 print('Accelerated Linear Algebra enabled')
 strategy = tf.distribute.get_strategy()
REPLICAS = strategy.num_replicas_in_sync
print(f'REPLICAS: {REPLICAS}')
 print("Tensorflow version " + tf.__version__ )
predictions = model.predict(X_test)
 results = np.argmax(predictions, axis = 1 )<save_to_csv>
class BaseConfig(object):
SEED = 101
TRAIN_DF = '.. /input/cassava-leaf-disease-classification/train.csv'
TRAIN_IMG_PATH = '.. /input/cassava-leaf-disease-classification/train_images/'
TEST_IMG_PATH = '.. /input/cassava-leaf-disease-classification/test_images/'
CLASS_MAP = '.. /input/cassava-leaf-disease-classification/label_num_to_disease_map.json'
submissions = pd.read_csv(".. /input/digit-recognizer/sample_submission.csv")
 submissions['Label'] = results
submissions.to_csv('submission.csv', index = False )<set_options>
def seed_all(s):
random.seed(s)
 np.random.seed(s)
 tf.random.set_seed(s)
 os.environ['TF_CUDNN_DETERMINISTIC'] = '1'
os.environ['PYTHONHASHSEED'] = str(s)
 seed_all(BaseConfig.SEED )
def set_seeds(offset):
np.random.seed(100+offset)
 return(100+offset)
 tempseed = set_seeds(0)
 image_width = 28
image_height = 28
batch_size = 256
no_epochs = 40
no_classes = 10
ensemble_size = 1
validation_split = 0.2
verbosity = 1
base_filters = 256 
<load_from_csv>
with open(os.path.join(BaseConfig.CLASS_MAP)) as file:
pprint.pprint(json.loads(file.read()))
train = pd.read_csv(".. /input/digit-recognizer/train.csv")
 finaltest = pd.read_csv(".. /input/digit-recognizer/test.csv")
 train['label'].value_counts(normalize=False )<choose_model_class>
temp_df = df.copy()
temp_df[['CBB', 'CBSD',
'CGM', 'CMD', 'Healthy']] = pd.get_dummies(temp_df["label"])
 fig = go.Figure(data=[go.Pie(labels=temp_df.columns[2:],values=temp_df.iloc[:, 2:].sum().values)])
 fig.show()
del temp_df
datagen = ImageDataGenerator(
 rotation_range=35,
width_shift_range=0.3,
height_shift_range=0.2,
shear_range=0.3,
zoom_range=0.2,
validation_split=validation_split,
horizontal_flip=False, 
)
<data_type_conversions>
def albu_transforms_train(data_resize):
return A.Compose([
A.RandomResizedCrop(data_resize, data_resize),
A.HorizontalFlip(p=0.5),
A.VerticalFlip(p=0.5),
A.ShiftScaleRotate(p=0.5),
A.RandomRotate90(p=0.5),
A.HueSaturationValue(hue_shift_limit=0.2, sat_shift_limit=0.2,
val_shift_limit=0.2, p=0.5),
A.RandomBrightnessContrast(brightness_limit=(-0.1,0.1),
contrast_limit=(-0.1, 0.1), p=0.5),
A.RandomShadow(shadow_roi=(0, 0.5, 1, 1),
shadow_dimension=5, p=0.5),
A.CoarseDropout(p=0.5),
A.ToFloat()
], p=1.)
def albu_transforms_valid(data_resize):
return A.Compose([
A.ToFloat() ,
A.CenterCrop(data_resize, data_resize, p=1.) ,
A.Resize(data_resize, data_resize),
], p=1.)
def albu_transforms_inference(data_resize):
return A.Compose([
A.Transpose(p=0.5),
A.VerticalFlip(p=0.5),
A.HorizontalFlip(p=0.5),
A.RandomRotate90(p=0.5),
A.ShiftScaleRotate(p=0.5),
A.HueSaturationValue(hue_shift_limit=0.2,
sat_shift_limit=0.2,
val_shift_limit=0.2, p=0.5),
A.ToFloat() ,
A.RandomResizedCrop(data_resize, data_resize)
 ], p=1.)
trainlabels = train['label']
trainimages = train.drop(['label'], axis = 1)
 trainimages = trainimages.values.reshape(-1, image_width, image_height, 1)
 trainimages = trainimages.astype('float32')
 trainimages = trainimages/255
testset = finaltest.values.reshape(-1, image_width, image_height, 1)
 testset = testset.astype('float32')
 testset = testset/255 
<split>
def CutMix(image, label, DIM, PROBABILITY = 1.0):
CLASSES = 5
imgs = []; labs = []
for j in range(len(image)) :
P = tf.cast(tf.random.uniform([],0,1)<=PROBABILITY, tf.int32)
 k = tf.cast(tf.random.uniform([],0,len(image)) ,tf.int32)
 x = tf.cast(tf.random.uniform([],0,DIM),tf.int32)
 y = tf.cast(tf.random.uniform([],0,DIM),tf.int32)
 b = tf.random.uniform([],0,1)
 WIDTH = tf.cast(DIM * tf.math.sqrt(1-b),tf.int32)* P
ya = tf.math.maximum(0,y-WIDTH//2)
 yb = tf.math.minimum(DIM,y+WIDTH//2)
 xa = tf.math.maximum(0,x-WIDTH//2)
 xb = tf.math.minimum(DIM,x+WIDTH//2)
 one = image[j,ya:yb,0:xa,:]
two = image[k,ya:yb,xa:xb,:]
three = image[j,ya:yb,xb:DIM,:]
middle = tf.concat([one,two,three],axis=1)
 img = tf.concat([image[j,0:ya,:,:],middle,image[j,yb:DIM,:,:]],axis=0)
 imgs.append(img)
 a = tf.cast(WIDTH*WIDTH/DIM/DIM,tf.float32)
 labs.append(( 1-a)*label[j] + a*label[k])
 image2 = tf.reshape(tf.stack(imgs),(len(image),DIM,DIM,3))
label2 = tf.reshape(tf.stack(labs),(len(image),CLASSES))
return image2,label2
x_train, x_test, y_train, y_test = train_test_split(trainimages, trainlabels, test_size = validation_split )<train_model>
def MixUp(image, label, DIM, PROBABILITY = 1.0):
CLASSES = 5
imgs = []; labs = []
for j in range(len(image)) :
P = tf.cast(tf.random.uniform([],0,1)<=PROBABILITY, tf.float32)
 k = tf.cast(tf.random.uniform([],0,len(image)) ,tf.int32)
 a = tf.random.uniform([],0,1)*P
img1 = image[j,]
img2 = image[k,]
imgs.append(( 1-a)*img1 + a*img2)
 labs.append(( 1-a)*label[j] + a*label[k])
 image2 = tf.reshape(tf.stack(imgs),(len(image),DIM,DIM,3))
label2 = tf.reshape(tf.stack(labs),(len(image),CLASSES))
return image2,label2
train_generator = datagen.flow(x_train, y_train, batch_size=batch_size, shuffle=True, subset='training')
 val_generator = datagen.flow(x_test, y_test, batch_size=batch_size, subset='validation')
<choose_model_class>
sys.path.insert(0, "/kaggle/input/pyutils")
 def FMix(image, label, DIM, alpha=1, decay_power=3, max_soft=0.0, reformulate=False):
lam, mask = sample_mask(alpha, decay_power,(DIM, DIM), max_soft, reformulate)
 index = tf.constant(np.random.permutation(int(image.shape[0])))
 mask = np.expand_dims(mask, -1)
 image1 = image * mask
image2 = tf.gather(image, index)*(1 - mask)
 image3 = image1 + image2
label1 = label * lam
label2 = tf.gather(label, index)*(1 - lam)
 label3 = label1 + label2
return image3, label3
models = list()
for i in range(ensemble_size):
model = Sequential()
model.add(Conv2D(filters =(int(base_filters/8)) , kernel_size =(7,7), padding = 'Same', activation = 'relu', input_shape =(image_width, image_height, 1)))
 model.add(Conv2D(filters =(base_filters/8), kernel_size =(7,7), padding = 'Same', activation = 'relu'))
model.add(BatchNormalization())
 model.add(MaxPooling2D(pool_size =(2,2), strides =(2,2)))
 model.add(Dropout(0.25, seed=tempseed))
model.add(Conv2D(filters =(base_filters/4), kernel_size =(5,5), padding = 'Same', activation = 'relu'))
model.add(Conv2D(filters =(base_filters/4), kernel_size =(5,5), padding = 'Same', activation = 'relu'))
model.add(BatchNormalization())
 model.add(MaxPooling2D(pool_size =(2,2), strides =(2,2)))
 model.add(Dropout(0.25, seed=tempseed))
model.add(Conv2D(filters =(base_filters/2), kernel_size =(3,3), padding = 'Same', activation = 'relu'))
model.add(Conv2D(filters =(base_filters/2), kernel_size =(3,3), padding = 'Same', activation = 'relu'))
model.add(BatchNormalization())
 model.add(MaxPooling2D(pool_size =(2,2), strides =(2,2)))
 model.add(Dropout(0.25, seed=tempseed))
model.add(Conv2D(filters =(base_filters), kernel_size =(3,3), padding = 'Same', activation = 'relu'))
model.add(Conv2D(filters =(base_filters), kernel_size =(3,3), padding = 'Same', activation = 'relu'))
model.add(BatchNormalization())
 model.add(MaxPooling2D(pool_size =(2,2), strides =(2,2)))
 model.add(Dropout(0.25, seed=tempseed))
model.add(Flatten())
 model.add(Dense(base_filters, activation = "relu"))
model.add(Dense(base_filters/2, activation = "relu"))
model.add(Dense(no_classes, activation = "softmax"))
models.insert(i, model)
 models[0].summary()<choose_model_class>
class CassavaGenerator(tf.keras.utils.Sequence):
def __init__(self, img_path, data, batch_size, random_state,
dim, shuffle=True, transform=None,
use_mixup=False, use_cutmix=False,
use_fmix=False, is_train=False):
self.dim = dim
self.data = data
self.random_state = random_state
self.shuffle = shuffle
self.img_path = img_path
self.is_train = is_train
self.augment = transform
self.use_cutmix = use_cutmix
self.use_mixup = use_mixup
self.use_fmix = use_fmix
self.batch_size = batch_size
self.list_idx = self.data.index.values
self.label = pd.get_dummies(self.data['label'],
columns = ['label'])if self.is_train else np.nan
self.on_epoch_end()
def __len__(self):
return int(np.floor(len(self.list_idx)/ self.batch_size))
def __getitem__(self, index):
batch_idx = self.indices[index*self.batch_size:(index+1)*self.batch_size]
idx = [self.list_idx[k] for k in batch_idx]
Data = np.empty(( self.batch_size, *self.dim))
Target = np.empty(( self.batch_size, 5), dtype = np.float32)
 for i, k in enumerate(idx):
image = cv2.imread(self.img_path + self.data['image_id'][k])
 image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
 res = self.augment(image=image)
 image = res['image']
if self.is_train:
Data[i,] = image
Target[i,] = self.label.iloc[k,].values
else:
Data[i,] = image
if np.random.rand() > 0.2 and self.use_cutmix:
Data, Target = CutMix(Data, Target, self.dim[0])
 elif np.random.rand() > 0.2 and self.use_mixup:
Data, Target = MixUp(Data, Target, self.dim[0])
 elif np.random.rand() > 0.1 and self.use_fmix:
Data, Target = FMix(Data, Target, self.dim[0])
 return Data, Target if self.is_train else Data
def on_epoch_end(self):
self.indices = np.arange(len(self.list_idx))
if self.shuffle:
np.random.seed(self.random_state)
 np.random.shuffle(self.indices )
optimizer = Adam(lr=0.0005, decay=1e-9 )<choose_model_class>
class TrainConfig(BaseConfig):
NUM_CLASS = 5
EPOCH = 25
TTA = 3
FOLDS = 3
VERBOSITY = 1
WORKERS = 2
LABEL_SMOOTH = 0
MULTIPROCESS = False
CLS_BLN_WGS = False
MixUp = False
CutMix = False
FMix = False
LR_RATE = {
'0' : 1e-3,
'1' : 1e-3,
'2' : 1e-3,
'3' : 1e-3,
'4' : 1e-3
}
BATCH_SIZE = {
'0' : 64,
'1' : 86,
'2' : 86,
'3' : 86,
'4' : 86
}
IMG_SIZE = {
'0': 260,
'1': 260,
'2': 260,
'3': 260,
'4': 260
}
BASE_NETS = {
'0' : [efn.EfficientNetB3,
'.. /input/efficientnet-keras-noisystudent-weights-b0b7/efficientnet-b3_noisy-student_notop.h5'],
'1' : [efn.EfficientNetB1,
'.. /input/efficientnet-keras-noisystudent-weights-b0b7/efficientnet-b1_noisy-student_notop.h5'],
'2' : [efn.EfficientNetB2,
'.. /input/efficientnet-keras-noisystudent-weights-b0b7/efficientnet-b2_noisy-student_notop.h5'],
'3' : [efn.EfficientNetB0,
'.. /input/efficientnet-keras-noisystudent-weights-b0b7/efficientnet-b0_noisy-student_notop.h5'],
'4' : [efn.EfficientNetB1,
'.. /input/efficientnet-keras-noisystudent-weights-b0b7/efficientnet-b1_noisy-student_notop.h5'],
}
for i in range(len(models)) :
models[i].compile(optimizer = optimizer, loss = "sparse_categorical_crossentropy", metrics = ["accuracy"] )<choose_model_class>
class CassavaClassifier(tf.keras.Model):
def __init__(self, dim, base_efnet):
super(CassavaClassifier, self ).__init__()
self.Base = base_efnet[0](input_shape=dim,include_top = False,
weights=base_efnet[1])
 self.GAP = tf.keras.layers.GlobalAveragePooling2D()
self.DENS = tf.keras.layers.Dense(512, activation=tf.nn.relu)
 self.DROP = tf.keras.layers.Dropout(0.5)
 self.OUT = tf.keras.layers.Dense(5, activation='softmax')
 def call(self, input_tensor, training=False):
x = self.Base(input_tensor)
 x = self.GAP(x)
 x = self.DENS(x)
 x = self.DROP(x)
 return self.OUT(x)
 def build_graph(self):
x = tf.keras.layers.Input(shape=(TrainConfig.IMG_SIZE['0'],
TrainConfig.IMG_SIZE['0'], 3))
return tf.keras.Model(inputs=[x],
outputs=self.call(x))
learning_rate_reduction = ReduceLROnPlateau(monitor = 'val_accuracy', patience = 3, verbose = 1, factor = 0.25, min_lr = 0.0000001 )<define_variables>
skf = StratifiedKFold(n_splits=TrainConfig.FOLDS, shuffle=True, random_state=BaseConfig.SEED)
 for fold,(trn_idx, val_idx)in enumerate(skf.split(np.arange(df.shape[0]), df.label.values)) :
df.loc[df.iloc[val_idx].index, 'fold'] = fold
print('Class distribution per fold.
 ', df.groupby('fold')['label'].value_counts() )
callbacks = [learning_rate_reduction]<train_model>
oof_pred = []; oof_tar = []; oof_names = []; oof_folds = []; oof_val = []
def count_data_items(length, b_max):
batch_size = sorted([int(length/n)for n in range(1, length+1)\
if length % n == 0 and length/n <= b_max], reverse=True)[0]
steps = length / batch_size
return batch_size, steps
def get_lr_callback(batch_size=8):
lr_start = 0.000005
lr_max = 0.00000125 * REPLICAS * batch_size
lr_min = 0.000001
lr_ramp_ep = 5
lr_sus_ep = 0
lr_decay = 0.8
def lrfn(epoch):
if epoch < lr_ramp_ep:
lr =(lr_max - lr_start)/ lr_ramp_ep * epoch + lr_start
elif epoch < lr_ramp_ep + lr_sus_ep:
lr = lr_max
else:
lr =(lr_max - lr_min)* lr_decay**(epoch - lr_ramp_ep - lr_sus_ep)+ lr_min
return lr
return tf.keras.callbacks.LearningRateScheduler(lrfn, verbose=False )
histories = list()
for i in range(len(models)) :
tempseed = set_seeds(i)
 histories.insert(i, models[i].fit_generator(
 train_generator,
epochs = no_epochs,
verbose = 1,
validation_data = val_generator,
callbacks = [callbacks] 
)) 
<save_to_csv>
class SymmetricCrossEntropy(tf.losses.Loss):
def __init__(self, alpha=0.1, beta=1.0):

 super(SymmetricCrossEntropy, self ).__init__()
self.alpha = alpha
self.beta = beta
def call(self, y_true, y_pred):
ce_loss = tf.reduce_mean(-tf.reduce_sum(y_true * \
tf.math.log(tf.clip_by_value(y_pred, 1e-7, 1.0)) ,
axis = -1))
rce_loss = tf.reduce_mean(-tf.reduce_sum(y_pred * \
tf.math.log(tf.clip_by_value(y_true, 1e-4, 1.0)) ,
axis = -1))
return self.alpha*ce_loss + self.beta*rce_loss
SCELoss = SymmetricCrossEntropy()
predictions = np.zeros(( testset.shape[0],10))
for i in range(ensemble_size):
predictions = predictions + models[i].predict(testset)
 finalpredictions = np.argmax(predictions, axis = 1)
 submissions = {'ImageID':list(range(1, len(finalpredictions)+ 1)) ,'Label': finalpredictions}
submission_df = pd.DataFrame(submissions ).astype('int')
 submission_df.head()
submission_df.to_csv('submission.csv', index=False )<load_pretrained>
skf = StratifiedKFold(n_splits=TrainConfig.FOLDS, shuffle=True, random_state=BaseConfig.SEED)
 for each_fold,(trn_idx, val_idx)in enumerate(skf.split(np.arange(df.shape[0]), df.label.values)) :
tx = CassavaTrainer(each_fold, trn_idx, val_idx)
 tx.fold_training()
break
def read_image_test_lw(img_id):
path = ".. /input/test/" + img_id + ".tif"
img = cv2.imread(path)/ 255
return img<choose_model_class>
oof = np.concatenate(oof_pred)
 true = np.concatenate(oof_tar)
 names = np.concatenate(oof_names)
 folds = np.concatenate(oof_folds)
 df_oof = pd.DataFrame(dict(
 image_id = names,
target = true,
pred = oof,
fold = folds 
))
print('Overall OOF Acc: ', accuracy_score(true, oof))
print('Overall OOF Balance Acc: ', balanced_accuracy_score(true, oof))
df_oof.to_csv('oof.csv', index=False)
 df_oof.head(10 )
def model_f(input_shape):
X_input = Input(input_shape)
 X = DenseNet201()(X_input)
 X = Dropout(0.5 )(X)
 X = Dense(1, activation='sigmoid', kernel_initializer = glorot_uniform(seed=0))(X)
 model = Model(inputs = X_input, outputs = X)
 return model<load_from_csv>
df_test = pd.DataFrame({
'image_id': os.listdir(BaseConfig.TEST_IMG_PATH),
})
 df_test.head()
df_data = pd.read_csv('.. /input/train_labels.csv')
 batch_size = 32
epochs = 8
random_state = 5
model_name = "model_best_1"
size_original = 96<split>
model_check_points = sorted(glob('./*.h5'))
print(f'Found {len(model_check_points)} Weights Files.')
 target = []
for i, each_check_points in enumerate(model_check_points):
model = CassavaClassifier(( TrainConfig.IMG_SIZE[str(i)],
TrainConfig.IMG_SIZE[str(i)], 3),
TrainConfig.BASE_NETS[str(i)])
 model.build(( None, *(TrainConfig.IMG_SIZE[str(i)],
TrainConfig.IMG_SIZE[str(i)], 3)))
 model.load_weights(each_check_points)
 tta_preds = []
for _ in range(TrainConfig.TTA):
test_batch, test_step = count_data_items(len(df_test),
TrainConfig.BATCH_SIZE[str(i)])
 test_generator = CassavaGenerator(BaseConfig.TEST_IMG_PATH, df_test,
test_batch, BaseConfig.SEED, 
(TrainConfig.IMG_SIZE[str(i)],
TrainConfig.IMG_SIZE[str(i)], 3),
shuffle = False, is_train = False,
transform = albu_transforms_inference(TrainConfig.IMG_SIZE[str(i)]))
pred = model.predict(test_generator, verbose=1)
 tta_preds.append(pred/TrainConfig.TTA)
 tta_preds = np.sum(tta_preds, axis=0)
 target.append(tta_preds/len(model_check_points))
del model, test_generator
gc.collect()
<create_dataframe><EOS> 
df_test.loc[:, 'label'] = np.argmax(np.sum(target, axis=0), axis=1)
 df_test.to_csv("submission.csv", index=False)
 df_test.head()