<jupyter_start><jupyter_text>**Packages**<jupyter_code>!pip install --quiet /kaggle/input/kerasapplications
!pip install --quiet /kaggle/input/efficientnet-git<jupyter_output><empty_output><jupyter_text>**Dependencies**<jupyter_code>import math, os, re, warnings, random, glob
import numpy as np
import pandas as pd
import tensorflow as tf
import tensorflow.keras.layers as L
import tensorflow.keras.backend as K
from tensorflow.keras import Sequential, Model
import efficientnet.tfkeras as efn

def seed_everything(seed=0):
    random.seed(seed)
    np.random.seed(seed)
    tf.random.set_seed(seed)
    os.environ['PYTHONHASHSEED'] = str(seed)
    os.environ['TF_DETERMINISTIC_OPS'] = '1'

seed = 0
seed_everything(seed)
warnings.filterwarnings('ignore')<jupyter_output><empty_output><jupyter_text>**Hardware**<jupyter_code>try:
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()
    print(f'Running on TPU {tpu.master()}')
except ValueError:
    tpu = None

if tpu:
    tf.config.experimental_connect_to_cluster(tpu)
    tf.tpu.experimental.initialize_tpu_system(tpu)
    strategy = tf.distribute.experimental.TPUStrategy(tpu)
else:
    strategy = tf.distribute.get_strategy()

AUTO = tf.data.experimental.AUTOTUNE
REPLICAS = strategy.num_replicas_in_sync
print(f'REPLICAS: {REPLICAS}')<jupyter_output>REPLICAS: 1<jupyter_text>**Parameters**<jupyter_code>BATCH_SIZE = 16 * REPLICAS
HEIGHT = 512
WIDTH = 512 
CHANNELS = 3
N_CLASSES = 5
TTA_STEPS = 3 # Do TTA if > 0<jupyter_output><empty_output><jupyter_text>**Load Data**<jupyter_code>def count_data_items(filenames):    
    n = [int(re.compile(r'-([0-9]*)\.').search(filename).group(1)) for filename in filenames]
    return np.sum(n)


database_base_path = '/kaggle/input/cassava-leaf-disease-classification/'
submission = pd.read_csv(f'{database_base_path}sample_submission.csv')
display(submission.head())

TEST_FILENAMES = tf.io.gfile.glob(f'{database_base_path}test_tfrecords/ld_test*.tfrec')
NUM_TEST_IMAGES = count_data_items(TEST_FILENAMES)
print(f'GCS: test: {NUM_TEST_IMAGES}')<jupyter_output><empty_output><jupyter_text>**Data Augmentation**<jupyter_code>def data_augment(image, label):
    p_spatial = tf.random.uniform([], 0, 1.0, dtype=tf.float32)
    p_rotate = tf.random.uniform([], 0, 1.0, dtype=tf.float32)
    p_pixel_1 = tf.random.uniform([], 0, 1.0, dtype=tf.float32)
    p_pixel_2 = tf.random.uniform([], 0, 1.0, dtype=tf.float32)
    p_pixel_3 = tf.random.uniform([], 0, 1.0, dtype=tf.float32)
            
    # Flips
    image = tf.image.random_flip_left_right(image)
    image = tf.image.random_flip_up_down(image)
    if p_spatial > .75:
        image = tf.image.transpose(image)
        
    # Rotates
    if p_rotate > .75:
        image = tf.image.rot90(image, k=3) # rotate 270º
    elif p_rotate > .5:
        image = tf.image.rot90(image, k=2) # rotate 180º
    elif p_rotate > .25:
        image = tf.image.rot90(image, k=1) # rotate 90º
        
    # Pixel-level transforms
    if p_pixel_1 >= .4:
        image = tf.image.random_saturation(image, lower=.7, upper=1.3)
    if p_pixel_2 >= .4:
        image = tf.image.random_contrast(image, lower=.8, upper=1.2)
    if p_pixel_3 >= .4:
        image = tf.image.random_brightness(image, max_delta=.1)
            

    return image, label<jupyter_output><empty_output><jupyter_text>**Dataset Functions**<jupyter_code># Datasets utility functions
def get_name(file_path):
    parts = tf.strings.split(file_path, os.path.sep)
    name = parts[-1]
    return name

def decode_image(image_data):
    image = tf.image.decode_jpeg(image_data, channels=3)
    image = tf.cast(image, tf.float32) / 255.0
    
    return image

