{"cells":[{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"# Import packages\nimport pandas as pd\nimport numpy as np \nimport matplotlib.pyplot as plt\nimport os\n\nimport random # Randomly select a filename for viewing\nfrom keras.preprocessing.image import load_img # View image\nfrom PIL import Image\n\nfrom keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, BatchNormalization\nfrom keras.optimizers import RMSprop\nfrom keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint\nfrom keras.preprocessing.image import ImageDataGenerator\n\nfrom sklearn.model_selection import train_test_split\n\n# Directory\nmain_folder = r'../input'\ninput_file_train = r'train/train'\ninput_file_test = r'test1/test1'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Import training file\n## All training images are in a folder\n## Each image is labeled with cat or dog\n## The categories are converted to 0 (Cat) or 1 (Dog)\nfilenames = os.listdir(os.path.join(main_folder, input_file_train))\ncategories = []\nfor file in filenames:\n\tcategory = file.split(\".\")[0].lower()\n\tcategories.append(category)\n\ndataframe = pd.DataFrame({\"filename\":filenames, \"categories\":categories})\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# View sample data\nsample = random.choice(filenames)\nplt.imshow(load_img(os.path.join(main_folder, input_file_train, sample)))\n\nfrom PIL import Image\nim = Image.open(os.path.join(main_folder, input_file_train, sample))\nim.size","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Split the dataframe into train and val dataframe\nrandom_seed = 10\nbatch_size = 100\nimage_height, image_width, image_channels = 128, 128, 3\ntrain_df, val_df = train_test_split(dataframe, test_size = 0.2, random_state = random_seed)\ntrain_df.reset_index(inplace = True, drop = True)\nval_df.reset_index(inplace = True, drop = True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# ImageDataGenerator to load the images for training\n## Train datagen and generator\ntrain_datagen = ImageDataGenerator(\n\trotation_range = 15,\n\trescale = 1./255,\n\twidth_shift_range = 0.2, \n\theight_shift_range = 0.2, \n\thorizontal_flip = True, \n\tshear_range = 0.2, \n\tzoom_range = 0.2)\n\ntrain_generator = train_datagen.flow_from_dataframe(\n\tdataframe = train_df,\n\tdirectory = os.path.join(main_folder, input_file_train),\n\tx_col = \"filename\",\n\ty_col = \"categories\",\n\ttarget_size = (image_height, image_width),\n\tclass_mode = \"categorical\",\n\tbatch_size = batch_size)\n\n## Val datagen and generator\nval_datagen = ImageDataGenerator(rescale = 1./255)\nval_generator = val_datagen.flow_from_dataframe(\n\tdataframe = val_df,\n\tdirectory = os.path.join(main_folder, input_file_train),\n\tx_col = \"filename\",\n\ty_col = \"categories\",\n\ttarget_size = (image_height, image_width),\n\tclass_mode = \"categorical\",\n\tbatch_size = batch_size)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Model hyperparameters\ndropout_rate = 0.25\nfc_units_1 = 512\nfc_units_2 = 256\noutput_units = 2\nepochs = 50\n\n# Build the CNN model\nmodel = Sequential()\n\n## Conv layer 1\nmodel.add(Conv2D(filters = 32, kernel_size = 3, strides = 1, padding = \"same\",\n\tinput_shape = (image_height, image_width, image_channels), data_format = \"channels_last\"))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D())\nmodel.add(Dropout(rate = dropout_rate))\n\n## Conv layer 2\nmodel.add(Conv2D(filters = 64, kernel_size = 3, strides = 1, padding = \"same\"))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D())\nmodel.add(Dropout(rate = dropout_rate))\n\n## Conv layer 3\nmodel.add(Conv2D(filters = 128, kernel_size = 3, strides = 1, padding = \"same\"))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D())\nmodel.add(Dropout(rate = dropout_rate))\n\n## Output layer\nmodel.add(Flatten())\nmodel.add(Dense(units = fc_units_1, activation = \"relu\"))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(rate = dropout_rate))\nmodel.add(Dense(units = fc_units_2, activation = \"relu\"))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(rate = dropout_rate))\nmodel.add(Dense(units = output_units, activation = \"softmax\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Model summary\nmodel.summary()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Optimize and compile\noptimizer = RMSprop()\nmodel.compile(optimizer = optimizer, loss = \"categorical_crossentropy\", metrics = [\"accuracy\"])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create callbacks\n## Early Stop\n### Stop training if the val_loss does not decrease \nearlystop = EarlyStopping(monitor = \"val_acc\", patience = 10)\n\n## Reduce learning rate\nreduce_lr = ReduceLROnPlateau(monitor = \"val_acc\", factor = 0.75, verbose = 1, patience = 2, min_lr = 0.00001)\n\n## Save best model\ncheckpoint = ModelCheckpoint(filepath = os.path.join(main_folder, \"best weights.h5\"), monitor = \"val_acc\", save_best_only = True)\n\ncallbacks = [earlystop, reduce_lr]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Train the model\nhistory = model.fit_generator(\n\tgenerator = train_generator, \n\tsteps_per_epoch = len(train_df)//batch_size,\n\tepochs = epochs,\n\tcallbacks = callbacks,\n\tvalidation_data = val_generator, \n\tvalidation_steps = len(val_df)//batch_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.save_weights(\"model.h5\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Visualize the training and validation loss and accuracy\nfig, ax = plt.subplots(2, 1, figsize = (12,12))\nax[0].plot(history.history[\"loss\"], color = \"b\", label = \"Training loss\")\nax[0].plot(history.history[\"val_loss\"], color = \"r\", label = \"Validation loss\")\nax[0].set_xticks(np.arange(1, epochs, 1))\nax[0].set_yticks(np.arange(0, 2.3, 0.2))\nax[0].legend(loc = \"best\", shadow = True)\n\nax[1].plot(history.history[\"acc\"], color = \"b\", label = \"Training accuracy\")\nax[1].plot(history.history[\"val_acc\"], color = \"r\", label = \"Valication accuracy\")\nax[1].set_xticks(np.arange(1, epochs))\nax[1].legend(loc = \"best\", shadow = True)\n\nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"##### TEST SET\n# Read and set up the generator\ntest_files = os.listdir(os.path.join(main_folder, input_file_test))\ntest_df = pd.DataFrame({\"filename\":test_files})\ntest_datagen = ImageDataGenerator(rescale = 1./255)\ntest_generator = test_datagen.flow_from_dataframe(\n\tdataframe = test_df,\n\tdirectory = os.path.join(main_folder, input_file_test),\n\tx_col = \"filename\",\n\ty_col = None,\n\ttarget_size = (image_height, image_width),\n\tclass_mode = None,\n\tbatch_size = batch_size,\n\tshuffle = False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Prediction on the test set\nprediction = model.predict_generator(\n\tgenerator = test_generator,\n\tsteps = np.ceil(len(test_df)/batch_size))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Convert from probability to label (0 or 1)\ntest_df[\"category\"] = np.argmax(prediction, axis = 1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Save prediction to csv for submission\nsubmission = test_df.copy()\nsubmission[\"filename\"] = submission[\"filename\"].apply(lambda x: x.split(\".\")[0])\nsubmission.rename(columns = {\"filename\":\"id\", \"category\":\"label\"}, inplace = True)\nsubmission.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.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}