{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport 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#for dirname, _, filenames in os.walk('/kaggle/input'):\n #   for filename in filenames:\n  #      print(os.path.join(dirname, filename))\n\n# You can write up to 5GB 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","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Credit:\nCredit goes to [Chris Deotte](https://www.kaggle.com/cdeotte) for the original notebook https://www.kaggle.com/cdeotte/how-to-create-tfrecords/ for reading the .tfrec files.\n\nI intend to add comments in due time to fully explain each step for others like me who had no clue how to decode .tfrec files.\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import tensorflow as tf\nfrom kaggle_datasets import KaggleDatasets\n\nIMAGE_SIZE= [256,256]; BATCH_SIZE = 32\n#GCS_DS_PATH = KaggleDatasets().get_gcs_path('siim-isic-melanoma-classification') # you can list the bucket with \"!gsutil ls $GCS_DS_PATH\"\nAUTO = tf.data.experimental.AUTOTUNE\nTRAINING_FILENAMES = tf.io.gfile.glob('/kaggle/input/256images/train*.tfrec')\n\nimage_dir = \"/kaggle/input/256images\"\ntrain_csv = \"/kaggle/input/siim-isic-melanoma-classification/train.csv\"\ntrain_meta = pd.read_csv(train_csv)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def decode_image(image_data):\n    image = tf.image.decode_jpeg(image_data, channels=3)\n    image = tf.cast(image, tf.float32) / 255.0  # convert image to floats in [0, 1] range\n    image = tf.reshape(image, [*IMAGE_SIZE, 3]) # explicit size needed for TPU\n    image = tf.image.resize(image, [256,256])\n    return image\n\ndef read_labeled_tfrecord(example):\n    LABELED_TFREC_FORMAT = {\n        \"image\": tf.io.FixedLenFeature([], tf.string), # tf.string means bytestring\n        \"target\": tf.io.FixedLenFeature([], tf.int64),  # shape [] means single element\n    }\n    example = tf.io.parse_single_example(example, LABELED_TFREC_FORMAT)\n    image = decode_image(example['image'])\n    label = tf.cast(example['target'], tf.int32)\n    return image, label # returns a dataset of (image, label) pairs\n\ndef load_dataset(filenames, labeled=True, ordered=False):\n    # Read from TFRecords. For optimal performance, reading from multiple files at once and\n    # disregarding data order. Order does not matter since we will be shuffling the data anyway.\n\n    ignore_order = tf.data.Options()\n    if not ordered:\n        ignore_order.experimental_deterministic = False # disable order, increase speed\n\n    dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTO) # automatically interleaves reads from multiple files\n    dataset = dataset.with_options(ignore_order) # uses data as soon as it streams in, rather than in its original order\n    dataset = dataset.map(read_labeled_tfrecord if labeled else read_unlabeled_tfrecord, num_parallel_calls=AUTO)\n    # returns a dataset of (image, label) pairs if labeled=True or (image, id) pairs if labeled=False\n    return dataset\n\ndef __len__(self):\n    return self.len\n\ndef get_training_dataset():\n    #Feed each of the files from TRAINING FILENAMES to the load_dataset function and save the output as \"dataset\"\n    dataset = load_dataset(TRAINING_FILENAMES, labeled=True)\n    dataset = dataset.repeat() # the training dataset must repeat for several epochs\n    dataset = dataset.shuffle(2048) #Shuffle the dataset to remove any correlation in the training data which may skew the model.\n    dataset = dataset.batch(BATCH_SIZE) #Combine consecutive elements of the dataset into chunks of size: BATCH_SIZE\n    #dataset = dataset.prefetch(AUTO) # prefetch next batch while training (autotune prefetch buffer size)\n\n    return dataset\nprint(\"Training data shapes:\")\nfor image, label in get_training_dataset().take(20):\n    print(image.shape, label.shape)\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from torch.utils.data import DataLoader, Dataset #Create an efficient dataloader set to feed images to the model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# numpy and matplotlib defaults\nnp.set_printoptions(threshold=15, linewidth=80)\nCLASSES = [0,1]\n\n\"\"\"def batch_to_numpy_images_and_labels(data):\n    images, labels = data\n    numpy_images = images.numpy()\n    numpy_labels = labels.numpy()\n    if numpy_labels.dtype == object: # binary string in this case, these are image ID strings\n        numpy_labels = [None for _ in enumerate(numpy_images)]\n    # If no labels, only image IDs, return None for labels (this is the case for test data)\n    return numpy_images, numpy_labels\n\"\"\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import math\nimport matplotlib.pyplot as plt","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import cv2\nimport tensorflow as tf\n\nfrom torch.utils.data.sampler import SequentialSampler\nfrom torchvision import transforms\n\nimport albumentations as A #Package of transformations\nfrom albumentations.pytorch.transforms import ToTensorV2\n\ntrain_loader = DataLoader(get_training_dataset(), batch_size = 16, shuffle = True, num_workers = 0)\n\nfrom torch import nn\nfrom torch.nn import functional as F\nimport torchvision.models as models\n\nmodel = models.resnet18(pretrained=True)\nmodel","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import torch\n\n#Set device\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n\n# Freeze pretrained model parameters to avoid backpropogating through them\nfor parameter in model.parameters():\n    parameter.requires_grad = False\n\n    \nfrom collections import OrderedDict\n\n# Build custom classifier\nclassifier = nn.Sequential(OrderedDict([('fc1', nn.Linear(512, 256)),\n                                        ('relu', nn.ReLU()),\n                                        ('drop', nn.Dropout(p=0.5)),\n                                        ('fc2', nn.Linear(256, 2)),\n                                        ('output', nn.LogSoftmax(dim=1))]))\n\nmodel.fc = classifier\nmodel.fc\n\nfor parameter in model.fc.parameters():\n    parameter.requires_grad = True\n\nmodel.to(device)\nmodel.fc.to(device)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Train the classifier\ndef train_classifier(model, optimizer, criterion, train_loader, epochs):\n\n    steps = 0\n    print_every = 5\n\n    for e in range(epochs):\n        #start = time.time()\n\n        model.train()\n\n        running_loss = 0\n        \n        for images, labels in iter(train_loader):            \n            images, labels = images.cuda(), labels.cuda()\n\n            steps += 1\n            print(\"Steps: \" + str(steps))\n\n            optimizer.zero_grad()\n\n            output = model.forward(images)\n            #print(\"Output Finished\", time.time() - start)\n            loss = criterion(output, labels)\n            loss.backward()\n            optimizer.step()\n\n            running_loss += loss.item()\n\n            if steps % print_every == 0:\n\n                model.eval()\n\n                # Turn off gradients for validation, saves memory and computations\n                #with torch.no_grad():\n                 #   validation_loss, accuracy = validation(model, valid_loader, criterion, device)\n\n                print(\"Epoch: {}/{}.. \".format(e+1, epochs),\n                      \"Training Loss: {:.3f}.. \".format(running_loss/print_every),\n                  #    \"Validation Loss: {:.3f}.. \".format(validation_loss/len(valid_loader)),\n                   #   \"Validation Accuracy: {:.3f}\".format(accuracy/len(valid_loader))\n                     )\n\n                running_loss = 0\n                model.train()\n                \n    model_path = \"/kaggle/working/Resnet181E.pth\"\n    torch.save(model, model_path)\n                \n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from torch import optim\n\n#Loss function\ncriterion = nn.CrossEntropyLoss()\n\n# Gradient descent optimizer\noptimizer = optim.Adam(model.fc.parameters(), lr=0.001)\n    \ntrain_classifier(model, optimizer, criterion, train_loader, epochs = 1)","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}