{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os, sys\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport skimage.io\nfrom skimage.transform import resize\nfrom imgaug import augmenters as iaa\nfrom tqdm import tqdm\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"72c425f3aaa2645215a3adc808fc188c5b59106d"},"cell_type":"markdown","source":"### Load dataset info"},{"metadata":{"trusted":true,"_uuid":"42315d01b95b8a901088befa4100b014a1416c7a"},"cell_type":"code","source":"path_to_train = '../input/train/'\ndata = pd.read_csv('../input/train.csv')\n\ntrain_dataset_info = []\nfor name, labels in zip(data['Id'], data['Target'].str.split(' ')):\n    train_dataset_info.append({\n        'path':os.path.join(path_to_train, name),\n        'labels':np.array([int(label) for label in labels])})\ntrain_dataset_info = np.array(train_dataset_info)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ae3dcb3e4a000051fc8947502a28d399d200a924"},"cell_type":"markdown","source":"### Create datagenerator"},{"metadata":{"trusted":true,"_uuid":"c21509d05e2882e6315fc7390d27658c0654fc15"},"cell_type":"code","source":"class data_generator:\n    \n    def create_train(dataset_info, batch_size, shape, augument=True):\n        assert shape[2] == 3\n        while True:\n            random_indexes = np.random.choice(len(dataset_info), batch_size)\n            batch_images = np.empty((batch_size, shape[0], shape[1], shape[2]))\n            batch_labels = np.zeros((batch_size, 28))\n            for i, idx in enumerate(random_indexes):\n                image = data_generator.load_image(\n                    dataset_info[idx]['path'], shape)   \n                if augument:\n                    image = data_generator.augment(image)\n                batch_images[i] = image\n                batch_labels[i][dataset_info[idx]['labels']] = 1\n            yield batch_images, batch_labels\n            \n    \n    def load_image(path, shape):\n        image_red_ch = skimage.io.imread(path+'_red.png')\n        image_yellow_ch = skimage.io.imread(path+'_yellow.png')\n        image_green_ch = skimage.io.imread(path+'_green.png')\n        image_blue_ch = skimage.io.imread(path+'_blue.png')\n\n        image_red_ch += (image_yellow_ch/2).astype(np.uint8) \n        image_green_ch += (image_yellow_ch/2).astype(np.uint8)\n\n        image = np.stack((\n            image_red_ch, \n            image_green_ch, \n            image_blue_ch), -1)\n        image = resize(image, (shape[0], shape[1]), mode='reflect')\n        return image\n                \n            \n    def augment(image):\n        augment_img = iaa.Sequential([\n            iaa.OneOf([\n                iaa.Affine(rotate=0),\n                iaa.Affine(rotate=90),\n                iaa.Affine(rotate=180),\n                iaa.Affine(rotate=270),\n                iaa.Fliplr(0.5),\n                iaa.Flipud(0.5),\n            ])], random_order=True)\n        \n        image_aug = augment_img.augment_image(image)\n        return image_aug","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"74687ae11e12c8d0559e5421a356a67e8ab01537"},"cell_type":"markdown","source":"\n### Show data"},{"metadata":{"trusted":true,"_uuid":"3f2ae48955c4b75b13dd9e9ad0d9e1c84214b019"},"cell_type":"code","source":"# create train datagen\ntrain_datagen = data_generator.create_train(\n    train_dataset_info, 5, (299,299,3), augument=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5f261d54682cbd326a01e09a0f92598228145d2d"},"cell_type":"code","source":"images, labels = next(train_datagen)\n\nfig, ax = plt.subplots(1,5,figsize=(25,5))\nfor i in range(5):\n    ax[i].imshow(images[i])\nprint('min: {0}, max: {1}'.format(images.min(), images.max()))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ddbc11bf72ecab4028380d64a08660a70a2da028"},"cell_type":"markdown","source":"### Create model"},{"metadata":{"trusted":true,"_uuid":"64bba0326be38da7add3594002563bea1c9703db"},"cell_type":"code","source":"from keras.layers import Input\nfrom keras.layers.merge import concatenate\nfrom keras.layers import Dense, Dropout, Flatten, Activation, Conv2D\nfrom keras.layers.convolutional import MaxPooling2D, AveragePooling2D\nfrom keras.layers.normalization import BatchNormalization\nfrom keras.models import Model\n\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.models import Sequential, load_model\nfrom keras.layers import Activation, Dropout, Flatten, Dense\nfrom keras.applications.inception_resnet_v2 import InceptionResNetV2\nfrom keras.applications.inception_v3 import InceptionV3\nfrom keras.callbacks import ModelCheckpoint\nfrom keras import metrics\nfrom keras.optimizers import Adam \nfrom keras import backend as K\nimport keras\n\n\ndef conv_block(x, nb_filter, nb_row, nb_col, padding = \"same\", strides = (1, 1), use_bias = False):\n    '''Defining a Convolution block that will be used throughout the network.'''\n    \n    x = Conv2D(nb_filter, (nb_row, nb_col), strides = strides, padding = padding, use_bias = use_bias)(x)\n    x = BatchNormalization(axis = -1, momentum = 0.9997, scale = False)(x)\n    x = Activation(\"relu\")(x)\n    \n    return x\n\ndef stem(input):\n    '''The stem of the pure Inception-v4 and Inception-ResNet-v2 networks. This is input part of those networks.'''\n    \n    # Input shape is 299 * 299 * 3 (Tensorflow dimension ordering)\n    x = conv_block(input, 32, 3, 3, strides = (2, 2), padding = \"same\") # 149 * 149 * 32\n    x = conv_block(x, 32, 3, 3, padding = \"same\") # 147 * 147 * 32\n    x = conv_block(x, 64, 3, 3) # 147 * 147 * 64\n\n    x1 = MaxPooling2D((3, 3), strides = (2, 2), padding = \"same\")(x)\n    x2 = conv_block(x, 96, 3, 3, strides = (2, 2), padding = \"same\")\n\n    x = concatenate([x1, x2], axis = -1) # 73 * 73 * 160\n\n    x1 = conv_block(x, 64, 1, 1)\n    x1 = conv_block(x1, 96, 3, 3, padding = \"same\")\n\n    x2 = conv_block(x, 64, 1, 1)\n    x2 = conv_block(x2, 64, 1, 7)\n    x2 = conv_block(x2, 64, 7, 1)\n    x2 = conv_block(x2, 96, 3, 3, padding = \"same\")\n\n    x = concatenate([x1, x2], axis = -1) # 71 * 71 * 192\n\n    x1 = conv_block(x, 192, 3, 3, strides = (2, 2), padding = \"same\")\n    \n    x2 = MaxPooling2D((3, 3), strides = (2, 2), padding = \"same\")(x)\n\n    x = concatenate([x1, x2], axis = -1) # 35 * 35 * 384\n    \n    return x\n\ndef inception_A(input):\n    '''Architecture of Inception_A block which is a 35 * 35 grid module.'''\n    \n    a1 = AveragePooling2D((3, 3), strides = (1, 1), padding = \"same\")(input)\n    a1 = conv_block(a1, 96, 1, 1)\n    \n    a2 = conv_block(input, 96, 1, 1)\n    \n    a3 = conv_block(input, 64, 1, 1)\n    a3 = conv_block(a3, 96, 3, 3)\n    \n    a4 = conv_block(input, 64, 1, 1)\n    a4 = conv_block(a4, 96, 3, 3)\n    a4 = conv_block(a4, 96, 3, 3)\n    \n    merged = concatenate([a1, a2, a3, a4], axis = -1)\n    \n    return merged\n\ndef inception_B(input):\n    '''Architecture of Inception_B block which is a 17 * 17 grid module.'''\n    \n    b1 = AveragePooling2D((3, 3), strides = (1, 1), padding = \"same\")(input)\n    b1 = conv_block(b1, 128, 1, 1)\n    \n    b2 = conv_block(input, 384, 1, 1)\n    \n    b3 = conv_block(input, 192, 1, 1)\n    b3 = conv_block(b3, 224, 1, 7)\n    b3 = conv_block(b3, 256, 7, 1)\n    \n    b4 = conv_block(input, 192, 1, 1)\n    b4 = conv_block(b4, 192, 7, 1)\n    b4 = conv_block(b4, 224, 1, 7)\n    b4 = conv_block(b4, 224, 7, 1)\n    b4 = conv_block(b4, 256, 1, 7)\n    \n    merged = concatenate([b1, b2, b3, b4], axis = -1)\n    \n    return merged\n\ndef inception_C(input):\n    '''Architecture of Inception_C block which is a 8 * 8 grid module.'''\n    \n    c1 = AveragePooling2D((3, 3), strides = (1, 1), padding = \"same\")(input)\n    c1 = conv_block(c1, 256, 1, 1)\n    \n    c2 = conv_block(input, 256, 1, 1)\n\n    c3 = conv_block(input, 384, 1, 1)\n    c31 = conv_block(c2, 256, 1, 3)\n    c32 = conv_block(c2, 256, 3, 1)\n    c3 = concatenate([c31, c32], axis = -1)\n\n    c4 = conv_block(input, 384, 1, 1)\n    c4 = conv_block(c3, 448, 3, 1)\n    c4 = conv_block(c3, 512, 1, 3)\n    c41 = conv_block(c3, 256, 1, 3)\n    c42 = conv_block(c3, 256, 3, 1)\n    c4 = concatenate([c41, c42], axis = -1)\n  \n    merged = concatenate([c1, c2, c3, c4], axis = -1)\n    \n    return merged\n\ndef reduction_A(input, k = 192, l = 224, m = 256, n = 384):\n    '''Architecture of a 35 * 35 to 17 * 17 Reduction_A block.'''\n\n    ra1 = MaxPooling2D((3, 3), strides = (2, 2), padding = \"same\")(input)\n    \n    ra2 = conv_block(input, n, 3, 3, strides = (2, 2), padding = \"same\")\n\n    ra3 = conv_block(input, k, 1, 1)\n    ra3 = conv_block(ra3, l, 3, 3)\n    ra3 = conv_block(ra3, m, 3, 3, strides = (2, 2), padding = \"same\")\n\n    merged = concatenate([ra1, ra2, ra3], axis = -1)\n    \n    return merged\n\ndef reduction_B(input):\n    '''Architecture of a 17 * 17 to 8 * 8 Reduction_B block.'''\n    \n    rb1 = MaxPooling2D((3, 3), strides = (2, 2), padding = \"same\")(input)\n    \n    rb2 = conv_block(input, 192, 1, 1)\n    rb2 = conv_block(rb2, 192, 3, 3, strides = (2, 2), padding = \"same\")\n    \n    rb3 = conv_block(input, 256, 1, 1)\n    rb3 = conv_block(rb3, 256, 1, 7)\n    rb3 = conv_block(rb3, 320, 7, 1)\n    rb3 = conv_block(rb3, 320, 3, 3, strides = (2, 2), padding = \"same\")\n    \n    merged = concatenate([rb1, rb2, rb3], axis = -1)\n    \n    return merged\n\ndef inception_v4(nb_classes = 1001, load_weights = True):\n    '''Creates the Inception_v4 network.'''\n    \n    init = Input((299, 299, 3)) # Channels last, as using Tensorflow backend with Tensorflow image dimension ordering\n    \n    # Input shape is 299 * 299 * 3\n    x = stem(init) # Output: 35 * 35 * 384\n    \n    # 4 x Inception A\n    for i in range(4):\n        x = inception_A(x)\n        # Output: 35 * 35 * 384\n        \n    # Reduction A\n    x = reduction_A(x, k = 192, l = 224, m = 256, n = 384) # Output: 17 * 17 * 1024\n\n    # 7 x Inception B\n    for i in range(7):\n        x = inception_B(x)\n        # Output: 17 * 17 * 1024\n        \n    # Reduction B\n    x = reduction_B(x) # Output: 8 * 8 * 1536\n\n    # 3 x Inception C\n    for i in range(3):\n        x = inception_C(x) \n        # Output: 8 * 8 * 1536\n        \n    # Average Pooling\n    x = AveragePooling2D((8, 8))(x) # Output: 1536\n\n    # Dropout\n    x = Dropout(0.2)(x) # Keep dropout 0.2 as mentioned in the paper\n    x = Flatten()(x) # Output: 1536\n\n    # Output layer\n    output = Dense(units = nb_classes, activation = \"softmax\")(x) # Output: 1000\n\n    model = Model(init, output, name = \"Inception-v4\")   \n        \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e7296424196067a0e0a8f2383c99bd2bb76281c4"},"cell_type":"code","source":"# keras.backend.clear_session()\nmodel=inception_v4(nb_classes = 28, load_weights = True)\n#model = create_model(input_shape=(299,299,3), n_out=28)\nmodel.compile(loss='binary_crossentropy', optimizer=Adam(1e-04),metrics=['acc'])\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2fbffd71262d7d7e591ad5955feb6b0c5ee61737"},"cell_type":"markdown","source":"### Train model"},{"metadata":{"trusted":true,"_uuid":"0343374956494b98425448b7aa9092a037aee401"},"cell_type":"code","source":"epochs = 100; batch_size = 16\ncheckpointer = ModelCheckpoint(\n    '../working/InceptionV4.h5', \n    verbose=2, \n    save_best_only=True)\n\n# split and suffle data \nnp.random.seed(2018)\nindexes = np.arange(train_dataset_info.shape[0])\nnp.random.shuffle(indexes)\ntrain_indexes = indexes[:27500]\nvalid_indexes = indexes[27500:]\n\n# create train and valid datagens\ntrain_generator = data_generator.create_train(\n    train_dataset_info[train_indexes], batch_size, (299,299,3), augument=True)\nvalidation_generator = data_generator.create_train(\n    train_dataset_info[valid_indexes], 100, (299,299,3), augument=False)\n\n# train model\nhistory = model.fit_generator(\n    train_generator,\n    steps_per_epoch=100,\n    validation_data=next(validation_generator),\n    epochs=epochs, \n    verbose=1,\n    callbacks=[checkpointer])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"884be9cb5e6c81d0ba382bc436810831b37e3e3f"},"cell_type":"code","source":"fig, ax = plt.subplots(1, 2, figsize=(15,5))\nax[0].set_title('loss')\nax[0].plot(history.epoch, history.history[\"loss\"], label=\"Train loss\")\nax[0].plot(history.epoch, history.history[\"val_loss\"], label=\"Validation loss\")\nax[1].set_title('acc')\nax[1].plot(history.epoch, history.history[\"acc\"], label=\"Train acc\")\nax[1].plot(history.epoch, history.history[\"val_acc\"], label=\"Validation acc\")\nax[0].legend()\nax[1].legend()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2a52b306cd27fc030cfd3f7583009945de7828ac"},"cell_type":"markdown","source":"### Create submit"},{"metadata":{"trusted":true,"_uuid":"9d9ee4a8c2b1fc75b9f8d58855e33b115e92134d"},"cell_type":"code","source":"submit = pd.read_csv('../input/sample_submission.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"782cdb0d614add0f41c11ea180bd45e5600d60fb"},"cell_type":"code","source":"%%time\npredicted = []\nfor name in tqdm(submit['Id']):\n    path = os.path.join('../input/test/', name)\n    image = data_generator.load_image(path, (299,299,3))\n    score_predict = model.predict(image[np.newaxis])[0]\n    label_predict = np.arange(28)[score_predict>=0.5]\n    str_predict_label = ' '.join(str(l) for l in label_predict)\n    predicted.append(str_predict_label)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"07043ed35ad009ce6edc017e4aa88ac82571a750"},"cell_type":"code","source":"submit['Predicted'] = predicted\nsubmit.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}