{"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":"# I. Giới thiệu chung\n## 1. Giới thiệu bài toán\n<span style=\"font-size: 18px\">\n    Ta có thể thấy protein đóng vai trò thiết yếu trong hầu như tất các quá trình của tế bào. Thông thường, nhiều protein kết hợp với nhau tại một vị trí cụ thể để thực hiện 1 nhiệm vụ, kết quả chính xác của nhiệm vụ này phụ thuộc vào loại protein nào có mặt. Như bạn thấy, sự phân bố của protein ở các tế bào khác nhau là khác nhau, làm phát sinh sự không đồng nhất về chức năng giữa các tế bào. Việc tìm ra những điểm khác biệt như vậy và lý do tại sao có sự phân bố khác nhau của protein giữa các tế bào có cùng chức năng là điều quan trọng để hiểu được cách thức hoạt động của các tế bào, tìm ra cách các căn bệnh phát triển, sau đó tìm ra các phương pháp điều trị tốt hơn cho những bệnh đó.\n</span>\n\n## 2. Dữ liệu\n<b style=\"font-size: 18px\">Human Protein Atlas - Single Cell Classification</b>\n<br>\n<span style=\"font-size: 18px\">Bộ dữ liệu có 3 loại ảnh PNG bao gồm các kích thước:</span>\n    \n<ul style=\"font-size: 18px\">\n    <li>1728x1728</li>\n    <li>2048x2048</li>\n    <li>3072x3072</li>\n</ul>\n\n<span style=\"font-size: 18px\">\n    Tất cả đều được chụp bằng kính hiển vi đồng tiêu (Confocal Microscopy)\n    <br>\n    Mỗi ảnh được chụp trên 4 kênh → 4 ảnh:\n<br>\n</span>\n<ul style=\"font-size: 18px\">\n    <li><code>red:</code> microtubule channels (<a href=\"https://vi.wikipedia.org/wiki/Vi_ống\">Vi ống</a>)</li>\n    <li><code>blue:</code> nuclei channels (<a href=\"https://vi.wikipedia.org/wiki/Nhân_tế_bào\">Nhân tế bào</a>)</li>\n    <li><code>yellow:</code> Endoplasmic Reticulum (ER) channels (<a href=\"https://vi.wikipedia.org/wiki/Mạng_lưới_nội_chất\">Lưới nội chất</a>)</li>\n    <li><code>green:</code> protein of interest (<a href=\"https://www.google.com/search?q=protein+of+interest&oq=protein+of+interest&aqs=edge..69i57j0l3j0i22i30l3.760j0j1&sourceid=chrome&ie=UTF-8\">???</a>)</li>\n</ul>\n\n## 3. Nhiệm vụ\n<span style=\"font-size: 18px\">\n    Có tất cả 19 nhãn cần phân lớp, 18 nhãn cho 18 loại tế bào và 1 nhãn cho những tế bào không xác định được cụ thể. \n    \n    \n</span>\n\n<pre style=\"font-size: 18px\">\n0.  Nucleoplasm  \n1.  Nuclear membrane   \n2.  Nucleoli   \n3.  Nucleoli fibrillar center   \n4.  Nuclear speckles   \n5.  Nuclear bodies   \n6.  Endoplasmic reticulum   \n7.  Golgi apparatus   \n8.  Intermediate filaments  \n9.  Actin filaments  \n10.  Microtubules      \n11.  Mitotic spindle   \n12.  Centrosome   \n13.  Plasma membrane   \n14.  Mitochondria   \n15.  Aggresome   \n16.  Cytosol   \n17.  Vesicles and punctate cytosolic patterns   \n18.  Negative  \n</pre>\n\n<span style=\"font-size: 18px\">\n    Tất cả các ảnh được thể hiện bằng 4 bộ lọc:\n</span>\n<ul style=\"font-size: 18px\">\n    <li>Bộ lọc màu xanh(<code>green</code>) được sử dụng để dự đoán và gán nhãn</li>\n    <li>3 bộ lọc còn lại(<code>red, blue, yellow</code>) được sử dụng để làm tài liệu tham khảo, cho thấy sự tương quan của tế bào giữa các bộ lọc</li>\n</ul>\n    \n### Nhiệm vụ chính\n<span style=\"font-size: 18px\">\nVới mỗi ảnh chúng ta đã được cho sẵn các nhãn của các tế bào xuất hiện trong ảnh.\n<br><b> Nhiệm vụ của chúng ta là segment ra các tế bào và gán nhãn cho các tế bào đó.</b>\n</span>","metadata":{}},{"cell_type":"markdown","source":"# II. Thực hiện","metadata":{}},{"cell_type":"code","source":"!pip install https://github.com/CellProfiling/HPA-Cell-Segmentation/archive/master.zip","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport tensorflow as tf\n\nimport hpacellseg.cellsegmentator as cellsegmentator\nfrom hpacellseg.utils import label_cell, label_nuclei\n\nfrom sklearn.preprocessing import MultiLabelBinarizer\n\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport plotly.graph_objects as go\nimport plotly.express as px","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DATA_DIR = \"/kaggle/input/hpa-single-cell-image-classification\"\ntrain = pd.read_csv(os.path.join(DATA_DIR,'train.csv'))\n\ncolours = ['_red.png', '_blue.png', '_yellow.png', '_green.png']\nTRAIN = '../input/hpa-single-cell-image-classification/train'\npaths = [[os.path.join(TRAIN, train.iloc[idx,0])+ colour for colour in colours] for idx in range(len(train))]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LABELS= {\n    0: \"Nucleoplasm\",\n    1: \"Nuclear membrane\",\n    2: \"Nucleoli\",\n    3: \"Nucleoli fibrillar center\",\n    4: \"Nuclear speckles\",\n    5: \"Nuclear bodies\",\n    6: \"Endoplasmic reticulum\",\n    7: \"Golgi apparatus\",\n    8: \"Intermediate filaments\",\n    9: \"Actin filaments\",\n    10: \"Microtubules\",\n    11: \"Mitotic spindle\",\n    12: \"Centrosome\",\n    13: \"Plasma membrane\",\n    14: \"Mitochondria\",\n    15: \"Aggresome\",\n    16: \"Cytosol\",\n    17: \"Vesicles and punctate cytosolic patterns\",\n    18: \"Negative\"\n}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data Visualize","metadata":{}},{"cell_type":"code","source":"train","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_csv = train.copy()\ntrain_csv['Label'] = train_csv['Label'].apply(lambda x: list(map(int,x.split(\"|\"))))\nmlb = MultiLabelBinarizer()\ntrain_csv[list(range(19))] = mlb.fit_transform(train_csv['Label'])\ntrain_csv.columns = [\"ID\", \"Label\"] + list(LABELS.values())\ntrain_csv.head(5)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_count = train_csv.iloc[:, 2:].sum()\npx.bar(label_count)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(3):\n    img_visual = TRAIN + '/' + train_csv['ID'].iloc[i]\n    r = plt.imread(img_visual + '_red' + '.png')\n    g = plt.imread(img_visual + '_green' + '.png')    \n    b = plt.imread(img_visual + '_blue' + '.png')\n    y = plt.imread(img_visual + '_yellow' + '.png')\n    fig, ax = plt.subplots(1,4, figsize=(10,20))\n    img = np.dstack((r, g, b, y))\n    ax[0].set_title('r_g_b_y')\n    ax[0].imshow(img)\n    ax[0].axis('off')\n\n    img = np.dstack((r, g, b))\n    ax[1].set_title('r_g_b')\n    ax[1].imshow(img)\n    ax[1].axis('off')\n\n    img = np.dstack((r, y, b))\n    ax[2].set_title('r_y_b')\n    ax[2].imshow(img)\n    ax[2].axis('off')\n\n    img = np.dstack((b, y, g))\n    ax[3].set_title(\"b_y_g\")\n    ax[3].imshow(img)\n    ax[3].axis('off')\n\n    plt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Input: list of image filters as png\n# Output: list of image filters as np.arrays\ndef image_to_arrays(path):\n    \n    image_arrays = list()\n    for image in path:\n        array = np.asarray(Image.open(image))\n        image_arrays.append(array)\n        \n    return image_arrays","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get single image that blends all RGBY into RGB\n# Introduce the images as arrays. Can use the function above.\n\ndef get_blended_image(images): \n    # get rgby images for sample\n\n    # blend rgby images into single array\n    blended_array = np.stack(images[:-1], 2)\n\n    # Create PIL Image\n    blended_image = Image.fromarray( np.uint8(blended_array) )\n    return blended_image","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Introduce list of image filters\n# Returns a processed image ready for the CNN and an encoded label as tensor\ndef image_prep(paths, label):\n\n    img = image_to_arrays(paths)\n    size = np.shape(img[0])[0]\n    img = tf.image.convert_image_dtype(img, dtype=tf.float32)\n    img = tf.reshape(img, (1, size, size, 3))\n    img = tf.image.resize(img, IMG_SIZE)\n\n    label = tf.strings.split(label, sep='|')\n    label = tf.strings.to_number(label, out_type=tf.int32)\n    label = tf.reduce_sum(tf.one_hot(indices=label, depth=19), axis=0)\n    label = tf.reshape(label, (1, 19))\n    \n    return img, label","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def apply_augmentation(image, label):\n    aug_img = tf.numpy_function(func=aug_fn, inp=[image], Tout=tf.float32)\n    aug_img.set_shape((IMG_SIZE[0], IMG_SIZE[0], 3))\n    \n    return aug_img, label","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_hist(hist):\n    plt.plot(hist.history[\"accuracy\"])\n    plt.plot(hist.history[\"val_accuracy\"])\n    plt.title(\"model accuracy\")\n    plt.ylabel(\"accuracy\")\n    plt.xlabel(\"epoch\")\n    plt.legend([\"train\", \"validation\"], loc=\"upper left\")\n    plt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"titles = ['microtubules', 'nuclei', 'endoplasmic reticulum', 'protein of interest']\nfig, axs = plt.subplots(3, 4, figsize =(16,8))\nfor entry in range(3):\n    for channel in range(4):\n        img = plt.imread(paths[entry][channel])\n        axs[entry, channel].imshow(img)        \n        if entry == 0:\n            axs[0, channel].set_title(titles[channel])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"NUC_MODEL = \"./nuclei-model.pth\"\nCELL_MODEL = \"./cell-model.pth\"\nsegmentator = cellsegmentator.CellSegmentator(\n    NUC_MODEL,\n    CELL_MODEL,\n    scale_factor=0.25,\n    device=\"cuda\",\n    padding=False,\n    multi_channel_model=True,\n)\n\nimage = paths[4]\narrays = image_to_arrays(image)\nnuclei = arrays[1]\ncell = arrays[:-1]\n\n# Nuclei segmentation\nnuc_segmentations = segmentator.pred_nuclei([nuclei])\n\nf, ax = plt.subplots(1, 2, figsize=(16,16))\nax[0].imshow(arrays[1])\nax[0].set_title('Original Nucleis', size=20)\nax[1].imshow(nuc_segmentations[0])\nax[1].set_title('Segmented Nucleis', size=20)\nplt.show()\n\n# Cell segmentation\ninter_step = [[i] for i in image[:-1]]\ncell_segmentations = segmentator.pred_cells(inter_step)\n\nf, ax = plt.subplots(1, 2, figsize=(16,16))\nax[0].imshow(get_blended_image(arrays))\nax[0].set_title('Original Cells', size=20)\nax[1].imshow(cell_segmentations[0])\nax[1].set_title('Segmented Cells', size=20)\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Nuclei mask\nnuclei_mask = label_nuclei(nuc_segmentations[0])\n# Cell masks\ncell_nuclei_mask, cell_mask = label_cell(nuc_segmentations[0], cell_segmentations[0])\n# Plotting\nf, ax = plt.subplots(1, 3, figsize=(16,16))\nax[0].imshow(nuclei_mask)\nax[0].set_title('Nuclei Mask', size=20)\nax[1].imshow(cell_nuclei_mask)\nax[1].set_title('Cell Nuclei Mask', size=20)\nax[2].imshow(cell_mask)\nax[2].set_title('Cell Mask', size=20)\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's stack the original image and the segmentation mask, to see how the segmentation worked out\nplt.figure(figsize=(20,20))\nplt.imshow(get_blended_image(arrays))\nplt.imshow(cell_mask, alpha=0.5)\nplt.title('Segmentation results', size=40)\nplt.axis('off')\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Unique vector of cell_mask numbers\nnumbers = set(np.ravel(cell_mask))\nnumbers.remove(0)\n\nfig = plt.figure(figsize=(25,8*len(numbers)/4))\nindex = 1\n\nax = fig.add_subplot(len(numbers)//4+1, 4, index)\nax.set_title(\"Complete Cell Mask\", size=16)\nplt.imshow(cell_mask)\n\nindex += 1\nfor number in numbers:\n    isolated_cell = np.where(cell_mask==number, cell_mask, 0)\n    ax = fig.add_subplot(len(numbers)//4+1, 4, index)\n    ax.set_title(f\"Segment {number}\", size=16)\n    plt.imshow(isolated_cell)\n    index += 1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.applications import EfficientNetB0\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras import layers\nfrom tensorflow.keras import Model\nimport wandb","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# We'll use EfficientNetB0 model, which requires an image dimension of (224,224,3).Therefor, we can only pass a 3 filter image... \n#We'll put aside the yellow filter for now.\nIMG_SIZE = [224, 224]\nBATCH_SIZE = 64\nAUTOTUNE = tf.data.experimental.AUTOTUNE\n\ncolours = ['_red.png', '_blue.png', '_green.png']\nTRAIN = '../input/hpa-single-cell-image-classification/train'\npaths = [[os.path.join(TRAIN, train.iloc[idx,0])+ colour for colour in colours] for idx in range(len(train))]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Processing the data for training:\ntraining_data = []\nfor i,path in enumerate(paths[:500]):\n    img, label = image_prep(path, train['Label'][i])\n    training_data.append([img,label])\n\ntrain_ds = tf.data.Dataset.from_tensor_slices(([training_data[i][0] for i in range(len(training_data))], [training_data[i][1] for i in range(len(training_data))]))\nlen(train_ds)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"val_data = []\nstart_img = 500\nval_num = 100\nfor i,path in enumerate(paths[start_img:start_img+val_num]):\n    img, label = image_prep(path, train['Label'][i+start_img])\n    val_data.append([img,label])\n\nval_ds = tf.data.Dataset.from_tensor_slices(([val_data[i][0] for i in range(len(val_data))], [val_data[i][1] for i in range(len(val_data))]))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_model = EfficientNetB0(include_top=False, weights='imagenet')\nbase_model.trainable = True\n\ninputs = layers.Input((IMG_SIZE[0], IMG_SIZE[0], 3))\n\nx = base_model(inputs, training=True)\nx = layers.GlobalAveragePooling2D()(x)\nx = layers.Dropout(0.5)(x)\noutputs = layers.Dense(len(LABELS), activation='sigmoid')(x)\n\ntf.keras.backend.clear_session()\n\nmodel = Model(inputs, outputs)\nmodel.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tf.keras.backend.clear_session()\n\nearlystopper = tf.keras.callbacks.EarlyStopping(\n    monitor='val_loss', patience=10, verbose=0, mode='min',\n    restore_best_weights=True\n)\n\nmodel.compile('adam', 'binary_crossentropy', metrics=[tf.keras.metrics.AUC(multi_label=True)])\n#model.compile('adam', 'binary_crossentropy', metrics=['accuracy'])\n#run = wandb.init(entity='ayush-thakur', project='hpa', job_type='train')\n\nhist = model.fit(train_ds, \n          epochs=50,\n          validation_data=val_ds,\n          verbose=1,\n          callbacks=[earlystopper]\n                )\n#plot_hist(hist)\n#run.finish()","metadata":{"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":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}