{"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":"# Import Modules","metadata":{}},{"cell_type":"code","source":"import sys\n\nsys.path.insert(0, '../input/computer-vision-training-fcis-21/')\n\nimport utils\n\nworking_dir = '../input/computer-vision-training-fcis-21/224/content/flowers/224/'\n\ntrain_dir = f'{working_dir}/train/train/'\ntest_dir = f'{working_dir}/test/test/'","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:29.887662Z","iopub.execute_input":"2021-09-22T02:24:29.888243Z","iopub.status.idle":"2021-09-22T02:24:30.017376Z","shell.execute_reply.started":"2021-09-22T02:24:29.888135Z","shell.execute_reply":"2021-09-22T02:24:30.016298Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\n\nimport matplotlib.pyplot as plt\n\nfrom tqdm import tqdm\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:30.228494Z","iopub.execute_input":"2021-09-22T02:24:30.228803Z","iopub.status.idle":"2021-09-22T02:24:30.235112Z","shell.execute_reply.started":"2021-09-22T02:24:30.228772Z","shell.execute_reply":"2021-09-22T02:24:30.233681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\n\nfrom tensorflow.keras.layers import *\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras import optimizers, losses, metrics, backend","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:30.545551Z","iopub.execute_input":"2021-09-22T02:24:30.546453Z","iopub.status.idle":"2021-09-22T02:24:36.025403Z","shell.execute_reply.started":"2021-09-22T02:24:30.546413Z","shell.execute_reply":"2021-09-22T02:24:36.024353Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Read N-Batches","metadata":{}},{"cell_type":"code","source":"train_nbatch = utils.num_of_batches(train_dir + '/origin')\n\nprint('No. Batches: %i'%train_nbatch)","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:36.027332Z","iopub.execute_input":"2021-09-22T02:24:36.027706Z","iopub.status.idle":"2021-09-22T02:24:36.055796Z","shell.execute_reply.started":"2021-09-22T02:24:36.027665Z","shell.execute_reply":"2021-09-22T02:24:36.054798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Explore","metadata":{}},{"cell_type":"code","source":"def plot(images: np.ndarray, nrows: int = 1, ncols: int = 4, figsize: tuple = (10, 6)):\n\n    fig, axs = plt.subplots(nrows=nrows, ncols=ncols, figsize=figsize)\n    \n    axs = axs.flatten()\n\n    for i in range(len(axs)):\n\n        axs[i].imshow(images[i].squeeze())\n\n        axs[i].grid(None)\n        axs[i].axis('off')\n    \n    \n    fig.tight_layout()\n    \n    return fig, axs","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:36.057347Z","iopub.execute_input":"2021-09-22T02:24:36.057848Z","iopub.status.idle":"2021-09-22T02:24:36.066328Z","shell.execute_reply.started":"2021-09-22T02:24:36.057808Z","shell.execute_reply":"2021-09-22T02:24:36.065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def sample(images, sample_size=4, random_state=42):\n    \n    random = np.random.RandomState(random_state)\n\n    indices = np.arange(0, 320)\n\n    random.shuffle(indices)\n    \n    indices = indices[:sample_size]    \n    \n    return images[indices]","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:36.069235Z","iopub.execute_input":"2021-09-22T02:24:36.069945Z","iopub.status.idle":"2021-09-22T02:24:36.077891Z","shell.execute_reply.started":"2021-09-22T02:24:36.0699Z","shell.execute_reply":"2021-09-22T02:24:36.076516Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Data","metadata":{}},{"cell_type":"code","source":"def train_val_split(val_size=0.2):\n    \n    train_size = 1.0 - val_size\n        \n    def get_tf_data(start, end):\n            \n        def data_generator():\n\n            for i in range(start, end):\n\n                batch_x = utils.read_batch(train_dir + '/origin', i)['x']\n                batch_y = utils.read_batch(train_dir + '/masks', i)['x']\n\n                batch_x = batch_x.astype('float32') / 255.0\n                batch_y = batch_y[..., None].astype('float32')\n                \n                for x, y in zip(batch_x, batch_y):\n                    \n                    yield x, y\n            \n        \n        output_types = tf.float32, tf.float32\n        output_shapes = tf.TensorShape([224, 224, 3]), tf.TensorShape([224, 224, 1])\n\n        tf_data = tf.data.Dataset.from_generator(data_generator, output_types=output_types, \n                                                 output_shapes=output_shapes)    \n        return tf_data\n    \n    def get_train_data():\n\n        start = 0\n        end = int(train_nbatch * train_size)\n        \n        return get_tf_data(start, end)\n\n    def get_val_data():\n\n        start = int(train_nbatch * train_size)\n        end = train_nbatch\n\n        return get_tf_data(start, end)\n    \n    return get_train_data(), get_val_data()","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:36.07949Z","iopub.execute_input":"2021-09-22T02:24:36.079893Z","iopub.status.idle":"2021-09-22T02:24:36.093905Z","shell.execute_reply.started":"2021-09-22T02:24:36.079851Z","shell.execute_reply":"2021-09-22T02:24:36.09283Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data, val_data = train_val_split(val_size=0.2)\n\ntrain_data = train_data.batch(32)\nval_data = val_data.batch(32)","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:36.284877Z","iopub.execute_input":"2021-09-22T02:24:36.285132Z","iopub.status.idle":"2021-09-22T02:24:38.380092Z","shell.execute_reply.started":"2021-09-22T02:24:36.285105Z","shell.execute_reply":"2021-09-22T02:24:38.378131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train_data.as_numpy_iterator().next()[0].shape\n# train_data.as_numpy_iterator().next()[1].shape\n\n# val_data.as_numpy_iterator().next()[0].shape\n# val_data.as_numpy_iterator().next()[1].shape","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:38.382172Z","iopub.execute_input":"2021-09-22T02:24:38.382631Z","iopub.status.idle":"2021-09-22T02:24:38.387962Z","shell.execute_reply.started":"2021-09-22T02:24:38.38259Z","shell.execute_reply":"2021-09-22T02:24:38.38644Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"class Unet:\n    \n    def __init__(self, n_filters, activation):\n\n        self.n_filters = n_filters\n        self.activation = activation\n        \n        self.n = 1\n        \n        self.memory = {}\n\n    def pool_block(self, input_z):\n\n        pool_size = 2\n\n        z = MaxPooling2D(pool_size=pool_size)(input_z)\n        z = Dropout(0.1)(z)\n\n        return z\n\n    def conv2d_block(self, input_z, mem=True):\n\n        if mem:\n\n            name = f'conv_{(self.n)}'\n\n        else:\n\n            name = f'tconv_{(self.n // 2)}'\n\n        z = Conv2D(filters=self.n_filters * self.n, kernel_size=3, padding='same')(input_z)\n        z = Activation(self.activation)(z)\n        z = BatchNormalization()(z)\n\n        z = Conv2D(filters=self.n_filters * self.n, kernel_size=3, padding='same', name=name)(z)\n        z = Activation(self.activation)(z)\n        z = BatchNormalization()(z)\n\n        if mem:\n            \n            self.memory[name] = z\n            \n            self.n *=2\n              \n        return z\n    \n    def tconv2d_block(self, input_z):\n\n        assert self.n >= 2, f'n = {self.n}'\n\n        self.n //=2\n\n        conv_name = f'conv_{self.n // 2}'\n\n        z = Conv2DTranspose(filters=self.n_filters * self.n, kernel_size=3, strides = 2, padding='same')(input_z)        \n        z = concatenate([z, self.memory[conv_name]])\n        z = Dropout(0.1)(z)\n\n        return z\n    \n    def encoder_block(self, input_z):\n\n        z = self.conv2d_block(input_z)\n        z = self.pool_block(z)\n\n        return z\n\n    def decoder_block(self, input_z):\n\n        z = self.tconv2d_block(input_z)\n        z = self.conv2d_block(z, mem=False)\n\n        return z\n  \n    def build(self, inputs, nlevels=4):\n\n        z = inputs\n\n        for i in range(nlevels):\n\n            z = self.encoder_block(z)\n\n        z = self.conv2d_block(z)\n        \n        for i in range(nlevels):\n\n            z = self.decoder_block(z)\n            \n        return z","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:47.197493Z","iopub.execute_input":"2021-09-22T02:24:47.197876Z","iopub.status.idle":"2021-09-22T02:24:47.217789Z","shell.execute_reply.started":"2021-09-22T02:24:47.197831Z","shell.execute_reply":"2021-09-22T02:24:47.21628Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_model(n_filters=8, nlevels=4, activation='relu', summary=False):\n    \n    unet = Unet(n_filters=n_filters, activation=activation)\n\n    inputs = Input(shape=(224, 224, 3))\n\n    z = unet.build(inputs, nlevels=nlevels)\n    \n    model = Model(inputs=[inputs], outputs=[z])\n\n    if summary:\n\n        model.summary()\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:47.995703Z","iopub.execute_input":"2021-09-22T02:24:47.996247Z","iopub.status.idle":"2021-09-22T02:24:48.003192Z","shell.execute_reply.started":"2021-09-22T02:24:47.996199Z","shell.execute_reply":"2021-09-22T02:24:48.00192Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tf_iou = tf.metrics.MeanIoU(2)","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:48.847127Z","iopub.execute_input":"2021-09-22T02:24:48.847978Z","iopub.status.idle":"2021-09-22T02:24:49.174425Z","shell.execute_reply.started":"2021-09-22T02:24:48.847931Z","shell.execute_reply":"2021-09-22T02:24:49.173352Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def iou_eval(y_true, y_pred, threshold=0.5):\n        \n    y_pred = tf.greater(y_pred, threshold)\n    \n    tf_iou.update_state(y_true, y_pred)\n    \n    return tf_iou.result()","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:49.83717Z","iopub.execute_input":"2021-09-22T02:24:49.837481Z","iopub.status.idle":"2021-09-22T02:24:49.842728Z","shell.execute_reply.started":"2021-09-22T02:24:49.837437Z","shell.execute_reply":"2021-09-22T02:24:49.841792Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"inputs = Input((224, 224, 3))\n\nunet_0 = create_model(summary=False, n_filters=16, nlevels=5, activation='relu')\n\nz = unet_0(inputs)\n\noutput = Conv2D(1, (1, 1), activation='sigmoid', name='output')(z)\n\nmodel = Model(inputs, [output])\n\noptimizer = optimizers.Adam(learning_rate=1e-3)\n\nloss = {}\nmetric = {}\n\nloss['output'] = losses.BinaryCrossentropy('output_loss', label_smoothing=0.5)\nmetric['output'] = iou_eval\n\nmodel.compile(optimizer=optimizer, loss=loss, metrics=metric)\n\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:24:50.646224Z","iopub.execute_input":"2021-09-22T02:24:50.647384Z","iopub.status.idle":"2021-09-22T02:24:51.592716Z","shell.execute_reply.started":"2021-09-22T02:24:50.647323Z","shell.execute_reply":"2021-09-22T02:24:51.591621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.fit(train_data, epochs=100, validation_data=val_data)","metadata":{"execution":{"iopub.status.busy":"2021-09-22T02:25:32.158921Z","iopub.execute_input":"2021-09-22T02:25:32.160015Z","iopub.status.idle":"2021-09-22T02:25:32.167847Z","shell.execute_reply.started":"2021-09-22T02:25:32.159975Z","shell.execute_reply":"2021-09-22T02:25:32.166637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save('./model.h5')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Optimize Threshold","metadata":{}},{"cell_type":"code","source":"y_pred = model.predict(val_data)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"_, y_val = val_data.unbatch().batch(1400).as_numpy_iterator().next()\n\nprint(y_val.shape)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"iou_eval(y_val, y_pred[:len(y_val)], threshold=0.5)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predict","metadata":{}},{"cell_type":"code","source":"test_nbatches = utils.num_of_batches(test_dir + '/origin')\n\nprint('No. Batches: %i'%test_nbatches)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data = utils.read_nbatch(test_dir + 'origin/', 108, 108 + test_nbatches)\n\ntest_ids = test_data['id']\ntest_x = test_data['x'].astype('float32') / 255.0\n\ntest_size = len(test_ids)\n\nprint(test_size)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_masks = model.predict(test_x) > 0.5","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x_sample = sample(test_x, random_state=42)\ny_sample = sample(test_masks, random_state=42)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.style.use('grayscale')\n\nfig, ax = plot(x_sample)\nfig, ax = plot(y_sample)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{}},{"cell_type":"code","source":"submission = utils.Submission(shape=(224, 224))\n\nsubmission.init()\n\nfor i in tqdm(range(test_size)):\n    \n    submission.update(test_ids[i], test_masks[i])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.export('submission.csv')","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}