{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 概要\nTensorflow, Kerasによる画像分類の方法について説明します。<br> \nこのnotebookでは簡単なEDAとモデルの学習を行います。<br> \n\n### 1. 準備 \n- ファイル構成\n- ライブラリのインポート\n- 設定\n\n### 2. データ理解\n- データの読み込み\n- 画像データの可視化\n- 各画像に対してのラベル比率の確認\n\n### 3. モデリング\n- データ分割方法の定義\n- データ前処理の定義\n- 分類モデルの定義\n- モデルの学習（層化k分割交差検証）\n - 損失関数の定義<br>\n - 最適化手法の定義<br>\n - スコアの算出<br>\n\n### 4. 推論\nhttps://www.kaggle.com/takuyatone/cassava-keras-tf-baseline-inference","metadata":{}},{"cell_type":"markdown","source":"# 1. 準備 ","metadata":{}},{"cell_type":"markdown","source":"## ファイル構成","metadata":{}},{"cell_type":"code","source":"!ls /kaggle/input/cassava-leaf-disease-classification","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:23:24.115674Z","iopub.execute_input":"2021-07-14T01:23:24.116034Z","iopub.status.idle":"2021-07-14T01:23:24.761847Z","shell.execute_reply.started":"2021-07-14T01:23:24.115994Z","shell.execute_reply":"2021-07-14T01:23:24.760917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ライブラリのインポート","metadata":{}},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import accuracy_score\n\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing import image\nfrom tensorflow.keras.models import Sequential, Model,load_model\nfrom tensorflow.keras.applications.vgg16 import VGG16,preprocess_input\nfrom tensorflow.keras.applications import EfficientNetB0\nfrom tensorflow.keras.applications.resnet50 import ResNet50\nfrom tensorflow.keras.layers import Conv2D, MaxPool2D, GlobalAveragePooling2D, Flatten, Dense, Dropout\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint\nimport cv2\n\nprint('tensorflow version:', tf.__version__)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:24:15.174525Z","iopub.execute_input":"2021-07-14T01:24:15.174851Z","iopub.status.idle":"2021-07-14T01:24:20.81426Z","shell.execute_reply.started":"2021-07-14T01:24:15.174819Z","shell.execute_reply":"2021-07-14T01:24:20.813461Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# seed固定\ndef seed_everything(seed=1234):\n    #random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    tf.random.set_seed(seed)\n    \nseed_everything(seed=42)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:24:44.860503Z","iopub.execute_input":"2021-07-14T01:24:44.860882Z","iopub.status.idle":"2021-07-14T01:24:44.868382Z","shell.execute_reply.started":"2021-07-14T01:24:44.860852Z","shell.execute_reply":"2021-07-14T01:24:44.867587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# GPUの確認\nfrom tensorflow.python.client import device_lib\nprint(device_lib.list_local_devices())","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:24:54.035964Z","iopub.execute_input":"2021-07-14T01:24:54.036287Z","iopub.status.idle":"2021-07-14T01:24:56.004669Z","shell.execute_reply.started":"2021-07-14T01:24:54.036258Z","shell.execute_reply":"2021-07-14T01:24:56.003469Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 設定","metadata":{}},{"cell_type":"code","source":"class CFG:\n    debug=True\n    size=64\n    epochs=10\n    batch_size=64\n    val_batch_size=128\n    seed=42\n    target_size=5\n    target_col='label'\n    n_fold=5\n    trn_fold=[0, 1, 2, 3, 4]","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:54:40.300534Z","iopub.execute_input":"2021-07-14T01:54:40.300871Z","iopub.status.idle":"2021-07-14T01:54:40.305395Z","shell.execute_reply.started":"2021-07-14T01:54:40.300842Z","shell.execute_reply":"2021-07-14T01:54:40.30458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#  2. データ理解","metadata":{}},{"cell_type":"markdown","source":"## データの読み込み","metadata":{}},{"cell_type":"code","source":"if os.path.exists('/kaggle/input'):\n    # kaggle環境\n    DATA_DIR = '/kaggle/input/cassava-leaf-disease-classification/'\nelse:\n    # ローカル環境\n    DATA_DIR = '../../data/raw/'\n    \nOUTPUT_DIR = './'\nif not os.path.exists(OUTPUT_DIR):\n    os.makedirs(OUTPUT_DIR)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:29:38.090729Z","iopub.execute_input":"2021-07-14T01:29:38.091089Z","iopub.status.idle":"2021-07-14T01:29:38.098298Z","shell.execute_reply.started":"2021-07-14T01:29:38.091058Z","shell.execute_reply":"2021-07-14T01:29:38.097585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv(DATA_DIR + 'train.csv')\ntest = pd.read_csv(DATA_DIR + 'sample_submission.csv')\nlabel_map = pd.read_json(DATA_DIR + 'label_num_to_disease_map.json', \n                         orient='index')\ndisplay(train.head())\ndisplay(test.head())\ndisplay(label_map)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:29:43.571043Z","iopub.execute_input":"2021-07-14T01:29:43.571355Z","iopub.status.idle":"2021-07-14T01:29:43.804558Z","shell.execute_reply.started":"2021-07-14T01:29:43.571326Z","shell.execute_reply":"2021-07-14T01:29:43.803864Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 画像データの可視化","metadata":{}},{"cell_type":"code","source":"# 画像の読み込み\nimage = plt.imread(DATA_DIR + 'train_images/1000015157.jpg')\n\n# 画像の表示\nplt.imshow(image);","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:30:31.576556Z","iopub.execute_input":"2021-07-14T01:30:31.577005Z","iopub.status.idle":"2021-07-14T01:30:31.940188Z","shell.execute_reply.started":"2021-07-14T01:30:31.576969Z","shell.execute_reply":"2021-07-14T01:30:31.939305Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label0_images = train[train['label'] == 0]['image_id'].to_list()\nlabel1_images = train[train['label'] == 1]['image_id'].to_list()\nlabel2_images = train[train['label'] == 2]['image_id'].to_list()\nlabel3_images = train[train['label'] == 3]['image_id'].to_list()\nlabel4_images = train[train['label'] == 4]['image_id'].to_list()","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:30:42.033442Z","iopub.execute_input":"2021-07-14T01:30:42.033894Z","iopub.status.idle":"2021-07-14T01:30:42.047256Z","shell.execute_reply.started":"2021-07-14T01:30:42.033849Z","shell.execute_reply":"2021-07-14T01:30:42.046458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def showImages(images):\n\n    random_images = [np.random.choice(images) for i in range(8)]\n\n    plt.figure(figsize=(12,5))\n\n    for i in range(8):\n        plt.subplot(2, 4, i + 1)\n        img = plt.imread(DATA_DIR + \"/train_images/\"+ random_images[i])\n        plt.imshow(img)\n        plt.axis('off')\n\n    plt.tight_layout()","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:30:46.809624Z","iopub.execute_input":"2021-07-14T01:30:46.809951Z","iopub.status.idle":"2021-07-14T01:30:46.8159Z","shell.execute_reply.started":"2021-07-14T01:30:46.809921Z","shell.execute_reply":"2021-07-14T01:30:46.814613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# label 0\nshowImages(label0_images)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:31:04.970867Z","iopub.execute_input":"2021-07-14T01:31:04.971421Z","iopub.status.idle":"2021-07-14T01:31:06.103165Z","shell.execute_reply.started":"2021-07-14T01:31:04.971372Z","shell.execute_reply":"2021-07-14T01:31:06.102324Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# label 1\nshowImages(label1_images)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:30:49.533419Z","iopub.execute_input":"2021-07-14T01:30:49.533876Z","iopub.status.idle":"2021-07-14T01:30:50.458371Z","shell.execute_reply.started":"2021-07-14T01:30:49.533841Z","shell.execute_reply":"2021-07-14T01:30:50.45761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# label 2\nshowImages(label2_images)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:30:50.459488Z","iopub.execute_input":"2021-07-14T01:30:50.459919Z","iopub.status.idle":"2021-07-14T01:30:51.369594Z","shell.execute_reply.started":"2021-07-14T01:30:50.459877Z","shell.execute_reply":"2021-07-14T01:30:51.368579Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# label 3\nshowImages(label3_images)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:30:51.371343Z","iopub.execute_input":"2021-07-14T01:30:51.371687Z","iopub.status.idle":"2021-07-14T01:30:52.34054Z","shell.execute_reply.started":"2021-07-14T01:30:51.371654Z","shell.execute_reply":"2021-07-14T01:30:52.33938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# label 4\nshowImages(label4_images)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:33:09.99452Z","iopub.execute_input":"2021-07-14T01:33:09.995099Z","iopub.status.idle":"2021-07-14T01:33:10.942371Z","shell.execute_reply.started":"2021-07-14T01:33:09.99505Z","shell.execute_reply":"2021-07-14T01:33:10.941589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 各画像に対してのラベル比率の確認","metadata":{}},{"cell_type":"code","source":"sns.distplot(train['label'], kde=False)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:36:50.338348Z","iopub.execute_input":"2021-07-14T01:36:50.338715Z","iopub.status.idle":"2021-07-14T01:36:50.54632Z","shell.execute_reply.started":"2021-07-14T01:36:50.338684Z","shell.execute_reply":"2021-07-14T01:36:50.545519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. モデリング","metadata":{}},{"cell_type":"markdown","source":"## データ分割方法の定義","metadata":{}},{"cell_type":"code","source":"if CFG.debug:\n    train = train[:3000]\n\ntrain['label'] = train['label'].astype(str)\nfolds = train.copy()\nFold = StratifiedKFold(n_splits=CFG.n_fold, shuffle=True, random_state=CFG.seed)\nfor n, (train_index, val_index) in enumerate(Fold.split(folds, folds[CFG.target_col])):\n    folds.loc[val_index, 'fold'] = int(n)\nfolds['fold'] = folds['fold'].astype(int)\nprint(folds.groupby(['fold', CFG.target_col]).size())","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:54:54.862476Z","iopub.execute_input":"2021-07-14T01:54:54.862816Z","iopub.status.idle":"2021-07-14T01:54:54.887572Z","shell.execute_reply.started":"2021-07-14T01:54:54.862787Z","shell.execute_reply":"2021-07-14T01:54:54.88654Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"folds.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:38:50.670384Z","iopub.execute_input":"2021-07-14T01:38:50.670743Z","iopub.status.idle":"2021-07-14T01:38:50.681416Z","shell.execute_reply.started":"2021-07-14T01:38:50.67071Z","shell.execute_reply":"2021-07-14T01:38:50.680552Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## データ前処理の定義","metadata":{}},{"cell_type":"code","source":"# https://keras.io/ja/preprocessing/image/\ntrain_datagen = ImageDataGenerator(rescale=1./255,\n                                   rotation_range=20,\n                                   width_shift_range=0.2,\n                                   height_shift_range=0.2,\n                                   shear_range=0.1,\n                                   zoom_range=0.2,\n                                   horizontal_flip=True)\nval_datagen = ImageDataGenerator(rescale=1./255)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:49:22.839725Z","iopub.execute_input":"2021-07-14T01:49:22.840055Z","iopub.status.idle":"2021-07-14T01:49:22.84654Z","shell.execute_reply.started":"2021-07-14T01:49:22.840025Z","shell.execute_reply":"2021-07-14T01:49:22.845247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"generator = train_datagen.flow_from_dataframe(dataframe = train,\n                                              directory = DATA_DIR + \"train_images\",\n                                              x_col = 'image_id',\n                                              y_col = 'label',\n                                              target_size = (CFG.size, CFG.size),\n                                              color_mode = \"rgb\",\n                                              class_mode = \"categorical\",\n                                              batch_size = 1,\n                                              shuffle = True,\n                                              subset = 'training')","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:49:40.385834Z","iopub.execute_input":"2021-07-14T01:49:40.386158Z","iopub.status.idle":"2021-07-14T01:49:41.997273Z","shell.execute_reply.started":"2021-07-14T01:49:40.386126Z","shell.execute_reply":"2021-07-14T01:49:41.995676Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ジェネレーターで8枚生成して、表示する。\nplt.figure(figsize=(10, 5))\nfor i in range(8):\n    batches = next(generator)  # (NumBatches, Height, Width, Channels) の4次元データを返す。\n    # 画像として表示するため、3次元データにする。\n    gen_img = batches[0][0]\n\n    plt.subplot(2, 4, i + 1)\n    plt.imshow(gen_img)\n    plt.axis('off')\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:49:57.432898Z","iopub.execute_input":"2021-07-14T01:49:57.43323Z","iopub.status.idle":"2021-07-14T01:49:58.091645Z","shell.execute_reply.started":"2021-07-14T01:49:57.433199Z","shell.execute_reply":"2021-07-14T01:49:58.089962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 分類モデルの定義","metadata":{}},{"cell_type":"code","source":"def vgg16_model(num_classes=None):\n\n    base_model = VGG16(weights='imagenet', include_top=False, input_shape=(CFG.size, CFG.size, 3), pooling='avg')\n    output = Dense(num_classes, activation='softmax')(base_model.output)\n    model = Model(base_model.input, output)\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:52:18.849056Z","iopub.execute_input":"2021-07-14T01:52:18.849387Z","iopub.status.idle":"2021-07-14T01:52:18.855452Z","shell.execute_reply.started":"2021-07-14T01:52:18.849356Z","shell.execute_reply":"2021-07-14T01:52:18.853681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model=vgg16_model(CFG.target_size)\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:52:20.107236Z","iopub.execute_input":"2021-07-14T01:52:20.107582Z","iopub.status.idle":"2021-07-14T01:52:21.408012Z","shell.execute_reply.started":"2021-07-14T01:52:20.107549Z","shell.execute_reply":"2021-07-14T01:52:21.407143Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## モデルの学習","metadata":{}},{"cell_type":"code","source":"def train_loop(folds, fold):\n\n    print(f\"========== fold: {fold} training ==========\")\n\n    # ====================================================\n    # train data, validation data\n    # ====================================================\n    trn_idx = folds[folds['fold'] != fold].index\n    val_idx = folds[folds['fold'] == fold].index\n\n    train_folds = folds.loc[trn_idx].reset_index(drop=True)\n    valid_folds = folds.loc[val_idx].reset_index(drop=True)\n\n    # ====================================================\n    # generator\n    # ====================================================\n    \n    train_datagen = ImageDataGenerator(rescale=1./255,\n                                   rotation_range=20,\n                                   width_shift_range=0.2,\n                                   height_shift_range=0.2,\n                                   shear_range=0.2,\n                                   zoom_range=0.2,\n                                   horizontal_flip=True)\n    val_datagen = ImageDataGenerator(rescale=1./255)\n    \n    train_generator = train_datagen.flow_from_dataframe(dataframe = train_folds,\n                                                        directory = DATA_DIR + \"train_images\",\n                                                        x_col = 'image_id',\n                                                        y_col = 'label',\n                                                        target_size = (CFG.size, CFG.size),\n                                                        color_mode = \"rgb\",\n                                                        class_mode = \"categorical\",\n                                                        batch_size = CFG.batch_size,\n                                                        shuffle = True)\n\n    val_generator = val_datagen.flow_from_dataframe(dataframe = valid_folds,\n                                                    directory = DATA_DIR + \"train_images\",\n                                                    x_col = 'image_id',\n                                                    y_col = 'label',\n                                                    target_size = (CFG.size, CFG.size),\n                                                    color_mode = \"rgb\",\n                                                    class_mode = \"categorical\",\n                                                    batch_size = CFG.val_batch_size,\n                                                    shuffle = False)\n \n    # ====================================================\n    # callbacks\n    # ====================================================  \n    save_model = tf.keras.callbacks.ModelCheckpoint(\n                    f'fold-{fold}.h5', monitor='val_loss', verbose=0, save_best_only=True,\n                    save_weights_only=True, mode='min', save_freq='epoch')\n\n    \n    \n    early_stopping = tf.keras.callbacks.EarlyStopping(monitor='val_loss',patience=5, min_delta = 0.0001,\n                                                      verbose=1, mode='min'),\n    \n    reduce_lr_op = ReduceLROnPlateau(monitor = 'val_loss', factor = 0.5, patience = 2,\n                                     verbose = 1, min_delta = 0.0001, mode = 'min')\n    \n    callbacks = [save_model, early_stopping, reduce_lr_op]\n\n    # ====================================================\n    # optimizer #SGD\n    # ====================================================   \n    optimizer = Adam(lr=0.0001)\n    \n    # ====================================================\n    # loss\n    # ====================================================\n    loss = tf.keras.losses.CategoricalCrossentropy(from_logits = False, label_smoothing=0.0001,name='categorical_crossentropy' )\n    \n    # ====================================================\n    # model\n    # ====================================================\n    model = vgg16_model(num_classes=CFG.target_size)    \n    model.compile(optimizer = optimizer, loss = loss, metrics = ['categorical_accuracy'])\n\n    # ====================================================\n    # training\n    # ====================================================\n    train_steps = train_generator.n//train_generator.batch_size\n    val_steps = val_generator.n//val_generator.batch_size\n    \n    \n    history = model.fit(\n                    train_generator,\n                    steps_per_epoch=train_steps,\n                    epochs=CFG.epochs,\n                    validation_data=val_generator,\n                    callbacks=callbacks,\n                    validation_steps=val_steps\n                    )\n\n    # ====================================================\n    # predict\n    # ====================================================\n    print('Loading best model...')\n    model.load_weights(f'fold-{fold}.h5')\n    \n    print('Predicting OOF...')\n    pred = model.predict(val_generator, verbose=1)\n    \n    valid_folds[[str(c) for c in range(5)]] = pred\n    valid_folds['preds'] = pred.argmax(1) \n    \n    # ====================================================\n    # plot\n    # ====================================================   \n    plt.figure(figsize=(10,3))\n    plt.plot(np.arange(len(history.history['categorical_accuracy'])),history.history['categorical_accuracy'],'-o',label='Train ACC',color='#ff7f0e')\n    plt.plot(np.arange(len(history.history['val_categorical_accuracy'])),history.history['val_categorical_accuracy'],'-o',label='Val ACC',color='#1f77b4')\n    x = np.argmax( history.history['val_categorical_accuracy'] ); y = np.max( history.history['val_categorical_accuracy'] )\n    xdist = plt.xlim()[1] - plt.xlim()[0]; ydist = plt.ylim()[1] - plt.ylim()[0]\n    plt.scatter(x,y,s=200,color='#1f77b4'); plt.text(x-0.03*xdist,y-0.13*ydist,'max acc\\n%.2f'%y,size=14)\n    plt.ylabel('ACC',size=14); plt.xlabel('Epoch',size=14)\n    plt.legend(loc=2)\n    plt2 = plt.gca().twinx()\n    plt2.plot(np.arange(len(history.history['loss'])),history.history['loss'],'-o',label='Train Loss',color='#2ca02c')\n    plt2.plot(np.arange(len(history.history['val_loss'])),history.history['val_loss'],'-o',label='Val Loss',color='#d62728')\n    x = np.argmin( history.history['val_loss'] ); y = np.min( history.history['val_loss'] )\n    ydist = plt.ylim()[1] - plt.ylim()[0]\n    plt.scatter(x,y,s=200,color='#d62728'); plt.text(x-0.03*xdist,y+0.05*ydist,'min loss',size=14)\n    plt.ylabel('Loss',size=14)\n    plt.title(f'FOLD {fold} - Image Size {CFG.size}',size=16)\n    plt.legend(loc=3)\n    plt.show()\n\n    return valid_folds","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:55:17.2654Z","iopub.execute_input":"2021-07-14T01:55:17.265837Z","iopub.status.idle":"2021-07-14T01:55:17.304245Z","shell.execute_reply.started":"2021-07-14T01:55:17.265798Z","shell.execute_reply":"2021-07-14T01:55:17.303113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"folds.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:55:18.500694Z","iopub.execute_input":"2021-07-14T01:55:18.501011Z","iopub.status.idle":"2021-07-14T01:55:18.513966Z","shell.execute_reply.started":"2021-07-14T01:55:18.50098Z","shell.execute_reply":"2021-07-14T01:55:18.513191Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_score(y_true, y_pred):\n    return accuracy_score(y_true, y_pred)\n\n\ndef get_result(result_df):\n    preds = result_df['preds'].values\n    labels = result_df[CFG.target_col].astype(int).values\n    score = get_score(labels, preds)\n    print(f'Score: {score:<.5f}')\n\n\n# train \noof_df = pd.DataFrame()\nfor fold in range(CFG.n_fold):\n    if fold in CFG.trn_fold:\n        _oof_df = train_loop(folds, fold)\n        oof_df = pd.concat([oof_df, _oof_df])\n        print(f\"========== fold: {fold} result ==========\")\n        get_result(_oof_df)\n# CV result\nprint(f\"========== CV ==========\")\nget_result(oof_df)\n# save result\noof_df.to_csv(OUTPUT_DIR+'oof_df.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T01:55:19.310919Z","iopub.execute_input":"2021-07-14T01:55:19.311218Z","iopub.status.idle":"2021-07-14T02:16:33.110617Z","shell.execute_reply.started":"2021-07-14T01:55:19.311189Z","shell.execute_reply":"2021-07-14T02:16:33.109613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}