{"cells":[{"metadata":{"trusted":false},"cell_type":"code","source":"import gc\nimport os\nimport warnings\nimport numpy as np \nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm\n\nfrom keras import backend as K\nfrom keras import optimizers, applications\nfrom keras.models import Sequential, Model\nfrom keras.layers import Dense, Dropout, Flatten, Activation, Conv2D, GlobalAveragePooling3D\nfrom sklearn.metrics import f1_score\nfrom keras.optimizers import Adam, SGD\nfrom keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau, TensorBoard\nfrom datetime import datetime \nwarnings.filterwarnings(action='ignore')\n\nK.image_data_format()\n\nimport PIL\nfrom PIL import ImageDraw\n\nfrom sklearn.model_selection import train_test_split","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"DATA_PATH = './input/'\nos.listdir(DATA_PATH)\n\n# 이미지 폴더 경로\nTRAIN_IMG_PATH = os.path.join(DATA_PATH, 'train')\nTEST_IMG_PATH = os.path.join(DATA_PATH, 'test')\n\n# CSV 파일 경로\ndf_train = pd.read_csv(os.path.join(DATA_PATH, 'train.csv'))\ndf_test = pd.read_csv(os.path.join(DATA_PATH, 'test.csv'))\ndf_class = pd.read_csv(os.path.join(DATA_PATH, 'class.csv'))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## ROI Cropping "},{"metadata":{"trusted":false},"cell_type":"code","source":"# # Crop Train Imgs \n# for file_name in df_train['img_file']:\n#     pos = df_train.loc[df_train[\"img_file\"] == file_name,\n#                ['bbox_x1','bbox_y1', 'bbox_x2', 'bbox_y2']].values.reshape(-1)\n#     img = PIL.Image.open(os.path.join(TRAIN_IMG_PATH, file_name))\n#     img_crop = img.crop(pos)\n#     img_crop.save(os.path.join(TRAIN_IMG_PATH, 'crop', file_name))","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# # Crop Test Imgs \n# for file_name in df_test['img_file']:\n#     pos = df_test.loc[df_test[\"img_file\"] == file_name,\n#                ['bbox_x1','bbox_y1', 'bbox_x2', 'bbox_y2']].values.reshape(-1)\n#     img = PIL.Image.open(os.path.join(TEST_IMG_PATH,'gray3', file_name))\n#     img_crop = img.crop(pos)\n#     img_crop.save(os.path.join(TEST_IMG_PATH, 'crop', file_name))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## RGB2Gray"},{"metadata":{"trusted":false},"cell_type":"code","source":"# for file_name in df_train['img_file']:\n#     img = PIL.Image.open(os.path.join(TRAIN_IMG_PATH, 'gray', file_name)).convert('RGB')\n#     img.save(os.path.join(TRAIN_IMG_PATH, 'gray3', file_name))","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# for file_name in df_test['img_file']:\n#     img = PIL.Image.open(os.path.join(TEST_IMG_PATH,'gray', file_name)).convert('RGB')\n#     img.save(os.path.join(TEST_IMG_PATH, 'gray3', file_name))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Cross Validation (K-fold)"},{"metadata":{"trusted":false},"cell_type":"code","source":"df_train[\"class\"] = df_train[\"class\"].astype('str')\ndf_train = df_train[['img_file', 'class']]\ndf_test = df_test[['img_file']]\nits = np.arange(df_train.shape[0])\n\nfold = 5\nX_train = []\nX_val = []\nidx_list =  [i for i in range(df_train.shape[0])]\n\nval_size = int(df_train.shape[0] / fold)\nval_index = [0,]\nval_index+=[df_train.shape[0] - i*val_size for i in reversed(range(fold))]\nprint(val_index)\n\nfor i in range(len(val_index)-1):\n    X_val.append(df_train.iloc[val_index[i]:val_index[i+1], :])\n    X_train.append(df_train.iloc[idx_list[:val_index[i]]+idx_list[val_index[i+1]:],:])\n\nprint(df_test.shape)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Generator"},{"metadata":{"trusted":false},"cell_type":"code","source":"from keras.applications.resnet50 import ResNet50, preprocess_input\nfrom keras.preprocessing.image import ImageDataGenerator\n\n# Parameter\nimg_size = (299, 299)\nnb_test_samples = len(df_test)\nbatch_size = 64\n\n# Define Generator config\ntrain_datagen = ImageDataGenerator(\n    horizontal_flip = True, \n    vertical_flip = False,\n    zoom_range=0.2,\n    width_shift_range = 0.2,\n    height_shift_range = 0.2,\n    rotation_range = 25,\n    fill_mode='nearest',\n    preprocessing_function=preprocess_input)\n\n# Test Generator\ntest_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)\ntest_generator = test_datagen.flow_from_dataframe(\n    dataframe=df_test,\n    directory='./input/test/crop/',\n    x_col='img_file',\n    y_col=None,\n    target_size= img_size,\n    color_mode='rgb',\n    class_mode=None,\n    batch_size=batch_size,\n    shuffle=False\n)    \n\ntrain_generator = []\nvalidation_generator = []\nnb_train_samples = []\nnb_validation_samples = []\nfor i in range(fold):\n    nb_train_samples.append(len(X_train[i]))\n    nb_validation_samples.append(len(X_val[i]))\n \n    val_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)\n\n    # Make Generator\n    train_generator.append(train_datagen.flow_from_dataframe(\n        dataframe=X_train[i], \n        directory='./input/train/gray3/',\n        x_col = 'img_file',\n        y_col = 'class',\n        target_size = img_size,\n        color_mode='rgb',\n        class_mode='categorical',\n        batch_size=batch_size,\n        seed=44\n    ))\n\n    validation_generator.append(val_datagen.flow_from_dataframe(\n        dataframe=X_val[i], \n        directory='./input/train/gray3/',\n        x_col = 'img_file',\n        y_col = 'class',\n        target_size = img_size,\n        color_mode='rgb',\n        class_mode='categorical',\n        batch_size=batch_size,\n        shuffle=False\n    ))\n\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Get model"},{"metadata":{"trusted":false},"cell_type":"code","source":"def get_model():\n    model = applications.InceptionResNetV2(weights=None, \n                          include_top=False,\n                          input_shape=(img_size[0],img_size[1], 3))\n    model.load_weights('./inceptionresnetv2/inception_resnet_v2_weights_tf_dim_ordering_tf_kernels_notop.h5')\n    model.trainable = False\n    \n    #Adding custom layers \n    x = model.output\n    x = GlobalAveragePooling2D()(x)\n#     x = Flatten()(x)\n    x = Dense(1024, activation=\"selu\", kernel_initializer='he_normal')(x)\n    x = Dropout(0.3)(x)\n    predictions = Dense(196, activation=\"softmax\", kernel_initializer='he_normal')(x)\n    model_final = Model(input = model.input, output = predictions)\n    # model_final.summary()\n\n    #model_final.compile(optimizer=SGD(lr=0.01, momentum=0.9),loss='categorical_crossentropy',metrics=['acc'])\n    #model_final.compile(optimizers.rmsprop(lr=0.001, decay=1e-6),loss='categorical_crossentropy',metrics=['acc'])\n#     model_final.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['acc'])\n    model_final.compile(optimizer=optimizers.Adadelta(rho=0.95),loss='categorical_crossentropy',metrics=['acc'])  \n    return model_final","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"def micro_f1(y_true, y_pred):\n    return f1_score(y_true, y_pred, average='micro')","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"def get_steps(num_samples, batch_size):\n    if (num_samples % batch_size) > 0 :\n        return (num_samples // batch_size) + 1\n    else :\n        return num_samples // batch_size","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Train"},{"metadata":{"scrolled":false,"trusted":false},"cell_type":"code","source":"epochs = 50\n\nfor i in range(fold):\n    print(datetime.now())\n    print('fold %d' %(i+1))\n    filepath = \"./models/my_inceptionresnetv2_model_\"+\"f%d\"%(i+1)+\"_{val_acc:.2f}_{val_loss:.4f}.h5\"\n    \n    model_final = get_model()\n    \n    checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose = 1, save_best_only=True, mode='auto', period=1)\n    es = EarlyStopping(monitor='val_acc', min_delta = 0, patience=6, verbose=1, mode='auto')\n    RR = ReduceLROnPlateau(\n        monitor = 'val_loss', \n        factor = 0.5, \n        patience = 4, \n        min_lr=0.000001, \n        verbose=1, \n        mode='min')\n    \n    logdir=\"logs/scalars/\" + datetime.now().strftime(\"%Y%m%d-%H%M%S\")\n    tensorboard_callback = TensorBoard(log_dir=logdir)\n\n    callbackList = [checkpoint, es, RR, tensorboard_callback]\n    \n    history = model_final.fit_generator(\n        train_generator[i],\n        steps_per_epoch = get_steps(nb_train_samples[i], batch_size),\n        epochs=epochs,\n        validation_data = validation_generator[i],\n        validation_steps = get_steps(nb_validation_samples[i], batch_size),\n        callbacks = callbackList,\n        verbose = 0\n    )\n    \n    # Plot training & validation accuracy values\n    plt.plot(history.history['acc'])\n    plt.plot(history.history['val_acc'])\n    plt.title('Model accuracy')\n    plt.ylabel('Accuracy')\n    plt.xlabel('Epoch')\n    plt.legend(['Train', 'Test'], loc='upper left')\n    plt.show()\n    \n    # Plot training & validation loss values\n    plt.plot(history.history['loss'])\n    plt.plot(history.history['val_loss'])\n    plt.title('Model loss')\n    plt.ylabel('Loss')\n    plt.xlabel('Epoch')\n    plt.legend(['Train', 'Test'], loc='upper left')\n    plt.show()\n\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Ensemble"},{"metadata":{"trusted":false},"cell_type":"code","source":"model_names = os.listdir('./models')\npredictions = []\nfor i, name in enumerate(model_names):\n    model = get_model()\n    model.load_weights('./models/'+name)\n    test_generator.reset()\n    pred = model.predict_generator(\n        generator = test_generator,\n        steps = get_steps(nb_test_samples, batch_size),\n        verbose=1\n    )\n    predictions.append(pred)\n\ny_pred_fiinal_model = np.mean(predictions, axis=0)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Make results"},{"metadata":{"trusted":false},"cell_type":"code","source":"predicted_class_indices=np.argmax(y_pred_fiinal_model, axis=1)\n\n# Generator class dictionary mapping\nlabels = (train_generator[0].class_indices)\nlabels = dict((v,k) for k,v in labels.items())\npredictions = [labels[k] for k in predicted_class_indices]\n\nsubmission = pd.read_csv(os.path.join(DATA_PATH, 'sample_submission.csv'))\nsubmission[\"class\"] = predictions\nsubmission.to_csv(\"submission.csv\", index=False)\nsubmission.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Model Load"},{"metadata":{"trusted":false},"cell_type":"code","source":"model_final = get_model()\nmodel_final.load_weights('./models/my_inceptionresnetv2_model_0.95_0.1901.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"%%time\ntest_generator.reset()\nprediction = new_model.predict_generator(\n    generator = test_generator,\n    steps = get_steps(nb_test_samples, batch_size),\n    verbose=1\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predicted_class_indices=np.argmax(prediction, axis=1)\n\n# Generator class dictionary mapping\nlabels = (train_generator[0].class_indices)\nlabels = dict((v,k) for k,v in labels.items())\npredictions = [labels[k] for k in predicted_class_indices]\n\nsubmission = pd.read_csv(os.path.join(DATA_PATH, 'sample_submission.csv'))\nsubmission[\"class\"] = predictions\nsubmission.to_csv(\"submission.csv\", index=False)\nsubmission.head()","execution_count":null,"outputs":[]}],"metadata":{"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.4"}},"nbformat":4,"nbformat_minor":1}