{"cells":[{"metadata":{},"cell_type":"markdown","source":" # **TEMAT PROJEKTU:**   Histopathologic Cancer Detection\n\n**AUTORZY:**  \nPaulina Radomska  \nAleksandra Wirecka  \nMarta Denisiuk  "},{"metadata":{},"cell_type":"markdown","source":"# **CEL PROJEKTU:**\nStworzenie modelu, który może analizować skany węzłów chłonnych i przewidywać, czy obraz zawiera tkankę przerzutową, czyli raka."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\n\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D\nfrom tensorflow.keras.layers import Dense, Dropout, Flatten, Activation, BatchNormalization\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau, ModelCheckpoint\nfrom tensorflow.keras.optimizers import Adam\n\nimport cv2\nimport os\n\nfrom sklearn.utils import shuffle   # tablice losowania/wykonywania losowych permutacji kolekcji\nfrom sklearn.model_selection import train_test_split    # dzielenie tablic lub macierzy na losowe podzbiory pociągów i testów\nimport shutil   # operacje na plikach\nimport matplotlib.pyplot as plt\n\nfrom sklearn.metrics import roc_curve, roc_auc_score, confusion_matrix   # oblicza obszar pod krzywą charakterystyki\n\nimport plotly.graph_objects as go\n\nimport plotly.figure_factory as ff\n%matplotlib inline\n\ntf.random.set_seed(101)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **DANE I ICH WSTĘPNA ANALIZA**"},{"metadata":{"trusted":true},"cell_type":"code","source":"path = \"../input/histopathologic-cancer-detection/\"\n\n# ładujemy zestawy szkoleniowe\ntrain = pd.read_csv(path + 'train_labels.csv')\ntest = pd.read_csv(path + 'sample_submission.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# ile obrazków ma każdy z zestawów?\nprint(len(train))\nprint(len(test))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_data=train","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"directory = path + \"train/\"\nfnames = [os.path.join(directory, fname) for fname in os.listdir(directory)]\nslownik = {'png' : 0, 'jpg': 0, 'jpeg' : 0, 'tiff': 0, 'bmp' :0,'tif':0}\n\nfor i in fnames:\n    if i.lower().endswith(('png', 'jpg', 'jpeg', 'tiff', 'bmp', 'tif')):\n        slownik[(i.split('.')[3])] += 1\nprint(slownik)\n\n#widzimy, że mamy same tif, więc sprawdzamy czy wszystkie zdjęcia zostały w tym formacie zapisane,\nif len(fnames) == slownik['tif']:\n    print('True')\n# czyli wszystkie są w tif","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# tworzymy ramkę danych obrazów szkoleniowych\nprint(df_data.shape)\ndf_data['id']=df_data['id'].apply(lambda x: x+'.tif')\ndf_data.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Zbiór danych zawiera 220 025 obrazów do treningu, które są oznaczone 0 lub 1.  \n0 oznacza wynik negatywny, tj. brak raka, a 1 oznacza wynik pozytywny, tj. obraz zawiera przerzuty (raka).  \n\nZbiór danych zawiera również 57 458 obrazów testowych, które posłużą do oceny przesłanych przez nas materiałów. Próbki testowe są nieoznaczone, więc nie będą używane do budowy i oceny naszego modelu."},{"metadata":{"trusted":true},"cell_type":"code","source":"count = df_data['label'].value_counts()\n\nprint(\"Ilość pozytywnych skanów raka:\", count[1])\nprint(\"Ilość pozytywnych skanów raka w procentach:\", round(count[1] / df_data.shape[0], 3) * 100)\nprint(\"Ilość neatywnych skanów raka:\", count[0])\nprint(\"Ilość negatywnych skanów raka w procentach:\", round(count[0] / df_data.shape[0], 3) * 100)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Zbiór danych szkoleniowych składa się ze 130 908 negatywów i 89 117 pozytywów, co stanowi odpowiednio około 59.5% i 40.5%, jak pokazano na poniższym wykresie kołowym.  "},{"metadata":{"trusted":true},"cell_type":"code","source":"labels = ['Negatywy', 'Pozytywy']\nfig1, ax1 = plt.subplots()\ncolors = ['#66b3ff','#ff6666']\nax1.pie(count, labels=labels,autopct='%1.1f%%',startangle=90,colors=colors)  \nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **WIZUALIZACJA OBRAZÓW**"},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, axs = plt.subplots(3,3,figsize=(8, 5), dpi=150)\n\n\nimages = []\nfor i in range(3):\n    for j in range(3):\n        \n        tran = np.random.randint(0,1000)\n                \n        image = cv2.imread(path + \"train/\" + df_data.iloc[tran]['id'])\n        images.append(axs[i, j].imshow(image))\n        \n        if df_data.iloc[tran]['label'] == 1:\n            axs[i,j].set_title('Nowotwór')\n        else:\n            axs[i,j].set_title('Brak nowotworu')\n            \n        axs[i,j].set_xticks([])\n        axs[i,j].set_yticks([])\n        \n\n    \nplt.show()\ndel images","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Z przedstawionych obrazków trudno jest ustalić cechy odróżniające komórki nowotworowe od nienowotworowych.\nMożemy zauważyć, że istnieją obrazy komórek rakowych i nierakowych o podobnych kolorach oraz z dużą i małą liczbą okrągłych węzłów.\nSpójrzmy, jak kreśli się częstotliwość kanałów kolorów losowo wybranego obrazka dla dwóch możliwych kategorii."},{"metadata":{"trusted":true},"cell_type":"code","source":"cancer_data = df_data[(df_data.label==1)]\ncancer_image = cancer_data.iloc[900]['id']\nimg = cv2.imread(path + \"train/\" + cancer_image)\nplt.imshow(img)\nplt.title(\"Komórka rakowa\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.hist(img[:, :, 0].ravel(), bins = 256, color = 'red')\nplt.hist(img[:, :, 1].ravel(), bins = 256, color = 'Green')\nplt.hist(img[:, :, 2].ravel(), bins = 256, color = 'Blue')\nplt.xlabel('Intensywność')\nplt.ylabel('Ilość')\nplt.legend(['Red_Channel', 'Green_Channel', 'Blue_Channel'])\nplt.title(\"Częstotliwość kanałów kolorów komórek rakowych\")\nplt.show()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"non_cancer_data = df_data[(df_data.label==0)]\nnon_cancer_image = non_cancer_data.iloc[500]['id']\n\nimg = cv2.imread(path + \"train/\" + non_cancer_image)\nplt.imshow(img)\nplt.title(\"Brak komórki rakowej\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.hist(img[:, :, 0].ravel(), bins = 256, color = 'red')\nplt.hist(img[:, :, 1].ravel(), bins = 256, color = 'Green')\nplt.hist(img[:, :, 2].ravel(), bins = 256, color = 'Blue')\nplt.xlabel('Intensywność')\nplt.ylabel('Ilość')\nplt.legend(['Red_Channel', 'Green_Channel', 'Blue_Channel'])\nplt.title(\"Częstotliwość kanałów kolorów przy braku komórek rakowych\")\nplt.show()\n\ndel img, non_cancer_data, cancer_data","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **PODZIAŁ NA ZBIÓR TRENINGOWY I WALIDACYJNY**"},{"metadata":{},"cell_type":"markdown","source":"Ponieważ zbiór danych jest bardzo duży, a uczenie modelu przy użyciu całego zestawu danych byłoby bardzo czasochłonne, zdecydowałyśmy się zmniejszyć liczbę próbek uczących, które będą używane.  \nOpierając się na wykonanych próbach i pouczających błędach zdecydowałyśmy się na użycie łącznie 20 000 próbek, tj.  \n10 000 pozytywnych i 10 000 negatywnych.  \nZadany rozmiar próbki powinien być wystarczająco duży, aby reprezentować pełny zestaw danych uczących, jednocześnie umożliwiając stosunkowo szybkie wytrenowanie modelu. \n\nUstaliłyśmy, aby zrównać liczbę pozytywnych i negatywnych próbek, by dokładność nie została wypaczona przez proste dopasowanie modelu do częstszego wyniku."},{"metadata":{"trusted":true},"cell_type":"code","source":"# zbiór danych zawiera obrazy histopatologiczne, każdy obraz ma rozmiar 96px * 96px\n# ustawiamy wymagania wstępne\nsample_size = 10000     # ilość próbek do szkolenia\nimage_size = 96         # rozmiar obrazka\nimage_channels = 3      # kanały obrazu","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_neg = df_data[df_data['label'] == 0].sample(sample_size, random_state = 101)\ndf_pos = df_data[df_data['label'] == 1].sample(sample_size, random_state = 101)\n\ndata = pd.concat([df_neg, df_pos], axis=0).reset_index(drop=True)   # złączenie obiektów negatywnych i pozytywnych w jedną ramkę danych\ndata = shuffle(data)    # przetasowanie listy (zreorganizowanie kolejności elementów listy)\n\nprint(data['label'].value_counts())\nprint(data.shape)\nprint(data)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test['label'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Ponieważ obrazy testowe (zmienna *test*) nie miały etykiet innych niż *label=0*, podzieliłyśmy nasze 20000 próbek szkoleniowych na zestaw treningowy i walidacyjny.  \nZdecydowałyśmy się wykorzystać 90% obrazów do trenowania modelu, a 10% zarezerwować do jego walidacji.  \n\nPróbki podzielono losowo. Zdecydowałyśmy się na metodę stratyfikację, aby jeszcze raz zachować liczbę pozytywów i negatywów w każdym zestawie, aby model nie był wypaczony w kierunku najczęstszego wyniku."},{"metadata":{"trusted":true},"cell_type":"code","source":"data_train, data_valid = train_test_split(data, test_size=.1, random_state=101, stratify=data['label'])\n# stratify tworzy zrównoważony zestaw walidacyjny\n\nprint(data_train.shape)\nprint(data_valid.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(data_train['label'].value_counts())\nprint(data_valid['label'].value_counts())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Ustaliłyśmy, że łatwiejsze niż prowadzenie listy obrazków i ciągłe jej czytanie, będzie stworzenie katalogów/folderów.  \nUtworzyłyśmy katalogi do przechowywania obrazów, odpowiednio katalog treningowy i walidacyjny. Następnie obrazy zostały posortowane do odpowiednich folderów."},{"metadata":{"trusted":true},"cell_type":"code","source":"# nowy katalog\nbase_dir='base_dir'\nos.mkdir(base_dir)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# tworzymy dwa foldery wewnątrz \"base_dir\"\n# train_dir\n    # a_non_cancer_tissue\n    # b_cancer_tissue\n\n# valid_dir\n    # a_non_cancer_tissue\n    # b_cancer_tissue\n    \n# ścieżka do \"base_dir\", by dołączyć nazwy nowych folderów\n# train_dir\ntrain_dir = os.path.join(base_dir, 'train_dir')\nos.mkdir(train_dir)\n\n# valid_dir\nvalid_dir = os.path.join(base_dir, 'valid_dir')\nos.mkdir(valid_dir)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# w każdym folderze tworzymy osobne foldery dla każdej klasy - a_non_cancer_tissue, b_cancer_tissue\n# dla train_dir\nnon_cancer_tissue = os.path.join(train_dir, 'a_non_cancer_tissue')\nos.mkdir(non_cancer_tissue)\n\ncancer_tissue = os.path.join(train_dir, 'b_cancer_tissue')\nos.mkdir(cancer_tissue)\n\n\n# dla valid_dir\nnon_cancer_tissue = os.path.join(valid_dir, 'a_non_cancer_tissue')\nos.mkdir(non_cancer_tissue)\ncancer_tissue = os.path.join(valid_dir, 'b_cancer_tissue')\nos.mkdir(cancer_tissue)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# sprawdzamy, czy foldery rzeczywiście istnieją\nos.listdir('base_dir/valid_dir')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# ustawiamy id jako indeks w zmiennej data\ndata.set_index('id', inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# lista obrazów treningowych i walidacyjnych\ntrain_list = list(data_train['id'])\nvalid_list = list(data_valid['id'])\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# przenosimy obrazy do folderów\nfor image in train_list:\n    \n    # wydobycie etykiety (label)\n    tlab = data.loc[image,'label']\n    \n    if tlab == 0:\n        label = 'a_non_cancer_tissue'\n    if tlab == 1:\n        label = 'b_cancer_tissue'\n    \n    # ścieżka źródłowa\n    src = os.path.join('../input/histopathologic-cancer-detection/train', image)\n    # docelowa ścieżka\n    dst = os.path.join(train_dir, label, image)\n    # skopiowanie obrazu ze źródła do miejsca docelowego\n    shutil.copyfile(src, dst)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(len(os.listdir('base_dir/train_dir/a_non_cancer_tissue')))\nprint(len(os.listdir('base_dir/train_dir/b_cancer_tissue')))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for image in valid_list:\n    \n    tlab = data.loc[image,'label']\n    \n    if tlab == 0:\n        label = 'a_non_cancer_tissue'\n    if tlab == 1:\n        label = 'b_cancer_tissue'\n    \n    src = os.path.join('../input/histopathologic-cancer-detection/train', image)\n    dst = os.path.join(valid_dir, label, image)\n    shutil.copyfile(src, dst)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(len(os.listdir('base_dir/valid_dir/a_non_cancer_tissue')))\nprint(len(os.listdir('base_dir/valid_dir/b_cancer_tissue')))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Obrazy zostały wstępnie przetworzone przy użyciu funkcji *keras ImageDataGenerator* (\"powiększanie/rozszerzenie danych w czasie rzeczywistym\") \n\nMetoda *flow_from_directory()* umożliwia odczytywanie obrazów bezpośrednio z katalogu i powiększanie ich podczas uczenia się modelu sieci neuronowej na danych szkoleniowych.  \nMetoda oczekuje, że obrazy należące do różnych klas są obecne w różnych folderach, ale znajdują się wewnątrz tego samego folderu nadrzędnego."},{"metadata":{"trusted":true},"cell_type":"code","source":"train_path = path + 'train/'\ntest_path = path + 'test/'\n\nnum_train_samples = len(data_train)\nnum_valid_samples = len(data_valid)\ntrain_batch_size = 32\nvalid_batch_size = 32\n\ntrain_steps = np.ceil(num_train_samples / train_batch_size)\nvalid_steps = np.ceil(num_valid_samples / valid_batch_size)\n# ceil zwraca tzw. \"sufit\", górne zaokrąglenie","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"datagen = ImageDataGenerator(rescale=1./255, vertical_flip=True, horizontal_flip=True, rotation_range=90, shear_range=0.05)\n\n# rescale - oryginalne obrazy składają się ze współczynników RGB w 0-255, ale takie wartości są zbyt wysokie \n# dla naszego modelu do przetwarzania, więc oczekujemy wartości od 0 do 1 (skalując za pomocą 1/255)\n# vertical_flip - losowe przerzucanie danych wejściowych w pionie\n# horizontal_flip - losowe przerzucanie danych wejściowych w poziomie\n# rotation_range - zakres stopni dla losowych obrotów\n# shear_range - intensywność ścinania (kąt ścinania w kierunku przeciwnym do ruchu wskazówek zegara w stopniach)\n\n# katalog - ścieżka do folderu nadrzędnego, który zawiera podfolder dla różnych obrazów klas\n# target_size - rozmiar obrazu wejściowego\n# batch_size - rozmiar partii danych\n# class_mode - dla etykiet binarnych 'binary'/dla etykiet zakodowanych 'categorical'\n\ntrain_data_gen = datagen.flow_from_directory(train_dir,\n                                        target_size=(image_size,image_size),\n                                        batch_size=train_batch_size,\n                                        class_mode='binary')\n\nvalid_data_gen = datagen.flow_from_directory(valid_dir,\n                                        target_size=(image_size,image_size),\n                                        batch_size=valid_batch_size,\n                                        class_mode='binary')\n\n\ntest_data_gen = datagen.flow_from_directory(valid_dir,\n                                        target_size=(image_size,image_size),\n                                        batch_size=1,\n                                        class_mode='binary',\n                                        shuffle=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **MODEL**"},{"metadata":{"trusted":true},"cell_type":"code","source":"kernel_size = (3,3) # wysokość i szerokość okna splotu\nfilters = 32 # wymiar przestrzeni wyjściowej\n\nmodel = Sequential()\nmodel.add(Conv2D(filters, kernel_size, activation = 'relu', input_shape = (image_size, image_size, 3)))\n\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Conv2D(64, kernel_size, use_bias=False))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\n# normalizacja danych wejściowych\nmodel.add(BatchNormalization())\nmodel.add(Activation(\"relu\")) \nmodel.add(Dropout(0.3))\n# Dropout jest techniką, w której losowo wybrane neurony są ignorowane podczas treningu. \n# Ich wkład w aktywację neuronów niższego rzędu jest czasowo usuwany na przejściu do przodu i wszelkie aktualizacje wagi nie są stosowane.\n\n# spłaszczenie danych\nmodel.add(Flatten())\n# zwykła gęsto połączona warstwa\nmodel.add(Dense(256, use_bias=False))\nmodel.add(BatchNormalization())\nmodel.add(Activation(\"relu\"))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(1, activation = \"sigmoid\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(optimizer='adam',\n              loss='binary_crossentropy',\n              metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.utils.vis_utils import plot_model\n\n# wykres warstw modelu\nplot_model(model, to_file='model_plot.png', show_shapes=True, show_layer_names=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# zmniejsza współczynnik uczenia się, gdy wskaźnik przestaje się poprawiać\nreduce = ReduceLROnPlateau(monitor='val_loss', patience=1, verbose=1, factor=0.5, mode='min')\n\nmc = ModelCheckpoint('best_model.h5', monitor='val_accuracy', mode='max', verbose=1, save_best_only=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\n\nhistory = model.fit(train_data_gen, steps_per_epoch=train_steps, \n                    validation_data=valid_data_gen,\n                    validation_steps=valid_steps,\n                    epochs=10,\n                   callbacks=[mc, reduce])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Wygenerowałyśmy prognozy dla próbek walidacyjnych i porównałyśmy te prognozy z rzeczywistymi wynikami.  \nPoniższa krzywa ROC przedstawia wskaźniki prawdziwie pozytywne i fałszywie dodatnie. \n\nGeneralnie celem problemów klasyfikacyjnych jest maksymalizacja pola powierzchni pod krzywą ROC, próbując uzyskać wartość możliwie jak najbliższą 1."},{"metadata":{"trusted":true},"cell_type":"code","source":"pred = model.predict(test_data_gen, steps=len(test_data_gen), verbose=1)\nfpr, tpr, thresholds_keras = roc_curve(test_data_gen.classes, pred)\nroc_auc_score(test_data_gen.classes, pred)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pred","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(1)\nplt.plot([0, 1], [0, 1])\nplt.plot(fpr, tpr)\nplt.xlabel('False Positive Rate')\nplt.ylabel('True Positive Rate')\nplt.title('ROC Curve')\nplt.legend(loc='best')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_hist(history):\n    hist = pd.DataFrame(history.history)\n    hist['epoch'] = history.epoch\n\n    fig = go.Figure()\n    fig.add_trace(go.Scatter(x=hist['epoch'], y=hist['accuracy'], name='accuracy', mode='markers+lines'))\n    fig.add_trace(go.Scatter(x=hist['epoch'], y=hist['val_accuracy'], name='val_accuracy', mode='markers+lines'))\n    fig.update_layout(width=1000, height=500, title='Accuracy vs. Val Accuracy', xaxis_title='Epoki', yaxis_title='Accuracy', yaxis_type='log')\n    fig.show()\n\n    fig = go.Figure()\n    fig.add_trace(go.Scatter(x=hist['epoch'], y=hist['loss'], name='loss', mode='markers+lines'))\n    fig.add_trace(go.Scatter(x=hist['epoch'], y=hist['val_loss'], name='val_loss', mode='markers+lines'))\n    fig.update_layout(width=1000, height=500, title='Loss vs. Val Loss', xaxis_title='Epoki', yaxis_title='Loss', yaxis_type='log')\n    fig.show()\n\nplot_hist(history)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y_pred=[]\ny_true=[]\ndef predict_img(model, img):\n    X=np.array(img)/255\n    X=cv2.resize(X,(image_size,image_size))\n    X=np.expand_dims(X,axis=0)\n    pred_class=model.predict_classes(X)\n    #print(pred_class)\n    y_pred.append(pred_class[0][0])\n    y_true.append(temp['label'])\n    if pred_class == 0:\n        plt.title(\"Non cancer\\n\" + str(temp['label']))\n    else:\n        plt.title(\"Cancer\\n\" + str(temp['label']))\n    plt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(13, 13))\nfor i in range(1,11):\n    temp = df_data.iloc[np.random.randint(0,100)]\n    img = cv2.imread(path + \"train/\" + temp['id'])\n    plt.subplot(1, 10, i)\n    plt.axis('off')\n    predict_img(model,img)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true},"cell_type":"code","source":"y_pred=[]\ny_true=[]\nfor i in range(1,101):\n    temp = df_data.iloc[np.random.randint(350,450)]\n    img = cv2.imread(path + \"train/\" + temp['id'])\n    predict_img(model,img)\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cm=confusion_matrix(y_true,y_pred)\ncm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_confusion_matrix(cm):\n    cm = cm[::-1]\n    cm = pd.DataFrame(cm, columns=['pred_0', 'pred_1'], index=['true_1', 'true_0'])\n\n    fig = ff.create_annotated_heatmap(z=cm.values, x=list(cm.columns), y=list(cm.index), colorscale='Hot', showscale=True, reversescale=True)\n    fig.update_layout(width=500, height=500, title='Confusion Matrix', font_size=16)\n    fig.show()\n\nplot_confusion_matrix(cm)","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}