{"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":"markdown","source":"## Imports","metadata":{}},{"cell_type":"code","source":"import os\nimport gc\nimport re\nimport cv2\nimport math\nimport time\nimport keras\nimport numpy\nimport pandas\nimport random\nimport tensorflow\nimport seaborn as sns\nfrom numba import cuda\nfrom PIL import Image\nimport keras.backend as K\nimport tensorflow as tf\nfrom typing import Tuple, List\nfrom pandas import DataFrame\nimport matplotlib.pyplot as plt\nfrom tensorflow.keras.layers import GlobalAveragePooling2D\nfrom keras.optimizers import RMSprop, SGD, Adam, Adamax\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.applications import ResNet50V2, ResNet152V2, ResNet50, MobileNetV2\nfrom keras.models import Model, Sequential, load_model, Input\nfrom keras.layers.core import Flatten, Dense, Dropout\nfrom keras.layers.normalization import BatchNormalization\nfrom keras.applications.mobilenet import preprocess_input\nfrom keras.layers.convolutional import Conv2D, MaxPooling2D\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-05-25T22:13:39.405906Z","iopub.execute_input":"2021-05-25T22:13:39.406332Z","iopub.status.idle":"2021-05-25T22:13:41.565347Z","shell.execute_reply.started":"2021-05-25T22:13:39.406248Z","shell.execute_reply":"2021-05-25T22:13:41.564567Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Setup","metadata":{}},{"cell_type":"code","source":"train_csv = pandas.read_csv(\"../input/plant-pathology-2021-fgvc8/train.csv\")\n# one_hot_train_csv = pandas.read_csv(\"../input/plant-pathology-models/one_hot_encoded_train.csv\")\n# train_images_dir = \"../input/plant-pathology-2021-resized/plant_pathology_2021_resized/train_images/620x403\"\n# train_images_dir = \"../input/plant-pathology-2021-resized/512x512_augmented/512x512_augmented\"\n# train_images_dir = \"../input/plant-pathology-2021-resized/512x512_augmented_4/512x512_augmented_4\"\ntrain_images_dir = \"../input/plant-pathology-2021-resized/512x512_augmented_combined/512x512_augmented_combined\"\n\n# train_images_dir = \"/kaggle/input/plant-pathology-2021-fgvc8/train_images\"\ntest_images_dir = \"../input/plant-pathology-2021-fgvc8/test_images\"\nws_splitter = re.compile(\"\\\\s+\")\nCLASSES = [\n    'healthy', \n    'scab frog_eye_leaf_spot complex', \n    'scab', \n    'complex', \n    'rust', \n    'frog_eye_leaf_spot', \n    'powdery_mildew', \n    'scab frog_eye_leaf_spot', \n    'frog_eye_leaf_spot complex', \n    'rust frog_eye_leaf_spot', \n    'powdery_mildew complex', \n    'rust complex'\n]\n\n\nDUPLICATE_IMAGES = [\n\"c5aff2e545d0a129.jpg\",\"c9d63696629107ed.jpg\",\"ae5074cfc9183763.jpg\",\"d64460a3b19f1cfc.jpg\",\n\"9ada65c5b0cc9a3c.jpg\",\"94c83b2d5fad6924.jpg\",\"ba99260ef46b18cb.jpg\",\"a3bb604d8a55995d.jpg\",\n\"949b6595a5b8ca3c.jpg\",\"dea33c5c0347aa4d.jpg\",\"e51690d8ad307dcb.jpg\",\"8c0731fff680c51e.jpg\",\n\"e83f715e56462a31.jpg\",\"9fc321ce60a69f0b.jpg\",\"bd8088cdad5f65e0.jpg\",\"cdf892b5b4865859.jpg\",\n\"f2c798246a0a9bdd.jpg\",\"f7d233d11aa8496c.jpg\",\"c1753cad2f31d492.jpg\",\"f3dc17a2b20d48ec.jpg\",\n\"aa0e969518e15d3f.jpg\",\"b5ec52491e3349ce.jpg\",\"ec83c7c04a1e9db9.jpg\",\"e5f27342ce1cb9a0.jpg\",\n\"9fad869f21b5b240.jpg\",\"d1f01e8d8a73274d.jpg\",\"d1dec0973c2cf4a1.jpg\",\"dbee22785d9285c4.jpg\",\n\"8f5263c61a8cdbe2.jpg\",\"965295a64a97859f.jpg\",\"f4cba4a7294d6585.jpg\",\"e9e8ad35c5871d06.jpg\",\n\"90f99ee1c1132bb6.jpg\",\"b7b0edd58a858217.jpg\",\"e7ecc583d571d202.jpg\",\"848d9f9e82d18e5e.jpg\",\n\"d3945c098edc9dd1.jpg\",\"eec64e8cf1c8d0c6.jpg\",\"df90901ccb664de6.jpg\",\"d0c766bc38e1978c.jpg\",\n\"86f963a16e70345e.jpg\",\"f90738a0d2f2c1db.jpg\",\"82ba3e933947b097.jpg\",\"c1a56069de75b899.jpg\",\n\"94b42695f24dad36.jpg\",\"d2266ac99461e9db.jpg\",\"90a5341f227ce5f9.jpg\",\"bb1891fa8c61e663.jpg\",\n\"a7e613159fb22859.jpg\",\"85897ea7f064b26a.jpg\",\"ca782c131f5ce0fc.jpg\",\"d7ec32d72c84dc18.jpg\",\n\"a9b2e4b09297bc2b.jpg\",\"d2d9c2bca7a72458.jpg\",\n\"augmented_c5aff2e545d0a129.jpg\",\"augmented_c9d63696629107ed.jpg\",\"augmented_ae5074cfc9183763.jpg\",\n\"augmented_d64460a3b19f1cfc.jpg\",\"augmented_9ada65c5b0cc9a3c.jpg\",\"augmented_94c83b2d5fad6924.jpg\",\n\"augmented_ba99260ef46b18cb.jpg\",\"augmented_a3bb604d8a55995d.jpg\",\"augmented_949b6595a5b8ca3c.jpg\",\n\"augmented_dea33c5c0347aa4d.jpg\",\"augmented_e51690d8ad307dcb.jpg\",\"augmented_8c0731fff680c51e.jpg\",\n\"augmented_e83f715e56462a31.jpg\",\"augmented_9fc321ce60a69f0b.jpg\",\"augmented_bd8088cdad5f65e0.jpg\",\n\"augmented_cdf892b5b4865859.jpg\",\"augmented_f2c798246a0a9bdd.jpg\",\"augmented_f7d233d11aa8496c.jpg\",\n\"augmented_c1753cad2f31d492.jpg\",\"augmented_f3dc17a2b20d48ec.jpg\",\"augmented_aa0e969518e15d3f.jpg\",\n\"augmented_b5ec52491e3349ce.jpg\",\"augmented_ec83c7c04a1e9db9.jpg\",\"augmented_e5f27342ce1cb9a0.jpg\",\n\"augmented_9fad869f21b5b240.jpg\",\"augmented_d1f01e8d8a73274d.jpg\",\"augmented_d1dec0973c2cf4a1.jpg\",\n\"augmented_dbee22785d9285c4.jpg\",\"augmented_8f5263c61a8cdbe2.jpg\",\"augmented_965295a64a97859f.jpg\",\n\"augmented_f4cba4a7294d6585.jpg\",\"augmented_e9e8ad35c5871d06.jpg\",\"augmented_90f99ee1c1132bb6.jpg\",\n\"augmented_b7b0edd58a858217.jpg\",\"augmented_e7ecc583d571d202.jpg\",\"augmented_848d9f9e82d18e5e.jpg\",\n\"augmented_d3945c098edc9dd1.jpg\",\"augmented_eec64e8cf1c8d0c6.jpg\",\"augmented_df90901ccb664de6.jpg\",\n\"augmented_d0c766bc38e1978c.jpg\",\"augmented_86f963a16e70345e.jpg\",\"augmented_f90738a0d2f2c1db.jpg\",\n\"augmented_82ba3e933947b097.jpg\",\"augmented_c1a56069de75b899.jpg\",\"augmented_94b42695f24dad36.jpg\",\n\"augmented_d2266ac99461e9db.jpg\",\"augmented_90a5341f227ce5f9.jpg\",\"augmented_bb1891fa8c61e663.jpg\",\n\"augmented_a7e613159fb22859.jpg\",\"augmented_85897ea7f064b26a.jpg\",\"augmented_ca782c131f5ce0fc.jpg\",\n\"augmented_d7ec32d72c84dc18.jpg\",\"augmented_a9b2e4b09297bc2b.jpg\",\"augmented_d2d9c2bca7a72458.jpg\",\n\"augmented2_c5aff2e545d0a129.jpg\",\"augmented2_c9d63696629107ed.jpg\",\"augmented2_ae5074cfc9183763.jpg\",\n\"augmented2_d64460a3b19f1cfc.jpg\",\"augmented2_9ada65c5b0cc9a3c.jpg\",\"augmented2_94c83b2d5fad6924.jpg\",\n\"augmented2_ba99260ef46b18cb.jpg\",\"augmented2_a3bb604d8a55995d.jpg\",\"augmented2_949b6595a5b8ca3c.jpg\",\n\"augmented2_dea33c5c0347aa4d.jpg\",\"augmented2_e51690d8ad307dcb.jpg\",\"augmented2_8c0731fff680c51e.jpg\",\n\"augmented2_e83f715e56462a31.jpg\",\"augmented2_9fc321ce60a69f0b.jpg\",\"augmented2_bd8088cdad5f65e0.jpg\",\n\"augmented2_cdf892b5b4865859.jpg\",\"augmented2_f2c798246a0a9bdd.jpg\",\"augmented2_f7d233d11aa8496c.jpg\",\n\"augmented2_c1753cad2f31d492.jpg\",\"augmented2_f3dc17a2b20d48ec.jpg\",\"augmented2_aa0e969518e15d3f.jpg\",\n\"augmented2_b5ec52491e3349ce.jpg\",\"augmented2_ec83c7c04a1e9db9.jpg\",\"augmented2_e5f27342ce1cb9a0.jpg\",\n\"augmented2_9fad869f21b5b240.jpg\",\"augmented2_d1f01e8d8a73274d.jpg\",\"augmented2_d1dec0973c2cf4a1.jpg\",\n\"augmented2_dbee22785d9285c4.jpg\",\"augmented2_8f5263c61a8cdbe2.jpg\",\"augmented2_965295a64a97859f.jpg\",\n\"augmented2_f4cba4a7294d6585.jpg\",\"augmented2_e9e8ad35c5871d06.jpg\",\"augmented2_90f99ee1c1132bb6.jpg\",\n\"augmented2_b7b0edd58a858217.jpg\",\"augmented2_e7ecc583d571d202.jpg\",\"augmented2_848d9f9e82d18e5e.jpg\",\n\"augmented2_d3945c098edc9dd1.jpg\",\"augmented2_eec64e8cf1c8d0c6.jpg\",\"augmented2_df90901ccb664de6.jpg\",\n\"augmented2_d0c766bc38e1978c.jpg\",\"augmented2_86f963a16e70345e.jpg\",\"augmented2_f90738a0d2f2c1db.jpg\",\n\"augmented2_82ba3e933947b097.jpg\",\"augmented2_c1a56069de75b899.jpg\",\"augmented2_94b42695f24dad36.jpg\",\n\"augmented2_d2266ac99461e9db.jpg\",\"augmented2_90a5341f227ce5f9.jpg\",\"augmented2_bb1891fa8c61e663.jpg\",\n\"augmented2_a7e613159fb22859.jpg\",\"augmented2_85897ea7f064b26a.jpg\",\"augmented2_ca782c131f5ce0fc.jpg\",\n\"augmented2_d7ec32d72c84dc18.jpg\",\"augmented2_a9b2e4b09297bc2b.jpg\",\"augmented2_d2d9c2bca7a72458.jpg\",\n\".DS_Store\"\n]\n","metadata":{"execution":{"iopub.status.busy":"2021-05-25T22:13:41.567157Z","iopub.execute_input":"2021-05-25T22:13:41.567496Z","iopub.status.idle":"2021-05-25T22:13:41.733059Z","shell.execute_reply.started":"2021-05-25T22:13:41.567467Z","shell.execute_reply":"2021-05-25T22:13:41.732279Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data Visualization","metadata":{}},{"cell_type":"code","source":"def show_label_frequency():\n    frequency = dict()\n    for i in range(0, len(train_csv)):\n        label = train_csv.iloc[i][\"labels\"]\n        if label in frequency:\n            frequency[label] = frequency[label] + 1\n        else:\n            frequency[label] = 1\n    plt.figure(figsize=(15,10))\n    plt.bar(range(len(frequency)), list(frequency.values()), align='center')\n    plt.xticks(range(len(frequency)), list(frequency.keys()))\n    plt.xticks(rotation=90)\n    plt.show()\n\ndef show_image_sizes():\n    train_images = os.listdir(train_images_dir)\n    for img_name in train_images:\n        img = Image.open(\"{}/{}\".format(train_images_dir, img_name))\n        print(img.size)\n\nshow_label_frequency()\n# train_csv.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-25T22:13:41.734813Z","iopub.execute_input":"2021-05-25T22:13:41.735325Z","iopub.status.idle":"2021-05-25T22:13:43.186549Z","shell.execute_reply.started":"2021-05-25T22:13:41.735287Z","shell.execute_reply":"2021-05-25T22:13:43.185663Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data Generation","metadata":{}},{"cell_type":"code","source":"class PlantDataGenerator:\n    start: int\n    end: int\n    batch_size: int\n    input_shape: Tuple[int, int, int]\n    length = 0\n    images = []\n    \n    def __init__(self, start: int, end: int, batch_size: int, input_shape=(940, 611, 3)):\n        self.start = start\n        self.end = end\n        self.batch_size = batch_size\n        self.input_shape = input_shape\n        train_images = os.listdir(train_images_dir)\n        images = train_images[self.start:self.end]\n        for img_name in DUPLICATE_IMAGES:\n            if img_name in images:\n                images.remove(img_name)\n                \n        random.shuffle(images)\n        self.images = images\n        self.length = len(train_images[self.start:self.end])\n    \n    def generate(self):\n        batch_start = 0\n        batch_end = self.batch_size\n        images = self.images\n        while True:\n            batch_images = images[batch_start:batch_end]\n            x_inputs = []\n            y_outputs = []\n            # start = time.time()\n            for image_name in batch_images:\n                img_id = image_name\n                if \"augmented_\" in img_id:\n                    img_id = img_id.replace(\"augmented_\", \"\")\n                elif \"augmented2_\" in img_id:\n                    img_id = img_id.replace(\"augmented2_\", \"\")\n                img_path = \"{}/{}\".format(train_images_dir, image_name)\n                label = train_csv.loc[train_csv[\"image\"] == img_id].iloc[0][\"labels\"]\n                img = Image.open(img_path)\n#                 img = img.resize(self.input_shape[0:2])\n                img = numpy.array(img)\n                y = []\n                for class_name in CLASSES:\n                    if class_name == label:\n                        y.append(1.0)\n                    else:\n                        y.append(0.0)\n                y = numpy.array(y)\n                y_outputs.append(y)\n                x_inputs.append(img)\n#                 print(\"{}: {}: {}\".format(image_name, y, labels))\n            # elapsed = time.time() - start\n            # print(\"Loaded {} batch in {} seconds\".format(self.batch_size, elapsed))\n            x_inputs = numpy.array(x_inputs)\n            y_outputs = numpy.array(y_outputs)\n            yield x_inputs, y_outputs\n            batch_start += self.batch_size\n            batch_end += self.batch_size\n            if batch_end > len(images) and batch_start >= len(images):\n                batch_start = 0\n                batch_end = self.batch_size\n                random.shuffle(self.images)\n            elif batch_end >= len(images):\n                batch_end = len(images) - 1","metadata":{"execution":{"iopub.status.busy":"2021-05-25T22:13:43.187988Z","iopub.execute_input":"2021-05-25T22:13:43.188339Z","iopub.status.idle":"2021-05-25T22:13:43.201387Z","shell.execute_reply.started":"2021-05-25T22:13:43.188302Z","shell.execute_reply":"2021-05-25T22:13:43.200349Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Submission","metadata":{}},{"cell_type":"code","source":"def submit(model: Model, img_dir: str, output_dir: str, input_shape: Tuple[int, int, int], threshold=0.5):\n    images = os.listdir(img_dir)\n    print(\"Starting submission!\")\n    output = open(\"{}/submission.csv\".format(output_dir), \"w\")\n    output.write(\"image,labels\")\n    count = 0\n    total_start = time.time()\n    for img_name in images:\n        start = time.time()\n        img_path = \"{}/{}\".format(img_dir, img_name)\n        img = Image.open(img_path)\n        img = img.resize(input_shape[0:2])\n        img = numpy.array(img)\n        x = img.reshape((1,) + input_shape)\n        prediction = CLASSES[numpy.argmax(model.predict(x)[0])]\n        output.write(\"\\n{},{}\".format(img_name, prediction))\n        elapsed = time.time() - start\n        count += 1\n        if count % 500 == 0:\n            try:\n                minutes = (time.time() - total_start) / 60\n                percent_complete = (count / len(images)) * 100.0\n                print(\"[{}/{}]: Made {} predictions in {:.2f} minutes. {:.2f}% complete\".format(count, len(images), count, minutes, percent_complete))\n            except Exception as e:\n                pass\n    total_elapsed = (time.time() - total_start) / 60.0\n    print(\"\\n\\nCompleted {} predictions in {:.2f} minutes!\".format(count, total_elapsed))\n    print(\"_________________________________________________________\")\n    output.close()","metadata":{"execution":{"iopub.status.busy":"2021-05-25T22:13:43.204302Z","iopub.execute_input":"2021-05-25T22:13:43.204756Z","iopub.status.idle":"2021-05-25T22:13:43.217447Z","shell.execute_reply.started":"2021-05-25T22:13:43.204716Z","shell.execute_reply":"2021-05-25T22:13:43.216777Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model","metadata":{}},{"cell_type":"code","source":"def plant_model13(input_shape) -> Sequential:\n    resnet = ResNet50(weights=\"imagenet\", include_top=False, input_shape=input_shape)\n    resnet.trainable = True\n    model = Sequential(name=\"plant_model13\")\n    model.add(resnet)\n    model.add(Flatten())\n    model.add(Dense(512, activation=\"relu\"))\n    model.add(Dropout(0.5))\n    model.add(BatchNormalization())\n    model.add(Dense(512, activation=\"relu\"))\n    model.add(Dropout(0.5))\n    model.add(BatchNormalization())\n    model.add(Dense(512, activation=\"relu\"))\n    model.add(Dropout(0.5))\n    model.add(BatchNormalization())\n    model.add(Dense(len(CLASSES), activation=\"softmax\"))\n    model.compile(optimizer=SGD(lr=5e-4), loss=\"categorical_crossentropy\", metrics=[\"accuracy\"])\n    model.summary()\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-05-25T22:13:43.218971Z","iopub.execute_input":"2021-05-25T22:13:43.219378Z","iopub.status.idle":"2021-05-25T22:13:43.23169Z","shell.execute_reply.started":"2021-05-25T22:13:43.219322Z","shell.execute_reply":"2021-05-25T22:13:43.231031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Validation","metadata":{}},{"cell_type":"code","source":"def format_label_string(y, threshold):\n    label = \"\"\n    for i in range(0, len(y)):\n        if y[i] > threshold:\n            if i == 0:\n                label = \"{} \".format(CLASSES[i])\n            else:\n                label = \"{}{} \".format(label, CLASSES[i])\n    if label == \"\":\n        label = \"healthy\"\n    label = label.strip()\n    return label\n\ndef validate(model: Model, start: int, end: int, input_shape: Tuple[int, int, int], batch_size=8, threshold=0.8):\n    data_gen = PlantDataGenerator(start, end, batch_size, input_shape=input_shape)\n    data_set = data_gen.generate()\n    batches = int(numpy.ceil(data_gen.length / batch_size)) - 1\n    correct = 0\n    total = 0\n    \n    \n    predictions_out = open(\"predictions.csv\", \"w\")\n    predictions_out.write(\"Correct,Prediction,Answer\")\n    for class_name in CLASSES:\n        predictions_out.write(\",{}\".format(class_name))\n    print(\"Validating {}\".format(model.name))\n    for k in range(0, batches):\n        batch_x, batch_y = data_set.__next__()\n        for i in range(0, len(batch_x)):\n            x = batch_x[i].reshape((1,) + input_shape)\n            y = CLASSES[numpy.argmax(batch_y[i])]\n            probabilities = model.predict(x)[0]\n            prediction = CLASSES[numpy.argmax(probabilities)]\n            predictions_out.write(\"\\n{},{},{}\".format(\n                y == prediction, \n                prediction, y\n            ))\n            for p in probabilities:\n                predictions_out.write(\",{}\".format(p))\n            if y == prediction:\n                correct += 1\n            if total % 100 == 0:\n                print(\"[{}/{}]: A: {}, P: {}\".format(total, batches * batch_size, y, prediction))\n            total += 1\n    predictions_out.close()\n    avg_acc = correct / total\n    print(\"\\n\\Correctly predicted {}/{} with:\\n\\tAvg. Accuracy: {}\".format(correct, total, avg_acc))\n    print(\"\\n____________________________________________________\")","metadata":{"execution":{"iopub.status.busy":"2021-05-25T22:13:43.233417Z","iopub.execute_input":"2021-05-25T22:13:43.233853Z","iopub.status.idle":"2021-05-25T22:13:43.248583Z","shell.execute_reply.started":"2021-05-25T22:13:43.233814Z","shell.execute_reply":"2021-05-25T22:13:43.247812Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training","metadata":{}},{"cell_type":"code","source":"def train(\n    model: Model, \n    epochs: int, \n    start: int, \n    end: int, \n    input_shape: Tuple[int, int, int], \n    batch_size=6, \n    validation_split=0.1, \n    use_augmentation=False):\n    start_time = time.time()\n    if use_augmentation:\n        data_set = load_augmented_data(input_shape, validation_split, batch_size)\n        history = model.fit(data_set, epochs=epochs, batch_size=batch_size)\n    else:\n        data_gen = PlantDataGenerator(start, end, batch_size, input_shape=input_shape)\n        data_set = data_gen.generate()\n        steps_per_epoch = int(numpy.ceil(data_gen.length / batch_size)) - 1\n        history = model.fit(\n            data_set, \n            epochs=epochs, \n            batch_size=batch_size, \n            steps_per_epoch=steps_per_epoch\n        )\n    model.save(\"{}.keras\".format(model.name))\n    elapsed = time.time() - start_time\n    if \"accuracy\" in history.history:\n        avg_accuracy = numpy.average(history.history[\"accuracy\"])\n        avg_loss = numpy.average(history.history[\"loss\"])\n        print(\n            \"\\n\\nCompleted {} epoch in {} seconds with:\\n\\tAvg. Accuracy: {}%\\n\\tAvg. Loss: {}\".format(\n                epochs, \n                elapsed, \n                avg_accuracy, \n                avg_loss\n            )\n        )\n    else:\n        print(\"\\n\\nCompleted {} epoch(s) in {} seconds:\".format(epochs, elapsed))\n        for key in history.history:\n            if \"accuracy\" in key or \"loss\" in key:\n                print(\"   {}: {}%\".format(key, numpy.average(history.history[key])))\n        print(\"\\n___________________________________________\")\n    return history","metadata":{"execution":{"iopub.status.busy":"2021-05-25T22:13:43.249966Z","iopub.execute_input":"2021-05-25T22:13:43.250472Z","iopub.status.idle":"2021-05-25T22:13:43.262434Z","shell.execute_reply.started":"2021-05-25T22:13:43.250435Z","shell.execute_reply":"2021-05-25T22:13:43.261763Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Runtime","metadata":{}},{"cell_type":"code","source":"# input_shape = (940, 611, 3)\ninput_shape = (512, 512, 3)\ndstart = 6000\ndend = None\nvalidation_split = 0.1\nbatch_size = 16\n# model = plant_model13(input_shape)\nmodel = load_model(\"/kaggle/input/d/tylerswann/plant-pathology-models/plant_model9_14.keras\")\n# history = train(model, epochs=10, start=dstart, end=dend, input_shape=input_shape, batch_size=batch_size, validation_split=validation_split, use_augmentation=False)\n# validate(model, 0, dstart, input_shape, threshold=0.5)\nsubmit(model, test_images_dir, \"/kaggle/working\", input_shape)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T22:13:43.264005Z","iopub.execute_input":"2021-05-25T22:13:43.264425Z","iopub.status.idle":"2021-05-25T22:15:14.342788Z","shell.execute_reply.started":"2021-05-25T22:13:43.26439Z","shell.execute_reply":"2021-05-25T22:15:14.341841Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Metrics","metadata":{}},{"cell_type":"code","source":"try:\n    if history is not None:\n        fig, axes = plt.subplots(1, 2, figsize=(30,10))\n        axes[0].plot(history.history[\"accuracy\"])\n        axes[0].set_title('Model Accuracy')\n        axes[0].set_ylabel('Accuracy')\n        axes[0].set_xlabel('Epoch')\n        axes[1].plot(history.history[\"loss\"])\n        axes[1].set_title('Model Loss')\n        axes[1].set_ylabel('Loss')\n        axes[1].set_xlabel('Epoch')\n        plt.show()\nexcept Exception as e:\n    pass","metadata":{"execution":{"iopub.status.busy":"2021-05-25T22:15:14.344173Z","iopub.execute_input":"2021-05-25T22:15:14.344692Z","iopub.status.idle":"2021-05-25T22:15:14.597383Z","shell.execute_reply.started":"2021-05-25T22:15:14.344652Z","shell.execute_reply":"2021-05-25T22:15:14.596529Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Deallocate Memory","metadata":{}},{"cell_type":"code","source":"cuda.select_device(0)\ncuda.close()\ndel model\nkeras.backend.clear_session()","metadata":{"execution":{"iopub.status.busy":"2021-05-25T22:15:14.598988Z","iopub.execute_input":"2021-05-25T22:15:14.599336Z","iopub.status.idle":"2021-05-25T22:15:14.993941Z","shell.execute_reply.started":"2021-05-25T22:15:14.599298Z","shell.execute_reply":"2021-05-25T22:15:14.992924Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a href=\"predictions.csv\">predictions.csv</a>","metadata":{}},{"cell_type":"markdown","source":"<a href=\"disease_classification.keras\">disease_classification.keras</a>","metadata":{}}]}