def center_crop(image):
    image = tf.reshape(image, [600, 800, CHANNELS]) # Original shape
    
    h, w = image.shape[0], image.shape[1]
    if h > w:
        image = tf.image.crop_to_bounding_box(image, (h - w) // 2, 0, w, w)
    else:
        image = tf.image.crop_to_bounding_box(image, 0, (w - h) // 2, h, h)
        
    image = tf.image.resize(image, [HEIGHT, WIDTH]) # Expected shape
    return image

def resize_image(image, label):
    image = tf.image.resize(image, [HEIGHT, WIDTH])
    image = tf.reshape(image, [HEIGHT, WIDTH, CHANNELS])
    return image, label

def process_path(file_path):
    name = get_name(file_path)
    img = tf.io.read_file(file_path)
    img = decode_image(img)
    return img, name

def get_dataset(files_path, shuffled=False, tta=False, extension='jpg'):
    dataset = tf.data.Dataset.list_files(f'{files_path}*{extension}', shuffle=shuffled)
    dataset = dataset.map(process_path, num_parallel_calls=AUTO)
    if tta:
        dataset = dataset.map(data_augment, num_parallel_calls=AUTO)
    dataset = dataset.map(resize_image, num_parallel_calls=AUTO)
    dataset = dataset.batch(BATCH_SIZE)
    dataset = dataset.prefetch(AUTO)
    return dataset<jupyter_output><empty_output><jupyter_text>**Models**<jupyter_code>model_path_list = glob.glob('/kaggle/input/b3models/*.h5')
model_path_list.sort()

print('Models to predict:')
print(*model_path_list, sep='\n')

def model_fn(input_shape, N_CLASSES):
    inputs = L.Input(shape=input_shape, name='inputs')
    base_model = efn.EfficientNetB7(input_tensor=inputs, 
                                    include_top=False, 
                                    weights=None, 
                                    pooling='avg')

    model = tf.keras.Sequential([
        base_model,
        L.Dropout(.25),
        L.Dense(N_CLASSES, activation='softmax', name='output')
    ])
    
    return model

with strategy.scope():
    model = model_fn((None, None, CHANNELS), N_CLASSES)
    
model.summary()<jupyter_output>Models to predict:
/kaggle/input/b3models/B7model_0.h5
/kaggle/input/b3models/B7model_1.h5
/kaggle/input/b3models/B7model_2.h5
/kaggle/input/b3models/B7model_3.h5
/kaggle/input/b3models/B7model_4.h5
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
efficientnet-b7 (Model)      (None, 2560)              64097680  
_________________________________________________________________
dropout (Dropout)            (None, 2560)              0         
_________________________________________________________________
output (Dense)               (None, 5)                 12805     
=================================================================
Total params: 64,110,485
Trainable params: 63,799,765
Non-trainable params: 310,720
_________________________________________________________________<jupyter_text>**Predictions**<jupyter_code>files_path = f'{database_base_path}test_images/'
test_preds = np.zeros((len(os.listdir(files_path)), N_CLASSES))


print('First model')
for model_path in model_path_list:
    print(model_path)
    K.clear_session()
    model.load_weights(model_path)

    if TTA_STEPS > 0:
        test_ds = get_dataset(files_path, tta=True)
        for step in range(TTA_STEPS):
            print(f'TTA step {step+1}/{TTA_STEPS}')
            x_test = test_ds.map(lambda image, image_name: image)
            test_preds += model.predict(x_test) / (TTA_STEPS * len(model_path_list))
    else:
        test_ds = get_dataset(files_path, tta=False)
        x_test = test_ds.map(lambda image, image_name: image)
        test_preds += model.predict(x_test) / len(model_path_list)
    
test_preds = np.argmax(test_preds, axis=-1)
image_names = [img_name.numpy().decode('utf-8') for img, img_name in iter(test_ds.unbatch())]<jupyter_output>First model
/kaggle/input/b3models/B7model_0.h5
TTA step 1/3
TTA step 2/3
TTA step 3/3
/kaggle/input/b3models/B7model_1.h5
TTA step 1/3
TTA step 2/3
TTA step 3/3
/kaggle/input/b3models/B7model_2.h5
TTA step 1/3
TTA step 2/3
TTA step 3/3
/kaggle/input/b3models/B7model_3.h5
TTA step 1/3
TTA step 2/3
TTA step 3/3
/kaggle/input/b3models/B7model_4.h5
TTA step 1/3
TTA step 2/3
TTA step 3/3<jupyter_text>**Submission**<jupyter_code>submission = pd.DataFrame({'image_id': image_names, 'label': test_preds})
submission.to_csv('submission.csv', index=False)
display(submission.head())<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13851969272039996, 'fraction_numerical': 0.027923423972686257, 'mean_word_length': 3.911377245508982, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '92681', 'license': 'MIT', 'n_tokens_mistral': 3125, 'n_tokens_neox': 2958, 'n_words': 513, 'path': 'Cassava_Disease_Classification/cassava-leaf-disease-test-01.ipynb', 'repo_name': 'Nathan-Weatherly/Projects', 'size': '8201'}