{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session\n\n# tensorflow imports\nimport tensorflow as tf\nfrom tensorflow.keras import datasets, layers, models\nimport matplotlib.pyplot as plt\nimport tensorflow_io as tfio\n\n# get dataset path\nfrom kaggle_datasets import KaggleDatasets\nGCS_PATH = KaggleDatasets().get_gcs_path()\n\n# regex\nimport re\n\n# EXTRA RUN INSTRUCTIONS\n# change Settings -> Accelerator -> TPU v3-8 to use TPU (avoid burning through TPU hours when not in session)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-output":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-04-26T01:23:37.75327Z","iopub.execute_input":"2022-04-26T01:23:37.753557Z","iopub.status.idle":"2022-04-26T01:23:38.636556Z","shell.execute_reply.started":"2022-04-26T01:23:37.753525Z","shell.execute_reply":"2022-04-26T01:23:38.635495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\"\"\"\nREFERENCE\n# Code is a mix of tutorials (kaggle and google codelabs tutorials) for the TPU dataloading\n# and Tensorflow tutorial for a basic cnn\n# Code has been modified to fit competition dataset, along with pre-processing to analyze the data\n\nTPU Tutorials:\nhttps://www.kaggle.com/docs/tpu\nhttps://www.kaggle.com/code/mgornergoogle/five-flowers-with-keras-and-xception-on-tpu/notebook\nhttps://codelabs.developers.google.com/codelabs/keras-flowers-tpu/#4\n\nAlong with, for CNN:\nhttps://www.tensorflow.org/tutorials/images/cnn\n\"\"\"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# DATA VISUALIZATION AND EXPLORATION\n\n# explore data","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ENABLE TPU\n\n# detect and init the TPU\ntpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()\n\n# instantiate a distribution strategy\ntpu_strategy = tf.distribute.experimental.TPUStrategy(tpu)","metadata":{"execution":{"iopub.status.busy":"2022-04-25T23:48:49.204296Z","iopub.execute_input":"2022-04-25T23:48:49.20457Z","iopub.status.idle":"2022-04-25T23:48:49.236167Z","shell.execute_reply.started":"2022-04-25T23:48:49.204539Z","shell.execute_reply":"2022-04-25T23:48:49.235205Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# SET HYPERPARAMETERS\n\n# ideal batch size is 128 per TPU core, (128 * 8 = 1024), TPU v3-8 the core count is 8\n# BATCH_SIZE = 16 * tpu_strategy.num_replicas_in_sync\nBATCH_SIZE = 16 \n\n# learning rate, should increase learning rate with batch size\nLEARNING_RATE = 1\n\n# number of epochs\nNUMBER_OF_EPOCHS = 1\n\n# activation function\nACTIVATION_FUNCTION = \"relu\" \n\n# send multiple batches to the TPU at once\nSTEPS_PER_EXECUTION = 32\n\n# training data split\nTRAINING_DATA_SPLIT = .7\n\n# image size\n# ideal image size for TPUs is 512 x 512 or 256 x 256 for imagenet\nIMAGE_WIDTH = 512\nIMAGE_HEIGHT = 512\nIMAGE_CHANNELS = 3","metadata":{"execution":{"iopub.status.busy":"2022-04-26T01:23:45.137815Z","iopub.execute_input":"2022-04-26T01:23:45.138145Z","iopub.status.idle":"2022-04-26T01:23:45.14441Z","shell.execute_reply.started":"2022-04-26T01:23:45.138091Z","shell.execute_reply":"2022-04-26T01:23:45.143388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"### DATA PRE-PROCESSING\n\n# -PROCESS TRAIN.CSV/LABEL DATA\n# get training data csv into panda object\ntrain_csv = pd.read_csv(\"../input/prostate-cancer-grade-assessment/train.csv\")\n\n# replace \"negative\" with 0+0 since they are equivalent\ntrain_csv['gleason_score'] = train_csv['gleason_score'].replace(\"negative\" ,\"0+0\")\n\n# drop lab and ISUP grade column from train_csv dataframe\ntrain_csv = train_csv.drop(columns=['data_provider','isup_grade'])\n\n# get categories/labels, should have 10, determine categories from unique labels of gleason_scores\ncategories = train_csv.gleason_score.unique()\ncategories_length = len(categories)\n\n# -PROCESS IMAGE DATA\n# split = len(image_filenames) - int(len(image_filenames) * TRAINING_DATA_SPLIT)\n\n# get list of training and testing filenames\n# training_filenames = image_filenames[split:]\n# testing_filenames = image_filenames[:split]\n\n# -CONVERT TIFF IMAGES\n# enter filename, return array of image as rgb and label\ndef decode_tiff_full(filename):\n    # get the bits for file name\n    bits = tf.io.read_file(filename)\n    # decode into tiff, array shape is [height, width, 4], 4 is RGBA\n    image_as_rgba = tfio.experimental.image.decode_tiff(bits)\n    # convert rgba to rgb\n    image_as_rgb = tfio.experimental.color.rgba_to_rgb(image_as_rgba)\n    # get image id from filename\n    image_id_from_filename = (re.search(\"(\\w*).tiff\", filename))[1]\n    # find row in train_csv data where image id matches filename\n    entry = train_csv.loc[train_csv['image_id'] == image_id_from_filename]\n    # set the label to the gleason score\n    label = entry['gleason_score'].to_numpy()[0]\n    return image_as_rgb, label\n\n# -BUILD DATA STREAMING\n# helper functions for TFRecord\n# warning, the input is a list of byte strings, which are themselves lists of bytes\ndef _bytestring_feature(list_of_bytestrings):\n  return tf.train.Feature(bytes_list=tf.train.BytesList(value=list_of_bytestrings))\n\ndef _int_feature(list_of_ints): # int64\n  return tf.train.Feature(int64_list=tf.train.Int64List(value=list_of_ints))\n\ndef _float_feature(list_of_floats): # float32\n  return tf.train.Feature(float_list=tf.train.FloatList(value=list_of_floats))\n\n# write a TFRecord\ndef read_TFRecord(filename):\n        feature = {\n        \"image\": _bytestring_feature([])\n    }\n\n# configure streaming options\ndataset = dataset.shuffle(1000)\ndataset = dataset.cache()\ndataset = dataset.repeat()\ndataset = dataset.batch(BATCH_SIZE)\nAUTOTUNE = tf.data.experimental.AUTOTUNE\nignore_order = tf.data.Options()\nignore_order.experimental_deterministic = False\ndataset = dataset.prefetch(AUTOTUNE)\n\nfilenames = tf.io.gfile.glob(GCS_PATH + \"/train_images/*.tiff\")\n#dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTOTUNE)\ndataset = dataset.with_options(ignore_order)\ndataset = dataset.map(read_TFRecord, num_parallel_calls=AUTOTUNE)\ndataset = force_images_sizes(dataset, (IMAGE_WIDTH, IMAGE_HEIGHT))\n\nprint(filenames[0])\nprint(decode_tiff(filenames[0]))","metadata":{"execution":{"iopub.status.busy":"2022-04-26T02:04:32.347724Z","iopub.execute_input":"2022-04-26T02:04:32.348039Z","iopub.status.idle":"2022-04-26T02:04:37.304786Z","shell.execute_reply.started":"2022-04-26T02:04:32.348007Z","shell.execute_reply":"2022-04-26T02:04:37.303343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\"\"\"\n\n# convert to numpy for iteration\n# train_csv_array = train_csv.to_numpy()\n# print(train_csv_array)\n\n# build TFRecord reader\ndef read_TFRecord(example):\n    features = {\n        \"image\": tf.io.FixedLenFeature([], tf.string),\n        \"class\": tf.io.FixedLenFeature([], tf.string)\n    }\n    example = tf.io.parse_single_example(example, features)\n    image = tfio.experimental.image.decode_tiff(example['image'], index=0, name=None)\n    class_label = tf.cast(example['class'], tf.int32)\n    return image\n    \n# set options\nignore_order = tf.data.Options()\nignore_order.experimental_deterministic = False\n\n# build training dataset\ntraining_dataset = tf.data.TFRecordDataset(training_filenames, num_parallel_reads=AUTO)\ntraining_dataset = dataset.with_options(ignore_order)\ntraining_dataset = dataset.map(read_TFRecord, num_parallel_calls=AUTO)\ntraining_dataset = force_image_sizes(dataset, (IMAGE_WIDTH, IMAGE_HEIGHT))\n\ntraining_dataset = load_dataset(training_filenames)\nprint(training_dataset) \n\n# training_dataste = tf.data.Dataset\n\n\ndef get_training_dataset():\n    dataset = load_dataset(training_filenames)\n    dataset = dataset.map(data_augment, num_parallel_calls=AUTO)\n    dataset = dataset.repeat()\n    dataset = dataset.shuffle(2048)\n    dataset = dataset.batch(BATCH_SIZE)\n    dataset = dataset.prefetch(AUTO) # prefetch next batch while training (autotune prefetch buffer size)\n    return dataset\n\ndef input_\n\ntrain_labels = np.empty((IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_CHANNELS), int)\ntest_labels = np.empty_like((IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_CHANNELS))\n\n\nprint(train_labels)\n\n# for row in train_csv_array\n\n# train_images = \n# train_labels =\n\n# test_images =\n# test_labels =\n\n# image data loading and construct arrays\n# print(image_dataset)\n\n\n# images should be converted to an ndarray with shape (# of images, 512 x 512, 3)\n# labels should be converted to an ndarray with shape (# of images, 1)\n# train_images, train_labels and test_images, test_labels should be constructed\n\n# normalize pixel values between 0 and 1\n# train_images =\n# test_images =\n\n###########################\n\n# image_dataset = tf.data.TFRecordDataset(image_filenames)\n\"\"\"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# DATA VISUALIZATION AND EXPLORATION\n\n# explore data","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# SET AND RUN MODEL\n\n# run model design and model compile within TPU strategy scope, to prepare for TPU computation\nwith tpu_strategy.scope():\n    # MODEL DESIGN (PART 1)\n    model = tf.keras.models.Sequential()\n    # Convolutional layers\n    # 64 filters, (3,3) feature kernel, input image 512x512 w/ 3 channels\n    model.add(tf.keras.layers.Conv2D(64, (3,3), activation=ACTIVATION_FUNCTION, input_shape=(IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_CHANNELS))\n    model.add(tf.keras.layers.MaxPooling2D((2, 2)))\n    model.add(tf.keras.layers.Conv2D(128, (3,3), activation=ACTIVATION_FUNCTION)\n    model.add(tf.keras.layers.MaxPooling2D((2, 2)))\n    model.add(tf.keras.layers.Conv2D(128, (3,3), activation=ACTIVATION_FUNCTION)\n    # Dense Layers\n    model.add(tf.keras.layers.Flatten())\n    # determine model summary to get shape from last layer of (Conv2D), print(model.summary)\n    model.add(tf.keras.layers.Dense(64, activation=ACTIVATION_FUNCTION))\n    # final output should be 10, since we have 10 classes (these are the gleason_scores)\n    model.add(tf.keras.layers.Dense(categories_length))\n\n    # COMPILE MODEL (PART 2)\n    # set optimizer for learning rate for adam optimizer\n    model_optimizer = keras.optimizers.Adam(LEARNING_RATE)\n\n    # compile model\n    model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy'], steps_per_execution=STEPS_PER_EXECUTION)\n\n# build history\nhistory = model.fit(train_images, train_labels, epochs=NUMBER_OF_EPOCHS, validation_data=(test_images, test_labels))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# MODEL EVALUATION\n\nplt.plot(history.history['accuracy'], label='accuracy')\nplt.plot(history.history['val_accuracy'], label='val_accuracy')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.ylim([0.5, 1])\nplt.legend(loc='lower_right')\n\ntest_loss, test_acc, model.evaluate()","metadata":{},"execution_count":null,"outputs":[]}]}