{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":10418,"databundleVersionId":862236,"sourceType":"competition"},{"sourceId":246060,"sourceType":"datasetVersion","datasetId":67658},{"sourceId":144372,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":122359,"modelId":145441}],"dockerImageVersionId":28450,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Table of contents\n\n1. [Preparaciones](#preparation)\n    * Ajustes de Kernel \n    * Cargar librerias y datos\n    * Codigo auxiliar\n    * Extraer los targets de train\n2. [Analisis exploratorio](#explore)\n    * ¿Qué proteínas aparecen con más frecuencia en las imágenes de entreno?\n    * ¿Cuales son los targets más comunes?\n    * ¿Que targets estan correlacionadas?\n    * ¿Cómo se agrupan los objetivos especiales y raros?\n    * ¿Cómo son las imágenes?\n    * ¿Cómo son las imágenes de objetivos específicos?\n3. [Construyendo los modelos](#baseline)\n    * Define the model\n    * How well does our model perform?\n    ","metadata":{}},{"cell_type":"markdown","source":"# Preparation <a class=\"anchor\" id=\"preparation\"></a>\n\n## Ajustes de kernel","metadata":{"_uuid":"bbba5a9f15329ac61510f60a84337c1fe2a6e98e"}},{"cell_type":"code","source":"class KernelSettings:\n    \n    def __init__(self, fit_baseline=False,\n                 fit_improved_baseline=True,\n                 fit_improved_higher_batchsize=False,\n                 fit_improved_without_dropout=False):\n        self.fit_baseline = fit_baseline\n        self.fit_improved_baseline = fit_improved_baseline\n        self.fit_improved_higher_batchsize = fit_improved_higher_batchsize\n        self.fit_improved_without_dropout = fit_improved_without_dropout","metadata":{"_kg_hide-input":true,"_uuid":"550027fb14c0774f8a58b5220548429126549131","execution":{"iopub.status.busy":"2024-10-23T16:09:48.498442Z","iopub.execute_input":"2024-10-23T16:09:48.498765Z","iopub.status.idle":"2024-10-23T16:09:48.504614Z","shell.execute_reply.started":"2024-10-23T16:09:48.498721Z","shell.execute_reply":"2024-10-23T16:09:48.503613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kernelsettings = KernelSettings(fit_baseline=False,\n                                fit_improved_baseline=False,\n                                fit_improved_higher_batchsize=False,\n                                fit_improved_without_dropout=False)","metadata":{"_uuid":"efd75058e48c0b7e962f4592ad14ec7d705196cb","execution":{"iopub.status.busy":"2024-10-23T16:09:48.515850Z","iopub.execute_input":"2024-10-23T16:09:48.516130Z","iopub.status.idle":"2024-10-23T16:09:48.520065Z","shell.execute_reply.started":"2024-10-23T16:09:48.516059Z","shell.execute_reply":"2024-10-23T16:09:48.519202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"use_dropout=True","metadata":{"_uuid":"32888a471d6e55cbcc2e1f88d1a6c974ae0e991f","execution":{"iopub.status.busy":"2024-10-23T16:09:48.531611Z","iopub.execute_input":"2024-10-23T16:09:48.531880Z","iopub.status.idle":"2024-10-23T16:09:48.535542Z","shell.execute_reply.started":"2024-10-23T16:09:48.531827Z","shell.execute_reply":"2024-10-23T16:09:48.534700Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Cargar librerias y datos","metadata":{"_uuid":"cce6944f02a874a8773859db189ab119393822ac"}},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd \n\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n%matplotlib inline\nfrom PIL import Image\nfrom scipy.misc import imread\n\nimport tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom sklearn.model_selection import GridSearchCV\nfrom sklearn.svm import SVC\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.neural_network import MLPClassifier\nfrom keras.applications import VGG16, ResNet50, DenseNet121\n\nsns.set()\n\nimport os\n# print(os.listdir(\"../input\"))\n\nimport warnings\nwarnings.filterwarnings(\"ignore\", category=DeprecationWarning)\nwarnings.filterwarnings(\"ignore\", category=UserWarning)\nwarnings.filterwarnings(\"ignore\", category=FutureWarning)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:09:48.537181Z","iopub.execute_input":"2024-10-23T16:09:48.537430Z","iopub.status.idle":"2024-10-23T16:09:48.553431Z","shell.execute_reply.started":"2024-10-23T16:09:48.537389Z","shell.execute_reply":"2024-10-23T16:09:48.552654Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_labels = pd.read_csv(\"../input/human-protein-atlas-image-classification/train.csv\")\ntrain_labels.head()","metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","execution":{"iopub.status.busy":"2024-10-23T16:09:48.554894Z","iopub.execute_input":"2024-10-23T16:09:48.555187Z","iopub.status.idle":"2024-10-23T16:09:48.616409Z","shell.execute_reply.started":"2024-10-23T16:09:48.555147Z","shell.execute_reply":"2024-10-23T16:09:48.615657Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"¿Cuántas muestras tenemos?","metadata":{"_uuid":"69a6b9c1584ebcf68b5aab128199f524daccd365"}},{"cell_type":"code","source":"train_labels.shape[0]","metadata":{"_uuid":"abaa2a7225e485102ceae9bdda12f4cf835c492f","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:09:48.618417Z","iopub.execute_input":"2024-10-23T16:09:48.618692Z","iopub.status.idle":"2024-10-23T16:09:48.623569Z","shell.execute_reply.started":"2024-10-23T16:09:48.618642Z","shell.execute_reply":"2024-10-23T16:09:48.622823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_path = \"../input/human-protein-atlas-image-classification/test/\"","metadata":{"_uuid":"3e1768f51c4d25820a791e9f0086093df2dc9d8a","execution":{"iopub.status.busy":"2024-10-23T16:09:48.625313Z","iopub.execute_input":"2024-10-23T16:09:48.625630Z","iopub.status.idle":"2024-10-23T16:09:48.631289Z","shell.execute_reply.started":"2024-10-23T16:09:48.625570Z","shell.execute_reply":"2024-10-23T16:09:48.630523Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv(\"../input/human-protein-atlas-image-classification/sample_submission.csv\")\nsubmission.head()","metadata":{"_uuid":"be475120f6769328bd53d4a65a7bab0cd3933987","execution":{"iopub.status.busy":"2024-10-23T16:09:48.632575Z","iopub.execute_input":"2024-10-23T16:09:48.632884Z","iopub.status.idle":"2024-10-23T16:09:48.660838Z","shell.execute_reply.started":"2024-10-23T16:09:48.632822Z","shell.execute_reply":"2024-10-23T16:09:48.660172Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_names = submission.Id.values\nprint(len(test_names))\nprint(test_names[0])","metadata":{"_uuid":"cb71c068ecdde2e8c13b578d5df0e851a652d56e","execution":{"iopub.status.busy":"2024-10-23T16:09:48.663215Z","iopub.execute_input":"2024-10-23T16:09:48.663478Z","iopub.status.idle":"2024-10-23T16:09:48.668059Z","shell.execute_reply.started":"2024-10-23T16:09:48.663430Z","shell.execute_reply":"2024-10-23T16:09:48.667275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Hay 11702 imágenes de prueba sobre las que se nos pide que hagamos predicciones.","metadata":{"_uuid":"f9897696eea56dadc4fa7172ef4a8c97f1d5ae98"}},{"cell_type":"markdown","source":"## Codigo Auxiliar","metadata":{"_uuid":"882bba3d7f68f209051fea3899f046bd96dc2915"}},{"cell_type":"code","source":"label_names = {\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:  \"Peroxisomes\",   \n    9:  \"Endosomes\",   \n    10:  \"Lysosomes\",   \n    11:  \"Intermediate filaments\",   \n    12:  \"Actin filaments\",   \n    13:  \"Focal adhesion sites\",   \n    14:  \"Microtubules\",   \n    15:  \"Microtubule ends\",   \n    16:  \"Cytokinetic bridge\",   \n    17:  \"Mitotic spindle\",   \n    18:  \"Microtubule organizing center\",   \n    19:  \"Centrosome\",   \n    20:  \"Lipid droplets\",   \n    21:  \"Plasma membrane\",   \n    22:  \"Cell junctions\",   \n    23:  \"Mitochondria\",   \n    24:  \"Aggresome\",   \n    25:  \"Cytosol\",   \n    26:  \"Cytoplasmic bodies\",   \n    27:  \"Rods & rings\"\n}\n\nreverse_train_labels = dict((v,k) for k,v in label_names.items())\n\ndef fill_targets(row):\n    row.Target = np.array(row.Target.split(\" \")).astype(np.int)\n    for num in row.Target:\n        name = label_names[int(num)]\n        row.loc[name] = 1\n    return row","metadata":{"_kg_hide-input":true,"_uuid":"beaac70d0392fab7c5b1d49649a8c994310320e4","execution":{"iopub.status.busy":"2024-10-23T16:09:48.670122Z","iopub.execute_input":"2024-10-23T16:09:48.670434Z","iopub.status.idle":"2024-10-23T16:09:48.682519Z","shell.execute_reply.started":"2024-10-23T16:09:48.670378Z","shell.execute_reply":"2024-10-23T16:09:48.681457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Extraer los targets de train","metadata":{"_uuid":"707280dec8e4b10dc743b5473ba8d1c4492141ff"}},{"cell_type":"code","source":"for key in label_names.keys():\n    train_labels[label_names[key]] = 0","metadata":{"_kg_hide-input":true,"_uuid":"13a1f4fd6b594cd4a225f6d79d966096d1c800ae","execution":{"iopub.status.busy":"2024-10-23T16:09:48.683735Z","iopub.execute_input":"2024-10-23T16:09:48.684006Z","iopub.status.idle":"2024-10-23T16:09:48.707952Z","shell.execute_reply.started":"2024-10-23T16:09:48.683959Z","shell.execute_reply":"2024-10-23T16:09:48.707212Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_labels = train_labels.apply(fill_targets, axis=1)\ntrain_labels.head()","metadata":{"_kg_hide-input":true,"_uuid":"3662893c91d0f74fe666300c214f67cfb03060c7","execution":{"iopub.status.busy":"2024-10-23T16:09:48.709451Z","iopub.execute_input":"2024-10-23T16:09:48.709729Z","iopub.status.idle":"2024-10-23T16:10:01.961944Z","shell.execute_reply.started":"2024-10-23T16:09:48.709679Z","shell.execute_reply":"2024-10-23T16:10:01.961037Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_labels = pd.DataFrame(data=test_names, columns=[\"Id\"])\nfor col in train_labels.columns.values:\n    if col != \"Id\":\n        test_labels[col] = 0\ntest_labels.head(1)","metadata":{"_uuid":"d6ff598935ed2a0094e9480a550eeea53be56abf","execution":{"iopub.status.busy":"2024-10-23T16:10:01.965228Z","iopub.execute_input":"2024-10-23T16:10:01.965594Z","iopub.status.idle":"2024-10-23T16:10:02.027195Z","shell.execute_reply.started":"2024-10-23T16:10:01.965524Z","shell.execute_reply":"2024-10-23T16:10:02.026248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Ok, currently we haven't made any predictions and except from Id all entries are filled with 0.","metadata":{"_uuid":"8621285b02148bf59458b19971f1a2904587ee2f"}},{"cell_type":"markdown","source":"# EDA <a class=\"anchor\" id=\"explore\"></a>","metadata":{}},{"cell_type":"markdown","source":"## ¿Qué proteínas aparecen con más frecuencia en las imágenes de entreno?","metadata":{"_uuid":"92c4d1a011febe16075e14722d19d8999e0e0b06"}},{"cell_type":"code","source":"target_counts = train_labels.drop([\"Id\", \"Target\"],axis=1).sum(axis=0).sort_values(ascending=False)\nplt.figure(figsize=(15,15))\nsns.barplot(y=target_counts.index.values, x=target_counts.values, order=target_counts.index)","metadata":{"_kg_hide-input":true,"_uuid":"f516b3a1a297a167264b0f22803de231096c9719","execution":{"iopub.status.busy":"2024-10-23T16:10:02.030547Z","iopub.execute_input":"2024-10-23T16:10:02.030892Z","iopub.status.idle":"2024-10-23T16:10:02.714323Z","shell.execute_reply.started":"2024-10-23T16:10:02.030828Z","shell.execute_reply":"2024-10-23T16:10:02.713586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Que podemos observar\n\n* Podemos ver que las estructuras proteicas más comunes pertenecen a componentes celulares de grano grueso como la membrana plasmática, el citosol y el núcleo. \n* En cambio, los componentes pequeños como las gotitas de lípidos, los peroxisomas, los endosomas, los lisosomas, los extremos de los microtúbulos, las varillas y los anillos aparecen muy raramente en nuestros datos de tren. Para estas clases la predicción será muy difícil, ya que sólo tenemos unos pocos ejemplos que pueden no cubrir todas las variabilidades y nuestro modelo probablemente se confundirá durante el proceso de aprendizaje con las clases principales. Debido a esta confusión haremos predicciones menos precisas sobre las clases menores.\n* En consecuencia, la precisión no es la puntuación adecuada para medir su rendimiento y la estrategia de validación debe ser muy precisa. ","metadata":{"_uuid":"af190deeab9f05afcba339f31c7162d841e58b33"}},{"cell_type":"markdown","source":"## ¿Cuales son los targets más comunes?","metadata":{"_uuid":"40bff26b2d170e9936c5e6ce4fbef12e7cb4f2ba"}},{"cell_type":"code","source":"train_labels[\"number_of_targets\"] = train_labels.drop([\"Id\", \"Target\"],axis=1).sum(axis=1)\ncount_perc = np.round(100 * train_labels[\"number_of_targets\"].value_counts() / train_labels.shape[0], 2)\nplt.figure(figsize=(20,5))\nsns.barplot(x=count_perc.index.values, y=count_perc.values, palette=\"Reds\")\nplt.xlabel(\"Number of targets per image\")\nplt.ylabel(\"% of train data\")","metadata":{"_uuid":"313f47ac92fa1ff241148af6282c200451edbea7","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:02.715624Z","iopub.execute_input":"2024-10-23T16:10:02.715856Z","iopub.status.idle":"2024-10-23T16:10:03.061759Z","shell.execute_reply.started":"2024-10-23T16:10:02.715816Z","shell.execute_reply":"2024-10-23T16:10:03.060672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Podemos observar que:\n\n* La mayoría de las imágenes de entrenamiento sólo tienen una o dos etiquetas de objetivo.\n* Más de 3 objetivos son muy raros.","metadata":{"_uuid":"d6e2a72c6f544f4d03a7f0e273a5819982b58108"}},{"cell_type":"markdown","source":"## ¿Que targets estan correlacionadas?\n\nVeamos si encontramos algunas correlaciones entre nuestros objetivos. De esta forma ya podemos ver que algunas proteínas suelen ir juntas.","metadata":{"_uuid":"cb957f819453857d62a96a236febabcfb9ce5a22"}},{"cell_type":"code","source":"plt.figure(figsize=(15,15))\nsns.heatmap(train_labels[train_labels.number_of_targets>1].drop(\n    [\"Id\", \"Target\", \"number_of_targets\"],axis=1\n).corr(), cmap=\"RdYlBu\", vmin=-1, vmax=1)","metadata":{"_uuid":"b3c0f5a77e34296416136ca2800b8623f94885d8","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:03.063652Z","iopub.execute_input":"2024-10-23T16:10:03.064282Z","iopub.status.idle":"2024-10-23T16:10:04.380799Z","shell.execute_reply.started":"2024-10-23T16:10:03.064214Z","shell.execute_reply":"2024-10-23T16:10:04.379974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Conclusión\n\n* Podemos ver que muchos de los target sólo tienen correlaciones muy ligeras. \n* Por el contrario, los endosomas y los lisosomas a menudo aparecen juntos y a veces parecen estar situados en el retículo endoplasmático. \n* Además encontramos que el huso mitótico a menudo viene junto con el puente citocinético. Esto tiene sentido ya que ambos participan en la división celular. Y en este proceso los microtúbulos y sus extremos son activos y participan también. En consecuencia, encontramos una correlación positiva entre estos objetivos.","metadata":{"_uuid":"c8083f38bf943a2d38c86544cf322ffe721d8a19","trusted":true}},{"cell_type":"markdown","source":"## ¿Cómo se agrupan los objetivos especiales y raros?","metadata":{"_uuid":"3b7bc009eb7ec4b6d24e4e0951d5d799ac42d289"}},{"cell_type":"markdown","source":"### Lysosomes and endosomes\n\nEmpecemos con estas características de alta correlación.","metadata":{"_uuid":"6f0bf1de2bf7c2550cd7bb320a16ce0d79b25087"}},{"cell_type":"code","source":"def find_counts(special_target, labels):\n    counts = labels[labels[special_target] == 1].drop(\n        [\"Id\", \"Target\", \"number_of_targets\"],axis=1\n    ).sum(axis=0)\n    counts = counts[counts > 0]\n    counts = counts.sort_values()\n    return counts","metadata":{"_uuid":"86c06ed4c0dbf02c605e447a5ecc40373b35771a","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:04.382153Z","iopub.execute_input":"2024-10-23T16:10:04.382392Z","iopub.status.idle":"2024-10-23T16:10:04.387812Z","shell.execute_reply.started":"2024-10-23T16:10:04.382352Z","shell.execute_reply":"2024-10-23T16:10:04.386999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lyso_endo_counts = find_counts(\"Lysosomes\", train_labels)\n\nplt.figure(figsize=(10,3))\nsns.barplot(x=lyso_endo_counts.index.values, y=lyso_endo_counts.values, palette=\"Blues\")\nplt.ylabel(\"Counts in train data\")","metadata":{"_uuid":"e2af724b721a15ebd294771629fb270c9ad9f0ae","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:04.389235Z","iopub.execute_input":"2024-10-23T16:10:04.389765Z","iopub.status.idle":"2024-10-23T16:10:04.554920Z","shell.execute_reply.started":"2024-10-23T16:10:04.389698Z","shell.execute_reply":"2024-10-23T16:10:04.554130Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Rods and rings","metadata":{"_uuid":"dc6dbcea143b60d0ef360e75d14b53b09d36e7be"}},{"cell_type":"code","source":"rod_rings_counts = find_counts(\"Rods & rings\", train_labels)\nplt.figure(figsize=(15,3))\nsns.barplot(x=rod_rings_counts.index.values, y=rod_rings_counts.values, palette=\"Greens\")\nplt.ylabel(\"Counts in train data\")","metadata":{"_uuid":"5f13e4113cfb00ec8b2de6d01fb548e10b794279","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:04.556953Z","iopub.execute_input":"2024-10-23T16:10:04.557538Z","iopub.status.idle":"2024-10-23T16:10:04.753254Z","shell.execute_reply.started":"2024-10-23T16:10:04.557314Z","shell.execute_reply":"2024-10-23T16:10:04.752240Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Peroxisomes","metadata":{"_uuid":"fea4a1a472bf60fdc1a5317a2e616c98b781f7ab"}},{"cell_type":"code","source":"peroxi_counts = find_counts(\"Peroxisomes\", train_labels)\n\nplt.figure(figsize=(15,3))\nsns.barplot(x=peroxi_counts.index.values, y=peroxi_counts.values, palette=\"Reds\")\nplt.ylabel(\"Counts in train data\")","metadata":{"_uuid":"11fef619f19eafc3657d693d05f7a50c786e0621","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:04.755257Z","iopub.execute_input":"2024-10-23T16:10:04.755827Z","iopub.status.idle":"2024-10-23T16:10:04.953215Z","shell.execute_reply.started":"2024-10-23T16:10:04.755752Z","shell.execute_reply":"2024-10-23T16:10:04.952324Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Microtubule ends","metadata":{"_uuid":"555447f455cac28ec0c84b09b89f32b657371470"}},{"cell_type":"code","source":"tubeends_counts = find_counts(\"Microtubule ends\", train_labels)\n\nplt.figure(figsize=(15,3))\nsns.barplot(x=tubeends_counts.index.values, y=tubeends_counts.values, palette=\"Purples\")\nplt.ylabel(\"Counts in train data\")","metadata":{"_uuid":"a543faa3994e6bd7b57fda135ea4b5bea40efed3","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:04.956901Z","iopub.execute_input":"2024-10-23T16:10:04.957197Z","iopub.status.idle":"2024-10-23T16:10:05.132014Z","shell.execute_reply.started":"2024-10-23T16:10:04.957140Z","shell.execute_reply":"2024-10-23T16:10:05.131009Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Nuclear speckles","metadata":{"_uuid":"0a04ae9a48f60f02021c0dba920b2ac3d6d65b38"}},{"cell_type":"code","source":"nuclear_speckles_counts = find_counts(\"Nuclear speckles\", train_labels)\n\nplt.figure(figsize=(15,3))\nsns.barplot(x=nuclear_speckles_counts.index.values, y=nuclear_speckles_counts.values, palette=\"Oranges\")\nplt.xticks(rotation=\"70\")\nplt.ylabel(\"Counts in train data\");","metadata":{"_uuid":"85d838037fc3310b9eef31dc4e6c64e1bc35efec","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:05.133925Z","iopub.execute_input":"2024-10-23T16:10:05.134424Z","iopub.status.idle":"2024-10-23T16:10:05.488225Z","shell.execute_reply.started":"2024-10-23T16:10:05.134222Z","shell.execute_reply":"2024-10-23T16:10:05.487321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Conclusión\n\n* Podemos ver que incluso con targets muy poco frecuentes encontramos algún tipo de agrupación con otras targets que revelan dónde parece estar localizada la estructura de la proteína. \n* Por ejemplo, podemos ver que las varillas y los anillos tienen algo que ver con el núcleo mientras que los peroxisomas pueden estar localizados tanto en el núcleo como en el citosol. ","metadata":{"_uuid":"ba2b973b09d2436f65e8775b214d377d46b29188"}},{"cell_type":"markdown","source":"## Como se ven las imagenes\n\n","metadata":{"_uuid":"0714e168ea347df2111124d0f341de3172bac00d"}},{"cell_type":"code","source":"from os import listdir\n\nfiles = listdir(\"../input/human-protein-atlas-image-classification/train\")\nfor n in range(10):\n    print(files[n])","metadata":{"_kg_hide-input":true,"_uuid":"1d11fa62aaa798cfcb8671b7aac0e4cd4fa18776","execution":{"iopub.status.busy":"2024-10-23T16:10:05.489669Z","iopub.execute_input":"2024-10-23T16:10:05.490180Z","iopub.status.idle":"2024-10-23T16:10:05.582320Z","shell.execute_reply.started":"2024-10-23T16:10:05.490124Z","shell.execute_reply":"2024-10-23T16:10:05.581537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Parece que para un id de imagen, hay diferentes canales de color presentes. Mirando en la descripción de datos de esta competición podemos encontrar que:\n\n* Cada imagen se divide en 4 archivos de imagen diferentes. \n* Estos 4 archivos corresponden a 4 filtros diferentes:\n    * Un filtro verde para la estructura de la proteína de interés.\n    * un filtro **azul** para el **núcleo**.\n    * Un filtro **rojo** para los **microtúbulos**.\n    * Filtro amarillo para el retículo endoplasmático.\n* Cada imagen tiene un tamaño de 512 x 512","metadata":{"_uuid":"8f8804380faaaeb428227dec5ee280f27c57baea"}},{"cell_type":"code","source":"len(files) / 4 == train_labels.shape[0]","metadata":{"_kg_hide-input":true,"_uuid":"8545dd9afec3e0cdc02873375ba81ff4f4658aab","execution":{"iopub.status.busy":"2024-10-23T16:10:05.584273Z","iopub.execute_input":"2024-10-23T16:10:05.584748Z","iopub.status.idle":"2024-10-23T16:10:05.590451Z","shell.execute_reply.started":"2024-10-23T16:10:05.584685Z","shell.execute_reply":"2024-10-23T16:10:05.589655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ¿Qué aspecto tienen las imágenes de objetivos específicos?\n\nMientras miramos ejemplos, podemos construir un cargador por lotes:","metadata":{"_uuid":"b89a5ae1b6e358d7100c79e5a2cdc5d77ff88cc2"}},{"cell_type":"code","source":"train_path = \"../input/human-protein-atlas-image-classification/train/\"","metadata":{"_uuid":"ce954da724c8a400c12080f8c3f986a537d4a4c4","execution":{"iopub.status.busy":"2024-10-23T16:10:05.592044Z","iopub.execute_input":"2024-10-23T16:10:05.592373Z","iopub.status.idle":"2024-10-23T16:10:05.597949Z","shell.execute_reply.started":"2024-10-23T16:10:05.592315Z","shell.execute_reply":"2024-10-23T16:10:05.597176Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_image(basepath, image_id):\n    images = np.zeros(shape=(4,512,512))\n    images[0,:,:] = imread(basepath + image_id + \"_green\" + \".png\")\n    images[1,:,:] = imread(basepath + image_id + \"_red\" + \".png\")\n    images[2,:,:] = imread(basepath + image_id + \"_blue\" + \".png\")\n    images[3,:,:] = imread(basepath + image_id + \"_yellow\" + \".png\")\n    return images\n\ndef make_image_row(image, subax, title):\n    subax[0].imshow(image[0], cmap=\"Greens\")\n    subax[1].imshow(image[1], cmap=\"Reds\")\n    subax[1].set_title(\"stained microtubules\")\n    subax[2].imshow(image[2], cmap=\"Blues\")\n    subax[2].set_title(\"stained nucleus\")\n    subax[3].imshow(image[3], cmap=\"Oranges\")\n    subax[3].set_title(\"stained endoplasmatic reticulum\")\n    subax[0].set_title(title)\n    return subax\n\ndef make_title(file_id):\n    file_targets = train_labels.loc[train_labels.Id==file_id, \"Target\"].values[0]\n    title = \" - \"\n    for n in file_targets:\n        title += label_names[n] + \" - \"\n    return title","metadata":{"_uuid":"c7e4ffb20ebaee046d888620d0cf016f0cebf2c4","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:05.599387Z","iopub.execute_input":"2024-10-23T16:10:05.599717Z","iopub.status.idle":"2024-10-23T16:10:05.615149Z","shell.execute_reply.started":"2024-10-23T16:10:05.599663Z","shell.execute_reply":"2024-10-23T16:10:05.614418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TargetGroupIterator:\n    \n    def __init__(self, target_names, batch_size, basepath):\n        self.target_names = target_names\n        self.target_list = [reverse_train_labels[key] for key in target_names]\n        self.batch_shape = (batch_size, 4, 512, 512)\n        self.basepath = basepath\n    \n    def find_matching_data_entries(self):\n        train_labels[\"check_col\"] = train_labels.Target.apply(\n            lambda l: self.check_subset(l)\n        )\n        self.images_identifier = train_labels[train_labels.check_col==1].Id.values\n        train_labels.drop(\"check_col\", axis=1, inplace=True)\n    \n    def check_subset(self, targets):\n        return np.where(set(self.target_list).issubset(set(targets)), 1, 0)\n    \n    def get_loader(self):\n        filenames = []\n        idx = 0\n        images = np.zeros(self.batch_shape)\n        for image_id in self.images_identifier:\n            images[idx,:,:,:] = load_image(self.basepath, image_id)\n            filenames.append(image_id)\n            idx += 1\n            if idx == self.batch_shape[0]:\n                yield filenames, images\n                filenames = []\n                images = np.zeros(self.batch_shape)\n                idx = 0\n        if idx > 0:\n            yield filenames, images\n            ","metadata":{"_uuid":"090d1b258d2641e747e58a49376ab3d32b3893b8","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:05.616610Z","iopub.execute_input":"2024-10-23T16:10:05.616859Z","iopub.status.idle":"2024-10-23T16:10:05.629680Z","shell.execute_reply.started":"2024-10-23T16:10:05.616807Z","shell.execute_reply":"2024-10-23T16:10:05.628818Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"example_pro = [\"Lysosomes\", \"Endosomes\"]\nbatch_size_example = 20","metadata":{"_uuid":"445f454dc36c1f4056bc870e8810f219f1c560ea","execution":{"iopub.status.busy":"2024-10-23T16:10:05.631096Z","iopub.execute_input":"2024-10-23T16:10:05.631414Z","iopub.status.idle":"2024-10-23T16:10:05.640029Z","shell.execute_reply.started":"2024-10-23T16:10:05.631357Z","shell.execute_reply":"2024-10-23T16:10:05.639373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"imageloader = TargetGroupIterator(example_pro, batch_size_example, train_path)\nimageloader.find_matching_data_entries()\niterator = imageloader.get_loader()","metadata":{"_uuid":"6dcd0c8f57651ba21b82420edd37f70f93953215","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:05.641423Z","iopub.execute_input":"2024-10-23T16:10:05.641747Z","iopub.status.idle":"2024-10-23T16:10:05.842858Z","shell.execute_reply.started":"2024-10-23T16:10:05.641689Z","shell.execute_reply":"2024-10-23T16:10:05.842155Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"file_ids, images = next(iterator)\n\nfig, ax = plt.subplots(len(file_ids),4,figsize=(20,5*len(file_ids)))\nif ax.shape == (4,):\n    ax = ax.reshape(1,-1)\nfor n in range(len(file_ids)):\n    make_image_row(images[n], ax[n], make_title(file_ids[n]))","metadata":{"_kg_hide-input":true,"_uuid":"5f7c98a6e15c081fcbe54c4e678ea2ea5ae4fbd7","execution":{"iopub.status.busy":"2024-10-23T16:10:05.844136Z","iopub.execute_input":"2024-10-23T16:10:05.844359Z","iopub.status.idle":"2024-10-23T16:10:23.476891Z","shell.execute_reply.started":"2024-10-23T16:10:05.844321Z","shell.execute_reply":"2024-10-23T16:10:23.476063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Conclusión\n\n* Observando estos pocos ejemplos ya podemos obtener algunas ideas:\n    * La tinción de las proteínas diana en el canal verde no tuvo el mismo éxito. Las **imágenes difieren en sus intensidades y las proteínas diana no siempre están localizadas de la misma manera**. La primera imagen que se obtiene con el cargador muestra endosomas repartidos por toda la célula y en la segunda y tercera se encuentran endosomas y lisosomas más concentrados alrededor del núcleo. \n    * Especialmente **en el canal rojo podemos ver diferencias morfológicas**. Parece como si las células fueran de diferentes tipos. Esto es sólo una suposición, pero tal vez se podría utilizar la información del canal rojo para revelar los tipos de células. \n* Haciendo clic de nuevo en esta pestaña de código con otros objetivos se puede observar que las imágenes pueden contener diferentes densidades celulares. **A veces toda la imagen está cubierta de células y a veces sólo hay unas pocas**. Además podemos ver que **algunas imágenes tienen valores más altos mientras que otras son más apagadas con valores bajos en general**. Si queremos detectar los mismos objetivos a partir de diferentes imágenes brillantes, esto causará problemas, ya que esperamos que se encuentren en un rango de valores similar. \n","metadata":{"_uuid":"a66576fbdab4678c42d183017335d1ef27eed655"}},{"cell_type":"markdown","source":"# Construyendo un modelo base <a class=\"anchor\" id=\"baseline\"></a>","metadata":{"_uuid":"ad5c5a22a659540bcb3da81453a6ef2cfaa958cc"}},{"cell_type":"markdown","source":"### K-Fold Cross-Validation","metadata":{"_uuid":"8dd65575d8a244f142b060aeb5cca30db9f27576"}},{"cell_type":"code","source":"train_files = listdir(\"../input/human-protein-atlas-image-classification/train\")\ntest_files = listdir(\"../input/human-protein-atlas-image-classification/test\")\npercentage = np.round(len(test_files) / len(train_files) * 100)\n\nprint(\"The test set size turns out to be {} % compared to the train set.\".format(percentage))","metadata":{"_uuid":"b2d74fa662ec90ebc2912105848daf7301845ef8","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:23.478454Z","iopub.execute_input":"2024-10-23T16:10:23.478739Z","iopub.status.idle":"2024-10-23T16:10:23.607768Z","shell.execute_reply.started":"2024-10-23T16:10:23.478684Z","shell.execute_reply":"2024-10-23T16:10:23.606795Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Para comprender el rendimiento de nuestro modelo, utilizaremos **la validación cruzada k-fold**. Los datos de entrenamiento se dividen en k fragmentos y cada fragmento se utiliza una vez para probar el rendimiento de la predicción, mientras que los demás se utilizan para el entrenamiento. Como nuestros objetivos muestran relaciones que parecen estar agrupadas de alguna manera, el rendimiento por fragmento de prueba probablemente depende en gran medida de la distribución de objetivos por fragmento de prueba. Por ejemplo, puede haber trozos con objetivos muy poco frecuentes que obtengan una mala puntuación y algunos trozos con objetivos muy frecuentes y una puntuación muy buena. Para reducir este efecto, **repetiremos el K-Fold varias veces** y observaremos las distribuciones de scoing al final.","metadata":{"_uuid":"2d9613edd4f1a05b54d79dbe142b78e8cbec7625"}},{"cell_type":"markdown","source":"Como nuestros datos de prueba tienen un tamaño del 38% en comparación con el conjunto de entrenamiento, tiene sentido utilizar la validación cruzada triple, en la que el conjunto de prueba tiene un tamaño del 33% en comparación con el conjunto de entrenamiento. Como estamos trabajando con redes neuronales que pueden ser exigentes en recursos computacionales, vamos a utilizar sólo 1 repetición. ","metadata":{"_uuid":"d94c71d94925daa6fe0a71a07c1da985925f7d91"}},{"cell_type":"code","source":"from sklearn.model_selection import RepeatedKFold\n\nsplitter = RepeatedKFold(n_splits=3, n_repeats=1, random_state=0)","metadata":{"_uuid":"29a024cbd71145018c36342a5e8a483b6e010f5b","execution":{"iopub.status.busy":"2024-10-23T16:10:23.609205Z","iopub.execute_input":"2024-10-23T16:10:23.609479Z","iopub.status.idle":"2024-10-23T16:10:23.613478Z","shell.execute_reply.started":"2024-10-23T16:10:23.609429Z","shell.execute_reply":"2024-10-23T16:10:23.612784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Este divisor es ahora un generador. Por lo tanto, si llama al método splitters split, obtendrá un pliegue de los pliegues K repetidos. Por consiguiente, si elegimos n_repeats=2, obtendremos 6 pliegues en total: 3 pliegues para la primera validación cruzada y otros 3 pliegues para la validación cruzada repetida. Realizaremos la división en los identificadores de imagen. De esta manera podemos cargar fácilmente las imágenes y los objetivos dados los chunk ids.","metadata":{}},{"cell_type":"code","source":"partitions = []\n\nfor train_idx, test_idx in splitter.split(train_labels.index.values):\n    partition = {}\n    partition[\"train\"] = train_labels.Id.values[train_idx]\n    partition[\"validation\"] = train_labels.Id.values[test_idx]\n    partitions.append(partition)\n    print(\"TRAIN:\", train_idx, \"TEST:\", test_idx)\n    print(\"TRAIN:\", len(train_idx), \"TEST:\", len(test_idx))","metadata":{"_uuid":"539a35dfd7d735d7068f32277146e60e15729e55","execution":{"iopub.status.busy":"2024-10-23T16:10:23.615049Z","iopub.execute_input":"2024-10-23T16:10:23.615595Z","iopub.status.idle":"2024-10-23T16:10:23.631898Z","shell.execute_reply.started":"2024-10-23T16:10:23.615294Z","shell.execute_reply":"2024-10-23T16:10:23.631055Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"partitions[0][\"train\"][0:5]","metadata":{"_uuid":"65f4c326d8f32f13872d0dfaaad2bbbfdda257a7","execution":{"iopub.status.busy":"2024-10-23T16:10:23.640251Z","iopub.execute_input":"2024-10-23T16:10:23.640514Z","iopub.status.idle":"2024-10-23T16:10:23.646081Z","shell.execute_reply.started":"2024-10-23T16:10:23.640463Z","shell.execute_reply":"2024-10-23T16:10:23.645120Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Recopilación de ideas\n\nA continuación, vamos a construir un modelo sencillo. Primero, es importante tener en cuenta algunas ideas clave:\n\n- **Nos enfocaremos únicamente en el canal verde de las imágenes**. Según la competencia, este canal muestra las proteínas targets teñidas, por lo que probablemente sea el más relevante. Las otras imágenes proporcionan referencias sobre los microtúbulos, el núcleo y el retículo endoplasmático. No estamos seguros de cuánta información ofrecen y, por el momento, al incluirlas solo aumentaríamos innecesariamente la complejidad del modelo con una cantidad masiva de pesos de red que no son esenciales.\n\n- **Usaremos generadores para cargar los lotes de imágenes según sea necesario**, evitando cargar todo el conjunto de datos de una sola vez. Las funciones de keras como `fit_generator`, `evaluate_generator`, y `predict_generator` permiten conectar estos generadores de forma sencilla, sin tener que preocuparnos por cómo keras maneja internamente este proceso.\n\n- Es recomendable escribir una **pequeña clase para realizar un preprocesamiento básico de las imágenes**. Esto nos permitirá modificar la fase de preprocesado de manera flexible, sin interferir con el modelo o la carga de datos.\n\n- También crearé una **pequeña clase que agrupe los parámetros que se compartan entre el cargador de datos, el preprocesador y el modelo base**. Al usar una instancia de esta clase, evitaremos problemas de desajuste de parámetros, como aquellos que podrían ocurrir durante la configuración y compilación de las capas de la red.","metadata":{"_uuid":"e0c336986b46a35c224dd447190fbb8c553bb64a"}},{"cell_type":"code","source":"class ModelParameter:\n    \n    def __init__(self, basepath,\n                 num_classes=28,\n                 image_rows=512,\n                 image_cols=512,\n                 batch_size=200,\n                 n_channels=1,\n                 row_scale_factor=4,\n                 col_scale_factor=4,\n                 shuffle=False,\n                 n_epochs=1):\n        self.basepath = basepath\n        self.num_classes = num_classes\n        self.image_rows = image_rows\n        self.image_cols = image_cols\n        self.batch_size = batch_size\n        self.n_channels = n_channels\n        self.shuffle = shuffle\n        self.row_scale_factor = row_scale_factor\n        self.col_scale_factor = col_scale_factor\n        self.scaled_row_dim = np.int(self.image_rows / self.row_scale_factor)\n        self.scaled_col_dim = np.int(self.image_cols / self.col_scale_factor)\n        self.n_epochs = n_epochs","metadata":{"_uuid":"96df4f1aa1085b95b806b48071c0737d45a5b708","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:23.647791Z","iopub.execute_input":"2024-10-23T16:10:23.648078Z","iopub.status.idle":"2024-10-23T16:10:23.656567Z","shell.execute_reply.started":"2024-10-23T16:10:23.648023Z","shell.execute_reply":"2024-10-23T16:10:23.655866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"parameter = ModelParameter(train_path)","metadata":{"_uuid":"96b80b33c817ad07deac345e36c46c062255c60d","execution":{"iopub.status.busy":"2024-10-23T16:10:23.657884Z","iopub.execute_input":"2024-10-23T16:10:23.658169Z","iopub.status.idle":"2024-10-23T16:10:23.663602Z","shell.execute_reply.started":"2024-10-23T16:10:23.658105Z","shell.execute_reply":"2024-10-23T16:10:23.662684Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Image Preprocessor","metadata":{"_uuid":"4497282fcdc0d68554e3878bb82bae8942eda681"}},{"cell_type":"code","source":"from skimage.transform import resize\n\nclass ImagePreprocessor:\n    \n    def __init__(self, modelparameter):\n        self.parameter = modelparameter\n        self.basepath = self.parameter.basepath\n        self.scaled_row_dim = self.parameter.scaled_row_dim\n        self.scaled_col_dim = self.parameter.scaled_col_dim\n        self.n_channels = self.parameter.n_channels\n    \n    def preprocess(self, image):\n        image = self.resize(image)\n        image = self.reshape(image)\n        image = self.normalize(image)\n        return image\n    \n    def resize(self, image):\n        image = resize(image, (self.scaled_row_dim, self.scaled_col_dim))\n        return image\n    \n    def reshape(self, image):\n        image = np.reshape(image, (image.shape[0], image.shape[1], self.n_channels))\n        return image\n    \n    def normalize(self, image):\n        image /= 255 \n        return image\n    \n    def load_image(self, image_id):\n        image = np.zeros(shape=(512,512,4))\n        image[:,:,0] = imread(self.basepath + image_id + \"_green\" + \".png\")\n        image[:,:,1] = imread(self.basepath + image_id + \"_blue\" + \".png\")\n        image[:,:,2] = imread(self.basepath + image_id + \"_red\" + \".png\")\n        image[:,:,3] = imread(self.basepath + image_id + \"_yellow\" + \".png\")\n        return image[:,:,0:self.parameter.n_channels]\n        ","metadata":{"_uuid":"2674c1331715aeab66a0194b3ad31afa7cfc3444","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:23.664781Z","iopub.execute_input":"2024-10-23T16:10:23.665210Z","iopub.status.idle":"2024-10-23T16:10:23.683630Z","shell.execute_reply.started":"2024-10-23T16:10:23.665082Z","shell.execute_reply":"2024-10-23T16:10:23.682765Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preprocessor = ImagePreprocessor(parameter)","metadata":{"_uuid":"589121752a0ca1693c7e794655047f947a476b8e","execution":{"iopub.status.busy":"2024-10-23T16:10:23.684736Z","iopub.execute_input":"2024-10-23T16:10:23.684993Z","iopub.status.idle":"2024-10-23T16:10:23.694689Z","shell.execute_reply.started":"2024-10-23T16:10:23.684946Z","shell.execute_reply":"2024-10-23T16:10:23.693925Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"example = images[0,0]\npreprocessed = preprocessor.preprocess(example)\nprint(example.shape)\nprint(preprocessed.shape)\n\nfig, ax = plt.subplots(1,2,figsize=(20,10))\nax[0].imshow(example, cmap=\"Greens\")\nax[1].imshow(preprocessed.reshape(parameter.scaled_row_dim,parameter.scaled_col_dim), cmap=\"Greens\")","metadata":{"_kg_hide-input":true,"_uuid":"cc9f0ff3eecc870337c475533b4c1cffed704403","execution":{"iopub.status.busy":"2024-10-23T16:10:23.696040Z","iopub.execute_input":"2024-10-23T16:10:23.696522Z","iopub.status.idle":"2024-10-23T16:10:24.323861Z","shell.execute_reply.started":"2024-10-23T16:10:23.696461Z","shell.execute_reply":"2024-10-23T16:10:24.322964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Puede ver que hemos perdido mucha información al reducir la escala de la imagen.","metadata":{"_uuid":"615d734ed90fb1def88151c5365443d61b411536"}},{"cell_type":"markdown","source":"### Data Generator\n","metadata":{"_uuid":"2b3cecd1dde678563c35405a7ddde5c35314677b"}},{"cell_type":"code","source":"import keras\n\nclass DataGenerator(keras.utils.Sequence):\n    \n    def __init__(self, list_IDs, labels, modelparameter, imagepreprocessor):\n        self.current_epoch = 0\n        self.params = modelparameter\n        self.labels = labels\n        self.list_IDs = list_IDs\n        self.dim = (self.params.scaled_row_dim, self.params.scaled_col_dim)\n        self.batch_size = self.params.batch_size\n        self.n_channels = self.params.n_channels\n        self.num_classes = self.params.num_classes\n        self.shuffle = self.params.shuffle\n        self.preprocessor = imagepreprocessor\n        self.on_epoch_end()\n    \n    def on_epoch_end(self):\n        self.indexes = np.arange(len(self.list_IDs))\n        if self.shuffle == True:\n            np.random.shuffle(self.indexes, random_state=self.current_epoch)\n            self.current_epoch += 1\n    \n    def get_targets_per_image(self, identifier):\n        return self.labels.loc[self.labels.Id==identifier].drop(\n                [\"Id\", \"Target\", \"number_of_targets\"], axis=1).values\n            \n    def __data_generation(self, list_IDs_temp):\n        'Generates data containing batch_size samples' # X : (n_samples, *dim, n_channels)\n        # Initialization\n        X = np.empty((self.batch_size, *self.dim, self.n_channels))\n        y = np.empty((self.batch_size, self.num_classes), dtype=int)\n        # Generate data\n        for i, identifier in enumerate(list_IDs_temp):\n            # Store sample\n            image = self.preprocessor.load_image(identifier)\n            image = self.preprocessor.preprocess(image)\n            X[i] = image\n            # Store class\n            y[i] = self.get_targets_per_image(identifier)\n        return X, y\n    \n    def __len__(self):\n        'Denotes the number of batches per epoch'\n        return int(np.floor(len(self.list_IDs) / self.batch_size))\n    \n    def __getitem__(self, index):\n        'Generate one batch of data'\n        # Generate indexes of the batch\n        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]\n        # Find list of IDs\n        list_IDs_temp = [self.list_IDs[k] for k in indexes]\n        # Generate data\n        X, y = self.__data_generation(list_IDs_temp)\n        return X, y","metadata":{"_uuid":"6e77e06f77164446a8689b55fd56734f943368b1","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:10:24.325179Z","iopub.execute_input":"2024-10-23T16:10:24.325408Z","iopub.status.idle":"2024-10-23T16:10:24.343800Z","shell.execute_reply.started":"2024-10-23T16:10:24.325369Z","shell.execute_reply":"2024-10-23T16:10:24.343005Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class PredictGenerator:\n    \n    def __init__(self, predict_Ids, imagepreprocessor, predict_path):\n        self.preprocessor = imagepreprocessor\n        self.preprocessor.basepath = predict_path\n        self.identifiers = predict_Ids\n    \n    def predict(self, model):\n        y = np.empty(shape=(len(self.identifiers), self.preprocessor.parameter.num_classes))\n        for n in range(len(self.identifiers)):\n            image = self.preprocessor.load_image(self.identifiers[n])\n            image = self.preprocessor.preprocess(image)\n            image = image.reshape((1, *image.shape))\n            y[n] = model.predict(image)\n        return y","metadata":{"_uuid":"7867efb076524384d57556b13283aeb45b0ea1dd","execution":{"iopub.status.busy":"2024-10-23T16:10:24.345147Z","iopub.execute_input":"2024-10-23T16:10:24.345418Z","iopub.status.idle":"2024-10-23T16:10:24.355106Z","shell.execute_reply.started":"2024-10-23T16:10:24.345366Z","shell.execute_reply":"2024-10-23T16:10:24.354348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Modelos con diferentes arquitecturas","metadata":{}},{"cell_type":"code","source":"!pip install --upgrade tensorflow","metadata":{"execution":{"iopub.status.busy":"2024-10-23T16:10:24.356454Z","iopub.execute_input":"2024-10-23T16:10:24.356774Z","iopub.status.idle":"2024-10-23T16:12:58.756191Z","shell.execute_reply.started":"2024-10-23T16:10:24.356721Z","shell.execute_reply":"2024-10-23T16:12:58.755312Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### ","metadata":{"_uuid":"48e03c679baabe6f4a57cb9da335ccb6d6f9710b"}},{"cell_type":"code","source":"from keras.models import Sequential\nfrom keras.layers import Dense, Dropout, Flatten\nfrom keras.layers import Conv2D, MaxPooling2D\nfrom keras.losses import binary_crossentropy\nfrom keras.optimizers import Adadelta\nfrom keras.initializers import VarianceScaling\n\n\nclass BaseLineModel:\n    \n    def __init__(self, modelparameter):\n        self.params = modelparameter\n        self.num_classes = self.params.num_classes\n        self.img_rows = self.params.scaled_row_dim\n        self.img_cols = self.params.scaled_col_dim\n        self.n_channels = self.params.n_channels\n        self.input_shape = (self.img_rows, self.img_cols, self.n_channels)\n        self.my_metrics = ['accuracy']\n    \n    def build_model(self):\n        self.model = Sequential()\n        self.model.add(Conv2D(16, kernel_size=(3, 3), activation='relu', input_shape=self.input_shape,\n                             kernel_initializer=VarianceScaling(seed=0)))\n        self.model.add(Conv2D(32, (3, 3), activation='relu',\n                             kernel_initializer=VarianceScaling(seed=0)))\n        self.model.add(MaxPooling2D(pool_size=(2, 2)))\n        self.model.add(Dropout(0.25))\n        self.model.add(Flatten())\n        self.model.add(Dense(64, activation='relu',\n                            kernel_initializer=VarianceScaling(seed=0),))\n        self.model.add(Dropout(0.5))\n        self.model.add(Dense(self.num_classes, activation='sigmoid'))\n    \n    def compile_model(self):\n        self.model.compile(loss=keras.losses.binary_crossentropy,\n              optimizer=keras.optimizers.Adadelta(),\n              metrics=self.my_metrics)\n    \n    def set_generators(self, train_generator, validation_generator):\n        self.training_generator = train_generator\n        self.validation_generator = validation_generator\n    \n    def learn(self):\n        return self.model.fit_generator(generator=self.training_generator,\n                    validation_data=self.validation_generator,\n                    epochs=self.params.n_epochs, \n                    use_multiprocessing=True,\n                    workers=8)\n    \n    def score(self):\n        return self.model.evaluate_generator(generator=self.validation_generator,\n                                      use_multiprocessing=True, \n                                      workers=8)\n    \n    def predict(self, predict_generator):\n        y = predict_generator.predict(self.model)\n        return y\n    \n    def save(self, modeloutputpath):\n        self.model.save(modeloutputpath)\n    \n    def load(self, modelinputpath):\n        self.model = load_model(modelinputpath)","metadata":{"_uuid":"76a48f7a606ef5293bfc465871c707ce9b3900a8","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:12:58.757960Z","iopub.execute_input":"2024-10-23T16:12:58.758219Z","iopub.status.idle":"2024-10-23T16:12:58.779003Z","shell.execute_reply.started":"2024-10-23T16:12:58.758177Z","shell.execute_reply":"2024-10-23T16:12:58.778177Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Training the baseline on the first cv-fold","metadata":{"_uuid":"79ae4ddf40420cb60ed564e515dc6a8fe3fd2d82"}},{"cell_type":"code","source":"# Datasets\npartition = partitions[0]\nlabels = train_labels\n\nprint(\"Number of samples in train: {}\".format(len(partition[\"train\"])))\nprint(\"Number of samples in validation: {}\".format(len(partition[\"validation\"])))","metadata":{"_uuid":"819cb636a11da079e2f2a387a8cad6c3a7bd3105","execution":{"iopub.status.busy":"2024-10-23T16:12:58.780240Z","iopub.execute_input":"2024-10-23T16:12:58.780560Z","iopub.status.idle":"2024-10-23T16:12:58.790709Z","shell.execute_reply.started":"2024-10-23T16:12:58.780457Z","shell.execute_reply":"2024-10-23T16:12:58.789800Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"A continuación tenemos que configurar nuestros generadores de datos: Necesitamos dos durante el entrenamiento, uno para las imágenes de entrenamiento y otro para las imágenes de validación. De esta forma podemos pasar ambos al modelo y observar cómo cambia el rendimiento de validación durante el entrenamiento en las imágenes de entrenamiento. De esta forma podemos ver el punto de cambio, cuando la pérdida de entrenamiento disminuye y la pérdida de validación aumenta. En esta situación, el modelo aprende demasiados detalles de las imágenes de entrenamiento. Sufre de sobreajuste y pierde su capacidad de hacer buenas predicciones en las imágenes de validación. \n","metadata":{"_uuid":"d611a18a40ed80ba6296c3f819d38e8628030fe2"}},{"cell_type":"code","source":"training_generator = DataGenerator(partition['train'], labels, parameter, preprocessor)\nvalidation_generator = DataGenerator(partition['validation'], labels, parameter, preprocessor)","metadata":{"_uuid":"453d8dc45e28db3d49ed281dd698f03fe1aa1cb8","execution":{"iopub.status.busy":"2024-10-23T16:12:58.791991Z","iopub.execute_input":"2024-10-23T16:12:58.792443Z","iopub.status.idle":"2024-10-23T16:12:58.797503Z","shell.execute_reply.started":"2024-10-23T16:12:58.792231Z","shell.execute_reply":"2024-10-23T16:12:58.796694Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In addition we like to make predictions for the validation data and for the test submission data. For the test submission data we need to create a new instance of an ImagePreprocessor with same model parameters. During call of predict generator its basepath of the images is changed from train to testpath:","metadata":{"_uuid":"955f4994a2e8487ee9e311a858f2c38e0db62b74"}},{"cell_type":"code","source":"predict_generator = PredictGenerator(partition['validation'], preprocessor, train_path)","metadata":{"_uuid":"a14c3eacf85fd5e92908ce4983c9e7b4d054a77a","execution":{"iopub.status.busy":"2024-10-23T16:12:58.799029Z","iopub.execute_input":"2024-10-23T16:12:58.799515Z","iopub.status.idle":"2024-10-23T16:12:58.804654Z","shell.execute_reply.started":"2024-10-23T16:12:58.799453Z","shell.execute_reply":"2024-10-23T16:12:58.803767Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_preprocessor = ImagePreprocessor(parameter)\nsubmission_predict_generator = PredictGenerator(test_names, test_preprocessor, test_path)","metadata":{"_uuid":"693471536246aefc2e57d61abd423616688eed94","execution":{"iopub.status.busy":"2024-10-23T16:12:58.805798Z","iopub.execute_input":"2024-10-23T16:12:58.806032Z","iopub.status.idle":"2024-10-23T16:12:58.812407Z","shell.execute_reply.started":"2024-10-23T16:12:58.805993Z","shell.execute_reply":"2024-10-23T16:12:58.811541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Run computation and store results as csv\ntarget_names = train_labels.drop([\"Target\", \"number_of_targets\", \"Id\"], axis=1).columns\n\nif kernelsettings.fit_baseline == True:\n    model = BaseLineModel(parameter)\n    model.build_model()\n    model.compile_model()\n    model.set_generators(training_generator, validation_generator)\n    history = model.learn()\n    \n    proba_predictions = model.predict(predict_generator)\n    baseline_proba_predictions = pd.DataFrame(index = partition['validation'],\n                                              data=proba_predictions,\n                                              columns=target_names)\n    baseline_proba_predictions.to_csv(\"baseline_predictions.csv\")\n    baseline_losses = pd.DataFrame(history.history[\"loss\"], columns=[\"train_loss\"])\n    baseline_losses[\"val_loss\"] = history.history[\"val_loss\"]\n    baseline_losses.to_csv(\"baseline_losses.csv\")\n    \n    \n    submission_proba_predictions = model.predict(submission_predict_generator)\n    baseline_labels = test_labels.copy()\n    baseline_labels.loc[:, test_labels.drop([\"Id\", \"Target\"], axis=1).columns.values] = submission_proba_predictions\n    baseline_labels.to_csv(\"baseline_submission_proba.csv\")\n# If you already have done a baseline fit once, \n# you can load predictions as csv and further fitting is not neccessary:\nelse:\n    baseline_proba_predictions = pd.read_csv(\"../input/protein-atlas-eab-predictions/baseline_predictions.csv\", index_col=0)\n    baseline_losses = pd.read_csv(\"../input/protein-atlas-eab-predictions/baseline_losses.csv\", index_col=0)\n    baseline_labels = pd.read_csv(\"../input/protein-atlas-eab-predictions/baseline_submission_proba.csv\", index_col=0)","metadata":{"_uuid":"6bdc3802ae488499de2afacb32e2e93bee5dccf4","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:12:58.813590Z","iopub.execute_input":"2024-10-23T16:12:58.813857Z","iopub.status.idle":"2024-10-23T16:12:59.063615Z","shell.execute_reply.started":"2024-10-23T16:12:58.813808Z","shell.execute_reply":"2024-10-23T16:12:59.062937Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from tensorflow.keras.applications import VGG16, ResNet50, DenseNet121\n# from tensorflow.keras.layers import Flatten\n# from sklearn.svm import SVC\n# from sklearn.neural_network import MLPClassifier\n# from sklearn.model_selection import GridSearchCV\n# import numpy as np\n\n# # Arquitecturas CNN sin la capa final\n# def get_base_model(architecture, input_shape=(128, 128, 1)):\n#     if architecture == 'lenet':\n#         model = models.Sequential()\n#         model.add(layers.Conv2D(6, (5, 5), activation='relu', input_shape=(32, 32, 1)))\n#         model.add(layers.AveragePooling2D())\n#         model.add(layers.Conv2D(16, (5, 5), activation='relu'))\n#         model.add(layers.AveragePooling2D())\n#         model.add(layers.Flatten())\n#         return model\n#     elif architecture == 'vgg16':\n#         base_model = VGG16(weights=None, include_top=False, input_shape=input_shape)\n#     elif architecture == 'resnet':\n#         base_model = ResNet50(weights='imagenet', include_top=False, input_shape=input_shape)\n#     elif architecture == 'densenet':\n#         base_model = DenseNet121(weights='imagenet', include_top=False, input_shape=input_shape)\n    \n#     # Agregar capa de flattening al final del modelo\n#     model = models.Sequential([base_model, Flatten()])\n#     return model\n\n# architecture = 'vgg16'  \n\n# cnn_model = get_base_model(architecture)\n\n# features_train = []\n# labels_train = []\n\n# for i in range(len(training_generator)):\n#     X_batch, y_batch = training_generator[i]\n#     features_batch = cnn_model.predict(X_batch)\n#     features_train.append(features_batch)\n#     labels_train.append(y_batch)\n\n# features_train = np.vstack(features_train)\n# labels_train = np.vstack(labels_train)\n\n# features_val = []\n# labels_val = []\n\n# for i in range(len(validation_generator)):\n#     X_batch, y_batch = validation_generator[i]\n#     features_batch = cnn_model.predict(X_batch)\n#     features_val.append(features_batch)\n#     labels_val.append(y_batch)\n\n# # Convertir listas a matrices numpy\n# features_val = np.vstack(features_val)\n# labels_val = np.vstack(labels_val)\n\n# # Clasificadores de MLP\n# mlp = MLPClassifier()\n\n# # Hiperparámetros para GridSearch\n# param_grid = {\n#     'hidden_layer_sizes': [(1,), (10,), (100,), (1000,), (10000,)],\n#     'activation': ['relu', 'tanh', 'logistic']\n# }\n\n# # GridSearchCV para el clasificador MLP\n# grid = GridSearchCV(mlp, param_grid, cv=3)\n# grid.fit(features_train, labels_train)\n\n# # Evaluación en validación\n# print(\"Mejores parámetros:\", grid.best_params_)\n# print(\"Precisión en validación:\", grid.score(features_val, labels_val))","metadata":{"execution":{"iopub.status.busy":"2024-10-23T16:12:59.064946Z","iopub.execute_input":"2024-10-23T16:12:59.065217Z","iopub.status.idle":"2024-10-23T16:12:59.070823Z","shell.execute_reply.started":"2024-10-23T16:12:59.065170Z","shell.execute_reply":"2024-10-23T16:12:59.069936Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validation_labels = train_labels.loc[train_labels.Id.isin(partition[\"validation\"])].copy()\nvalidation_labels.shape","metadata":{"_uuid":"8ed1e7784c82006e8aa08eb1e18a06cd4af8ecd8","execution":{"iopub.status.busy":"2024-10-23T16:12:59.072536Z","iopub.execute_input":"2024-10-23T16:12:59.072886Z","iopub.status.idle":"2024-10-23T16:12:59.099160Z","shell.execute_reply.started":"2024-10-23T16:12:59.072818Z","shell.execute_reply":"2024-10-23T16:12:59.098386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"baseline_proba_predictions.shape","metadata":{"_uuid":"bff003f4dab07bc1a63fff252507e113c7029cad","execution":{"iopub.status.busy":"2024-10-23T16:12:59.100785Z","iopub.execute_input":"2024-10-23T16:12:59.101141Z","iopub.status.idle":"2024-10-23T16:12:59.106973Z","shell.execute_reply.started":"2024-10-23T16:12:59.101065Z","shell.execute_reply":"2024-10-23T16:12:59.106185Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score as accuracy\n\ny_true = validation_labels.drop([\"Id\", \"Target\", \"number_of_targets\"], axis=1).values\ny_pred = np.where(baseline_proba_predictions.values > 0.5, 1, 0)\n\naccuracy(y_true.flatten(), y_pred.flatten())","metadata":{"_uuid":"cebda6fe90a579b4f007e95c27b71e1d503ca84e","execution":{"iopub.status.busy":"2024-10-23T16:12:59.108303Z","iopub.execute_input":"2024-10-23T16:12:59.108631Z","iopub.status.idle":"2024-10-23T16:12:59.139899Z","shell.execute_reply.started":"2024-10-23T16:12:59.108585Z","shell.execute_reply":"2024-10-23T16:12:59.139186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred[0]","metadata":{"_uuid":"c3f79558fd86530e8baf01eb1b4a233f5eea9cc4","execution":{"iopub.status.busy":"2024-10-23T16:12:59.141025Z","iopub.execute_input":"2024-10-23T16:12:59.141264Z","iopub.status.idle":"2024-10-23T16:12:59.146541Z","shell.execute_reply.started":"2024-10-23T16:12:59.141225Z","shell.execute_reply":"2024-10-23T16:12:59.145748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_true[0]","metadata":{"_uuid":"1bdefea146c0c50bc9d78fb2ddf41c2f9e4b1f14","execution":{"iopub.status.busy":"2024-10-23T16:12:59.148145Z","iopub.execute_input":"2024-10-23T16:12:59.148624Z","iopub.status.idle":"2024-10-23T16:12:59.155146Z","shell.execute_reply.started":"2024-10-23T16:12:59.148565Z","shell.execute_reply":"2024-10-23T16:12:59.154189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"proba_predictions = baseline_proba_predictions.values\nhot_values = validation_labels.drop([\"Id\", \"Target\", \"number_of_targets\"], axis=1).values.flatten()\none_hot = (hot_values.sum()) / hot_values.shape[0] * 100\nzero_hot = (hot_values.shape[0] - hot_values.sum()) / hot_values.shape[0] * 100\n\nfig, ax = plt.subplots(1,2, figsize=(20,5))\nsns.distplot(proba_predictions.flatten() * 100, color=\"DodgerBlue\", ax=ax[0])\nax[0].set_xlabel(\"Probability in %\")\nax[0].set_ylabel(\"Density\")\nax[0].set_title(\"Predicted probabilities\")\nsns.barplot(x=[\"label = 0\", \"label = 1\"], y=[zero_hot, one_hot], ax=ax[1])\nax[1].set_ylim([0,100])\nax[1].set_title(\"True target label count\")\nax[1].set_ylabel(\"Percentage\");","metadata":{"_kg_hide-input":true,"_uuid":"851060fb988a7942a3325349e9999f57f2a6225f","execution":{"iopub.status.busy":"2024-10-23T16:12:59.156466Z","iopub.execute_input":"2024-10-23T16:12:59.156730Z","iopub.status.idle":"2024-10-23T16:12:59.934417Z","shell.execute_reply.started":"2024-10-23T16:12:59.156675Z","shell.execute_reply":"2024-10-23T16:12:59.933344Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Conclusión\n\n* Podemos ver que nuestro modelo siempre fue muy incierto para predecir la presencia de una proteína diana. Todas las probabilidades son cercanas a cero y sólo hay unos pocos con objetivos donde nuestro modelo predijo una estructura de proteína con más del 10%.\n* Si echamos un vistazo al recuento de etiquetas de dianas verdaderas, podemos ver que la mayoría de nuestras dianas se rellenan con cero. Esto corresponde a una ausencia de proteínas objetivo correspondientes. Esto tiene sentido: Para cada imagen tenemos una alta probabilidad de contener 1 o 2 estructuras de proteínas diana. Sus valores de etiqueta son uno, mientras que todos los demás son cero. \n* En consecuencia, nuestra alta precisión pertenece a la alta predicción correcta de la ausencia de proteínas diana. Por el contrario, no fuimos capaces de predecir la presencia de una proteína diana, ¡que es la parte más relevante! \n* Ahora debería sonar una campana ¿Ha oído hablar alguna vez de las clases desequilibradas y de la confusión de modelos? \n","metadata":{"_uuid":"4ee24c3b3799e06b86d54c5a24323b6b5902d0ed"}},{"cell_type":"markdown","source":"### ¿A qué objetivos pertenecen las probabilidades predichas altas y pequeñas?","metadata":{"_uuid":"6475127409a86d7c4da3544478456d0d17c148eb"}},{"cell_type":"code","source":"mean_predictions = np.mean(proba_predictions, axis=0)\nstd_predictions = np.std(proba_predictions, axis=0)\nmean_targets = validation_labels.drop([\"Id\", \"Target\", \"number_of_targets\"], axis=1).mean()\n\nlabels = validation_labels.drop([\"Id\", \"Target\", \"number_of_targets\"], axis=1).columns.values\n\nfig, ax = plt.subplots(1,2,figsize=(20,5))\nsns.barplot(x=labels,\n            y=mean_predictions,\n            ax=ax[0])\nax[0].set_xticklabels(labels=labels,\n                      rotation=90)\nax[0].set_ylabel(\"Mean predicted probability\")\nax[0].set_title(\"Mean predicted probability per class over all samples\")\nsns.barplot(x=labels,\n           y=std_predictions,\n           ax=ax[1])\nax[1].set_xticklabels(labels=labels,\n                      rotation=90)\nax[1].set_ylabel(\"Standard deviation\")\nax[1].set_title(\"Standard deviation of predicted probability per class over all samples\");","metadata":{"_kg_hide-input":true,"_uuid":"7174d05d4e824c290df5149e6990827a076755a7","execution":{"iopub.status.busy":"2024-10-23T16:12:59.936549Z","iopub.execute_input":"2024-10-23T16:12:59.937309Z","iopub.status.idle":"2024-10-23T16:13:01.134204Z","shell.execute_reply.started":"2024-10-23T16:12:59.937233Z","shell.execute_reply":"2024-10-23T16:13:01.133187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(1,1,figsize=(20,5))\nsns.barplot(x=labels, y=mean_targets.values, ax=ax)\nax.set_xticklabels(labels=labels,\n                      rotation=90)\nax.set_ylabel(\"Percentage of hot (1)\")\nax.set_title(\"Percentage of hot counts (ones) per target class\")","metadata":{"_uuid":"b058c1f00898dad04957433672e726822426e478","execution":{"iopub.status.busy":"2024-10-23T16:13:01.135691Z","iopub.execute_input":"2024-10-23T16:13:01.136028Z","iopub.status.idle":"2024-10-23T16:13:01.613282Z","shell.execute_reply.started":"2024-10-23T16:13:01.135964Z","shell.execute_reply":"2024-10-23T16:13:01.612406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Conclusión\n\n* Nuestro modelo de referencia parece haber aprendido algo, aunque ese algo no tenga muy buena pinta. \n* Echando un vistazo a la desviación estándar podemos ver que todas las muestras tienen casi los mismos valores predichos. No hay desviación, no hay diferencia entre ellas. Esto es, por supuesto, muy malo.\n\nVayamos un paso más allá y echemos un vistazo al Cytosol (elija otra característica si lo desea). Aquí podemos ver una desviación estándar más alta que para todas las demás muestras y quizás su distribución correspondiente empieza a divergir, intentando hacerse bimodal. Esto sería estupendo ya que indica que el modelo empieza a resolver el problema de la clasificación binaria para este objetivo:\n","metadata":{"_uuid":"e3717835b45904306c0b00f66949ef8f8f7f86a2"}},{"cell_type":"code","source":"feature = \"Cytosol\"","metadata":{"_uuid":"7a42ae9d8ae2881ab558c3b140588e961ac17545","execution":{"iopub.status.busy":"2024-10-23T16:13:01.614714Z","iopub.execute_input":"2024-10-23T16:13:01.615219Z","iopub.status.idle":"2024-10-23T16:13:01.619206Z","shell.execute_reply.started":"2024-10-23T16:13:01.615161Z","shell.execute_reply":"2024-10-23T16:13:01.618370Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(20,5))\nsns.distplot(baseline_proba_predictions[feature].values[0:-10], color=\"Purple\")\nplt.xlabel(\"Predicted probabilites of {}\".format(feature))\nplt.ylabel(\"Density\")\nplt.xlim([0,1])","metadata":{"_uuid":"d96f5b4f4b62fb463bbe2266998d09e759289c37","execution":{"iopub.status.busy":"2024-10-23T16:13:01.620562Z","iopub.execute_input":"2024-10-23T16:13:01.621058Z","iopub.status.idle":"2024-10-23T16:13:01.952464Z","shell.execute_reply.started":"2024-10-23T16:13:01.621001Z","shell.execute_reply":"2024-10-23T16:13:01.951619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"No, no parece que nuestro modelo empiece a separar bien. La moda se aproxima a la fracción de recuentos de un solo disparo en todas las muestras. Al menos la cola plana da esperanzas de que el aprendizaje pueda estar en marcha.  Pero nuestro próximo objetivo debería ser averiguar qué ajustar para que nuestro modelo empiece a aprender de verdad. \n","metadata":{"_uuid":"ee00e75c559f74b7f1b50c8f55bf1e7c22107591"}},{"cell_type":"markdown","source":"# Modelo de mejora en un paso <a class=«anchor» id=«onestep»></a>\n\n\nOk, de nuevo demos un paso atrás y elijamos las proteínas diana más comunes que están presentes en nuestros datos: nucleoplasma, citosol y membrana plasmática. Si no somos capaces de predecirlas podemos irnos a casa y quedarnos en la cama.","metadata":{"_uuid":"2ae9aa27baa88d6a0eaf913e9215339881ad6444"}},{"cell_type":"code","source":"wishlist = [\"Nucleoplasm\", \"Cytosol\", \"Plasma membrane\"]","metadata":{"_uuid":"bd5d3dc8105a731c940e1996241fa1b0e32fcec1","execution":{"iopub.status.busy":"2024-10-23T16:13:01.953899Z","iopub.execute_input":"2024-10-23T16:13:01.954400Z","iopub.status.idle":"2024-10-23T16:13:01.958727Z","shell.execute_reply.started":"2024-10-23T16:13:01.954341Z","shell.execute_reply":"2024-10-23T16:13:01.957872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### La lista de deseos objetivo\n\nPara introducir una lista de deseos objetivo que podamos cambiar cuando queramos necesitamos mejorar el generador de datos. Para ello vamos a extender la clase que ya hemos escrito.\nEchando un vistazo más de cerca al generador base puedes ver que sólo hay una línea de código en def data_generation(self, list_IDs_temp) que tenemos que cambiar, concretamente la parte con y[i] = ... dentro del bucle for sobre temp list ids (identificadores de imagen del lote). Para facilitar las cosas, he añadido un pequeño método al DataGenerator que ya teníamos:\n\n```\ndef get_targets_per_image(self, identificador):\n        return self.labels.loc[self.labels.Id==identificador].drop(\n                [«Id», «Target», «number_of_targets»], axis=1).values\n```\n\nEste método sólo evita pasar directamente a y[i], los objetivos por imagen en un lote. Ahora, podemos sobrescribir este método en nuestro ImprovedDataGenerator sin perder funcionalidad:\n","metadata":{"_uuid":"e9c23453f175fc3768f4b94b659c96f8fb72c547"}},{"cell_type":"code","source":"class ImprovedDataGenerator(DataGenerator):\n    \n    # in contrast to the base DataGenerator we add a target wishlist to init\n    def __init__(self, list_IDs, labels, modelparameter, imagepreprocessor, target_wishlist):\n        super().__init__(list_IDs, labels, modelparameter, imagepreprocessor)\n        self.target_wishlist = target_wishlist\n    \n    def get_targets_per_image(self, identifier):\n        return self.labels.loc[self.labels.Id==identifier][self.target_wishlist].values","metadata":{"_uuid":"24b1f61b38bc5ec85150f0ffbeb1000d2b4c4ee2","execution":{"iopub.status.busy":"2024-10-23T16:13:01.960124Z","iopub.execute_input":"2024-10-23T16:13:01.960621Z","iopub.status.idle":"2024-10-23T16:13:01.970804Z","shell.execute_reply.started":"2024-10-23T16:13:01.960552Z","shell.execute_reply":"2024-10-23T16:13:01.970099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Añadir métricas de puntuación\n\nYa hemos visto que la puntuación de precisión es una ilusión y no ayuda a averiguar lo buenas que son nuestras predicciones. Echemos un vistazo más de cerca a la puntuación de la competición y sus alternativas:\n\n* **Puntuación de la macro F1**:\n* Tenemos 28 clases diferentes que son **muy diferentes en su frecuencia de presencia**.  Además tenemos que lidiar con **clases muy desequilibradas por objetivo**. Incluso para el objetivo más común, el nucleoplasma, sólo hay un 40% de muestras que lo muestran y un 60% que no. Este desequilibrio se hace aún más dramático para objetivos poco frecuentes como bastones y anillos. Deberíamos **dar más importancia a los verdaderos positivos**. \n* Bueno, hay **un problema con la puntuación de la competencia** que podemos usar para medir el rendimiento de nuestro modelo: **La media f1. La media no es robusta frente a los valores atípicos y, en consecuencia, no es muy informativa para comprender la distribución de las puntuaciones f1 para cada clase objetivo. Quizás hagamos buenas predicciones para Cytosol pero malas para Nucleoplasmn... ¿quién sabe? Por lo tanto, estaría bien introducir otras cantidades estadísticas como **mín**, **máx** y **desviación estándar**. De esta manera podemos ver lo peor y obtener algunas ideas de cómo las puntuaciones se distribuyen entre las clases. \n","metadata":{"_uuid":"66ad84e730aea51fed90d03a40e6615726ea88fb"}},{"cell_type":"code","source":"import keras.backend as K\n\ndef base_f1(y_true, y_pred):\n    y_pred = K.round(y_pred)\n    tp = K.sum(K.cast(y_true*y_pred, 'float'), axis=0)\n    tn = K.sum(K.cast((1-y_true)*(1-y_pred), 'float'), axis=0)\n    fp = K.sum(K.cast((1-y_true)*y_pred, 'float'), axis=0)\n    fn = K.sum(K.cast(y_true*(1-y_pred), 'float'), axis=0)\n\n    p = tp / (tp + fp + K.epsilon())\n    r = tp / (tp + fn + K.epsilon())\n\n    f1 = 2*p*r / (p+r+K.epsilon())\n    f1 = tf.where(tf.is_nan(f1), tf.zeros_like(f1), f1)\n    return f1\n\ndef f1_min(y_true, y_pred):\n    f1 = base_f1(y_true, y_pred)\n    return K.min(f1)\n\ndef f1_max(y_true, y_pred):\n    f1 = base_f1(y_true, y_pred)\n    return K.max(f1)\n\ndef f1_mean(y_true, y_pred):\n    f1 = base_f1(y_true, y_pred)\n    return K.mean(f1)\n\ndef f1_std(y_true, y_pred):\n    f1 = base_f1(y_true, y_pred)\n    return K.std(f1)","metadata":{"_uuid":"b1d64d6e4dbc439fb135cd77d0d0ef2d65706c96","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:13:01.972462Z","iopub.execute_input":"2024-10-23T16:13:01.973209Z","iopub.status.idle":"2024-10-23T16:13:01.988747Z","shell.execute_reply.started":"2024-10-23T16:13:01.972847Z","shell.execute_reply":"2024-10-23T16:13:01.987732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"baseline_losses.head()","metadata":{"_uuid":"d013c1fa453c8f5007fdc133392774e14f79c072","execution":{"iopub.status.busy":"2024-10-23T16:13:01.990362Z","iopub.execute_input":"2024-10-23T16:13:01.990820Z","iopub.status.idle":"2024-10-23T16:13:02.007537Z","shell.execute_reply.started":"2024-10-23T16:13:01.990636Z","shell.execute_reply":"2024-10-23T16:13:02.006592Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"No contiene las pérdidas que se obtienen tras computar cada lote. Pero un momento... **¿Cómo actualiza gradientes nuestro modelo? ¿Después de cada lote? ¿Después de una época?** \n\nSi echamos un vistazo a las redes feedforward simples que están estrechamente relacionadas con las CNNs añadir el descenso de gradiente, podemos ver que el aprendizaje significa calcular las derivadas de la pérdida con respecto a los pesos sobre todas las muestras:\n\n$$ w_{i,j}^{new} = w_{i,j}^{old} - \\eta \\cdot \\partial_{w_{i,j}} E$$\n\nCon un conjunto de muestras de observación independientes, podemos obtener los gradientes de esta forma:\n\n$$\\partial_w_{i,j}} E = \\sum_{n=1}^{N} \\partial_w_{i,j}} E_{n}$$","metadata":{"_uuid":"77f5c9bfaeb37ab7f50be0227fcd103e88e9f07b"}},{"cell_type":"code","source":"class TrackHistory(keras.callbacks.Callback):\n    \n    def on_train_begin(self, logs={}):\n        self.losses = []\n\n    def on_batch_end(self, batch, logs={}):\n        self.losses.append(logs.get('loss'))","metadata":{"_kg_hide-input":true,"_uuid":"0a007ca6bde3b124e400c0b1b89e6075b3d8c5b0","execution":{"iopub.status.busy":"2024-10-23T16:13:02.010052Z","iopub.execute_input":"2024-10-23T16:13:02.010559Z","iopub.status.idle":"2024-10-23T16:13:02.017059Z","shell.execute_reply.started":"2024-10-23T16:13:02.010504Z","shell.execute_reply":"2024-10-23T16:13:02.016283Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ImprovedModel(BaseLineModel):\n    \n    def __init__(self, modelparameter,\n                 use_dropout,\n                 my_metrics=[f1_mean, f1_std, f1_min, f1_max]):\n        \n        super().__init__(modelparameter)\n        self.my_metrics = my_metrics\n        self.use_dropout = use_dropout\n        \n    def learn(self):\n        self.history = TrackHistory()\n        return self.model.fit_generator(generator=self.training_generator,\n                    validation_data=self.validation_generator,\n                    epochs=self.params.n_epochs, \n                    use_multiprocessing=True,\n                    workers=8,\n                    callbacks = [self.history])\n    \n    def build_model(self):\n        self.model = Sequential()\n        self.model.add(Conv2D(16, kernel_size=(3, 3), activation='relu', input_shape=self.input_shape,\n                             kernel_initializer=VarianceScaling(seed=0),))\n        self.model.add(Conv2D(32, (3, 3), activation='relu',\n                             kernel_initializer=VarianceScaling(seed=0),))\n        self.model.add(MaxPooling2D(pool_size=(2, 2)))\n        if self.use_dropout:\n            self.model.add(Dropout(0.25))\n        self.model.add(Flatten())\n        self.model.add(Dense(64, activation='relu',\n                            kernel_initializer=VarianceScaling(seed=0),))\n        if self.use_dropout:\n            self.model.add(Dropout(0.5))\n        self.model.add(Dense(self.num_classes, activation='sigmoid'))","metadata":{"_uuid":"0b763fe315bbc0960599bb4149bce9f600ef45f3","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:13:02.020685Z","iopub.execute_input":"2024-10-23T16:13:02.021030Z","iopub.status.idle":"2024-10-23T16:13:02.035165Z","shell.execute_reply.started":"2024-10-23T16:13:02.020976Z","shell.execute_reply":"2024-10-23T16:13:02.034218Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"parameter = ModelParameter(train_path, num_classes=len(wishlist), n_epochs=5, batch_size=64)\npreprocessor = ImagePreprocessor(parameter)\nlabels = train_labels","metadata":{"_uuid":"42c9c106d61b9abebfa072a2ff3b731788ac81a1","execution":{"iopub.status.busy":"2024-10-23T16:13:02.036483Z","iopub.execute_input":"2024-10-23T16:13:02.036746Z","iopub.status.idle":"2024-10-23T16:13:02.044938Z","shell.execute_reply.started":"2024-10-23T16:13:02.036687Z","shell.execute_reply":"2024-10-23T16:13:02.044179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"training_generator = ImprovedDataGenerator(partition['train'], labels,\n                                           parameter, preprocessor, wishlist)\nvalidation_generator = ImprovedDataGenerator(partition['validation'], labels,\n                                             parameter, preprocessor, wishlist)\npredict_generator = PredictGenerator(partition['validation'], preprocessor, train_path)","metadata":{"_uuid":"50c9977084282e37842555172e3484aa769f95fc","execution":{"iopub.status.busy":"2024-10-23T16:13:02.046231Z","iopub.execute_input":"2024-10-23T16:13:02.046811Z","iopub.status.idle":"2024-10-23T16:13:02.053341Z","shell.execute_reply.started":"2024-10-23T16:13:02.046728Z","shell.execute_reply":"2024-10-23T16:13:02.052575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_preprocessor = ImagePreprocessor(parameter)\nsubmission_predict_generator = PredictGenerator(test_names, test_preprocessor, test_path)","metadata":{"_uuid":"f61880dc94df0b2292e797afd724a7d15edebb68","execution":{"iopub.status.busy":"2024-10-23T16:13:02.054531Z","iopub.execute_input":"2024-10-23T16:13:02.054793Z","iopub.status.idle":"2024-10-23T16:13:02.062013Z","shell.execute_reply.started":"2024-10-23T16:13:02.054738Z","shell.execute_reply":"2024-10-23T16:13:02.061275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Run computation and store results as csv\nif kernelsettings.fit_improved_baseline == True:\n    model = ImprovedModel(parameter, use_dropout=use_dropout)\n    model.build_model()\n    model.compile_model()\n    model.set_generators(training_generator, validation_generator)\n    epoch_history = model.learn()\n    proba_predictions = model.predict(predict_generator)\n    #model.save(\"improved_model.h5\")\n    \n    improved_proba_predictions = pd.DataFrame(proba_predictions, columns=wishlist)\n    improved_proba_predictions.to_csv(\"improved_predictions.csv\")\n    improved_losses = pd.DataFrame(epoch_history.history[\"loss\"], columns=[\"train_loss\"])\n    improved_losses[\"val_loss\"] = epoch_history.history[\"val_loss\"]\n    improved_losses.to_csv(\"improved_losses.csv\")\n    improved_batch_losses = pd.DataFrame(model.history.losses, columns=[\"batch_losses\"])\n    improved_batch_losses.to_csv(\"improved_batch_losses.csv\")\n    \n    improved_submission_proba_predictions = model.predict(submission_predict_generator)\n    improved_test_labels = test_labels.copy()\n    improved_test_labels.loc[:, wishlist] = improved_submission_proba_predictions\n    improved_test_labels.to_csv(\"improved_submission_proba.csv\")\n# If you already have done a baseline fit once, \n# you can load predictions as csv and further fitting is not neccessary:\nelse:\n    improved_proba_predictions = pd.read_csv(\"../input/protein-atlas-eab-predictions/improved_predictions.csv\", index_col=0)\n    improved_losses= pd.read_csv(\"../input/protein-atlas-eab-predictions/improved_losses.csv\", index_col=0)\n    improved_batch_losses = pd.read_csv(\"../input/protein-atlas-eab-predictions/improved_batch_losses.csv\", index_col=0)\n    improved_test_labels = pd.read_csv(\"../input/protein-atlas-eab-predictions/improved_submission_proba.csv\",\n                                      index_col=0)","metadata":{"_uuid":"85e7b6b70322d7d0b7739ebe75455e0275379b32","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:13:02.063220Z","iopub.execute_input":"2024-10-23T16:13:02.063452Z","iopub.status.idle":"2024-10-23T16:13:02.200546Z","shell.execute_reply.started":"2024-10-23T16:13:02.063406Z","shell.execute_reply":"2024-10-23T16:13:02.199873Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(2,1,figsize=(20,13))\nax[0].plot(np.arange(1,6), improved_losses[\"train_loss\"].values, 'r--o', label=\"train_loss\")\nax[0].plot(np.arange(1,6), improved_losses[\"val_loss\"].values, 'g--o', label=\"validation_loss\")\nax[0].set_xlabel(\"Epoch\")\nax[0].set_ylabel(\"Loss\")\nax[0].set_title(\"Loss evolution per epoch\")\nax[0].legend()\nax[1].plot(improved_batch_losses.batch_losses.values, 'r-+', label=\"train_batch_losses\")\nax[1].set_xlabel(\"Number of update steps in total\")\nax[1].set_ylabel(\"Train loss\")\nax[1].set_title(\"Train loss evolution per batch\");","metadata":{"_uuid":"2f1db258ec422d2a16b42335a140aab8e3a9c6c5","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:13:02.202227Z","iopub.execute_input":"2024-10-23T16:13:02.202640Z","iopub.status.idle":"2024-10-23T16:13:02.739296Z","shell.execute_reply.started":"2024-10-23T16:13:02.202490Z","shell.execute_reply":"2024-10-23T16:13:02.738572Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### ¿Qué nos dice la pérdida?\n\nLa pérdida es muy ruidosa. Al reducir el tamaño del lote, aumentamos el número de pasos de aprendizaje. Por lo tanto nuestro modelo aprende más rápido. Pero... ¡con un tamaño de lote menor **hay menos muestras de las que aprender, de las que calcular gradientes**! Los gradientes que obtenemos pueden ser muy específicos para las imágenes y las etiquetas de clase cubiertas por el lote del paso de aprendizaje actual. **Hemos hecho un compromiso**. Obtuvimos más velocidad de aprendizaje, pero pagamos con una calidad de gradiente reducida. Antes de volver a aumentar el tamaño del lote y esperar demasiado para obtener predicciones, podríamos mejorar eligiendo otro camino:\n\n1. Regularización del peso\n2. Recorte de gradiente\n\nEstos dos serán los próximos pasos de mejora. Sin embargo, queda una pregunta: ¿Ha empezado a aprender nuestro modelo? ¿Podemos ver una fuerza separadora que intenta dividir las predicciones de cero y uno?","metadata":{"_uuid":"a9a9f5d6b095c92334d2f878a0dd16fc79157a3c"}},{"cell_type":"code","source":"fig, ax = plt.subplots(3,1,figsize=(25,15))\nsns.distplot(improved_proba_predictions.values[:,0], color=\"Orange\", ax=ax[0])\nax[0].set_xlabel(\"Predicted probabilites of {}\".format(improved_proba_predictions.columns.values[0]))\nax[0].set_xlim([0,1])\nsns.distplot(improved_proba_predictions.values[:,1], color=\"Purple\", ax=ax[1])\nax[1].set_xlabel(\"Predicted probabilites of {}\".format(improved_proba_predictions.columns.values[1]))\nax[1].set_xlim([0,1])\nsns.distplot(improved_proba_predictions.values[:,2], color=\"Limegreen\", ax=ax[2])\nax[2].set_xlabel(\"Predicted probabilites of {}\".format(improved_proba_predictions.columns.values[2]))\nax[2].set_xlim([0,1]);","metadata":{"_uuid":"47c0b8d3e90ea26ceed1298255db8688e2aab942","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-10-23T16:13:02.741505Z","iopub.execute_input":"2024-10-23T16:13:02.742143Z","iopub.status.idle":"2024-10-23T16:13:04.027859Z","shell.execute_reply.started":"2024-10-23T16:13:02.742053Z","shell.execute_reply":"2024-10-23T16:13:04.027045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Esto tiene mucho mejor aspecto que las distribuciones que obtuvimos con el modelo de referencia **Así que aumentar las épocas mientras disminuimos el tamaño del lote ayudó a nuestro modelo ya que hicimos más pasos de aprendizaje.** Pero... podemos ver mucho ruido después de 100 lotes durante la disminución de pérdidas. Consecuentemente hacemos grandes saltos en el espacio de pesos con cada paso de actualización lote por lote. ¡Eso no es agradable! A veces estos saltos podrían incluso conducir a la explosión de las pérdidas también. Entonces el salto era tan grande que escapamos de regiones agradables que conducen a un mínimo local de pérdida. \n","metadata":{"_uuid":"504a4336ccac32dee731574f11c705e93292ea75","trusted":true}},{"cell_type":"markdown","source":"\n### Elegir los umbrales de decisión\n\nPara ello necesitamos de nuevo los datos de validación. Aquí sabemos para cada predicción de la lista de deseos el valor verdadero del objetivo. Con este conocimiento podríamos empezar a establecer umbrales manualmente comparando las distribuciones de probabilidad para las representaciones caliente y cero para cada objetivo de la lista de deseos. Veamos las probabilidades predichas:\n","metadata":{"_uuid":"28165a341e2ee736bc2958708be82d3b7d1714c2"}},{"cell_type":"code","source":"improved_proba_predictions.set_index(partition[\"validation\"], inplace=True)\nimproved_proba_predictions.head(5)","metadata":{"_uuid":"8e5abe41c6dd10e5045378951149c881467b8e83","execution":{"iopub.status.busy":"2024-10-23T16:13:04.029180Z","iopub.execute_input":"2024-10-23T16:13:04.029423Z","iopub.status.idle":"2024-10-23T16:13:04.046703Z","shell.execute_reply.started":"2024-10-23T16:13:04.029382Z","shell.execute_reply":"2024-10-23T16:13:04.045895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validation_labels.set_index(\"Id\", inplace=True)\nvalidation_labels.head(5)","metadata":{"_uuid":"3cfadd0b9682ec57cca21b893e32a25b4a7ec53b","execution":{"iopub.status.busy":"2024-10-23T16:13:04.048119Z","iopub.execute_input":"2024-10-23T16:13:04.048375Z","iopub.status.idle":"2024-10-23T16:13:04.106976Z","shell.execute_reply.started":"2024-10-23T16:13:04.048327Z","shell.execute_reply":"2024-10-23T16:13:04.106172Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(3,1,figsize=(20,18))\nfor n in range(len(wishlist)):\n    sns.distplot(improved_proba_predictions.loc[validation_labels[wishlist[n]] == 1,\n                                                wishlist[n]], color=\"Green\", label=\"1-hot\", ax=ax[n])\n    sns.distplot(improved_proba_predictions.loc[validation_labels[wishlist[n]] == 0,\n                                                wishlist[n]], color=\"Red\", label=\"0-zero\", ax=ax[n])\n    ax[n].set_title(wishlist[n])\n    ax[n].legend()","metadata":{"_kg_hide-input":true,"_uuid":"7e58a811cb8d92e3f8c52706824cda7b53277fdd","execution":{"iopub.status.busy":"2024-10-23T16:13:04.108920Z","iopub.execute_input":"2024-10-23T16:13:04.109321Z","iopub.status.idle":"2024-10-23T16:13:06.131483Z","shell.execute_reply.started":"2024-10-23T16:13:04.109252Z","shell.execute_reply":"2024-10-23T16:13:06.130484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"th_cytosol = 0.4\nth_plasma_membrane = 0.2\nth_nucleoplasm = 0.55","metadata":{"_uuid":"6c0d3b8efddfdb1f9f3c92866295af9e98266af1","execution":{"iopub.status.busy":"2024-10-23T16:13:06.133165Z","iopub.execute_input":"2024-10-23T16:13:06.133539Z","iopub.status.idle":"2024-10-23T16:13:06.137824Z","shell.execute_reply.started":"2024-10-23T16:13:06.133459Z","shell.execute_reply":"2024-10-23T16:13:06.137012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"improved_submission = improved_test_labels.copy()\nimproved_submission.head(2)","metadata":{"_uuid":"16927f46c4e1d2cb62e120ae0aea43283000435a","execution":{"iopub.status.busy":"2024-10-23T16:13:06.139229Z","iopub.execute_input":"2024-10-23T16:13:06.139529Z","iopub.status.idle":"2024-10-23T16:13:06.192107Z","shell.execute_reply.started":"2024-10-23T16:13:06.139477Z","shell.execute_reply":"2024-10-23T16:13:06.191387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"improved_submission[\"Nucleoplasm\"] = np.where(improved_test_labels[\"Nucleoplasm\"] >= th_nucleoplasm, 1, 0)\nimproved_submission[\"Cytosol\"] = np.where(improved_test_labels[\"Cytosol\"] >= th_cytosol, 1, 0)\nimproved_submission[\"Plasma membrane\"] = np.where(\n    improved_test_labels[\"Plasma membrane\"] >= th_plasma_membrane, 1, 0)\n\nimproved_submission.head(5)","metadata":{"_uuid":"7cd092a77f581062cc87939b15546dd6213cd425","execution":{"iopub.status.busy":"2024-10-23T16:13:06.193222Z","iopub.execute_input":"2024-10-23T16:13:06.193449Z","iopub.status.idle":"2024-10-23T16:13:06.250240Z","shell.execute_reply.started":"2024-10-23T16:13:06.193410Z","shell.execute_reply":"2024-10-23T16:13:06.249497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def transform_to_target(row):\n    target_list = []\n    for col in validation_labels.drop([\"Target\", \"number_of_targets\"], axis=1).columns:\n        if row[col] == 1:\n            target_list.append(str(reverse_train_labels[col]))\n    if len(target_list) == 0:\n        return str(0)\n    return \" \".join(target_list)","metadata":{"_uuid":"982875cafa09f46bae181edf731c00854b2a406f","execution":{"iopub.status.busy":"2024-10-23T16:13:06.251449Z","iopub.execute_input":"2024-10-23T16:13:06.251709Z","iopub.status.idle":"2024-10-23T16:13:06.257665Z","shell.execute_reply.started":"2024-10-23T16:13:06.251659Z","shell.execute_reply":"2024-10-23T16:13:06.256981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"improved_submission[\"Predicted\"] = improved_submission.apply(lambda l: transform_to_target(l), axis=1)","metadata":{"_uuid":"c6b856b9f06a03f12840eed0acb98ceb5a25d26c","execution":{"iopub.status.busy":"2024-10-23T16:13:06.258936Z","iopub.execute_input":"2024-10-23T16:13:06.259200Z","iopub.status.idle":"2024-10-23T16:13:20.826190Z","shell.execute_reply.started":"2024-10-23T16:13:06.259157Z","shell.execute_reply":"2024-10-23T16:13:20.825321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = improved_submission.loc[:, [\"Id\", \"Predicted\"]]\nsubmission.head()","metadata":{"_uuid":"96daaf0f72812ea5714ea5bf6557995f4b8e2fad","execution":{"iopub.status.busy":"2024-10-23T16:13:20.827786Z","iopub.execute_input":"2024-10-23T16:13:20.828018Z","iopub.status.idle":"2024-10-23T16:13:20.852043Z","shell.execute_reply.started":"2024-10-23T16:13:20.827980Z","shell.execute_reply":"2024-10-23T16:13:20.851033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv(\"improved_submission.csv\", index=False)","metadata":{"_uuid":"0070acecd4f4bbe497ed8cd694ae5080dda9d0d1","execution":{"iopub.status.busy":"2024-10-23T16:13:20.853734Z","iopub.execute_input":"2024-10-23T16:13:20.854057Z","iopub.status.idle":"2024-10-23T16:13:20.934915Z","shell.execute_reply.started":"2024-10-23T16:13:20.853999Z","shell.execute_reply":"2024-10-23T16:13:20.933972Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ¿Cómo podemos hacer frente a los saltos de gradiente?\n\nIntentemos profundizar en el problema. Calculamos los gradientes con respecto a los pesos después de procesar cada lote de esta manera:\n\n$$ \\partial_{w_{i,j}} E = \\sum_{m=1}^{M} \\partial_{w_{i,j}} E_{m} $$","metadata":{"_uuid":"39049822930c3d8219f1552fdeefe17ab98bbe90"}},{"cell_type":"markdown","source":"Si observamos la suma podemos ver una desventaja... está impulsada principalmente por contribuciones altas. **Una imagen en el lote que causa gradientes positivos o negativos muy altos para el peso $w_{i,j}$ tiene más impacto en el gradiente global que las imágenes con valores absolutos bajos**. Esto puede ser malo especialmente en el caso de imágenes atípicas que no son representativas para explicar el patrón en los datos.\n\n¿Cómo resolver este problema?\n\nEn primer lugar, podríamos volver a elegir un tamaño de lote mayor. Al reducir el tamaño del lote, hacemos un compromiso: aumentamos la velocidad de aprendizaje pero incrementamos el riesgo de gradientes de baja calidad. Por lo tanto, antes de jugar con otras estrategias, deberíamos dar un paso atrás de nuevo. Con un batch_size de 128 y un número de epochs de 10, obtenemos estas pérdidas:\n","metadata":{"_uuid":"4fb02efae72d20df876cc9bb7ac45082d097f59b"}},{"cell_type":"code","source":"parameter = ModelParameter(train_path, num_classes=len(wishlist), n_epochs=10, batch_size=128)\npreprocessor = ImagePreprocessor(parameter)\nlabels = train_labels\n\ntraining_generator = ImprovedDataGenerator(partition['train'], labels,\n                                           parameter, preprocessor, wishlist)\nvalidation_generator = ImprovedDataGenerator(partition['validation'], labels,\n                                             parameter, preprocessor, wishlist)\npredict_generator = PredictGenerator(partition['validation'], preprocessor, train_path)","metadata":{"_uuid":"7a09eb6a0ab7bf90acd75fe67ee49b70c27ba9b6","execution":{"iopub.status.busy":"2024-10-23T16:13:20.936381Z","iopub.execute_input":"2024-10-23T16:13:20.936718Z","iopub.status.idle":"2024-10-23T16:13:20.943684Z","shell.execute_reply.started":"2024-10-23T16:13:20.936646Z","shell.execute_reply":"2024-10-23T16:13:20.942858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Run computation and store results as csv\nif kernelsettings.fit_improved_higher_batchsize == True:\n    model = ImprovedModel(parameter, use_dropout=True)\n    model.build_model()\n    model.compile_model()\n    model.set_generators(training_generator, validation_generator)\n    epoch_history = model.learn()\n    proba_predictions = model.predict(predict_generator)\n    #model.save(\"improved_model.h5\")\n    improved_proba_predictions = pd.DataFrame(proba_predictions, columns=wishlist)\n    improved_proba_predictions.to_csv(\"improved_hbatch_predictions.csv\")\n    improved_losses = pd.DataFrame(epoch_history.history[\"loss\"], columns=[\"train_loss\"])\n    improved_losses[\"val_loss\"] = epoch_history.history[\"val_loss\"]\n    improved_losses.to_csv(\"improved_hbatch_losses.csv\")\n    improved_batch_losses = pd.DataFrame(model.history.losses, columns=[\"batch_losses\"])\n    improved_batch_losses.to_csv(\"improved_hbatch_batch_losses.csv\")\n# If you already have done a baseline fit once, \n# you can load predictions as csv and further fitting is not neccessary:\nelse:\n    improved_proba_predictions = pd.read_csv(\n        \"../input/protein-atlas-eab-predictions/improved_hbatch_predictions.csv\", index_col=0)\n    improved_losses= pd.read_csv(\n        \"../input/protein-atlas-eab-predictions/improved_hbatch_losses.csv\", index_col=0)\n    improved_batch_losses = pd.read_csv(\"../input/protein-atlas-eab-predictions/improved_hbatch_batch_losses.csv\", index_col=0)","metadata":{"_kg_hide-input":true,"_uuid":"38b88513d1b012758603075c8aede2de510f6dcf","execution":{"iopub.status.busy":"2024-10-23T16:13:20.945824Z","iopub.execute_input":"2024-10-23T16:13:20.946295Z","iopub.status.idle":"2024-10-23T16:13:21.035656Z","shell.execute_reply.started":"2024-10-23T16:13:20.946115Z","shell.execute_reply":"2024-10-23T16:13:21.034795Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(2,1,figsize=(20,13))\nax[0].plot(np.arange(1,11), improved_losses[\"train_loss\"].values, 'r--o', label=\"train_loss\")\nax[0].plot(np.arange(1,11), improved_losses[\"val_loss\"].values, 'g--o', label=\"validation_loss\")\nax[0].set_xlabel(\"Epoch\")\nax[0].set_ylabel(\"Loss\")\nax[0].set_title(\"Loss evolution per epoch\")\nax[0].legend()\nax[1].plot(improved_batch_losses.batch_losses.values, 'r-+', label=\"train_batch_losses\")\nax[1].set_xlabel(\"Number of update steps in total\")\nax[1].set_ylabel(\"Train loss\")\nax[1].set_title(\"Train loss evolution per batch\");","metadata":{"_kg_hide-input":true,"_uuid":"35dd109e7815f69ded0a5971a090ce62abded409","execution":{"iopub.status.busy":"2024-10-23T16:13:21.037384Z","iopub.execute_input":"2024-10-23T16:13:21.037711Z","iopub.status.idle":"2024-10-23T16:13:21.802085Z","shell.execute_reply.started":"2024-10-23T16:13:21.037647Z","shell.execute_reply":"2024-10-23T16:13:21.801195Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(3,1,figsize=(25,15))\nsns.distplot(improved_proba_predictions.values[:,0], color=\"Orange\", ax=ax[0])\nax[0].set_xlabel(\"Predicted probabilites of {}\".format(improved_proba_predictions.columns.values[0]))\nax[0].set_xlim([0,1])\nsns.distplot(improved_proba_predictions.values[:,1], color=\"Purple\", ax=ax[1])\nax[1].set_xlabel(\"Predicted probabilites of {}\".format(improved_proba_predictions.columns.values[1]))\nax[1].set_xlim([0,1])\nsns.distplot(improved_proba_predictions.values[:,2], color=\"Limegreen\", ax=ax[2])\nax[2].set_xlabel(\"Predicted probabilites of {}\".format(improved_proba_predictions.columns.values[2]))\nax[2].set_xlim([0,1]);","metadata":{"_kg_hide-input":true,"_uuid":"050ca6f928f647f4fde6f12d386c09839ed6e983","execution":{"iopub.status.busy":"2024-10-23T16:13:21.803761Z","iopub.execute_input":"2024-10-23T16:13:21.804127Z","iopub.status.idle":"2024-10-23T16:13:23.090283Z","shell.execute_reply.started":"2024-10-23T16:13:21.804048Z","shell.execute_reply":"2024-10-23T16:13:23.089434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Run computation and store results as csv\nif kernelsettings.fit_improved_without_dropout == True:\n    model = ImprovedModel(parameter, use_dropout=False)\n    model.build_model()\n    model.compile_model()\n    model.set_generators(training_generator, validation_generator)\n    epoch_history = model.learn()\n    proba_predictions = model.predict(predict_generator)\n    #model.save(\"improved_model.h5\")\n    improved_proba_predictions = pd.DataFrame(proba_predictions, columns=wishlist)\n    improved_proba_predictions.to_csv(\"improved_nodropout_predictions.csv\")\n    improved_losses = pd.DataFrame(epoch_history.history[\"loss\"], columns=[\"train_loss\"])\n    improved_losses[\"val_loss\"] = epoch_history.history[\"val_loss\"]\n    improved_losses.to_csv(\"improved_nodropout_losses.csv\")\n    improved_batch_losses = pd.DataFrame(model.history.losses, columns=[\"batch_losses\"])\n    improved_batch_losses.to_csv(\"improved_nodropout_batch_losses.csv\")\n# If you already have done a baseline fit once, \n# you can load predictions as csv and further fitting is not neccessary:\nelse:\n    improved_proba_predictions_no_dropout = pd.read_csv(\n        \"../input/protein-atlas-eab-predictions/improved_nodropout_predictions.csv\", index_col=0)\n    improved_losses_no_dropout= pd.read_csv(\n        \"../input/protein-atlas-eab-predictions/improved_nodropout_losses.csv\", index_col=0)\n    improved_batch_losses_no_dropout = pd.read_csv(\n        \"../input/protein-atlas-eab-predictions/improved_nodropout_batch_losses.csv\", index_col=0)","metadata":{"_uuid":"099f2156b82eab629f301f8cf82a9d8874e4b465","execution":{"iopub.status.busy":"2024-10-23T16:13:23.091895Z","iopub.execute_input":"2024-10-23T16:13:23.092251Z","iopub.status.idle":"2024-10-23T16:13:23.162042Z","shell.execute_reply.started":"2024-10-23T16:13:23.092185Z","shell.execute_reply":"2024-10-23T16:13:23.161047Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(2,1,figsize=(20,13))\nax[0].plot(np.arange(1,11), improved_losses[\"train_loss\"].values, 'r--o', label=\"train_loss_dropout\")\nax[0].plot(np.arange(1,11), improved_losses_no_dropout[\"train_loss\"].values, 'r-o', label=\"train_loss_no_dropout\")\nax[0].plot(np.arange(1,11), improved_losses[\"val_loss\"].values, 'g--o', label=\"validation_loss\")\nax[0].plot(np.arange(1,11), improved_losses_no_dropout[\"val_loss\"].values, 'g-o', label=\"validation_loss_no_dropout\")\nax[0].set_xlabel(\"Epoch\")\nax[0].set_ylabel(\"Loss\")\nax[0].set_title(\"Loss evolution per epoch\")\nax[0].legend()\nax[1].plot(improved_batch_losses.batch_losses.values[-800::], 'r-+', label=\"train_batch_losses_dropout\")\nax[1].plot(improved_batch_losses_no_dropout.batch_losses.values[-800::], 'b-+',\n           label=\"train_batch_losses_no_dropout\")\nax[1].set_xlabel(\"Number of update steps in total\")\nax[1].set_ylabel(\"Train loss\")\nax[1].set_title(\"Train loss evolution per batch\");\nax[1].legend();","metadata":{"_uuid":"51e482ffa9ff1ef8867992a10dceb238bc0c2fc3","execution":{"iopub.status.busy":"2024-10-23T16:13:23.163387Z","iopub.execute_input":"2024-10-23T16:13:23.163674Z","iopub.status.idle":"2024-10-23T16:13:24.039282Z","shell.execute_reply.started":"2024-10-23T16:13:23.163615Z","shell.execute_reply":"2024-10-23T16:13:24.038552Z"},"trusted":true},"execution_count":null,"outputs":[]}]}