{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"#\n# Attempt to use ResNet50\n# \n#\n\nimport numpy as np \nimport pandas as pd \n\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\n\nfrom PIL import Image  \nfrom IPython.display import display \n\nimport tensorflow as tf\nfrom tensorflow.keras.utils import to_categorical, Sequence\nfrom tensorflow.keras.models import Model, Sequential\nfrom tensorflow.keras.layers import Input, Dense, Dropout, Flatten, Conv2D, MaxPool2D, BatchNormalization\nfrom tensorflow.keras.applications.resnet50 import ResNet50\n\nimport os\nimport datetime\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"root_path = '/kaggle/input/hpa-single-cell-image-classification/'\n\nCHANNELS = np.array(['blue', 'green', 'red', 'yellow'])\n\nCLASSES = np.array([\n    'Nucleoplasm',\n    'Nuclear membrane',\n    'Nucleoli',\n    'Nucleoli fibrillar center',\n    'Nuclear speckles',\n    'Nuclear bodies',\n    'Endoplasmic reticulum',\n    'Golgi apparatus',\n    'Intermediate filaments',\n    'Actin filaments',\n    'Microtubules',\n    'Mitotic spindle',\n    'Centrosome',\n    'Plasma membrane',\n    'Mitochondria',\n    'Aggresome',\n    'Cytosol',\n    'Vesicles and punctate cytosolic patterns',\n    'Negative'\n])\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Build Labels\n\nTake in a trainning set dataframe and build a dataframe containing labels.  The resulting lables data frame will contain a column for each class with the value of zero or one."},{"metadata":{"trusted":true},"cell_type":"code","source":"def build_labels(df):\n    # dataframe with column for each class\n    labels = list()\n    \n    for index, sample in df.iterrows():\n        # zero out class array\n        label = [0] * 19\n        \n        # for each class found in training sample, flip lablel value to one\n        for clazz in sample['Label'].split('|'):\n            label[int(clazz)] = 1\n\n        # Append label to list\n        labels.append( np.array(label) )\n\n    return np.vstack(labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Create Image Data For Each Channel\n\nCreate 3d array containing each image for all channels."},{"metadata":{"trusted":true},"cell_type":"code","source":"def read_image_data(id):\n    channels = None\n\n    for channel in CHANNELS:\n        image = Image.open('/kaggle/input/hpa-single-cell-image-classification/train/{}_{}.png'.format(id, channel))\n        image = image.resize((IMAGE_SIZE, IMAGE_SIZE))\n\n        image_array = np.array(image)\n        #print(\"Image Size: {}\".format(np.shape(image_array)))\n\n        channels = [image_array] if channels is None else np.append(channels, [image_array], axis=0) \n        #print(\"\\rBuilding channel: (id={}, channel={}, channel_size={})\".format(id, channel, np.shape(channels)), end=\"\")\n\n    #print(\"\\rCorrelating channel: (id={}, channel_size={})             \".format(id, np.shape(channels)))\n    channels = correlate_channels(channels)\n    return channels","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plot Training Data With Images"},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_samples(df_samples, df_labels):\n    \n    for sample_index, sample in df_samples.iterrows():\n\n        fig = plt.figure(figsize=(25,25))\n        index = 1\n\n        for channel in CHANNELS:\n            ax = fig.add_subplot(1, CHANNEL_SIZE, index)\n            path = root_path + 'train/{}_{}.png'.format(sample['ID'], channel)\n            image = mpimg.imread(path)\n            imgplot = plt.imshow(image)\n            index = index + 1\n\n            ax.set_title(\"{}\\n{}\\n{}\".format(label_description(df_labels[train_index]), channel, image.shape))\n\n        \n        \n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Convert (3, 2048, 2048) to (2048, 2048, 3)\ndef correlate_channels(channels):\n    image = np.full((IMAGE_SIZE, IMAGE_SIZE, len(channels)), None)\n    images = list()\n    for channel_index, channel in enumerate(channels):\n        images.append(channel)\n    correlated_image = np.stack(images, axis=2)\n    return np.asarray(correlated_image).astype(np.int)    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def label_description(label):\n    description = \"\"\n    for index in range(len(CLASSES)):\n        if label[index] == 1:\n            if len(description) > 0:\n                description = description + \", \"\n            description = description + CLASSES[index]\n    return description\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Timer Functions\n\nFunctions to support tracking elapsed times."},{"metadata":{"trusted":true},"cell_type":"code","source":"time_start = datetime.datetime.now()\nprevious_mark = datetime.datetime.now()\ntimes = {}\n\nMARK_PREP = \"Finished Preparations\"\nMARK_TRAIN = \"Finished Trainning\"\nMARK_TEST = \"Finished Trainning\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ndef time_mark(position):\n    mark = datetime.datetime.now()\n    times[position] = (mark - previous_mark, mark - time_start)\n    print(\"Time elapsed: mark={},  total={}\".format(str(times[position][0]), str(times[position][1])))\n    \n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Parameters"},{"metadata":{"trusted":true},"cell_type":"code","source":"IMAGE_SIZE = 1024\nCHANNEL_SIZE = len(CHANNELS)\nCLASS_SIZE = len(CLASSES)\n# Note: Will get OOM on kaggle with full dataset\nSAMPLE_SIZE = 2000\nBATCH_SIZE = 2\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Read Full Trainning Data\n\nRead full set of training data from ```train.csv```"},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train = pd.read_csv(root_path + 'train.csv')\nprint(\"Trainning data length: {}\".format(len(df_train)))\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# if sample size is set then reduce trainning set accordingly\nif SAMPLE_SIZE > -1:\n    df_train = df_train.sample(SAMPLE_SIZE)\n    df_train.reset_index(inplace=True);\n\n# split 80, 10, 10\ndf_train, df_validation, df_test = np.split(df_train, [int(.8*len(df_train)), int(.9*len(df_train))]) \n    \n# reindex after split\ndf_train.reset_index(inplace=True)\ndf_validation.reset_index(inplace=True)\ndf_test.reset_index(inplace=True)\n\n# build labels\ndf_train_labels = build_labels( df_train )\ndf_validation_labels = build_labels( df_validation )\ndf_test_labels = build_labels( df_test )\n\nprint(\"Trainning sample size:  {}\".format(len(df_train)))\nprint(\"Trainning labels size:  {}\".format(len(df_train_labels)))\nprint(\"\")\nprint(\"Validation sample size: {}\".format(len(df_validation)))\nprint(\"Validation labels size: {}\".format(len(df_validation_labels)))\nprint(\"\")\nprint(\"Test sample size:       {}\".format(len(df_test)))\nprint(\"Test labels size:       {}\".format(len(df_test_labels)))\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class DataGenerator(Sequence):\n    def __init__(self, list_ids, labels, batch_size, image_size, channel_size):\n        self.list_ids = list_ids\n        self.labels = labels\n        self.batch_size = batch_size\n        self.image_size = image_size\n        self.channel_size = channel_size\n        self.indexes = list(list_ids.index.values)\n        \n    def __len__(self):\n        return int(np.floor(len(self.list_ids) / self.batch_size))\n    \n    \n    def __getitem__(self, index):\n        # Generate indexes of the batch\n        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]\n\n        # Find list of IDs\n        temp_list_ids = [self.list_ids[k] for k in indexes]\n\n        # Generate data\n        X, y = self.__data_generation(temp_list_ids)\n\n        return X, y\n\n    \n    def __data_generation(self, temp_list_ids):\n        label_values = list()\n        batch = list()\n        for id in temp_list_ids:\n            index = self.list_ids[self.list_ids == id].index\n            label_values.append(self.labels[index])\n            channels = read_image_data(id)\n            batch.append(channels)\n\n        return np.array( batch ), np.array( label_values ).reshape(-1,19)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Build Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"\n#weights = '../input/tf-keras-resnet/resnet50_notop.h5'\nmodel_resnet = ResNet50(weights=None, input_tensor=Input(shape=(IMAGE_SIZE, IMAGE_SIZE, CHANNEL_SIZE)), include_top=False)\n#model_resnet.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\nmodel_base = model_resnet.layers[-2].output\nconnected_model = tf.keras.layers.GlobalMaxPooling2D()(model_base)\nconnected_model = Dense(CLASS_SIZE, activation='sigmoid')(connected_model)\n\n\nmodel = Model(model_resnet.input, connected_model)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Set parameters in pre-train model to False\n#for layer in model_resnet.layers:\n#    layer.trainable = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\nmodel.compile(optimizer=tf.keras.optimizers.Adam(lr=0.001), \n        loss=tf.keras.losses.BinaryCrossentropy(),\n        metrics=[tf.keras.metrics.Accuracy(), tf.keras.metrics.AUC(), tf.keras.metrics.Precision()]\n    )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Print the model\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_generator = DataGenerator(df_train['ID'], df_train_labels, BATCH_SIZE, IMAGE_SIZE, CHANNEL_SIZE)\nvalidation_generator = DataGenerator(df_validation['ID'], df_validation_labels, BATCH_SIZE, IMAGE_SIZE, CHANNEL_SIZE)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"time_mark(MARK_PREP)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Train Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"\n\nhistory = model.fit(train_generator,\n        validation_data=validation_generator,\n        epochs = 5\n    )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"time_mark(MARK_TRAIN)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Test Predictions\n\nUse the portion of trainning data set asside for testing to see how predictions hold up."},{"metadata":{"trusted":true},"cell_type":"code","source":"def clean_prediction(prediction):\n    for batch_index in range(len(prediction)):\n        for class_index in range(len(prediction[batch_index])):\n            prediction[batch_index][class_index] = 1 if prediction[batch_index][class_index] >= 0.50 else 0\n    return np.array(prediction).astype(np.int) \n\ncorrect = 0;\ntotal = 0;\n\nfor index, test in df_test.iterrows():\n    channels = read_image_data(test['ID'])\n    prediction = model.predict(channels.reshape(-1, IMAGE_SIZE, IMAGE_SIZE, 4))\n    prediction = clean_prediction(prediction)\n    \n    # validate prediction\n    is_correct = np.all(df_test_labels[index] == prediction[0])\n    result = \"Correct. \" if is_correct else \"Incorrect\"\n    \n    #print(\"ID: {} {} {}\".format(test['ID'], result, label_description(prediction[0])))\n    \n    # accumulate\n    if is_correct == True:\n        correct = correct + 1\n    total = total + 1\n    \n    print (\"\\rPrecition details: (total={},correct={},percentage_correct={}%)    \".format(total, correct, int(correct / total * 100)), end=\"\")\n\nprint (\"\")\nprint (\"\")\nprint (\"Total predictions:   {}\".format(total))\nprint (\"Correct predictions: {}\".format(correct))\nprint (\"Precentage correct:  {}%\".format(int(correct / total * 100)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"time_mark(MARK_TEST)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}