{"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":"Обучите нейронную сеть любой архитектуры, которой не было на курсе, либо нейронную сеть\nразобранной архитектуры, но на том датасете, которого не было на уроках. Сделайте анализ того, что\nвам помогло в улучшения работы нейронной сети","metadata":{}},{"cell_type":"markdown","source":"Буду работать с датасетом Caravana Cars и попробую обучить нейронную сеть U-net на предобученной модели на ResNet50","metadata":{}},{"cell_type":"markdown","source":"### Загрузка библиотек:","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport cv2\nimport keras\n\nfrom tensorflow.keras.applications.resnet50 import ResNet50, preprocess_input\n\nfrom keras.models import Model\nfrom keras.layers import Dense, GlobalAveragePooling2D, Dropout, UpSampling2D, Conv2D, MaxPooling2D, Activation, Concatenate\nfrom keras import backend as K","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:02.510712Z","iopub.execute_input":"2022-11-24T09:07:02.511307Z","iopub.status.idle":"2022-11-24T09:07:02.522835Z","shell.execute_reply.started":"2022-11-24T09:07:02.511265Z","shell.execute_reply":"2022-11-24T09:07:02.521810Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# загрузка и распаковка данных\n!unzip -oq /kaggle/input/carvana-image-masking-challenge/train.zip\n!unzip -oq /kaggle/input/carvana-image-masking-challenge/train_masks.zip\n!unzip -oq /kaggle/input/carvana-image-masking-challenge/train_masks.csv.zip","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:02.527111Z","iopub.execute_input":"2022-11-24T09:07:02.528458Z","iopub.status.idle":"2022-11-24T09:07:12.044167Z","shell.execute_reply.started":"2022-11-24T09:07:02.528418Z","shell.execute_reply":"2022-11-24T09:07:12.042789Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('./train_masks.csv')\ndf.shape","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:12.046591Z","iopub.execute_input":"2022-11-24T09:07:12.048249Z","iopub.status.idle":"2022-11-24T09:07:12.394467Z","shell.execute_reply.started":"2022-11-24T09:07:12.048202Z","shell.execute_reply":"2022-11-24T09:07:12.393274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#разделение датасета на трейн и валидацию\n\nval_size = 0.2\nval_split = int(val_size * df.shape[0])\n\ntrain_df = df[:-val_split]\nval_df = df[-val_split:]\n\ntrain_df.shape, val_df.shape","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:12.396399Z","iopub.execute_input":"2022-11-24T09:07:12.396788Z","iopub.status.idle":"2022-11-24T09:07:12.405219Z","shell.execute_reply.started":"2022-11-24T09:07:12.396748Z","shell.execute_reply":"2022-11-24T09:07:12.404103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head(3)","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:12.408397Z","iopub.execute_input":"2022-11-24T09:07:12.409312Z","iopub.status.idle":"2022-11-24T09:07:12.420679Z","shell.execute_reply.started":"2022-11-24T09:07:12.409276Z","shell.execute_reply":"2022-11-24T09:07:12.419505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"val_df.head(3)","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:12.422809Z","iopub.execute_input":"2022-11-24T09:07:12.423201Z","iopub.status.idle":"2022-11-24T09:07:12.432157Z","shell.execute_reply.started":"2022-11-24T09:07:12.423164Z","shell.execute_reply":"2022-11-24T09:07:12.431031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# функция для декодирования rle-строки\n\ndef rle_decode(mask_rle, shape=(1280, 1918, 1)):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (height,width) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n    '''\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n\n    s = mask_rle.split()\n    \n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    \n    ends = starts + lengths    \n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n        \n    img = img.reshape(shape)\n    return img","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:12.433868Z","iopub.execute_input":"2022-11-24T09:07:12.434663Z","iopub.status.idle":"2022-11-24T09:07:12.443123Z","shell.execute_reply.started":"2022-11-24T09:07:12.434565Z","shell.execute_reply":"2022-11-24T09:07:12.442200Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_name, mask_rle = train_df.iloc[0]\n\nimg = cv2.imread(f'./train/{img_name}')\nmask = rle_decode(mask_rle)","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:12.444232Z","iopub.execute_input":"2022-11-24T09:07:12.444533Z","iopub.status.idle":"2022-11-24T09:07:12.479553Z","shell.execute_reply.started":"2022-11-24T09:07:12.444499Z","shell.execute_reply":"2022-11-24T09:07:12.478738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# картинка и соответствующая ей маска\nfig, ax = plt.subplots(1, 2, figsize=(25, 25))\nax[0].imshow(img)\nax[1].imshow(mask)\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:12.481464Z","iopub.execute_input":"2022-11-24T09:07:12.481789Z","iopub.status.idle":"2022-11-24T09:07:13.406761Z","shell.execute_reply.started":"2022-11-24T09:07:12.481756Z","shell.execute_reply":"2022-11-24T09:07:13.405042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# создадим функцию по предобработке изображений и масок и приведению их к размеру 256*256, а также батчи для обучения модели\ndef keras_generator(df, batch_size, preprocess_input=None):\n    while True:\n        X_batch = []\n        y_batch = []\n        \n        for i in range(batch_size):\n            img_name, mask_rle = df.sample(1).values[0]\n            img = cv2.imread(f'./train/{img_name}')\n            mask = rle_decode(mask_rle)\n            \n            img = cv2.resize(img, (256, 256))\n            mask = cv2.resize(mask, (256, 256))\n            \n            X_batch += [img]\n            y_batch += [mask]\n\n        if preprocess_input:\n            X_batch = preprocess_input(np.array(X_batch))\n        else:\n            X_batch = np.array(X_batch) / 255.0\n            \n        y_batch = np.array(y_batch, dtype='float')\n\n        yield X_batch, y_batch","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:13.408478Z","iopub.execute_input":"2022-11-24T09:07:13.409388Z","iopub.status.idle":"2022-11-24T09:07:13.419368Z","shell.execute_reply.started":"2022-11-24T09:07:13.409326Z","shell.execute_reply":"2022-11-24T09:07:13.417870Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for X, y in keras_generator(val_df, batch_size=32):\n    print(X.shape, y.shape)\n    break","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:13.430120Z","iopub.execute_input":"2022-11-24T09:07:13.431008Z","iopub.status.idle":"2022-11-24T09:07:15.031553Z","shell.execute_reply.started":"2022-11-24T09:07:13.430933Z","shell.execute_reply":"2022-11-24T09:07:15.030362Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Создание модели","metadata":{}},{"cell_type":"code","source":"# базовая модель ResNet50 без последних слоев\n\nbase_model = ResNet50(weights='imagenet', input_shape=(256, 256, 3), include_top=False)\n \nbase_out = base_model.output\nbase_out","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:15.033174Z","iopub.execute_input":"2022-11-24T09:07:15.033954Z","iopub.status.idle":"2022-11-24T09:07:16.367856Z","shell.execute_reply.started":"2022-11-24T09:07:15.033899Z","shell.execute_reply":"2022-11-24T09:07:16.366890Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_model.summary()","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:16.369213Z","iopub.execute_input":"2022-11-24T09:07:16.369578Z","iopub.status.idle":"2022-11-24T09:07:16.394865Z","shell.execute_reply.started":"2022-11-24T09:07:16.369541Z","shell.execute_reply":"2022-11-24T09:07:16.393646Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#  выбираем слои для проброса в U-Net (выбираем те, что идут после функции активации)\n\nconv1 = base_model.get_layer('conv1_relu').output  # (128, 128, 64)\nconv2 = base_model.get_layer('conv2_block1_out').output  # (64, 64, 256)\nconv3 = base_model.get_layer('conv3_block1_1_relu').output  # (32, 32, 128)\nconv4 = base_model.get_layer('conv4_block2_2_relu').output  # (16, 16, 256)\nconv5 = base_model.get_layer('conv5_block1_2_relu').output  # (8, 8, 512)","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:16.396210Z","iopub.execute_input":"2022-11-24T09:07:16.397106Z","iopub.status.idle":"2022-11-24T09:07:16.405895Z","shell.execute_reply.started":"2022-11-24T09:07:16.397071Z","shell.execute_reply":"2022-11-24T09:07:16.404980Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"up1 = UpSampling2D(2, interpolation='bilinear')(conv5)\nconc_1 = Concatenate()([up1, conv4])\nconv_conc_1 = Conv2D(256, (3, 3), padding='same', activation='relu')(conc_1)\n\nup2 = UpSampling2D(2, interpolation='bilinear')(conv_conc_1)\nconc_2 = Concatenate()([up2, conv3])\nconv_conc_2 = Conv2D(128, (3, 3), padding='same', activation='relu')(conc_2)\n\nup3 = UpSampling2D(2, interpolation='bilinear')(conv_conc_2)\nconc_3 = Concatenate()([up3, conv2])\nconv_conc_3 = Conv2D(64, (3, 3), padding='same', activation='relu')(conc_3)\n\nup4 = UpSampling2D(2, interpolation='bilinear')(conv_conc_3)\nconc_4 = Concatenate()([up4, conv1])\nconv_conc_4 = Conv2D(32, (3, 3), padding='same', activation='relu')(conc_4)\n\nup5 = UpSampling2D(2, interpolation='bilinear')(conv_conc_4)\nconv_conc_5 = Conv2D(1, (3, 3), padding='same', activation='sigmoid')(up5)\n","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:16.407379Z","iopub.execute_input":"2022-11-24T09:07:16.407727Z","iopub.status.idle":"2022-11-24T09:07:16.481480Z","shell.execute_reply.started":"2022-11-24T09:07:16.407694Z","shell.execute_reply":"2022-11-24T09:07:16.480471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"unet_50 = Model(inputs=base_model.input, outputs=conv_conc_5)\nunet_50.summary()","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:16.482788Z","iopub.execute_input":"2022-11-24T09:07:16.483373Z","iopub.status.idle":"2022-11-24T09:07:16.517688Z","shell.execute_reply.started":"2022-11-24T09:07:16.483336Z","shell.execute_reply":"2022-11-24T09:07:16.516744Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"checkpoint_best = keras.callbacks.ModelCheckpoint('unet_50_best.h5',\n                                                  monitor='val_loss',\n                                                  verbose=0,\n                                                  save_best_only=True,\n                                                  save_weights_only=False,\n                                                  mode='auto',\n                                                  period=1)\n\ncallbacks = [checkpoint_best]","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:16.519073Z","iopub.execute_input":"2022-11-24T09:07:16.521384Z","iopub.status.idle":"2022-11-24T09:07:16.527488Z","shell.execute_reply.started":"2022-11-24T09:07:16.521334Z","shell.execute_reply":"2022-11-24T09:07:16.526549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#компиляция модели\nfrom tensorflow.keras.optimizers import Adam\n\nunet_50.compile(optimizer=Adam(), loss='binary_crossentropy',  metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:16.529258Z","iopub.execute_input":"2022-11-24T09:07:16.529669Z","iopub.status.idle":"2022-11-24T09:07:16.545355Z","shell.execute_reply.started":"2022-11-24T09:07:16.529630Z","shell.execute_reply":"2022-11-24T09:07:16.544325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#обучение модели\n\n%time\nbatch_size = 20\n\nhistory = unet_50.fit(keras_generator(train_df, batch_size, preprocess_input),\n            steps_per_epoch=100,\n            epochs=5, verbose=1,\n            callbacks=callbacks,\n            validation_data=keras_generator(val_df, batch_size, preprocess_input),\n            validation_steps=10)","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:07:16.547167Z","iopub.execute_input":"2022-11-24T09:07:16.547563Z","iopub.status.idle":"2022-11-24T09:12:43.130422Z","shell.execute_reply.started":"2022-11-24T09:07:16.547526Z","shell.execute_reply":"2022-11-24T09:12:43.129373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(history.history['val_accuracy'], label='test')\nplt.plot(history.history['accuracy'], label='train')\nplt.legend()\nplt.xlabel('epoch')\nplt.ylabel('accuracy')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:12:43.133372Z","iopub.execute_input":"2022-11-24T09:12:43.133767Z","iopub.status.idle":"2022-11-24T09:12:43.417053Z","shell.execute_reply.started":"2022-11-24T09:12:43.133731Z","shell.execute_reply":"2022-11-24T09:12:43.416010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"unet_50.evaluate(keras_generator(val_df, batch_size, preprocess_input), steps=25)","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:12:43.418457Z","iopub.execute_input":"2022-11-24T09:12:43.419136Z","iopub.status.idle":"2022-11-24T09:12:56.508616Z","shell.execute_reply.started":"2022-11-24T09:12:43.419098Z","shell.execute_reply":"2022-11-24T09:12:56.507638Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for X, y in keras_generator(val_df, 16, preprocess_input):\n    plt.imshow(X[1])\n    print(X[1].min(), X[1].max())\n    break","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:12:56.510227Z","iopub.execute_input":"2022-11-24T09:12:56.510616Z","iopub.status.idle":"2022-11-24T09:12:57.080024Z","shell.execute_reply.started":"2022-11-24T09:12:56.510579Z","shell.execute_reply":"2022-11-24T09:12:57.078888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred = unet_50.predict(X)\nidx = 1\nfig, axes = plt.subplots(1, 2, figsize=(15, 15))\naxes[0].imshow(X[idx])\naxes[1].imshow(pred[idx, ..., 0] > 0.5)\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-11-24T09:12:57.081398Z","iopub.execute_input":"2022-11-24T09:12:57.081846Z","iopub.status.idle":"2022-11-24T09:12:58.189055Z","shell.execute_reply.started":"2022-11-24T09:12:57.081809Z","shell.execute_reply":"2022-11-24T09:12:58.187897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"По метрикам и по визуализации получили, на мой взгляд, очень хороший результат. Добиться его помог подбор архитектуры сети и ее параметров.","metadata":{}}]}