{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install -U 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 # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n# visulization\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n%matplotlib inline\n\nimport os\nimport gc # garbage collection\nimport glob # extract path via pattern matching\nimport random\nimport math\nimport cv2 # read image\n# store to disk\nimport pickle\nimport h5py # like numpy array\n\n\nfrom sklearn.model_selection import train_test_split\nfrom keras.utils import to_categorical\n\nfrom keras.models import Sequential, Model\nfrom keras.models import load_model\nfrom keras.layers import Input, Dense, Conv2D, MaxPool2D, AveragePooling2D\nfrom keras.layers import Flatten, Dropout, BatchNormalization, Activation\nfrom keras.layers import Add\nfrom keras.optimizers import SGD, RMSprop, Adam\nfrom keras import regularizers\nimport keras\n\nfrom keras.callbacks import ModelCheckpoint, EarlyStopping\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ROOT_DIR = '../input/state-farm-distracted-driver-detection/' #change the path\nTRAIN_DIR = ROOT_DIR + 'imgs/train/'\nTEST_DIR = ROOT_DIR + 'imgs/test/'\ndriver_imgs_list = pd.read_csv(ROOT_DIR + \"driver_imgs_list.csv\")\nsample_submission = pd.read_csv(ROOT_DIR + \"sample_submission.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_image(path, img_height=None, img_width=None, rotate=False, color_type=0):\n    img = cv2.imread(path, color_type)\n    if img_width and img_height:\n        img = cv2.resize(img, (img_width, img_height))\n    if rotate is True:\n        rows, cols = img.shape\n        rotation_angle = random.uniform(10,-10)\n        M = cv2.getRotationMatrix2D((cols/2, rows/2), rotation_angle, 1)\n        img = cv2.warpAffine(img, M, (cols,rows))\n    return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"random_list = np.random.permutation(len(driver_imgs_list))[:50]\ndf_copy = driver_imgs_list.iloc[random_list]\nimage_paths = [TRAIN_DIR+row.classname+'/'+row.img \n                   for (index, row) in df_copy.iterrows()]\nimage_shapes = [get_image(path).shape for path in image_paths]\nprint(set(image_shapes))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img_path_list = []\nlabel_list = []\nfor index, row in driver_imgs_list.iterrows():\n    img_path_list.append('{0}{1}/{2}'.format(TRAIN_DIR, row.classname, row.img))\n    label_list.append(int(row.classname[1]))\n# One hot vector representation of labels\ny_labels_one_hot = to_categorical(label_list, dtype=np.int8)\nx_img_path = np.array(img_path_list)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.utils import shuffle\n\nnp.save('x_img_path.npy', x_img_path)\nnp.save('y_labels_one_hot.npy', y_labels_one_hot)\n\nx_img_path_shuffled, y_labels_one_hot_shuffled = shuffle(x_img_path, y_labels_one_hot)\n\n# saving the shuffled file.\n# you can load them later using np.load().\nnp.save('y_labels_one_hot_shuffled.npy', y_labels_one_hot_shuffled)\nnp.save('x_img_path_shuffled.npy', x_img_path_shuffled)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n# Used this line as our filename array is not a numpy array.\nx_img_path_shuffled_numpy = np.array(x_img_path_shuffled)\n\nX_train_filenames, X_val_filenames, y_train, y_val = train_test_split(\n    x_img_path_shuffled_numpy, y_labels_one_hot_shuffled, test_size=0.2, random_state=1)\n\nprint(X_train_filenames.shape) # (3800,)\nprint(y_train.shape)           # (3800, 12)\n\nprint(X_val_filenames.shape)   # (950,)\nprint(y_val.shape)             # (950, 12)\n\n# You can save these files as well. As you will be using them later for training and validation of your model.\nnp.save('X_train_filenames.npy', X_train_filenames)\nnp.save('y_train.npy', y_train)\n\nnp.save('X_val_filenames.npy', X_val_filenames)\nnp.save('y_val.npy', y_val)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"IMG_HEIGHT = 64\nIMG_WIDTH = 64\nBATCH_SIZE = 32\nCHANNEL = 3\nclass Img_Generator(keras.utils.Sequence):\n    def __init__(self, image_filenames, labels, batch_size) :\n        self.image_filenames = image_filenames\n        self.labels = labels\n        self.batch_size = batch_size\n    def __len__(self) :\n        return (np.ceil(len(self.image_filenames) / float(self.batch_size))).astype(np.int)\n    def __getitem__(self, idx) :\n        batch_x = self.image_filenames[idx * self.batch_size : (idx+1) * self.batch_size]\n        batch_y = self.labels[idx * self.batch_size : (idx+1) * self.batch_size]\n        img_list = []\n        for file_name in batch_x:\n            if CHANNEL == 1:\n                original_img = cv2.imread(file_name, 0)\n            else:\n                original_img = cv2.imread(file_name, 1)\n            im = cv2.resize(original_img, (IMG_HEIGHT, IMG_WIDTH))\n            #color = [0, 0, 0]\n            #new_im = cv2.copyMakeBorder(im, 40, 40, 0, 0, cv2.BORDER_CONSTANT, value=color)\n            #im = cv2.resize(new_im, (224, 224))\n            img_list.append(im)\n        img_batch = np.array(img_list)\n        if CHANNEL == 1:\n            img_batch = np.expand_dims(img_batch, axis=-1)\n        return img_batch, np.array(batch_y)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# size of input [BATCH_SIZE, IMG_HEIGHT, IMG_WIDTH, CHANNEL]\ntrain_gen = Img_Generator(X_train_filenames, y_train, BATCH_SIZE)\nval_gen = Img_Generator(X_val_filenames, y_val, BATCH_SIZE)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!rm -f saved_models/weights_best_efficient.hdf5","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras import optimizers\nfrom efficientnet.keras import EfficientNetB5\nfrom keras.layers import (Activation, Dropout, Flatten, Dense, GlobalMaxPooling2D,\n                          BatchNormalization, Input, Conv2D, GlobalAveragePooling2D,concatenate,Concatenate,multiply, LocallyConnected2D, Lambda)\n\nnb_train_samples = 17943\nnb_validation_samples = 4481\n\nIMAGENET_WEIGHTS_HASHES = {\n    'efficientnet-b5': ('30172f1d45f9b8a41352d4219bf930ee'\n                        '3339025fd26ab314a817ba8918fefc7d',\n                        '9d197bc2bfe29165c10a2af8c2ebc675'\n                        '07f5d70456f09e584c71b822941b1952')\n}\nIMAGENET_WEIGHTS_PATH = (\n    'https://github.com/Callidior/keras-applications/'\n    'releases/download/efficientnet/')\n\neff_net = EfficientNetB5(weights= None, include_top=False, input_shape=(64, 64, 3))\nin_lay = Input(shape=(64,64,3))\n\nfile_name = \"efficientnet-b5\" + '_weights_tf_dim_ordering_tf_kernels_autoaugment_notop.h5'\nfile_hash = IMAGENET_WEIGHTS_HASHES[\"efficientnet-b5\"][1]\nweights_path = keras.utils.get_file(\n            file_name,\n            IMAGENET_WEIGHTS_PATH + file_name,\n            cache_subdir='models',\n            file_hash=file_hash,\n )\neff_net.load_weights(weights_path)\npt_depth = eff_net.get_output_shape_at(0)[-1]\npt_features = eff_net(in_lay)\nbn_features = BatchNormalization()(pt_features)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.layers import (Activation, Dropout, Flatten, Dense, GlobalMaxPooling2D,\n                          BatchNormalization, Input, Conv2D, GlobalAveragePooling2D,concatenate,Concatenate,multiply, LocallyConnected2D, Lambda)\n# here we do an attention mechanism to turn pixels in the GAP on an off\nattn_layer = Conv2D(64, kernel_size = (1,1), padding = 'same', activation = 'relu')(Dropout(0.5)(bn_features))\nattn_layer = Conv2D(16, kernel_size = (1,1), padding = 'same', activation = 'relu')(attn_layer)\nattn_layer = Conv2D(8, kernel_size = (1,1), padding = 'same', activation = 'relu')(attn_layer)\nattn_layer = Conv2D(1, kernel_size = (1,1), padding = 'valid', activation = 'sigmoid')(attn_layer)\n\nmask_features = multiply([attn_layer, bn_features])\ngap_features = GlobalAveragePooling2D()(mask_features)\ngap_mask = GlobalAveragePooling2D()(attn_layer)\n# to account for missing values from the attention model\ngap = Lambda(lambda x: x[0]/x[1], name = 'RescaleGAP')([gap_features, gap_mask])\ngap_dr = Dropout(0.25)(gap)\ndr_steps = Dropout(0.25)(Dense(128, activation = 'relu')(gap_dr))\nout_layer = Dense(10, activation = 'softmax')(dr_steps)\nretina_model = Model(inputs = [in_lay], outputs = [out_layer])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"retina_model.summary()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.callbacks import (ModelCheckpoint, LearningRateScheduler,\n                             EarlyStopping, ReduceLROnPlateau,CSVLogger)\n\nepochs = 15; batch_size = 32\ncheckpoint = ModelCheckpoint('../working/model_.h5', monitor='val_loss', verbose=1, \n                             save_best_only=True, mode='min', save_weights_only = True)\nreduceLROnPlat = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=4, \n                                   verbose=1, mode='auto', epsilon=0.0001)\nearly = EarlyStopping(monitor=\"val_loss\", \n                      mode=\"min\", \n                      patience=9)\ncsv_logger = CSVLogger(filename='../working/training_log.csv',\n                       separator=',',\n                       append=True)\n\ntrain_generator = train_gen\n# train_mixup = My_Generator(train_x, train_y, batch_size, is_train=True, mix=False, augment=True)\nvalid_generator = val_gen\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.callbacks import Callback\nclass QWKEvaluation(Callback):\n    def __init__(self, validation_data=(), batch_size=64, interval=1):\n        super(Callback, self).__init__()\n\n        self.interval = interval\n        self.batch_size = batch_size\n        self.valid_generator, self.y_val = validation_data\n        self.history = []\n\n    def on_epoch_end(self, epoch, logs={}):\n        if epoch % self.interval == 0:\n            y_pred = self.model.predict_generator(generator=self.valid_generator,\n                                                  steps=np.ceil(float(len(self.y_val)) / float(self.batch_size)),\n                                                  workers=1, use_multiprocessing=False,\n                                                  verbose=1)\n            def flatten(y):\n                return np.argmax(y, axis=1).reshape(-1)\n            \n            score = cohen_kappa_score(flatten(self.y_val),\n                                      flatten(y_pred),\n                                      labels=[0,1,2,3,4],\n                                      weights='quadratic')\n            print(\"\\n epoch: %d - QWK_score: %.6f \\n\" % (epoch+1, score))\n            self.history.append(score)\n            if score >= max(self.history):\n                print('saving checkpoint: ', score)\n                self.model.save('../working/model_bestqwk.h5')\n\nqwk = QWKEvaluation(validation_data=(valid_generator, y_val),\n                    batch_size=batch_size, interval=1)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for layer in retina_model.layers:\n    layer.trainable = False\n\nfor i in range(-3,0):\n    retina_model.layers[i].trainable = True\n\nretina_model.compile(\n    loss='categorical_crossentropy',\n    optimizer=Adam(1e-3),metrics=['accuracy'])\n\nretina_model.fit_generator(\n    train_generator,\n    steps_per_epoch=np.ceil(float(len(y_train)) / float(128)),\n    epochs=2,\n    workers=2, use_multiprocessing=True,\n    verbose=1,\n    callbacks=[early, checkpoint])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def kappa_loss(y_true, y_pred, y_pow=2, eps=1e-12, N=10, bsize=32, name='kappa'):\n    with tf.name_scope(name):\n        y_true = tf.to_float(y_true)\n        repeat_op = tf.to_float(tf.tile(tf.reshape(tf.range(0, N), [N, 1]), [1, N]))\n        repeat_op_sq = tf.square((repeat_op - tf.transpose(repeat_op)))\n        weights = repeat_op_sq / tf.to_float((N - 1) ** 2)\n    \n        pred_ = y_pred ** y_pow\n        try:\n            pred_norm = pred_ / (eps + tf.reshape(tf.reduce_sum(pred_, 1), [-1, 1]))\n        except Exception:\n            pred_norm = pred_ / (eps + tf.reshape(tf.reduce_sum(pred_, 1), [bsize, 1]))\n    \n        hist_rater_a = tf.reduce_sum(pred_norm, 0)\n        hist_rater_b = tf.reduce_sum(y_true, 0)\n    \n        conf_mat = tf.matmul(tf.transpose(pred_norm), y_true)\n    \n        nom = tf.reduce_sum(weights * conf_mat)\n        denom = tf.reduce_sum(weights * tf.matmul(\n            tf.reshape(hist_rater_a, [N, 1]), tf.reshape(hist_rater_b, [1, N])) /\n                              tf.to_float(bsize))\n    \n        return nom*0.5 / (denom + eps) + categorical_crossentropy(y_true, y_pred)*0.5","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import tensorflow as tf\nfrom keras.losses import binary_crossentropy, categorical_crossentropy\nfrom sklearn.metrics import f1_score, fbeta_score, cohen_kappa_score\n\nfor layer in retina_model.layers:\n    layer.trainable = True\ncallbacks_list = [checkpoint, csv_logger, reduceLROnPlat, early, qwk]\nretina_model.compile(\n            loss='categorical_crossentropy',\n            optimizer=Adam(lr=1e-4))\nretina_model.fit_generator(\n    train_generator,\n    steps_per_epoch=np.ceil(float(len(y_train)) / float(batch_size)),\n    validation_data=valid_generator,\n    validation_steps=np.ceil(float(len(y_val)) / float(batch_size)),\n    epochs=epochs,\n    verbose=1,\n    workers=1, use_multiprocessing=False,\n    callbacks=callbacks_list)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":4}