{"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":"code","source":"import tensorflow as tf\nimport time\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom PIL import Image\n\ndata_frame = pd.read_csv('/kaggle/input/rsna-breast-cancer-detection/train.csv')\n\ndata_frame['path'] = \"/kaggle/input/breast-images-png/\" + data_frame.patient_id.astype(str) + \"_\" + data_frame.image_id.astype(str) + \".png\"","metadata":{"execution":{"iopub.status.busy":"2023-04-06T20:27:09.153701Z","iopub.execute_input":"2023-04-06T20:27:09.154296Z","iopub.status.idle":"2023-04-06T20:27:09.345067Z","shell.execute_reply.started":"2023-04-06T20:27:09.15424Z","shell.execute_reply":"2023-04-06T20:27:09.343785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"strategy = tf.distribute.MirroredStrategy()\nprint('Number of devices: {}'.format(strategy.num_replicas_in_sync))\n\nIMG_SIZE = 256\n\nBATCH_SIZE = 32*strategy.num_replicas_in_sync\nAUTO = tf.data.AUTOTUNE\n\ndef load_dataset(df):\n    paths = df.path.values\n    labels = df.cancer.values\n    def decode_img(paths, labels):\n        raw = tf.io.read_file(paths)\n        img = tf.io.decode_png(raw, channels=3)\n        img = tf.image.resize(img, (IMG_SIZE, IMG_SIZE))\n        img = tf.reshape(img, (IMG_SIZE, IMG_SIZE, 3))\n        return img, tf.cast(labels, tf.float32)\n    ds = tf.data.Dataset.from_tensor_slices((paths, labels))\n    ds = ds.map(decode_img, num_parallel_calls=AUTO)\n    return ds\n\n\ndef get_dataset(df):\n    ds = load_dataset(df)\n    options = tf.data.Options()\n    options.experimental_distribute.auto_shard_policy = tf.data.experimental.AutoShardPolicy.OFF\n    ds = ds.with_options(options)\n    ds = ds.batch(BATCH_SIZE)\n    ds = ds.prefetch(AUTO)\n    return ds","metadata":{"execution":{"iopub.status.busy":"2023-04-06T20:27:10.397675Z","iopub.execute_input":"2023-04-06T20:27:10.398149Z","iopub.status.idle":"2023-04-06T20:27:10.415233Z","shell.execute_reply.started":"2023-04-06T20:27:10.398108Z","shell.execute_reply":"2023-04-06T20:27:10.414163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(10,10))\nfor i in range(25):\n    plt.subplot(5,5,i+1)\n    plt.xticks([])\n    plt.yticks([])\n    plt.grid(False)\n    plt.imshow(Image.open(data_frame.path.values[i]), cmap=plt.cm.binary)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-06T20:27:44.264378Z","iopub.execute_input":"2023-04-06T20:27:44.264882Z","iopub.status.idle":"2023-04-06T20:27:45.85159Z","shell.execute_reply.started":"2023-04-06T20:27:44.264838Z","shell.execute_reply":"2023-04-06T20:27:45.85017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_model():\n    model = tf.keras.Sequential([\n        tf.keras.layers.Conv2D(32, [3, 3], activation='sigmoid', input_shape=(256, 256, 3), padding=\"same\"),\n        tf.keras.layers.Conv2D(64, [3, 3], activation='sigmoid', padding=\"same\"),\n        tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),\n        tf.keras.layers.Dropout(0.25),\n        tf.keras.layers.Flatten(),\n        tf.keras.layers.Dense(128, activation='sigmoid'),\n        tf.keras.layers.Dropout(0.5),\n        tf.keras.layers.Dense(10, activation='softmax')\n    ])\n\n    model.compile(loss=tf.keras.losses.SparseCategoricalCrossentropy(),\n                optimizer=tf.keras.optimizers.Adam(),\n                metrics=['accuracy'])\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2023-04-06T20:39:07.769472Z","iopub.execute_input":"2023-04-06T20:39:07.769973Z","iopub.status.idle":"2023-04-06T20:39:07.780489Z","shell.execute_reply.started":"2023-04-06T20:39:07.769931Z","shell.execute_reply":"2023-04-06T20:39:07.778894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# buiding a model inside the strategy scope\nwith strategy.scope():\n    multi_gpu_model = build_model()\n    \nmulti_gpu_model.summary()\n\n# buiding a regular model on 1 GPU for performance comparison\nregular_model = build_model()","metadata":{"execution":{"iopub.status.busy":"2023-04-06T20:39:09.287711Z","iopub.execute_input":"2023-04-06T20:39:09.288335Z","iopub.status.idle":"2023-04-06T20:39:11.916973Z","shell.execute_reply.started":"2023-04-06T20:39:09.288264Z","shell.execute_reply":"2023-04-06T20:39:11.915401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training on 2 GPUs","metadata":{}},{"cell_type":"code","source":"EPOCHS = 5\nBATCH_SIZE = 32*strategy.num_replicas_in_sync\n\ntrain_data = get_dataset(data_frame)\n\nstart_time_multi = time.time()\nhistory_multi = multi_gpu_model.fit(train_data, epochs=EPOCHS)\nfinal_time_multi = time.time() - start_time_multi\nprint(\"--- %s seconds ---\" % (final_time_multi))","metadata":{"execution":{"iopub.status.busy":"2023-04-06T20:39:32.064484Z","iopub.execute_input":"2023-04-06T20:39:32.064922Z","iopub.status.idle":"2023-04-06T20:39:34.815989Z","shell.execute_reply.started":"2023-04-06T20:39:32.064886Z","shell.execute_reply":"2023-04-06T20:39:34.813478Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training on 1 GPU","metadata":{}},{"cell_type":"code","source":"BATCH_SIZE = 32\nregular_train_data = get_dataset(data_frame)\n\n\nstart_time_single = time.time()\nhistory_regular = regular_model.fit(regular_train_data, epochs=EPOCHS)\nfinal_time_single = time.time() - start_time_single\nprint(\"--- %s seconds ---\" % (final_time_single))","metadata":{"execution":{"iopub.status.busy":"2023-04-06T20:39:40.090383Z","iopub.execute_input":"2023-04-06T20:39:40.090883Z","iopub.status.idle":"2023-04-06T20:39:55.687223Z","shell.execute_reply.started":"2023-04-06T20:39:40.090841Z","shell.execute_reply":"2023-04-06T20:39:55.685664Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Performance Comparison\n## Accuracy Comparison","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfig, axs = plt.subplots(1, 2,figsize=(18,8))\naxs[0].plot(history_multi.history['accuracy'],label = '2 GPUs')\naxs[0].plot(history_regular.history['accuracy'],label = '1 GPU')\naxs[0].set_title('model accuracy')\naxs[0].set_ylabel('accuracy')\naxs[0].set_xlabel('epoch')\n\n\naxs[1].plot(history_multi.history['loss'],label = '2 GPUs')\naxs[1].plot(history_regular.history['loss'],label = '1 GPU')\naxs[1].set_title('model loss')\naxs[1].set_ylabel('loss')\naxs[1].set_xlabel('epoch')\n\nplt.legend()\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Computing Power Comparison","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(18,8))\nnb_images = len(train_data)\nplt.plot(['1GPU','2 GPUS'],[nb_images/(final_time_single/EPOCHS),nb_images/(final_time_multi/EPOCHS)],label = 'real scaling')\nplt.plot(['1GPU','2 GPUS'],[nb_images/(final_time_single/EPOCHS),2*nb_images/(final_time_single/EPOCHS)],label = 'theoritical scaling')\nplt.title('Nb of images processed per EPOCH')\nplt.ylabel('Nb of images processed per epoch')\nplt.xlabel('nb of GPUs')\nplt.legend()\nprint(\"We achieve %s percent of scaling\"% round((final_time_single/(2*final_time_multi))*100,2))","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}