{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport re\nfrom datetime import datetime\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nimport tensorflow as tf\nfrom kaggle_datasets import KaggleDatasets\n\n!pip install keras-metrics\nimport keras_metrics","metadata":{"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":"2021-07-02T14:29:21.130699Z","iopub.execute_input":"2021-07-02T14:29:21.131055Z","iopub.status.idle":"2021-07-02T14:29:22.043557Z","shell.execute_reply.started":"2021-07-02T14:29:21.131019Z","shell.execute_reply":"2021-07-02T14:29:22.042349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Tensorflow version \" + tf.__version__)\n\ntry:\n  tpu = tf.distribute.cluster_resolver.TPUClusterResolver()  # TPU detection\n  print('Running on TPU ', tpu.cluster_spec().as_dict()['worker'])\nexcept ValueError:\n  raise BaseException('ERROR: Not connected to a TPU runtime; please see the previous cell in this notebook for instructions!')\n\ntf.config.experimental_connect_to_cluster(tpu)\ntf.tpu.experimental.initialize_tpu_system(tpu)\ntpu_strategy = tf.distribute.TPUStrategy(tpu)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T14:29:22.052052Z","iopub.execute_input":"2021-07-02T14:29:22.052378Z","iopub.status.idle":"2021-07-02T14:29:27.496413Z","shell.execute_reply.started":"2021-07-02T14:29:22.052344Z","shell.execute_reply":"2021-07-02T14:29:27.4952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"GCS_PATH = KaggleDatasets().get_gcs_path('cassava-leaf-disease-classification')\ntfrec_fnames = tf.io.gfile.glob(GCS_PATH + '/train_tfrecords/ld_train*.tfrec')\nprint(GCS_PATH)\nlen(tfrec_fnames)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T14:35:46.146814Z","iopub.execute_input":"2021-07-02T14:35:46.147194Z","iopub.status.idle":"2021-07-02T14:35:46.815798Z","shell.execute_reply.started":"2021-07-02T14:35:46.147163Z","shell.execute_reply":"2021-07-02T14:35:46.814654Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_to_disease = pd.read_json('../input/cassava-leaf-disease-classification/label_num_to_disease_map.json',typ='series')\nlabel_to_disease","metadata":{"execution":{"iopub.status.busy":"2021-07-02T14:35:55.891706Z","iopub.execute_input":"2021-07-02T14:35:55.89209Z","iopub.status.idle":"2021-07-02T14:35:55.94264Z","shell.execute_reply.started":"2021-07-02T14:35:55.892056Z","shell.execute_reply":"2021-07-02T14:35:55.941758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_csv = pd.read_csv('../input/cassava-leaf-disease-classification/train.csv')","metadata":{"execution":{"iopub.status.busy":"2021-07-02T14:35:58.78077Z","iopub.execute_input":"2021-07-02T14:35:58.781313Z","iopub.status.idle":"2021-07-02T14:35:58.811233Z","shell.execute_reply.started":"2021-07-02T14:35:58.781279Z","shell.execute_reply":"2021-07-02T14:35:58.810442Z"},"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":"2021-07-02T14:36:00.225838Z","iopub.execute_input":"2021-07-02T14:36:00.226392Z","iopub.status.idle":"2021-07-02T14:36:00.255997Z","shell.execute_reply.started":"2021-07-02T14:36:00.226355Z","shell.execute_reply":"2021-07-02T14:36:00.254742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_fnames = tfrec_fnames[:12]\nvalid_fnames = tfrec_fnames[12:]\nprint(len(train_fnames), len(valid_fnames))","metadata":{"execution":{"iopub.status.busy":"2021-07-02T14:36:01.561161Z","iopub.execute_input":"2021-07-02T14:36:01.5616Z","iopub.status.idle":"2021-07-02T14:36:01.568458Z","shell.execute_reply.started":"2021-07-02T14:36:01.561557Z","shell.execute_reply":"2021-07-02T14:36:01.567106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"early_stop = tf.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 = tf.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":"2021-07-02T14:36:46.362053Z","iopub.execute_input":"2021-07-02T14:36:46.362456Z","iopub.status.idle":"2021-07-02T14:36:46.368973Z","shell.execute_reply.started":"2021-07-02T14:36:46.362422Z","shell.execute_reply":"2021-07-02T14:36:46.367634Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"AUTO = tf.data.experimental.AUTOTUNE\nBATCH_SIZE = 16 * tpu_strategy.num_replicas_in_sync\nIMAGE_SIZE = [512, 512]","metadata":{"execution":{"iopub.status.busy":"2021-07-02T14:37:18.982508Z","iopub.execute_input":"2021-07-02T14:37:18.982871Z","iopub.status.idle":"2021-07-02T14:37:18.98687Z","shell.execute_reply.started":"2021-07-02T14:37:18.982841Z","shell.execute_reply":"2021-07-02T14:37:18.986174Z"},"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    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)\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":"2021-07-02T14:37:22.421554Z","iopub.execute_input":"2021-07-02T14:37:22.422083Z","iopub.status.idle":"2021-07-02T14:37:22.429531Z","shell.execute_reply.started":"2021-07-02T14:37:22.422049Z","shell.execute_reply":"2021-07-02T14:37:22.428331Z"},"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":"2021-07-02T14:37:30.162563Z","iopub.execute_input":"2021-07-02T14:37:30.162941Z","iopub.status.idle":"2021-07-02T14:37:30.168168Z","shell.execute_reply.started":"2021-07-02T14:37:30.162896Z","shell.execute_reply":"2021-07-02T14:37:30.167038Z"},"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    def data_augment(image, target):\n        modified = tf.image.central_crop(image, cetral_fraction=0.8)\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":"2021-07-02T14:37:30.87156Z","iopub.execute_input":"2021-07-02T14:37:30.87219Z","iopub.status.idle":"2021-07-02T14:37:30.88058Z","shell.execute_reply.started":"2021-07-02T14:37:30.87213Z","shell.execute_reply":"2021-07-02T14:37:30.87952Z"},"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":"2021-07-02T14:37:31.882809Z","iopub.execute_input":"2021-07-02T14:37:31.883252Z","iopub.status.idle":"2021-07-02T14:37:31.889021Z","shell.execute_reply.started":"2021-07-02T14:37:31.883216Z","shell.execute_reply":"2021-07-02T14:37:31.888109Z"},"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":"2021-07-02T14:37:33.872596Z","iopub.execute_input":"2021-07-02T14:37:33.87305Z","iopub.status.idle":"2021-07-02T14:37:33.883444Z","shell.execute_reply.started":"2021-07-02T14:37:33.873013Z","shell.execute_reply":"2021-07-02T14:37:33.881937Z"},"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":"2021-07-02T14:37:39.957024Z","iopub.execute_input":"2021-07-02T14:37:39.957537Z","iopub.status.idle":"2021-07-02T14:37:39.962413Z","shell.execute_reply.started":"2021-07-02T14:37:39.957505Z","shell.execute_reply":"2021-07-02T14:37:39.9616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_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":"2021-07-02T14:37:55.426461Z","iopub.execute_input":"2021-07-02T14:37:55.427026Z","iopub.status.idle":"2021-07-02T14:37:55.877962Z","shell.execute_reply.started":"2021-07-02T14:37:55.426975Z","shell.execute_reply":"2021-07-02T14:37:55.876986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img, label = next(iter(train_ds))\nprint(img.numpy().max(), img.shape, img.dtype)\n\n#print(label)\n\ncurrent_balance = train_csv['label'].value_counts(normalize=True)\ncurrent_balance","metadata":{"execution":{"iopub.status.busy":"2021-07-02T14:37:58.831816Z","iopub.execute_input":"2021-07-02T14:37:58.832216Z","iopub.status.idle":"2021-07-02T14:38:04.427692Z","shell.execute_reply.started":"2021-07-02T14:37:58.832181Z","shell.execute_reply":"2021-07-02T14:38:04.4268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.environ[\"TFHUB_CACHE_DIR\"] = \"/kaggle/working\"\nfrom tensorflow.keras import applications\nimport tensorflow_hub as hub\nwith tpu_strategy.scope():\n    load_locally = tf.saved_model.LoadOptions(experimental_io_device='/job:localhost')\n    vgg_base = applications.MobileNet(include_top=False, input_shape=[224, 224, 3], weights = 'imagenet')\n    inputs = vgg_base.input\n    outputs = vgg_base.output\n    \n    f1 = tf.keras.layers.Flatten()(outputs)\n    d1 = tf.keras.layers.Dense(8, activation='relu')(f1)\n    preds = tf.keras.layers.Dense(5)(d1)\n    \n    model = tf.keras.Model(inputs = inputs, outputs = preds)\n\nmodel.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4),\n              loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True, label_smoothing=0.3),\n              metrics=['acc'])\n\nmodel.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":"2021-06-24T17:28:09.680075Z","iopub.execute_input":"2021-06-24T17:28:09.680461Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.environ[\"TFHUB_CACHE_DIR\"] = \"/kaggle/working\"\nfrom tensorflow.keras import applications\nimport tensorflow_hub as hub\nwith tpu_strategy.scope():\n    load_locally = tf.saved_model.LoadOptions(experimental_io_device='/job:localhost')\n    vgg_base = applications.VGG16(include_top=False, input_shape=[224, 224, 3], weights = 'imagenet')\n    inputs = vgg_base.input\n    outputs = vgg_base.output\n    \n    f1 = tf.keras.layers.Flatten()(outputs)\n    d1 = tf.keras.layers.Dense(8, activation='relu')(f1)    \n    preds = tf.keras.layers.Dense(5)(d1)\n    \n    model = tf.keras.Model(inputs = inputs, outputs = preds)\n\nmodel.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4, epsilon=1e-08),\n              loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True, label_smoothing=0.6),\n              metrics=['acc'])\n\nmodel.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":"2021-06-24T14:19:45.461515Z","iopub.execute_input":"2021-06-24T14:19:45.461873Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.environ[\"TFHUB_CACHE_DIR\"] = \"/kaggle/working\"\nfrom tensorflow.keras import applications\nimport tensorflow_hub as hub\nwith tpu_strategy.scope():\n    load_locally = tf.saved_model.LoadOptions(experimental_io_device='/job:localhost')\n    cassava = hub.KerasLayer('https://tfhub.dev/google/imagenet/mobilenet_v3_large_075_224/feature_vector/5', trainable=True, load_options=load_locally)\n\n    model = tf.keras.Sequential([tf.keras.Input(shape=(224,224,3)), cassava])\n    model.add(tf.keras.layers.Dense(5))\n    model.summary()\n\nmodel.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4),\n              loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),\n              metrics=['acc'])\n\nmodel.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":"2021-06-23T17:25:38.068997Z","iopub.execute_input":"2021-06-23T17:25:38.069442Z","iopub.status.idle":"2021-06-23T17:27:59.881362Z","shell.execute_reply.started":"2021-06-23T17:25:38.069408Z","shell.execute_reply":"2021-06-23T17:27:59.880563Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.environ[\"TFHUB_CACHE_DIR\"] = \"/kaggle/working\"\nfrom tensorflow.keras import applications\nimport tensorflow_hub as hub\nwith tpu_strategy.scope():\n    load_locally = tf.saved_model.LoadOptions(experimental_io_device='/job:localhost')\n    cassava = hub.KerasLayer('https://tfhub.dev/tensorflow/resnet_v1_152/feature_vector/1', trainable=True, load_options=load_locally)\n\n    model = tf.keras.Sequential([tf.keras.Input(shape=(224,224,3)), cassava])\n    model.add(tf.keras.layers.Dense(5))\n    model.summary()\n\nmodel.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),\n              loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),\n              metrics=['acc'])\n\nmodel.fit(train_ds, validation_data=valid_ds,\n          epochs=50, steps_per_epoch=train_steps,\n         callbacks=[reduce_lr])","metadata":{"execution":{"iopub.status.busy":"2021-06-23T17:50:22.379275Z","iopub.execute_input":"2021-06-23T17:50:22.379743Z","iopub.status.idle":"2021-06-23T17:50:22.777701Z","shell.execute_reply.started":"2021-06-23T17:50:22.379708Z","shell.execute_reply":"2021-06-23T17:50:22.774781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.fit(\n    train_ds,\n    validation_data=valid_ds, \n    epochs=100, \n    steps_per_epoch=train_steps\n)","metadata":{"execution":{"iopub.status.busy":"2021-06-07T06:58:19.080308Z","iopub.execute_input":"2021-06-07T06:58:19.081205Z","iopub.status.idle":"2021-06-07T06:58:21.111172Z","shell.execute_reply.started":"2021-06-07T06:58:19.081122Z","shell.execute_reply":"2021-06-07T06:58:21.108031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"json_model = model.to_json()#save the model architecture to JSON file\nwith open('keras_model.json', 'w') as json_file:\n    json_file.write(json_model)#saving the weights of the model\nmodel.save_weights('keras_model.h5')#Model loss and accuracy\nop = model.evaluate(valid_ds)\nprint('accuracy : ' + str(op[1]))","metadata":{"execution":{"iopub.status.busy":"2021-05-21T05:26:43.954475Z","iopub.execute_input":"2021-05-21T05:26:43.95475Z","iopub.status.idle":"2021-05-21T05:26:47.162067Z","shell.execute_reply.started":"2021-05-21T05:26:43.954724Z","shell.execute_reply":"2021-05-21T05:26:47.160907Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import skimage.io as io\nimport skimage.transform as trans\nimport numpy as np\nfrom keras.models import *\nfrom keras.layers import *\nfrom keras.optimizers import *\nfrom keras.callbacks import ModelCheckpoint, LearningRateScheduler\nfrom keras import backend as keras\n\nos.environ[\"TFHUB_CACHE_DIR\"] = \"/kaggle/working\"\nfrom tensorflow.keras import applications\nimport tensorflow_hub as hub\nwith tpu_strategy.scope():\n    model = Sequential([\n        #tf.keras.layers.experimental.preprocessing.Rescaling(1./255, input_shape=(224, 224, 3)),\n        tf.keras.layers.Input(shape=[224, 224, 3]),    \n        tf.keras.layers.Flatten(),\n        tf.keras.layers.Dense(1024, activation='relu'),\n        tf.keras.layers.Dense(512, activation='relu'),\n        tf.keras.layers.Dense(256, activation='relu'),\n        tf.keras.layers.Dense(128, activation='relu'),\n        tf.keras.layers.Dense(64, activation='relu'),\n        tf.keras.layers.Dense(32, activation='relu'),\n        tf.keras.layers.Dense(6)\n    ])\n    model.summary()","metadata":{"execution":{"iopub.status.busy":"2021-05-21T14:49:33.679417Z","iopub.execute_input":"2021-05-21T14:49:33.679815Z","iopub.status.idle":"2021-05-21T14:49:35.207379Z","shell.execute_reply.started":"2021-05-21T14:49:33.679785Z","shell.execute_reply":"2021-05-21T14:49:35.206401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),\n              loss=tf.keras.losses.CategoricalCrossentropy(from_logits=False),\n              metrics=['acc'])\n\nmodel.fit(\n    train_ds,\n    validation_data=valid_ds, \n    epochs=200, \n    steps_per_epoch=train_steps,     \n    callbacks=[early_stop, reduce_lr]\n)","metadata":{"execution":{"iopub.status.busy":"2021-05-21T14:49:35.208704Z","iopub.execute_input":"2021-05-21T14:49:35.208987Z","iopub.status.idle":"2021-05-21T14:50:31.333699Z","shell.execute_reply.started":"2021-05-21T14:49:35.20896Z","shell.execute_reply":"2021-05-21T14:50:31.331779Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.history.history['val_acc']","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_augmentation = tf.keras.Sequential(\n  [\n    tf.keras.layers.experimental.preprocessing.RandomFlip(\"horizontal\", \n                                                 input_shape=(224, 224, 3)),\n    tf.keras.layers.experimental.preprocessing.RandomRotation(0.1),\n    tf.keras.layers.experimental.preprocessing.RandomZoom(0.1),\n  ]\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.environ[\"TFHUB_CACHE_DIR\"] = \"/kaggle/working\"\nfrom tensorflow.keras import applications\nimport tensorflow_hub as hub\nwith tpu_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 = tf.keras.Model(tf.keras.layers.Input(shape=[224, 224, 3]), cassava)\n    model.summary()","metadata":{"execution":{"iopub.status.busy":"2021-07-02T14:39:29.197879Z","iopub.execute_input":"2021-07-02T14:39:29.198364Z","iopub.status.idle":"2021-07-02T14:39:36.634639Z","shell.execute_reply.started":"2021-07-02T14:39:29.198332Z","shell.execute_reply":"2021-07-02T14:39:36.632173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4),\n              loss=tf.keras.losses.CategoricalCrossentropy(from_logits=False),\n              metrics=['acc'])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(train_ds, validation_data=valid_ds,\n          epochs=500, steps_per_epoch=train_steps,\n          callbacks=[reduce_lr, early_stop])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\n\nconverter = tf.lite.TFLiteConverter.from_keras_model(model)\ntflite_model = converter.convert()\n\n# Save the model.\nwith open('model.tflite', 'wb') as f:\n  f.write(tflite_model)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}