{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport math\nimport argparse\nimport warnings\nimport collections\nimport tensorflow as tf\nimport tensorflow.keras.backend as K\nfrom sklearn.model_selection import train_test_split\n\nwarnings.filterwarnings(\"ignore\")\n\nphysical_devices = tf.config.experimental.list_physical_devices('GPU')\nassert len(physical_devices) > 0, \"Not enough GPU hardware devices available\"\ntf.config.experimental.set_memory_growth(physical_devices[0], True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_image(train_images_path, train_label_path):\n    all_images = []\n    all_labels = []\n    \n    with open(train_labels) as file:\n        for line in file.readlines()[1:]:\n            line = line.strip().split(\",\")\n            image_name = line[0]\n            image_label = int(line[1])\n            image_path = os.path.join(train_images, image_name)\n            \n            all_images.append(image_path)\n            all_labels.append(image_label)\n    return all_images, all_labels\n\ndef parse_function(filename, label):\n    image_string = tf.io.read_file(filename)\n    image = tf.io.decode_jpeg(image_string, channels=3)\n    image = tf.image.resize(image, [300, 300])\n    # image = tf.reshape(image, [224, 2, 3])\n    image = (tf.cast(image, tf.float32) - 127.5) / 127.5\n    image = tf.image.random_flip_left_right(image)\n    \n    return image, label","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\n\ndef swish(x):\n    return x * tf.nn.sigmoid(x)\n\ndef SEBlock(input_filters,se_output_filters,se_ratio=0.25):\n    def block(inputs):\n        num_reduced_filters = max(1, int(input_filters * se_ratio))\n        x = inputs\n        x = tf.keras.layers.Lambda(lambda a: K.mean(a, axis=[1, 2], keepdims=True))(x)\n        x = tf.keras.layers.Conv2D(num_reduced_filters,kernel_size=(1, 1),padding='same')(x)\n        x = swish(x)\n        x = tf.keras.layers.Conv2D(se_output_filters,kernel_size=(1, 1),padding='same',)(x)\n        x = tf.keras.layers.Activation('sigmoid')(x)\n        out = tf.keras.layers.Multiply()([x, inputs])\n        return out\n    return block\n\nclass DropConnect(tf.keras.layers.Layer):\n    def __init__(self, drop_connect_rate=0.):\n        super().__init__()\n        self.drop_connect_rate = drop_connect_rate\n\n    def call(self, inputs, training=None):\n        def drop_connect():\n            survival_prob = 1.0 - self.drop_connect_rate\n            batch_size = tf.shape(inputs)[0]\n            random_tensor = survival_prob\n            random_tensor += tf.random_uniform([batch_size, 1, 1, 1], dtype=inputs.dtype)\n            binary_tensor = tf.floor(random_tensor)\n            output = tf.div(inputs, survival_prob) * binary_tensor\n            return output\n        return K.in_train_phase(drop_connect, inputs, training=training)\n\ndef MBConvBlock(input_filters, output_filters,kernel_size, strides,expand_ratio,drop_connect_rate):\n    def block(inputs):\n        se_output_filters = input_filters * expand_ratio\n        if expand_ratio != 1:\n            x = tf.keras.layers.Conv2D(se_output_filters,kernel_size=(1, 1),padding='same',use_bias=False)(inputs)\n            x = tf.keras.layers.BatchNormalization()(x)\n            x = swish(x)\n        else:\n            x = inputs\n        x = tf.keras.layers.DepthwiseConv2D((kernel_size, kernel_size),strides=strides,padding='same',use_bias=False)(x)\n        x = tf.keras.layers.BatchNormalization()(x)\n        x = swish(x)\n        x = SEBlock(input_filters,se_output_filters)(x)\n        x = tf.keras.layers.Conv2D(output_filters,kernel_size=(1, 1),padding='same',use_bias=False)(x)\n        x = tf.keras.layers.BatchNormalization()(x)\n        if all(s == 1 for s in strides) and (input_filters == output_filters):\n            if drop_connect_rate:\n                x = DropConnect(drop_connect_rate)(x)\n\n            x = tf.keras.layers.Add()([x, inputs])\n        return x\n    return block\n\n\nBlockArgs = collections.namedtuple('BlockArgs', ['kernel_size', 'num_repeat', 'input_filters', 'output_filters','expand_ratio', 'strides'])\nblock_args_list = [\n    BlockArgs(kernel_size=3, num_repeat=1, input_filters=32, output_filters=16,expand_ratio=1, strides=[1, 1]),\n    BlockArgs(kernel_size=3, num_repeat=2, input_filters=16, output_filters=24,expand_ratio=6, strides=[2, 2]),\n    BlockArgs(kernel_size=5, num_repeat=2, input_filters=24, output_filters=40,expand_ratio=6, strides=[2, 2]),\n    BlockArgs(kernel_size=3, num_repeat=3, input_filters=40, output_filters=80,expand_ratio=6, strides=[2, 2]),\n    BlockArgs(kernel_size=5, num_repeat=3, input_filters=80, output_filters=112,expand_ratio=6, strides=[1, 1]),\n    BlockArgs(kernel_size=5, num_repeat=4, input_filters=112, output_filters=192,expand_ratio=6, strides=[2, 2]),\n    BlockArgs(kernel_size=3, num_repeat=1, input_filters=192, output_filters=320,expand_ratio=6, strides=[1, 1])\n]\nstride_count = 5\nnum_blocks = 16\n\ndef EfficientNet(input_shape,classes,width_coefficient: float,depth_coefficient: float,include_top=True,dropout_rate=0.,drop_connect_rate=0.): \n    inputs = tf.keras.layers.Input(shape=input_shape)\n    x = inputs\n    x = tf.keras.layers.Conv2D(filters=int(32*width_coefficient), kernel_size=(3,3),strides=(2,2),padding='same',use_bias=False)(x)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = swish(x)    \n    drop_connect_rate_per_block = drop_connect_rate / float(num_blocks)\n    for block_idx, block_args in enumerate(block_args_list):\n        my_input_filters = int(block_args.input_filters*width_coefficient)\n        my_output_filters = int(block_args.output_filters*width_coefficient)\n        my_num_repeat = math.ceil(block_args.num_repeat*depth_coefficient)\n        x = MBConvBlock(my_input_filters, my_output_filters,block_args.kernel_size, block_args.strides,block_args.expand_ratio,drop_connect_rate_per_block * block_idx)(x)\n        if my_num_repeat > 1:\n            my_input_filters = my_output_filters\n            my_strides = [1, 1]\n        for _ in range(my_num_repeat - 1):\n            x = MBConvBlock(my_input_filters, my_output_filters,block_args.kernel_size, my_strides,block_args.expand_ratio,drop_connect_rate_per_block * block_idx)(x)\n    x = tf.keras.layers.Conv2D(filters=int(1280*width_coefficient),kernel_size=(1, 1),padding='same',use_bias=False)(x)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = swish(x)\n    if include_top:\n        x = tf.keras.layers.GlobalAveragePooling2D()(x)\n        if dropout_rate > 0:\n            x = tf.keras.layers.Dropout(dropout_rate)(x)\n        x = tf.keras.layers.Dense(classes)(x)\n        x = tf.keras.layers.Activation('softmax')(x)\n    outputs = x\n    model = tf.keras.models.Model(inputs, outputs)\n    return model\n\ndef EfficientNetB0(input_shape,classes,include_top=True,dropout_rate=0.4,drop_connect_rate=0.): \n    return  EfficientNet(input_shape,classes,1.0,1.0,include_top=include_top,dropout_rate=dropout_rate,drop_connect_rate=drop_connect_rate)\n\ndef EfficientNetB1(input_shape,classes,include_top=True,dropout_rate=0.2,drop_connect_rate=0.): \n    return  EfficientNet(input_shape,classes,1.0,1.1,include_top=include_top,dropout_rate=dropout_rate,drop_connect_rate=drop_connect_rate)\n\ndef EfficientNetB2(input_shape,classes,include_top=True,dropout_rate=0.3,drop_connect_rate=0.): \n    return  EfficientNet(input_shape,classes,1.1,1.2,include_top=include_top,dropout_rate=dropout_rate,drop_connect_rate=drop_connect_rate)\n\ndef EfficientNetB3(input_shape,classes,include_top=True,dropout_rate=0.3,drop_connect_rate=0.): \n    return  EfficientNet(input_shape,classes,1.2,1.4,include_top=include_top,dropout_rate=dropout_rate,drop_connect_rate=drop_connect_rate)\n\ndef EfficientNetB4(input_shape,classes,include_top=True,dropout_rate=0.4,drop_connect_rate=0.): \n    return  EfficientNet(input_shape,classes,1.4,1.8,include_top=include_top,dropout_rate=dropout_rate,drop_connect_rate=drop_connect_rate)\n\ndef EfficientNetB5(input_shape,classes,include_top=True,dropout_rate=0.4,drop_connect_rate=0.): \n    return  EfficientNet(input_shape,classes,1.6,2.2,include_top=include_top,dropout_rate=dropout_rate,drop_connect_rate=drop_connect_rate)\n\ndef EfficientNetB6(input_shape,classes,include_top=True,dropout_rate=0.5,drop_connect_rate=0.): \n    return  EfficientNet(input_shape,classes,1.8,2.6,include_top=include_top,dropout_rate=dropout_rate,drop_connect_rate=drop_connect_rate)\n\ndef EfficientNetB7(input_shape,classes,include_top=True,dropout_rate=0.5,drop_connect_rate=0.): \n    return  EfficientNet(input_shape,classes,2.0,3.1,include_top=include_top,dropout_rate=dropout_rate,drop_connect_rate=drop_connect_rate)\n\ndef EfficientNetB8(input_shape,classes,include_top=True,dropout_rate=0.5,drop_connect_rate=0.): \n    return  EfficientNet(input_shape,classes,2.2,3.6,include_top=include_top,dropout_rate=dropout_rate,drop_connect_rate=drop_connect_rate)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"lr = 0.0001\nbatch_size = 48\nEPOCHS = 1\n\ntrain_images = \"../input/cassava-leaf-disease-classification/train_images\"\ntrain_labels = \"../input/cassava-leaf-disease-classification/train.csv\"\n\n\n# Build your model here\nmodel = EfficientNetB0(input_shape=(300, 300, 3),classes=5,include_top=True)\noptimizer = tf.keras.optimizers.Adam(lr)\n\n### Split train dataset and test dataset\nall_images, all_labels = load_image(train_images, train_labels)\ntrain_X, val_X, train_Y, val_Y = train_test_split(all_images, all_labels, test_size=0.2)\n\n### Train dataset\ntrain_filenames = tf.constant(train_X)\ntrain_labels = tf.constant(train_Y)\ntrain_dataset = tf.data.Dataset.from_tensor_slices((train_filenames, train_labels))\ntrain_dataset = train_dataset.shuffle(len(train_X)).map(parse_function).batch(batch_size)\n\n### Test dataset\nval_filenames = tf.constant(val_X)\nval_labels = tf.constant(val_Y)\nval_dataset = tf.data.Dataset.from_tensor_slices((val_filenames, val_labels))\nval_dataset = val_dataset.map(parse_function).batch(batch_size)\n\n# Choose an optimizer and loss function for training\nloss_object = tf.keras.losses.SparseCategoricalCrossentropy()\n\n# Select metrics to measure the loss and the accuracy of the model\ntrain_loss = tf.keras.metrics.Mean(name='train_loss')\ntrain_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')\n\ntest_loss = tf.keras.metrics.Mean(name='test_loss')\ntest_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='test_accuracy')\n\n# Use tf.GradientTape to train the model.\n@tf.function\ndef train_step(images, labels):\n    with tf.GradientTape() as tape:\n        predictions = model(images, training=True)\n        # print(\"=> label shape: \", labels.shape, \"pred shape\", predictions.shape)\n        loss = loss_object(labels, predictions)\n    gradients = tape.gradient(loss, model.trainable_variables)\n    optimizer.apply_gradients(zip(gradients, model.trainable_variables))\n    train_loss(loss)\n    train_accuracy(labels, predictions)\n\n@tf.function\ndef val_step(images, labels):\n    predictions = model(images)\n    t_loss = loss_object(labels, predictions)\n    test_loss(t_loss)\n    test_accuracy(labels, predictions)\n\nfor epoch in range(EPOCHS):\n    step = 0\n    for images, labels in train_dataset:\n        step += 1\n        train_step(images, labels)\n        if step %20 == 0:\n            print(\"Epoch:{}/{} Step:{}/{} Loss:{:.4f} Accuracy:{:.4f}\".format(epoch+1,\n                                                                              EPOCHS,\n                                                                              step,\n                                                                              math.ceil(len(train_X) / batch_size),\n                                                                              train_loss.result(),\n                                                                              train_accuracy.result()))\n    for val_images, val_labels in val_dataset:\n        val_step(val_images, val_labels)\n    print(\"#####\"*10)\n    print(\"Epoch: {}/{} Train loss:{:.4f} Train accuracy:{:.4f} \\\n           Val loss:{:.4f} Val accuracy:{:.4f}\".format(epoch+1,\n                                                       EPOCHS,\n                                                       train_loss.result(),\n                                                       train_accuracy.result(),\n                                                       test_loss.result(),\n                                                       test_accuracy.result()))\n    print(\"#####\"*10)\n    # Reset the metrics for the next epoch\n    train_loss.reset_states()\n    train_accuracy.reset_states()\n    test_loss.reset_states()\n    test_accuracy.reset_states()\n\n    model.save_weights(\"./saved_model/model\", save_format=\"h5\")","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}