{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install efficientnet","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\nimport tensorflow as tf\nfrom tensorflow.keras.layers import Dense, Flatten, LeakyReLU, BatchNormalization, Dropout\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.losses import CategoricalCrossentropy\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau\nimport tensorflow.keras.backend as K\nimport math\nfrom tqdm import tqdm\nfrom sklearn.model_selection import train_test_split\nimport efficientnet.tfkeras as efn \nimport os\nfrom kaggle_datasets import KaggleDatasets","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"try:\n    # TPU detection. No parameters necessary if TPU_NAME environment variable is\n    # set: this is always the case on Kaggle.\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n    print('Running on TPU ', tpu.master())\nexcept ValueError:\n    tpu = None\n\nif tpu:\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\nelse:\n    # Default distribution strategy in Tensorflow. Works on CPU and single GPU.\n    strategy = tf.distribute.get_strategy()\n\nprint(\"REPLICAS: \", strategy.num_replicas_in_sync)\nGCS_DS_PATH = KaggleDatasets().get_gcs_path('panda-512x512-crop-white-interarea')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"image_folder = '/512x512_crop_white_INTERAREA/'\ntrain = pd.read_csv('/kaggle/input/prostate-cancer-grade-assessment/train.csv')\ntrain = train[['image_id', 'isup_grade']]\ntrain['image_id'] = train['image_id'].apply(lambda x: GCS_DS_PATH + image_folder + x + '.png')\nx = train['image_id'].values\ny = pd.get_dummies(train['isup_grade']).astype('int32').values","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.05, random_state=666, stratify = train['isup_grade'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img_size = 512\nHEIGHT = img_size\nWIDTH = img_size\nCHANNELS = 3\nbatch_size = 8 * strategy.num_replicas_in_sync\nepochs = 30\nAUTO = tf.data.experimental.AUTOTUNE","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def decode_image(filename, label=None, image_size=(img_size, img_size)):\n    bits = tf.io.read_file(filename)\n    image = tf.image.decode_png(bits, channels=3)\n    image = tf.cast(image, tf.float32) / 255.0\n    image = tf.image.resize(image, image_size)\n    if label is None:\n        return image\n    else:\n        return image, label\ndef random_rotation(image):\n    # input image - is one image of size [dim,dim,3] not a batch of [b,dim,dim,3]\n    # output - image randomly rotated\n    DIM = HEIGHT\n    XDIM = DIM%2 #fix for size 331\n    \n    rotation = 15. * tf.random.normal([1],dtype='float32')\n    # CONVERT DEGREES TO RADIANS\n    rotation = math.pi * rotation / 180.\n    \n    # ROTATION MATRIX\n    c1 = tf.math.cos(rotation)\n    s1 = tf.math.sin(rotation)\n    one = tf.constant([1],dtype='float32')\n    zero = tf.constant([0],dtype='float32')\n    rotation_matrix = tf.reshape( tf.concat([c1,s1,zero, -s1,c1,zero, zero,zero,one],axis=0),[3,3] )\n\n    # LIST DESTINATION PIXEL INDICES\n    x = tf.repeat( tf.range(DIM//2,-DIM//2,-1), DIM )\n    y = tf.tile( tf.range(-DIM//2,DIM//2),[DIM] )\n    z = tf.ones([DIM*DIM],dtype='int32')\n    idx = tf.stack( [x,y,z] )\n    \n    # ROTATE DESTINATION PIXELS ONTO ORIGIN PIXELS\n    idx2 = K.dot(rotation_matrix,tf.cast(idx,dtype='float32'))\n    idx2 = K.cast(idx2,dtype='int32')\n    idx2 = K.clip(idx2,-DIM//2+XDIM+1,DIM//2)\n    \n    # FIND ORIGIN PIXEL VALUES \n    idx3 = tf.stack( [DIM//2-idx2[0,], DIM//2-1+idx2[1,]] )\n    d = tf.gather_nd(image, tf.transpose(idx3))\n        \n    return tf.reshape(d,[DIM,DIM,3])\ndef random_shear(image):\n    # input image - is one image of size [dim,dim,3] not a batch of [b,dim,dim,3]\n    # output - image randomly sheared\n    DIM = HEIGHT\n    XDIM = DIM%2 #fix for size 331\n    \n    shear = 5. * tf.random.normal([1],dtype='float32')\n    shear = math.pi * shear / 180.\n        \n    # SHEAR MATRIX\n    one = tf.constant([1],dtype='float32')\n    zero = tf.constant([0],dtype='float32')\n    c2 = tf.math.cos(shear)\n    s2 = tf.math.sin(shear)\n    shear_matrix = tf.reshape( tf.concat([one,s2,zero, zero,c2,zero, zero,zero,one],axis=0),[3,3] )    \n\n    # LIST DESTINATION PIXEL INDICES\n    x = tf.repeat( tf.range(DIM//2,-DIM//2,-1), DIM )\n    y = tf.tile( tf.range(-DIM//2,DIM//2),[DIM] )\n    z = tf.ones([DIM*DIM],dtype='int32')\n    idx = tf.stack( [x,y,z] )\n    \n    # ROTATE DESTINATION PIXELS ONTO ORIGIN PIXELS\n    idx2 = K.dot(shear_matrix,tf.cast(idx,dtype='float32'))\n    idx2 = K.cast(idx2,dtype='int32')\n    idx2 = K.clip(idx2,-DIM//2+XDIM+1,DIM//2)\n    \n    # FIND ORIGIN PIXEL VALUES \n    idx3 = tf.stack( [DIM//2-idx2[0,], DIM//2-1+idx2[1,]] )\n    d = tf.gather_nd(image, tf.transpose(idx3))\n        \n    return tf.reshape(d,[DIM,DIM,3])\ndef random_shift(image):\n    # input image - is one image of size [dim,dim,3] not a batch of [b,dim,dim,3]\n    # output - image randomly shifted\n    DIM = HEIGHT\n    XDIM = DIM%2 #fix for size 331\n    \n    height_shift = 16. * tf.random.normal([1],dtype='float32') \n    width_shift = 16. * tf.random.normal([1],dtype='float32') \n    one = tf.constant([1],dtype='float32')\n    zero = tf.constant([0],dtype='float32')\n        \n    # SHIFT MATRIX\n    shift_matrix = tf.reshape( tf.concat([one,zero,height_shift, zero,one,width_shift, zero,zero,one],axis=0),[3,3] )\n\n    # LIST DESTINATION PIXEL INDICES\n    x = tf.repeat( tf.range(DIM//2,-DIM//2,-1), DIM )\n    y = tf.tile( tf.range(-DIM//2,DIM//2),[DIM] )\n    z = tf.ones([DIM*DIM],dtype='int32')\n    idx = tf.stack( [x,y,z] )\n    \n    # ROTATE DESTINATION PIXELS ONTO ORIGIN PIXELS\n    idx2 = K.dot(shift_matrix,tf.cast(idx,dtype='float32'))\n    idx2 = K.cast(idx2,dtype='int32')\n    idx2 = K.clip(idx2,-DIM//2+XDIM+1,DIM//2)\n    \n    # FIND ORIGIN PIXEL VALUES \n    idx3 = tf.stack( [DIM//2-idx2[0,], DIM//2-1+idx2[1,]] )\n    d = tf.gather_nd(image, tf.transpose(idx3))\n        \n    return tf.reshape(d,[DIM,DIM,3])\ndef random_zoom(image):\n    # input image - is one image of size [dim,dim,3] not a batch of [b,dim,dim,3]\n    # output - image randomly zoomed\n    DIM = HEIGHT\n    XDIM = DIM%2 #fix for size 331\n    \n    height_zoom = 1.0 + tf.random.normal([1],dtype='float32')/10.\n    width_zoom = 1.0 + tf.random.normal([1],dtype='float32')/10.\n    one = tf.constant([1],dtype='float32')\n    zero = tf.constant([0],dtype='float32')\n        \n    # ZOOM MATRIX\n    zoom_matrix = tf.reshape( tf.concat([one/height_zoom,zero,zero, zero,one/width_zoom,zero, zero,zero,one],axis=0),[3,3] )\n\n    # LIST DESTINATION PIXEL INDICES\n    x = tf.repeat( tf.range(DIM//2,-DIM//2,-1), DIM )\n    y = tf.tile( tf.range(-DIM//2,DIM//2),[DIM] )\n    z = tf.ones([DIM*DIM],dtype='int32')\n    idx = tf.stack( [x,y,z] )\n    \n    # ROTATE DESTINATION PIXELS ONTO ORIGIN PIXELS\n    idx2 = K.dot(zoom_matrix,tf.cast(idx,dtype='float32'))\n    idx2 = K.cast(idx2,dtype='int32')\n    idx2 = K.clip(idx2,-DIM//2+XDIM+1,DIM//2)\n    \n    # FIND ORIGIN PIXEL VALUES \n    idx3 = tf.stack( [DIM//2-idx2[0,], DIM//2-1+idx2[1,]] )\n    d = tf.gather_nd(image, tf.transpose(idx3))\n        \n    return tf.reshape(d,[DIM,DIM,3])\ndef image_augment(filename, label):\n    image = decode_image(filename)\n    \n    image = tf.image.random_flip_left_right(image)\n    image = tf.image.random_flip_up_down(image)\n    image = random_rotation(image)\n    image = random_shear(image)\n    image = random_shift(image)\n    image = random_zoom(image)\n    \"\"\"\n    p_spatial = tf.random.uniform([1], minval=0, maxval=1, dtype='float32')\n    p_spatial2 = tf.random.uniform([1], minval=0, maxval=1, dtype='float32')\n    p_pixel = tf.random.uniform([1], minval=0, maxval=1, dtype='float32')\n    p_crop = tf.random.uniform([1], minval=0, maxval=1, dtype='float32')\n    \n    ### Spatial-level transforms\n    if p_spatial >= .2:\n        image = tf.image.random_flip_left_right(image)\n        image = tf.image.random_flip_up_down(image)\n        \n    if p_crop >= .7:\n        if p_crop >= .95:\n            image = tf.image.random_crop(image, size=[int(HEIGHT*.6), int(WIDTH*.6), CHANNELS])\n        elif p_crop >= .85:\n            image = tf.image.random_crop(image, size=[int(HEIGHT*.7), int(WIDTH*.7), CHANNELS])\n        elif p_crop >= .8:\n            image = tf.image.random_crop(image, size=[int(HEIGHT*.8), int(WIDTH*.8), CHANNELS])\n        else:\n            image = tf.image.random_crop(image, size=[int(HEIGHT*.9), int(WIDTH*.9), CHANNELS])\n        image = tf.image.resize(image, size=[HEIGHT, WIDTH])\n\n    if p_spatial2 >= .6:\n        if p_spatial2 >= .9:\n            image = transform_rotation(image)\n        elif p_spatial2 >= .8:\n            image = transform_zoom(image)\n        elif p_spatial2 >= .7:\n            image = transform_shift(image)\n        else:\n            image = transform_shear(image)\n        \n    ## Pixel-level transforms\n    if p_pixel >= .4:\n        if p_pixel >= .85:\n            image = tf.image.random_saturation(image, lower=0, upper=2)\n        elif p_pixel >= .65:\n            image = tf.image.random_contrast(image, lower=.8, upper=2)\n        elif p_pixel >= .5:\n            image = tf.image.random_brightness(image, max_delta=.2)\n        else:\n            image = tf.image.adjust_gamma(image, gamma=.6)\n            \"\"\"\n    return image, label","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_ds = (\n    tf.data.Dataset\n    .from_tensor_slices((x_train, y_train))\n    .map(image_augment, num_parallel_calls=AUTO)\n    .cache()\n    .shuffle(512)\n    .repeat()\n    .batch(batch_size)\n    .prefetch(AUTO)\n    )\n\ntest_ds = (\n    tf.data.Dataset\n    .from_tensor_slices((x_test, y_test))\n    .map(decode_image, num_parallel_calls=AUTO)\n    .cache()\n    .repeat()\n    .batch(batch_size)\n    .prefetch(AUTO)\n    )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def build_model():\n    base = efn.EfficientNetB6(weights='imagenet', input_shape=(img_size, img_size, 3), pooling = 'max', include_top = False)\n    x = base.output\n    x = Dense(512)(x)\n    x = LeakyReLU()(x)\n    x = BatchNormalization(axis = -1)(x)\n    x = Dropout(rate = 0.5)(x)\n    x = Dense(512)(x)\n    x = LeakyReLU()(x)\n    x = BatchNormalization(axis = -1)(x)\n    output = Dense(6, activation=\"softmax\")(x)\n    model = tf.keras.models.Model(inputs=base.input, outputs = output)\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with strategy.scope():\n    model = build_model()\n    model.compile(optimizer='adam', loss=CategoricalCrossentropy(label_smoothing=0.1), metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"reduce_lr = ReduceLROnPlateau(monitor='val_loss', \n                              patience=3,  \n                              verbose=1,  \n                              factor=0.5,   \n                              min_lr=0.00001)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit(\n            train_ds, \n            validation_data = test_ds, \n            steps_per_epoch=x_train.shape[0] // batch_size,            \n            validation_steps=x_test.shape[0] // batch_size,    \n            callbacks = [reduce_lr],\n            epochs=epochs\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.save('effnetb6_0.h5')","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}