Switch to unified view

a b/Notebooks/Training the CNN.ipynb
1
{
2
  "nbformat": 4,
3
  "nbformat_minor": 0,
4
  "metadata": {
5
    "kernelspec": {
6
      "display_name": "Python [conda env:datasci] *",
7
      "language": "python",
8
      "name": "conda-env-datasci-py"
9
    },
10
    "language_info": {
11
      "codemirror_mode": {
12
        "name": "ipython",
13
        "version": 3
14
      },
15
      "file_extension": ".py",
16
      "mimetype": "text/x-python",
17
      "name": "python",
18
      "nbconvert_exporter": "python",
19
      "pygments_lexer": "ipython3",
20
      "version": "3.7.5"
21
    },
22
    "colab": {
23
      "name": "Training the CNN.ipynb",
24
      "provenance": [],
25
      "collapsed_sections": []
26
    }
27
  },
28
  "cells": [
29
    {
30
      "cell_type": "markdown",
31
      "metadata": {
32
        "id": "efCvb66QStgP",
33
        "colab_type": "text"
34
      },
35
      "source": [
36
        "*To run this notebook, please provide the following four file paths:*"
37
      ]
38
    },
39
    {
40
      "cell_type": "code",
41
      "metadata": {
42
        "id": "Iukqj1IzStyn",
43
        "colab_type": "code",
44
        "colab": {}
45
      },
46
      "source": [
47
        "path_to_train = '/path/to/train/images'\n",
48
        "path_to_test = '/path/to/test/images'\n",
49
        "path_to_labels = '/path/to/labels.csv'\n",
50
        "\n",
51
        "path_to_save_model = '/path/to/save/model/to/cnn-checkpoint-{epoch:02d}-{val_accuracy:.2f}.hdf5'"
52
      ],
53
      "execution_count": 0,
54
      "outputs": []
55
    },
56
    {
57
      "cell_type": "markdown",
58
      "metadata": {
59
        "id": "XqBOX3Y4MWs3",
60
        "colab_type": "text"
61
      },
62
      "source": [
63
        "## **Installing & Importing Dependencies**"
64
      ]
65
    },
66
    {
67
      "cell_type": "code",
68
      "metadata": {
69
        "id": "jnq7FwiHKZwY",
70
        "colab_type": "code",
71
        "colab": {}
72
      },
73
      "source": [
74
        "!pip install keras"
75
      ],
76
      "execution_count": 0,
77
      "outputs": []
78
    },
79
    {
80
      "cell_type": "code",
81
      "metadata": {
82
        "id": "OTnWqAwiKZxb",
83
        "colab_type": "code",
84
        "colab": {}
85
      },
86
      "source": [
87
        "import tensorflow as tf\n",
88
        "import pandas as pd\n",
89
        "\n",
90
        "from keras import applications\n",
91
        "from keras import optimizers\n",
92
        "from keras import backend as k \n",
93
        "\n",
94
        "from keras.models import Sequential, Model\n",
95
        "from keras.layers import Dropout, Flatten, Dense, GlobalAveragePooling2D\n",
96
        "from keras.callbacks import ModelCheckpoint, LearningRateScheduler, TensorBoard, EarlyStopping\n",
97
        "from keras.preprocessing.image import ImageDataGenerator"
98
      ],
99
      "execution_count": 0,
100
      "outputs": []
101
    },
102
    {
103
      "cell_type": "code",
104
      "metadata": {
105
        "id": "N60M6zljKZxs",
106
        "colab_type": "code",
107
        "colab": {}
108
      },
109
      "source": [
110
        "# Make sure that GPU is available on the machine\n",
111
        "assert tf.test.is_gpu_available()\n",
112
        "assert tf.test.is_built_with_cuda()"
113
      ],
114
      "execution_count": 0,
115
      "outputs": []
116
    },
117
    {
118
      "cell_type": "markdown",
119
      "metadata": {
120
        "id": "PIErVpE6NHx6",
121
        "colab_type": "text"
122
      },
123
      "source": [
124
        "## **Reading in Data Labels**"
125
      ]
126
    },
127
    {
128
      "cell_type": "code",
129
      "metadata": {
130
        "id": "SGUEeB-cKZx3",
131
        "colab_type": "code",
132
        "colab": {}
133
      },
134
      "source": [
135
        "labels_df = pd.read_csv(path_to_labels)\n",
136
        "\n",
137
        "# For flow_from_dataframe to function, string datatype is required\n",
138
        "labels_df = labels_df.astype(str)"
139
      ],
140
      "execution_count": 0,
141
      "outputs": []
142
    },
143
    {
144
      "cell_type": "code",
145
      "metadata": {
146
        "scrolled": true,
147
        "id": "qShGxNkPKZx7",
148
        "colab_type": "code",
149
        "colab": {},
150
        "outputId": "f6cf0aa8-a383-440a-e4ed-13499e3669af"
151
      },
152
      "source": [
153
        "# Inspect the DataFrame containing the labels\n",
154
        "labels_df.head(3)"
155
      ],
156
      "execution_count": 0,
157
      "outputs": [
158
        {
159
          "output_type": "execute_result",
160
          "data": {
161
            "text/html": [
162
              "<div>\n",
163
              "<style scoped>\n",
164
              "    .dataframe tbody tr th:only-of-type {\n",
165
              "        vertical-align: middle;\n",
166
              "    }\n",
167
              "\n",
168
              "    .dataframe tbody tr th {\n",
169
              "        vertical-align: top;\n",
170
              "    }\n",
171
              "\n",
172
              "    .dataframe thead th {\n",
173
              "        text-align: right;\n",
174
              "    }\n",
175
              "</style>\n",
176
              "<table border=\"1\" class=\"dataframe\">\n",
177
              "  <thead>\n",
178
              "    <tr style=\"text-align: right;\">\n",
179
              "      <th></th>\n",
180
              "      <th>Unnamed: 0</th>\n",
181
              "      <th>ID</th>\n",
182
              "      <th>any</th>\n",
183
              "    </tr>\n",
184
              "  </thead>\n",
185
              "  <tbody>\n",
186
              "    <tr>\n",
187
              "      <th>0</th>\n",
188
              "      <td>0</td>\n",
189
              "      <td>ID_000039fa0.png</td>\n",
190
              "      <td>0</td>\n",
191
              "    </tr>\n",
192
              "    <tr>\n",
193
              "      <th>1</th>\n",
194
              "      <td>1</td>\n",
195
              "      <td>ID_00005679d.png</td>\n",
196
              "      <td>0</td>\n",
197
              "    </tr>\n",
198
              "    <tr>\n",
199
              "      <th>2</th>\n",
200
              "      <td>2</td>\n",
201
              "      <td>ID_00008ce3c.png</td>\n",
202
              "      <td>0</td>\n",
203
              "    </tr>\n",
204
              "  </tbody>\n",
205
              "</table>\n",
206
              "</div>"
207
            ],
208
            "text/plain": [
209
              "  Unnamed: 0                ID any\n",
210
              "0          0  ID_000039fa0.png   0\n",
211
              "1          1  ID_00005679d.png   0\n",
212
              "2          2  ID_00008ce3c.png   0"
213
            ]
214
          },
215
          "metadata": {
216
            "tags": []
217
          },
218
          "execution_count": 19
219
        }
220
      ]
221
    },
222
    {
223
      "cell_type": "markdown",
224
      "metadata": {
225
        "id": "ElzPsVvaODOk",
226
        "colab_type": "text"
227
      },
228
      "source": [
229
        "## **Building Transfer-Learning Model**"
230
      ]
231
    },
232
    {
233
      "cell_type": "markdown",
234
      "metadata": {
235
        "id": "qFQ7sFZjx_ba",
236
        "colab_type": "text"
237
      },
238
      "source": [
239
        "*As our pretrained model, we choose VGG19 with ImageNet weights. Note that include_top = False (otherwise, we would be including VGG19's final 1000-node dense softmax prediction layer)*"
240
      ]
241
    },
242
    {
243
      "cell_type": "code",
244
      "metadata": {
245
        "id": "vh0b4EQtKZyN",
246
        "colab_type": "code",
247
        "colab": {}
248
      },
249
      "source": [
250
        "model = applications.VGG19(weights = \"imagenet\", include_top=False, input_shape = (128, 128, 3))"
251
      ],
252
      "execution_count": 0,
253
      "outputs": []
254
    },
255
    {
256
      "cell_type": "markdown",
257
      "metadata": {
258
        "id": "tszxYuOwyURR",
259
        "colab_type": "text"
260
      },
261
      "source": [
262
        "*Freeze the first three convolutional blocks, leave the last two unfrozen. Thereby, we transfer the model's knowledge of low-level features (like edges and angles) while allowing for it to learn new high-level features (like hemorrhages).*"
263
      ]
264
    },
265
    {
266
      "cell_type": "code",
267
      "metadata": {
268
        "id": "BruLVtwJKZ0g",
269
        "colab_type": "code",
270
        "colab": {}
271
      },
272
      "source": [
273
        "for layer in model.layers[0:12]:\n",
274
        "    layer.trainable = False"
275
      ],
276
      "execution_count": 0,
277
      "outputs": []
278
    },
279
    {
280
      "cell_type": "markdown",
281
      "metadata": {
282
        "id": "g_Kb-J_Qylgz",
283
        "colab_type": "text"
284
      },
285
      "source": [
286
        "*We append our own custom layers to the end of VGG19. Note that a single sigmoid final prediction node is equivalent to two softmax final prediction nodes.*"
287
      ]
288
    },
289
    {
290
      "cell_type": "code",
291
      "metadata": {
292
        "id": "Z7uPdX-8c5eU",
293
        "colab_type": "code",
294
        "colab": {}
295
      },
296
      "source": [
297
        "x = model.output\n",
298
        "x = Flatten()(x)\n",
299
        "\n",
300
        "x = Dense(1000, activation = 'relu')(x)\n",
301
        "x = Dropout(0.5)(x)\n",
302
        "x = Dense(1000, activation = 'relu')(x)\n",
303
        "output = Dense(1, activation = 'sigmoid')(x)\n",
304
        "\n",
305
        "custom_model = Model(inputs = model.input, outputs = output)"
306
      ],
307
      "execution_count": 0,
308
      "outputs": []
309
    },
310
    {
311
      "cell_type": "markdown",
312
      "metadata": {
313
        "id": "X49CwEDJy7tN",
314
        "colab_type": "text"
315
      },
316
      "source": [
317
        "*Compiling the model. The primary metric we care about is recall (that is, the CNN's ability to correctly detect intracranial hemorrhages).*"
318
      ]
319
    },
320
    {
321
      "cell_type": "code",
322
      "metadata": {
323
        "id": "xECXyzILnWTa",
324
        "colab_type": "code",
325
        "colab": {}
326
      },
327
      "source": [
328
        "custom_model.compile(loss = 'binary_crossentropy',\n",
329
        "                     optimizer = optimizers.Adam(lr=0.0001),\n",
330
        "                     metrics=['accuracy',\n",
331
        "                              tf.keras.metrics.Recall(),\n",
332
        "                              tf.keras.metrics.AUC(),\n",
333
        "                              tf.keras.metrics.Precision()])"
334
      ],
335
      "execution_count": 0,
336
      "outputs": []
337
    },
338
    {
339
      "cell_type": "markdown",
340
      "metadata": {
341
        "id": "u7BWA55koyNp",
342
        "colab_type": "text"
343
      },
344
      "source": [
345
        "# **Creating Train & Test Generators**"
346
      ]
347
    },
348
    {
349
      "cell_type": "code",
350
      "metadata": {
351
        "id": "fgTeFSx5olWu",
352
        "colab_type": "code",
353
        "colab": {}
354
      },
355
      "source": [
356
        "# Initializing train & test generators to flow train and test images straight from the folders\n",
357
        "# that they are stored in\n",
358
        "train_datagen = ImageDataGenerator(rescale = 1./255,\n",
359
        "                                   horizontal_flip = True,\n",
360
        "                                   fill_mode = \"nearest\",\n",
361
        "                                   zoom_range = 0.3,\n",
362
        "                                   width_shift_range = 0.3,\n",
363
        "                                   height_shift_range=0.3,\n",
364
        "                                   rotation_range=30)\n",
365
        "\n",
366
        "test_datagen = ImageDataGenerator(rescale = 1./255)"
367
      ],
368
      "execution_count": 0,
369
      "outputs": []
370
    },
371
    {
372
      "cell_type": "code",
373
      "metadata": {
374
        "id": "7-zf69uioyiE",
375
        "colab_type": "code",
376
        "colab": {}
377
      },
378
      "source": [
379
        "# We flow from DataFrames, that is, our images are not stored in class-specific folders---instead,\n",
380
        "# their labels are stored in separate files (specifically, in DataFrames)\n",
381
        "train_generator = train_datagen.flow_from_dataframe(dataframe=labels_df,\n",
382
        "                                                    directory= path_to_train,\n",
383
        "                                                    x_col='ID',\n",
384
        "                                                    y_col='any',\n",
385
        "                                                    target_size=(128, 128),\n",
386
        "                                                    class_mode='binary')\n",
387
        "\n",
388
        "test_generator = test_datagen.flow_from_dataframe(dataframe=labels_df,\n",
389
        "                                                  directory=path_to_test,\n",
390
        "                                                  x_col='ID',\n",
391
        "                                                  y_col='any',\n",
392
        "                                                  target_size=(128, 128),\n",
393
        "                                                  class_mode='binary')"
394
      ],
395
      "execution_count": 0,
396
      "outputs": []
397
    },
398
    {
399
      "cell_type": "markdown",
400
      "metadata": {
401
        "id": "_Xh6lg1tszMo",
402
        "colab_type": "text"
403
      },
404
      "source": [
405
        "# **Fitting the Model**"
406
      ]
407
    },
408
    {
409
      "cell_type": "code",
410
      "metadata": {
411
        "id": "HpcKttO0qdEe",
412
        "colab_type": "code",
413
        "colab": {}
414
      },
415
      "source": [
416
        "# Callbacks\n",
417
        "checkpoint = ModelCheckpoint(path_to_save_model, monitor='val_acc', verbose=1, save_best_only=False, save_weights_only=False, mode='auto', period=1)\n",
418
        "early_stopper = EarlyStopping(monitor='val_acc', min_delta=0, patience=3, verbose=1, mode='auto')"
419
      ],
420
      "execution_count": 0,
421
      "outputs": []
422
    },
423
    {
424
      "cell_type": "code",
425
      "metadata": {
426
        "id": "5e5xPMF2KZ1h",
427
        "colab_type": "code",
428
        "colab": {}
429
      },
430
      "source": [
431
        "# Fitting the model \n",
432
        "custom_model.fit_generator(train_generator,\n",
433
        "                           epochs = 50,\n",
434
        "                           validation_data = test_generator,\n",
435
        "                           callbacks = [checkpoint, early_stopper])"
436
      ],
437
      "execution_count": 0,
438
      "outputs": []
439
    }
440
  ]
441
}