{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Starter Code for Training a Model using Keras Application Pretrained Models.\n\nNote: This does not currently produce good results for RCIC data. However it does work well for MNIST."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"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\nimport os\nfor dirs in os.listdir('../input'):\n    print(dirs)\nif 'recursion-cellular-image-classification' in os.listdir('../input'):\n    DATA_DIR = '../input/recursion-cellular-image-classification'\nelse:\n    DATA_DIR = '../input'\n\nTRAIN_DIR = os.path.join(DATA_DIR, 'train')\nimport sys\n\ntry:\n    !git clone https://github.com/recursionpharma/rxrx1-utils\nexcept:\n    pass\n\nsys.path.append('rxrx1-utils')\nimport rxrx.io as rio\n\nfrom matplotlib import pyplot as plt\nimport keras","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Load in data"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"# Load train data\ntrain_data = pd.read_csv(os.path.join(DATA_DIR, 'train.csv'))\n# I want a complete list of images that we have - so I will duplicate evert entry in train_data for two sites\nsite_list = []\nfor id_code in train_data.id_code.unique():\n    site_list.append([id_code, 1])\n    site_list.append([id_code, 2])\n# Create dataframe of id codes and the two sites\nsite_df = pd.DataFrame(site_list, columns=['id_code', 'site'])    \n# Merge that site df into the train_data df.\ntrain_data = pd.merge(train_data, site_df, how='left', on='id_code')\n\n# Create a column that has the relative path to an image\ntrain_data['rel_path'] = train_data.apply(lambda x: os.path.join(\n            x.experiment, \n            'Plate{}'.format(x.plate),\n            '{}_s{}_w'.format(x.well, x.site))+'{channel}.png', axis=1)\n\ndisplay(train_data.head())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Configs"},{"metadata":{"trusted":true},"cell_type":"code","source":"IMAGE_SHAPE = (512, 512, 3)\nNUM_CLASSES = 1108","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# CV Split\nI will just arbitrarily split on the first of each experiment"},{"metadata":{"trusted":true},"cell_type":"code","source":"val_experiments = [\"HEPG2-01\", \"HUVEC-01\", \"RPE-01\", \"U2OS-01\"]\ncv_partition = {}\ncv_partition['train'] = []\ncv_partition['validate'] = []\ncv_partition['train'].append(np.array(train_data[~train_data.experiment.isin(val_experiments)].index))\ncv_partition['validate'].append(np.array(train_data[train_data.experiment.isin(val_experiments)].index))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Data Generator"},{"metadata":{"trusted":true},"cell_type":"code","source":"class DataGenerator(keras.utils.Sequence):\n    \n    def __init__(self, img_paths, labels, img_rootdir, batch_size, mode='train', img_shappe=(512, 512, 3), n_classes=1108 ):\n        self.img_paths = img_paths\n        self.labels = labels\n        self.img_rootdir = img_rootdir\n        self.batch_size = 8\n        self.mode = mode\n        self.img_shape = img_shappe\n        self.n_classes = n_classes\n        \n        # Create the indicies into the ID's and labels\n        self.indexes = np.arange(len(self.img_paths))\n        \n    def __len__(self):\n        'return the length of teh data generator (ie now many batches will be returned)'\n        return int(np.floor(len(self.img_paths) / self.batch_size))\n    \n    def __getitem__(self, batch_idx):\n        ' Generate one batch of data and return it'\n\n        # Get the indexes of this batch\n        batch_indexes = self.indexes[batch_idx*self.batch_size : (batch_idx+1)*self.batch_size]\n        \n        # Pre allocate\n        X = np.zeros((self.batch_size, *self.img_shape))\n        if self.mode == 'train':\n            #y = np.zeros((self.batch_size, self.config.NUM_CLASSES), dtype=np.float32)\n            y = np.zeros(self.batch_size, dtype=int)\n        \n        # Populate data\n        for batch_idx, img_idx in enumerate(batch_indexes):\n            X[batch_idx] = self.load_image(self.img_paths[img_idx])\n            if self.mode == 'train':\n                y[batch_idx] = self.labels[img_idx]\n        \n        # One-hot encode the labels\n        if self.mode == 'train':\n            y_onehot = keras.utils.to_categorical(\n                    y,\n                    num_classes=self.n_classes,\n                    dtype='float32'\n                )\n            \n        if self.mode == 'train':\n            return X, y_onehot\n        else:\n            return X\n    \n    def load_image(self, img_path):\n        channel_paths = []\n        for channel in range(6):\n            channel_paths.append(os.path.join(self.img_rootdir, img_path.format(channel=channel+1)))\n        img = rio.load_images_as_tensor(channel_paths)\n        img = rio.convert_tensor_to_rgb(img).astype(np.float32)\n        img -= np.mean(img, axis=(0, 1))\n        img /= 127.5\n\n        return img\n\ntrain_datagen = DataGenerator(\n            img_paths = train_data.rel_path.values[cv_partition['train'][0]],\n            labels = train_data.sirna.values[cv_partition['train'][0]],\n            img_rootdir = TRAIN_DIR,\n            batch_size = 8)\nval_datagen = DataGenerator(\n            img_paths = train_data.rel_path.values[cv_partition['validate'][0]],\n            labels = train_data.sirna.values[cv_partition['validate'][0]],\n            img_rootdir = TRAIN_DIR,\n            batch_size = 8)\n\n#X, y = train_datagen[0]\n#img = X[0] #load_image(train_data.at[1, 'rel_path'])\n#plt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Create a Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.applications.resnet50 import ResNet50\nfrom keras.layers import Input, Dense, Conv2D, GlobalAveragePooling2D, Dropout, GlobalMaxPooling2D\nfrom keras.models import Model\n\nbase_model = ResNet50(\n                input_tensor=Input(shape=IMAGE_SHAPE, name='Input_Tensor'),\n                pooling=None,\n                weights='imagenet',\n                include_top=False)\nx = base_model.output\nx = GlobalAveragePooling2D()(x)\nx = Dense(4096, activation='relu', name='head2')(x)\nx = Dropout(0.25)(x)\nx = Dense(2048, activation='relu', name='head3')(x)\nx = Dropout(0.25)(x)\nhead = Dense(NUM_CLASSES, activation='softmax', name='output')(x)\nmodel = Model(inputs=base_model.input, outputs=head)\n#model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(  loss='categorical_crossentropy',\n                optimizer=keras.optimizers.Adam(lr=0.001),\n                metrics=['categorical_accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import multiprocessing as mp\nprint('workeres = {}'.format(mp.cpu_count()))\nmodel_history = model.fit_generator(generator=train_datagen,\n                                   validation_data = val_datagen,\n                                   validation_steps=None,\n                                   epochs=10,\n                                   steps_per_epoch=100,\n                                   use_multiprocessing=True,\n                                   max_queue_size=10,\n                                   workers=mp.cpu_count())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(2, 1, figsize=(10, 20))\nprint(model_history.history.keys())\n# Plot model loss\nax[0].plot(model_history.history['loss'])\nax[0].plot(model_history.history['val_loss'])\nax[0].set_title('model loss')\nax[0].set_ylabel('loss')\nax[0].set_xlabel('epoch')\nax[0].legend(['train', 'test'], loc='upper left')\n\n# Plot model accuracy\nax[1].plot(model_history.history['categorical_accuracy'])\nax[1].plot(model_history.history['val_categorical_accuracy'])\nax[1].set_title('model accuracy')\nax[1].set_ylabel('accuracy')\nax[1].set_xlabel('epoch')\nax[1].legend(['train', 'test'], loc='upper left')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!rm -r rxrx1-utils","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":1}