{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":13836,"databundleVersionId":1718836,"sourceType":"competition"},{"sourceId":778,"sourceType":"modelInstanceVersion","modelInstanceId":645}],"dockerImageVersionId":30684,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install --upgrade pip\n!pip install keras\n!pip install --upgrade jupyter ipywidgets\n!pip install --upgrade tensorflow\n!pip install --upgrade tf-keras tensorflow-text\n!pip install keras-core\n!pip install --upgrade tensorflow-hub\n\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-04-30T11:28:20.843929Z","iopub.execute_input":"2024-04-30T11:28:20.844206Z","iopub.status.idle":"2024-04-30T11:30:58.076801Z","shell.execute_reply.started":"2024-04-30T11:28:20.844181Z","shell.execute_reply":"2024-04-30T11:30:58.075645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nos.environ['TF_USE_LEGACY_KERAS'] = '1'\nimport re\nfrom datetime import datetime\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nfrom kaggle_datasets import KaggleDatasets\n\nimport tensorflow as tf\n\nimport tf_keras as keras\n\nfrom tensorflow.keras.applications.efficientnet import EfficientNetB0\nfrom tensorflow.keras.applications.efficientnet import preprocess_input as effnet_preprocess_input\nimport tensorflow_datasets as tfds\nimport tensorflow_hub as hub","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:30:58.078943Z","iopub.execute_input":"2024-04-30T11:30:58.079258Z","iopub.status.idle":"2024-04-30T11:31:05.746172Z","shell.execute_reply.started":"2024-04-30T11:30:58.079229Z","shell.execute_reply":"2024-04-30T11:31:05.745165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.applications.efficientnet import EfficientNetB0\nfrom tensorflow.keras.applications.efficientnet import preprocess_input as effnet_preprocess_input","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:05.747410Z","iopub.execute_input":"2024-04-30T11:31:05.747950Z","iopub.status.idle":"2024-04-30T11:31:05.755219Z","shell.execute_reply.started":"2024-04-30T11:31:05.747922Z","shell.execute_reply":"2024-04-30T11:31:05.751817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow_datasets as tfds\nimport tensorflow_hub as hub","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:05.756641Z","iopub.execute_input":"2024-04-30T11:31:05.757045Z","iopub.status.idle":"2024-04-30T11:31:05.779268Z","shell.execute_reply.started":"2024-04-30T11:31:05.757012Z","shell.execute_reply":"2024-04-30T11:31:05.778335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(os.getenv('TF_USE_LEGACY_KERAS'))","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:05.782720Z","iopub.execute_input":"2024-04-30T11:31:05.783085Z","iopub.status.idle":"2024-04-30T11:31:05.791612Z","shell.execute_reply.started":"2024-04-30T11:31:05.783061Z","shell.execute_reply":"2024-04-30T11:31:05.790774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import tensorflow as tf\n\n# try:\n#   # Attempt TPU detection using `tf.distribute.cluster_resolver.TPUClusterResolver`\n#   tpu = tf.distribute.cluster_resolver.TPUClusterResolver(tpu='local')\n#   print('Running on TPU:', tpu.cluster_spec().as_dict().get('worker', 'CPU/GPU') if tpu else 'CPU/GPU')\n\n# except ValueError:\n#   # Handle the case where no TPU is found\n#   print('ERROR: Not connected to a TPU runtime!')\n#   raise BaseException('No TPU detected. Consider using CPU or GPU for training.')  # More informative error message\n\n# # Regardless of TPU availability, configure the strategy\nstrategy = tf.distribute.experimental.CentralStorageStrategy()  # Efficient strategy for most cases","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:05.792508Z","iopub.execute_input":"2024-04-30T11:31:05.792790Z","iopub.status.idle":"2024-04-30T11:31:06.097188Z","shell.execute_reply.started":"2024-04-30T11:31:05.792760Z","shell.execute_reply":"2024-04-30T11:31:06.096221Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Directly use the Kaggle dataset path without get_gcs_path\nGCS_PATH = '/kaggle/input/cassava-leaf-disease-classification'","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.098341Z","iopub.execute_input":"2024-04-30T11:31:06.098956Z","iopub.status.idle":"2024-04-30T11:31:06.107448Z","shell.execute_reply.started":"2024-04-30T11:31:06.098929Z","shell.execute_reply":"2024-04-30T11:31:06.106574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tfrec_fnames = tf.io.gfile.glob(GCS_PATH + '/train_tfrecords/ld_train*.tfrec')\nlen(tfrec_fnames)","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.108536Z","iopub.execute_input":"2024-04-30T11:31:06.108835Z","iopub.status.idle":"2024-04-30T11:31:06.128263Z","shell.execute_reply.started":"2024-04-30T11:31:06.108794Z","shell.execute_reply":"2024-04-30T11:31:06.127494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_to_disease = pd.read_json(os.path.join(GCS_PATH, 'label_num_to_disease_map.json'), typ='series')","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.129238Z","iopub.execute_input":"2024-04-30T11:31:06.129523Z","iopub.status.idle":"2024-04-30T11:31:06.147169Z","shell.execute_reply.started":"2024-04-30T11:31:06.129499Z","shell.execute_reply":"2024-04-30T11:31:06.146226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_csv = pd.read_csv(os.path.join(GCS_PATH, 'train.csv'))","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.148328Z","iopub.execute_input":"2024-04-30T11:31:06.148610Z","iopub.status.idle":"2024-04-30T11:31:06.177391Z","shell.execute_reply.started":"2024-04-30T11:31:06.148585Z","shell.execute_reply":"2024-04-30T11:31:06.176464Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_csv['disease'] = train_csv['label'].map(label_to_disease)\ntrain_csv.head()","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.178534Z","iopub.execute_input":"2024-04-30T11:31:06.178856Z","iopub.status.idle":"2024-04-30T11:31:06.197961Z","shell.execute_reply.started":"2024-04-30T11:31:06.178829Z","shell.execute_reply":"2024-04-30T11:31:06.196908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 75:25 train:valid\ntrain_fnames = tfrec_fnames[:12]\nvalid_fnames = tfrec_fnames[12:]\nprint(len(train_fnames), len(valid_fnames))","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.199059Z","iopub.execute_input":"2024-04-30T11:31:06.199374Z","iopub.status.idle":"2024-04-30T11:31:06.204423Z","shell.execute_reply.started":"2024-04-30T11:31:06.199348Z","shell.execute_reply":"2024-04-30T11:31:06.203456Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"early_stop = keras.callbacks.EarlyStopping(monitor = 'val_loss', min_delta = 0.001, \n                                              patience = 5, mode = 'min', verbose = 1,\n                                              restore_best_weights = True)\n\nreduce_lr = keras.callbacks.ReduceLROnPlateau(monitor = 'val_loss', factor = 0.3, \n                                                 patience = 2, min_delta = 0.001, \n                                                 mode = 'min', verbose = 1)","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.205739Z","iopub.execute_input":"2024-04-30T11:31:06.206072Z","iopub.status.idle":"2024-04-30T11:31:06.215844Z","shell.execute_reply.started":"2024-04-30T11:31:06.206048Z","shell.execute_reply":"2024-04-30T11:31:06.215004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"AUTO = tf.data.experimental.AUTOTUNE\nBATCH_SIZE = 32\nIMAGE_SIZE = [512, 512]\nprint(strategy.num_replicas_in_sync)","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.220473Z","iopub.execute_input":"2024-04-30T11:31:06.220771Z","iopub.status.idle":"2024-04-30T11:31:06.226576Z","shell.execute_reply.started":"2024-04-30T11:31:06.220748Z","shell.execute_reply":"2024-04-30T11:31:06.225707Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def _parse_function(proto):\n    # feature_description needs to be defined since datasets use graph-execution\n    # - its used to build their shape and type signature\n    feature_description = {\n        'image': tf.io.FixedLenFeature([], tf.string, default_value=''),\n        'image_name': tf.io.FixedLenFeature([], tf.string, default_value=''),\n        'target': tf.io.FixedLenFeature([], tf.int64, default_value=-1)\n    }\n\n    parsed_features = tf.io.parse_single_example(proto, feature_description)\n    image = tf.image.decode_jpeg(parsed_features['image'], channels=3)\n    image = tf.cast(image, tf.float32) # :: [0.0, 255.0]\n    image = tf.reshape(image, [*IMAGE_SIZE, 3])\n    target = tf.one_hot(parsed_features['target'], depth=5)\n    return image, target","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.227476Z","iopub.execute_input":"2024-04-30T11:31:06.227780Z","iopub.status.idle":"2024-04-30T11:31:06.237435Z","shell.execute_reply.started":"2024-04-30T11:31:06.227741Z","shell.execute_reply":"2024-04-30T11:31:06.236564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_dataset(tfrecords_fnames):\n    raw_ds = tf.data.TFRecordDataset(tfrecords_fnames, num_parallel_reads=AUTO)\n    parsed_ds = raw_ds.map(_parse_function, num_parallel_calls=AUTO)\n    return parsed_ds","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.238565Z","iopub.execute_input":"2024-04-30T11:31:06.239309Z","iopub.status.idle":"2024-04-30T11:31:06.246630Z","shell.execute_reply.started":"2024-04-30T11:31:06.239277Z","shell.execute_reply":"2024-04-30T11:31:06.245782Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_train_ds(train_fnames, with_aug=False):\n    ds = load_dataset(train_fnames)\n\n    def data_augment(image, target):\n        modified = tf.image.random_flip_left_right(image)\n        modified = tf.image.random_flip_up_down(image)\n        #modified = tf.image.random_brightness(modified, 0.2)\n        #modified = tf.image.random_contrast(modified, 0.2, 0.5)\n        #modified = tf.image.random_hue(modified, 0.2)\n        #modified = tf.image.random_saturation(modified, 5, 10)\n        modified = tf.clip_by_value(modified, 0.0, 255.0)\n        return modified, target\n\n    if with_aug:\n        ds = ds.map(data_augment, num_parallel_calls=AUTO)\n\n    return ds.repeat().shuffle(2048).batch(BATCH_SIZE, drop_remainder=True).prefetch(AUTO)","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.247601Z","iopub.execute_input":"2024-04-30T11:31:06.247870Z","iopub.status.idle":"2024-04-30T11:31:06.256984Z","shell.execute_reply.started":"2024-04-30T11:31:06.247849Z","shell.execute_reply":"2024-04-30T11:31:06.256117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_valid_ds(valid_fnames):\n    ds = load_dataset(valid_fnames)\n    ds = ds.batch(BATCH_SIZE, drop_remainder=True).prefetch(AUTO)\n    return ds","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.257997Z","iopub.execute_input":"2024-04-30T11:31:06.258283Z","iopub.status.idle":"2024-04-30T11:31:06.269611Z","shell.execute_reply.started":"2024-04-30T11:31:06.258254Z","shell.execute_reply":"2024-04-30T11:31:06.268865Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def count_data_items(filenames):\n    n = [int(re.compile(r\"-([0-9]*)\\.\").search(fname).group(1)) for fname in filenames]\n    return np.sum(n)\n\nn_train = count_data_items(train_fnames)\nn_valid = count_data_items(valid_fnames)\ntrain_steps = count_data_items(train_fnames) // BATCH_SIZE\nprint(\"TRAINING IMAGES:\", n_train, \", STEPS PER EPOCH:\", train_steps)\nprint(\"VALIDATION IMAGES:\", n_valid)","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.270593Z","iopub.execute_input":"2024-04-30T11:31:06.270913Z","iopub.status.idle":"2024-04-30T11:31:06.281480Z","shell.execute_reply.started":"2024-04-30T11:31:06.270887Z","shell.execute_reply":"2024-04-30T11:31:06.280619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def preprocess_fn(image, label):\n    image = image / 255.0\n    image = tf.image.resize(image, (224, 224))\n    label = tf.concat([label, [0]], axis=0)\n    return image, label","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.282539Z","iopub.execute_input":"2024-04-30T11:31:06.282889Z","iopub.status.idle":"2024-04-30T11:31:06.290292Z","shell.execute_reply.started":"2024-04-30T11:31:06.282857Z","shell.execute_reply":"2024-04-30T11:31:06.289448Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_fnames = tfrec_fnames[:12]\nvalid_fnames = tfrec_fnames[12:]\n\ntrain_ds = load_dataset(train_fnames)\ntrain_ds = train_ds.map(preprocess_fn, num_parallel_calls=AUTO)\ntrain_ds = train_ds.repeat().shuffle(2048).batch(BATCH_SIZE, drop_remainder=True).prefetch(AUTO)\n\nvalid_ds = load_dataset(valid_fnames)\nvalid_ds = valid_ds.map(preprocess_fn, num_parallel_calls=AUTO)\nvalid_ds = valid_ds.batch(BATCH_SIZE, drop_remainder=True).prefetch(AUTO)\n\ntrain_steps = count_data_items(train_fnames) // BATCH_SIZE","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.291333Z","iopub.execute_input":"2024-04-30T11:31:06.291749Z","iopub.status.idle":"2024-04-30T11:31:06.894423Z","shell.execute_reply.started":"2024-04-30T11:31:06.291718Z","shell.execute_reply":"2024-04-30T11:31:06.893517Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img, label = next(iter(train_ds))\nprint(img.numpy().max(), img.shape, img.dtype)","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:06.895460Z","iopub.execute_input":"2024-04-30T11:31:06.895757Z","iopub.status.idle":"2024-04-30T11:31:10.532797Z","shell.execute_reply.started":"2024-04-30T11:31:06.895726Z","shell.execute_reply":"2024-04-30T11:31:10.531839Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.environ[\"TFHUB_CACHE_DIR\"] = \"/kaggle/working\"\nwith strategy.scope():\n    load_locally = tf.saved_model.LoadOptions(experimental_io_device='/job:localhost')\n    cassava = hub.KerasLayer('https://tfhub.dev/google/cropnet/classifier/cassava_disease_V1/2', trainable=True, load_options=load_locally)\n    model = keras.Sequential([keras.Input(shape=(224,224,3)),\n                                 cassava])\n        ","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:10.534149Z","iopub.execute_input":"2024-04-30T11:31:10.534811Z","iopub.status.idle":"2024-04-30T11:31:14.937463Z","shell.execute_reply.started":"2024-04-30T11:31:10.534775Z","shell.execute_reply":"2024-04-30T11:31:14.936698Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#model.load_weights(\"/kaggle/working/preTrainedCropnet.keras\")","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:14.938744Z","iopub.execute_input":"2024-04-30T11:31:14.939175Z","iopub.status.idle":"2024-04-30T11:31:14.943503Z","shell.execute_reply.started":"2024-04-30T11:31:14.939141Z","shell.execute_reply":"2024-04-30T11:31:14.942566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(optimizer=keras.optimizers.Adam(learning_rate=1e-5),\n              loss=keras.losses.CategoricalCrossentropy(from_logits=False),\n              metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:14.944559Z","iopub.execute_input":"2024-04-30T11:31:14.944862Z","iopub.status.idle":"2024-04-30T11:31:14.975914Z","shell.execute_reply.started":"2024-04-30T11:31:14.944839Z","shell.execute_reply":"2024-04-30T11:31:14.974983Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.fit(train_ds, validation_data=valid_ds,\n          epochs=500, steps_per_epoch=train_steps,\n          callbacks=[reduce_lr, early_stop])","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:31:14.976983Z","iopub.execute_input":"2024-04-30T11:31:14.977240Z","iopub.status.idle":"2024-04-30T11:42:27.663640Z","shell.execute_reply.started":"2024-04-30T11:31:14.977218Z","shell.execute_reply":"2024-04-30T11:42:27.662731Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save(\"preTrainedCropnet5.keras\")","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:42:27.664755Z","iopub.execute_input":"2024-04-30T11:42:27.665047Z","iopub.status.idle":"2024-04-30T11:42:28.177526Z","shell.execute_reply.started":"2024-04-30T11:42:27.665020Z","shell.execute_reply":"2024-04-30T11:42:28.176713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{"execution":{"iopub.status.busy":"2024-04-30T11:42:28.178733Z","iopub.execute_input":"2024-04-30T11:42:28.179027Z","iopub.status.idle":"2024-04-30T11:42:28.205146Z","shell.execute_reply.started":"2024-04-30T11:42:28.179002Z","shell.execute_reply":"2024-04-30T11:42:28.204287Z"},"trusted":true},"execution_count":null,"outputs":[]}]}