{"cells":[{"metadata":{},"cell_type":"markdown","source":"## Preset before start"},{"metadata":{"trusted":true},"cell_type":"code","source":"cur_env = 'kaggle' # 'kaggle' or 'ubuntu' 둘중 하나 입력","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Module import "},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport cv2\nimport os\nfrom pathlib import Path\nimport skimage.io\n\nfrom sklearn.preprocessing import OneHotEncoder #One-hot 인코더\nimport keras.backend as K #케라스 버전 2.3.1\nimport random\nfrom sklearn.model_selection import train_test_split\nfrom keras.callbacks.callbacks import ModelCheckpoint, EarlyStopping\nfrom matplotlib.pyplot import imshow","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Model Loss function define\n- Loss Function - Quadratic Weighted Kappa"},{"metadata":{"trusted":true},"cell_type":"code","source":"def quadratic_kappa_coefficient(y_true, y_pred):\n    y_true = K.cast(y_true, \"float32\")\n    n_classes = K.cast(y_pred.shape[-1], \"float32\")\n    weights = K.arange(0, n_classes, dtype=\"float32\") / (n_classes - 1)\n    weights = (weights - K.expand_dims(weights, -1)) ** 2\n\n    hist_true = K.sum(y_true, axis=0)\n    hist_pred = K.sum(y_pred, axis=0)\n\n    E = K.expand_dims(hist_true, axis=-1) * hist_pred\n    E = E / K.sum(E, keepdims=False)\n\n    O = K.transpose(K.transpose(y_true) @ y_pred)  # confusion matrix\n    O = O / K.sum(O)\n\n    num = weights * O\n    den = weights * E\n\n    QWK = (1 - K.sum(num) / K.sum(den))\n    return QWK\n\ndef quadratic_kappa_loss(scale=2.0):\n    def _quadratic_kappa_loss(y_true, y_pred):\n        QWK = quadratic_kappa_coefficient(y_true, y_pred)\n        loss = -K.log(K.sigmoid(scale * QWK))\n        return loss\n        \n    return _quadratic_kappa_loss","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Build Model "},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.applications.vgg16 import VGG16\nfrom keras.applications.inception_v3 import InceptionV3\nfrom keras.applications.inception_resnet_v2 import InceptionResNetV2, decode_predictions\nfrom keras import models, Model\nfrom keras.layers import Input,Dense, Dropout, Flatten, Conv2D, MaxPool2D\nfrom keras.optimizers import Adam\nfrom keras.losses import categorical_crossentropy","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"input_shape = (299, 299, 3)\nif cur_env == 'ubuntu':\n    base_net = InceptionResNetV2(weights='keras_pre_trained_model/inception_resnet_v2_weights_tf_dim_ordering_tf_kernels_notop.h5', include_top=False, input_shape=input_shape)\n    #base_net = VGG16(weights='keras_pre_trained_model/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5', include_top=False, input_shape=input_shape)\nelse:\n    base_net = InceptionV3(weights='../input/keras-pretrained-models/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5', include_top=False, input_shape=input_shape)\n    #base_net = InceptionResNetV2(weights='../input/keras-pretrained-models/inception_resnet_v2_weights_tf_dim_ordering_tf_kernels_notop.h5', include_top=False, input_shape=input_shape)\n    #base_net = VGG16(weights='../input/keras_pretrained_models/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5', include_top=False, input_shape=input_shape)\n\nfor layer in base_net.layers:\n    layer.trainable = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = models.Sequential()\nmodel.add(base_net)\n\nmodel.add(Flatten())\nmodel.add(Dense(256, activation = \"relu\"))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(6, activation = \"softmax\"))\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = Model(inputs = model.input, outputs = model.output)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#loss = categorical_crossentropy,\nmodel.compile(optimizer = Adam(lr=1e-3), loss = quadratic_kappa_loss(scale=6.0), \\\n             metrics = ['accuracy',quadratic_kappa_coefficient])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## CSV read"},{"metadata":{"trusted":true},"cell_type":"code","source":"if cur_env == 'ubuntu':\n    dir = 'dataset/'\n    train_df = pd.read_csv(dir+'train.csv')\n    test_df = pd.read_csv(dir+'test.csv')\n    train_df['image_path'] = [dir + 'train_images/' +image_name +\".tiff\" for image_name in train_df['image_id']]\n    test_df['image_path'] = [dir + 'train_images/' +image_name +\".tiff\" for image_name in test_df['image_id']]\n\nelse: #캐글일 경우\n    HOME = Path(\"../input/prostate-cancer-grade-assessment\")\n    TRAIN = Path(\"train_images\")\n    CUSTOM = Path('../input/panda-conv-16x128x128/conv_train_images')\n    train_df = pd.read_csv(str(HOME)+'/train.csv')\n    test_df = pd.read_csv(str(HOME)+'/test.csv')\n    train_df['image_path'] = [str(HOME/TRAIN/image_name) + \".tiff\" for image_name in train_df['image_id']]\n    train_df['conv_image_path'] = [str(CUSTOM/image_name) +\".jpg\" for image_name in train_df['image_id']]\n    test_df['image_path'] = [str(HOME/TRAIN/image_name) + \".tiff\" for image_name in test_df['image_id']]\n    test_df['conv_image_path'] = [str(CUSTOM/image_name) +\".jpg\" for image_name in test_df['image_id']]\n\nprint(train_df.head(3))\nprint(test_df.head(3))\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# train_x = train_df['image_id']\n# train_y = train_df['isup_grade']\n# test_x = test_df['image_id']\n# print(f\"train_x : {len(train_x)}, train_y : {len(train_y)}, test_x : {len(test_x)}\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Data Encoder "},{"metadata":{"trusted":true},"cell_type":"code","source":"# 'isup_grade'를 기준으로 라벨인코딩 진행\nencoder = OneHotEncoder(handle_unknown = 'ignore')\nencoder_labels = pd.DataFrame(encoder.fit_transform(train_df[['isup_grade']]).toarray())\n#display(encoder_labels)\n\ntrain_df = pd.merge(train_df, encoder_labels, left_index=True, right_index=True)\ntrain_df.head(4)\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['conv_image_path'][0].endswith('.jpg')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# import matplotlib.pyplot as plt\n# print(train_df['conv_image_path'][0])\n# img = cv2.imread(train_df['conv_image_path'][0])\n\n# print(img.shape)\n\n# plt.imshow(img)\n# plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 이미지 호출"},{"metadata":{"trusted":true},"cell_type":"code","source":"# 이미지(tiff 파일) 호출 후 skimage를 통해 사이즈 축소 \n#input_shape = (256, 256, 3) #모델에 넣을 사이즈\n\ndef get_image(image_location):\n    #print(image_location)\n    if image_location.endswith('.tiff'): #tiff 일 경우\n        # 가장 작은 사이즈로 변환, 값은 -1, 0 ,1 ,2 ?\n        image = skimage.io.MultiImage(image_location)\n        image = image[-1]\n    else: # jpg일경우\n        image = cv2.imread(image_location)\n    \n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    \n    # input 사이즈로 이미지 리사이즈\n    image = cv2.resize(image, (input_shape[0], input_shape[1]))\n    \n    return image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Function that shuffles annotation rows and chooses batch_size samples\n#sequence = range(len(annotation_file))\n\ndef get_batch_ids(sequence, batch_size):\n    sequence = list(sequence)\n    random.shuffle(sequence)\n    batch = random.sample(sequence, batch_size)\n    return batch","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Basic data generator -> Next: add augmentation = False\n\ndef data_generator(data, batch_size):\n    while True:\n        data = data.reset_index(drop=True)\n        indices = list(data.index)\n\n        batch_ids = get_batch_ids(indices, batch_size)\n        batch = data.iloc[batch_ids]['conv_image_path']\n\n        X = [get_image(x) for x in batch]\n        Y = data[[0, 1, 2, 3, 4, 5]].values[batch_ids]\n\n        # Convert X and Y to arrays\n        X = np.array(X)\n        Y = np.array(Y)\n\n        yield X, Y\n\n# data: should be a pandas DF (train or val) obtained from train_test_split\n# batch_size: is the size of the number of images passed through the net in one step","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Split Train/Test data "},{"metadata":{"trusted":true},"cell_type":"code","source":"# Train -  Validation Split function\ntrain, val = train_test_split(train_df, test_size = 0.3, random_state = 42)\ndisplay(train['conv_image_path'][1506])\n#display(val.head(3))\nprint(len(train),len(val))\n# import matplotlib.pyplot as plt\n# print(train['conv_image_path'][1506])\n# img = cv2.imread(train['conv_image_path'][1506])\n# img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n# print(img.shape)\n\n# plt.imshow(img)\n# plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Some checkpoints\nif cur_env == 'ubuntu':\n    model_path = 'model_history/{epoch:02d}-{loss:.1f}-{val_loss:.1f}.h5'\nelse:\n    model_path = './model.h5'\n\nmodel_checkpoint = ModelCheckpoint(filepath=model_path, monitor = 'val_loss', verbose=0, save_best_only=True, save_weights_only=True)\nearly_stop = EarlyStopping(monitor='val_loss',patience=5,verbose=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Fit Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"EPOCHS = 50 \nBS = 200\n\nhistory = model.fit_generator(generator = data_generator(train, BS),\n                              validation_data = data_generator(val, BS),\n                              epochs = EPOCHS,\n                              verbose = 1,\n                              #steps_per_epoch = len(train)// BS,\\\n                              steps_per_epoch = 20,\n                              validation_steps = 20, \n                              #validation_steps = len(val)// BS,\\\n                              callbacks =[model_checkpoint, early_stop])","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"import matplotlib.pyplot as plt\n# summarize history for loss\nplt.plot(history.history['loss'])\nplt.plot(history.history['val_loss'])\nplt.title('model loss')\nplt.ylabel('loss')\nplt.xlabel('epoch')\nplt.legend(['train', 'test'], loc='upper left')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Predict Test data "},{"metadata":{"trusted":false},"cell_type":"code","source":"if cur_env == 'ubuntu': \n    sample_submission = pd.read_csv('dataset/sample_submission.csv')\nelse: #캐글일 경우\n    sample_submission = pd.read_csv('../input/prostate-cancer-grade-assessment/sample_submission.csv')\n    TEST = Path(\"test_images\")\n    test_ann = pd.read_csv(HOME/'test.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"if os.path.exists(f'../input/prostate-cancer-grade-assessment/test_images/'):\n    print('inference!')\n\n    predictions = []\n    for img_id in test_ann['image_id']:\n        img = str(HOME/TEST/img_id) + \".tiff\"\n        print(img)\n        image = get_image(img)\n        image = image[np.newaxis,:]\n        prediction = model.predict(image)\n        # if we have 1 at multiple locations\n        ind = np.where(prediction == np.amax(prediction))\n        final_prediction = random.sample(list(ind[1]), 1)[0].astype(int)\n        predictions.append(final_prediction)\n\n    sample_submission = pd.DataFrame()\n    sample_submission['image_id'] = test_ann['image_id']\n    sample_submission['isup_grade'] = predictions\n    sample_submission\n\n    sample_submission.to_csv('submission.csv', index=False)\n    sample_submission.head()\nelse:\n    print('Test Images folder does not exist! Save the sample_submission.csv!')\n    sample_submission.to_csv('submission.csv', index=False)","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.10"}},"nbformat":4,"nbformat_minor":4}