{"cells":[{"cell_type":"markdown","metadata":{"_cell_guid":"42a8d3d9-de46-30f9-d085-8afb8120f68b"},"source":"This notebook was inspired by Thomas' kernel: https://www.kaggle.com/ponadto/complete-process-using-resnet-as-a-starting-point (thanks Thomas!)\n\nI wanted to use a simpler architecture (https://github.com/fchollet/keras/blob/master/examples/cifar10_cnn.py), but get more out of image augmentation. I'm using `keras`'es `ImageDataGenerator` with the `flow_from_directory` functionality (images generated directly from files in a specified directory)."},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"9fe89c7b-c5be-5618-b7a6-32814c9826cd"},"outputs":[],"source":"from __future__ import division\n\nfrom keras.models import Model\nfrom keras.models import Sequential\nfrom keras.layers import Input, Activation, merge, Dense, Flatten\nfrom keras.layers import Conv2D, MaxPooling2D, AveragePooling2D\n\nfrom keras.layers import Dense, Dropout, Activation, Flatten\nfrom keras.layers.normalization import BatchNormalization\nfrom keras import optimizers\n\nfrom keras.preprocessing.image import ImageDataGenerator"},{"cell_type":"markdown","metadata":{"_cell_guid":"3bfe3c4e-340f-56eb-37bc-7ae2d70bf43a"},"source":"## Config declarations"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"149372a9-9346-c815-5b5c-a9e5129588cf"},"outputs":[],"source":"conf = dict()\n\nconf['seed'] = 2017\nconf['num_classes'] = 3\nconf['num_channels'] = 3\n\n# Amount of data for training\nconf['num_epochs'] = 10#10\nconf['batch_size'] = 12#32\nconf['steps_per_epoch'] = 16\nconf['validation_steps'] = 16\n\nconf['num_workers'] = 1#8\n\n# Shape of image for CNN (Larger the better, but you need to increase CNN as well)\nim_sz = 64\nconf['image_shape'] = (im_sz, im_sz)\n\n# I wanted to see how will the model perform in case I use \"poolings\" other than `MaxPooling2D`\n# conf['pooling_strategy'] = AveragePooling2D\nconf['pooling_strategy'] = MaxPooling2D"},{"cell_type":"markdown","metadata":{"_cell_guid":"59c75e89-586d-4f26-683d-f2f34e7ab9ed"},"source":"## Create a simple model"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"22b8cae0-8118-57d6-fef3-b367805ea817"},"outputs":[],"source":"def create_model(conf):\n    ''' I borrowed the model from here: \n            https://github.com/fchollet/keras/blob/master/examples/cifar10_cnn.py\n    '''\n    num_channels = conf['num_channels']\n    num_classes = conf['num_classes']\n    img_rows, img_cols = conf['image_shape']\n    PoolingStrategy = conf['pooling_strategy']\n    \n    model = Sequential()\n\n    model.add(Conv2D(32, (3, 3), padding='valid',\n                     input_shape=(img_rows, img_cols, num_channels)))\n\n    model.add(Activation('relu'))\n    model.add(Conv2D(32, (3, 3))) \n    model.add(Activation('relu'))\n    model.add(PoolingStrategy(pool_size=(2, 2)))\n    model.add(Dropout(0.25))\n\n#     model.add(Conv2D(64, (3, 3), padding='valid'))\n#     model.add(Activation('relu'))\n#     model.add(Conv2D(64, (3, 3))) \n#     model.add(Activation('relu'))\n#     model.add(PoolingStrategy(pool_size=(2, 2)))\n#     model.add(Dropout(0.25))\n\n    model.add(Flatten())\n    model.add(BatchNormalization())\n    model.add(Dense(512))\n    model.add(Activation('relu'))\n    model.add(Dropout(0.5))\n    model.add(Dense(num_classes))\n    model.add(Activation('softmax'))\n\n    adam = optimizers.adam(lr=0.0001, decay=1e-6)\n\n    model.compile(loss='categorical_crossentropy',\n                  optimizer=adam,\n                  metrics=['accuracy'])\n\n    return model\n\n\n# The actual creation of the model\nmodel = create_model(conf)"},{"cell_type":"markdown","metadata":{"_cell_guid":"46aeb628-acc3-2903-8820-6ed13e6c19aa"},"source":"## Fitting the model using the `ImageDataGenerator` (with no actual validation set -- \"It's a trap!\")"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"147cab99-58f2-312d-21e5-1e15e6520586"},"outputs":[],"source":"print('Fit model...')\n\n# There was a problem with truncated images, solution found here:\n# http://stackoverflow.com/questions/12984426/python-pil-ioerror-image-file-truncated-with-big-images\n# and here's the solution...\nfrom PIL import ImageFile\nImageFile.LOAD_TRUNCATED_IMAGES = True\n\n\nSCALING = 1/255.\n\ntrain_datagen = ImageDataGenerator(\n                    rescale=SCALING,\n                    shear_range=0.2,\n                    zoom_range=0.2,\n                    horizontal_flip=True,\n                    vertical_flip=True)\n\ntrain_generator = train_datagen.flow_from_directory(\n                    '../input/train',\n                    target_size=conf['image_shape'],\n                    batch_size=conf['batch_size'],\n                    seed=conf['seed'])\n\n# Not really used; `model.predict_generator` failed after ~100 steps\ntest_datagen = ImageDataGenerator(\n                    rescale=SCALING)\ntest_generator = test_datagen.flow_from_directory(\n                    '../input/',\n                    target_size=conf['image_shape'],\n                    batch_size=conf['batch_size'],\n                    classes=['test'],\n                    class_mode=None,\n                    shuffle=False)\n\nmodel.fit_generator(train_generator,\n                    steps_per_epoch=conf['steps_per_epoch'],\n                    epochs=conf['num_epochs'],\n                    validation_data=train_generator,\n                    validation_steps=conf['validation_steps'],\n                    workers=conf['num_workers'])\n\nmodel.save('last_model.h5')"},{"cell_type":"markdown","metadata":{"_cell_guid":"df7b3fb4-c63b-8feb-9e17-2e316b4f60d2"},"source":"## Create submission files with prediction for submission"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"cc51ae47-ab0f-8100-2b4f-77dbf6375d7f"},"outputs":[],"source":"import pandas as pd\nimport cv2\nimport numpy as np\n\nsample_subm = pd.read_csv('../input/sample_submission.csv')\nids = sample_subm['image_name'].values\n\nfor id_ in ids:\n    print('Predict for image {}'.format(id_))\n    f = '../input/test/' + id_\n    image_list = []\n    \n    image = cv2.imread(f)\n    image = cv2.resize(image, conf['image_shape'])\n    image = SCALING*image\n    image_list.append(image)\n        \n    image_list = np.array(image_list)\n\n    predictions = model.predict(image_list, verbose=1, batch_size=1)\n\n    sample_subm.loc[sample_subm['image_name'] == id_, 'Type_1'] = predictions[0, 0]\n    sample_subm.loc[sample_subm['image_name'] == id_, 'Type_2'] = predictions[0, 1]\n    sample_subm.loc[sample_subm['image_name'] == id_, 'Type_3'] = predictions[0, 2]\n    \nsample_subm.to_csv(\"subm.csv\", index=False)"},{"cell_type":"markdown","metadata":{"_cell_guid":"40dd141b-69c5-80d0-7dc1-77adf732c22c"},"source":""}],"metadata":{"_change_revision":0,"_is_fork":false,"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.0"}},"nbformat":4,"nbformat_minor":0}