{"cells":[{"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\n%matplotlib inline\nimport numpy as np # linear algebra\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nimport matplotlib\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport seaborn as sns\nimport os as os\nimport sys\nimport warnings\nimport time\nwarnings.filterwarnings('ignore')\n\nsns.set(style='white', context='notebook', palette='deep')\nnp.random.seed(2)\nfrom IPython.display import Image\n\n# From Matplotlib\nfrom matplotlib.colors import ListedColormap\n\n# From Scikit Learn\nfrom sklearn import preprocessing, decomposition, tree\nfrom sklearn.neighbors import KNeighborsClassifier\nfrom sklearn.model_selection import train_test_split, cross_val_score\nfrom astropy.table import Table, Column\nfrom sklearn.preprocessing import LabelEncoder\nimport itertools\n\n# Set DEBUG = True to produce debug results\nDEBUG = False\n\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# ROOT_DIR = '../input/state-farm-distracted-driver-detection/' #change the path\n# TRAIN_DIR = ROOT_DIR + 'imgs/train/'\n# TEST_DIR = ROOT_DIR + 'imgs/test/'\n# driver_imgs_list = pd.read_csv(ROOT_DIR + \"driver_imgs_list.csv\")\n# sample_submission = pd.read_csv(ROOT_DIR + \"sample_submission.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.utils import class_weight, shuffle\n\n\nos.listdir('/kaggle/input/state-farm-distracted-driver-detection/imgs/')\nfoldernames = os.listdir('/kaggle/input/state-farm-distracted-driver-detection/imgs/train')\ncategories = []\nfiles = []\ni = 0\nfor folder in foldernames:\n    filenames = os.listdir(\"../input/state-farm-distracted-driver-detection/imgs/train/\" + folder);\n    for file in filenames:\n        files.append(\"../input/state-farm-distracted-driver-detection/imgs/train/\" + folder + \"/\" + file)\n        categories.append(i)\n    i = i + 1\n        \n        \ndf = pd.DataFrame({\n    'filename': files,\n    'category': categories\n})\n\ny = df['category']\ntrain_df = df\n\nx = train_df['filename']\ny = train_df['category']\n\nx, y = shuffle(x, y, random_state=1)\ny.hist()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sift = cv2.ORB_create()\n\ndef fd_sift(image) :\n    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n\n    kps, des = sift.detectAndCompute(image, None)\n    return des if des is not None else np.array([]).reshape(0, 128)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# global_features = []\n# labels          = y\n# fixed_size = (28,28,3)#(500,500,3)\n# for file in x:\n#     image = cv2.imread(file)\n#     image.resize(fixed_size)\n#     global_features.append(image)\nglobal_features = []\nlabels          = y\nfixed_size = (28,28,3)#(500,500,3)\nfor file in x:\n    image = cv2.imread(file)\n    image.resize(fixed_size)\n    fv_sift = fd_sift(image)\n    global_feature = np.hstack([fv_sift])\n    global_feature.resize(fixed_size)\n    global_features.append(global_feature)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in global_features[:10]:\n    print(i.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"targetNames = np.unique(labels)\ntargetNames","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"X_train = np.array(global_features)\nX_train = X_train.reshape(len(X_train),28*28*3)\nY_train = y\nlen(X_train),X_train.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_x, valid_x, train_y, valid_y = train_test_split(X_train, Y_train, \n                                                      test_size=0.2, \n                                                      stratify=Y_train, \n                                                      random_state=1)\nprint(train_x.shape)\nprint(train_y.shape)\nprint(valid_x.shape)\nprint(valid_y.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"start_time = time.perf_counter()\ntrain_results = []\ntest_results = []\n# search for an optimal value of k for KNN MOdel\nk_range = list(range(1,5))\nk_scores = []\nfor k in k_range:\n    knn = KNeighborsClassifier(n_neighbors=k, n_jobs=-1, algorithm='ball_tree', leaf_size=40, weights='uniform')\n    scores = cross_val_score(knn, train_x, train_y, cv=10, scoring='accuracy', n_jobs=-1)\n    k_scores.append(scores.mean())\nif DEBUG:\n    print(k_scores) \nprint(time.perf_counter() - start_time, \"seconds\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if DEBUG:\n    scores = pd.DataFrame(k_scores)\n    print(scores)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.plot(k_range, k_scores)\nplt.xlabel('K Value for KNN')\nplt.ylabel('Cross-Validated Accuracy')\nplt.title('KNN Model for Accuracy')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"MSE = [1 - x for x in k_scores]\n\n# determining best k\noptimal_k = k_range[MSE.index(min(MSE))]\n\n# plot misclassification error vs k\nplt.plot(k_range, MSE)\nplt.xlabel('Number of Neighbors K')\nplt.ylabel('Misclassification Error')\nplt.title('KNN Model for Misclassification Error')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"start_time = time.perf_counter()\n#KNN train model. Call up my model and name it clf_knn\nclf_knn = KNeighborsClassifier(n_neighbors=3, n_jobs=-1, algorithm='ball_tree', leaf_size=40, weights='uniform')\n#Call up the model to see the parameters you can tune (and their default setting)\nprint(clf_knn)\n#Fit clf to the training data\nclf_knn = clf_knn.fit(train_x, train_y)\n#Predict clf_knn model again test data\ntarget_predicted_knn = clf_knn.predict(valid_x)\nprint(time.perf_counter() - start_time, \"seconds\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"target_predicted_knn","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.metrics import f1_score, fbeta_score, cohen_kappa_score, accuracy_score\n\n\naccuracy_score(valid_y,target_predicted_knn)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"scores = cross_val_score(clf_knn, valid_x, valid_y, cv=10, scoring='accuracy', n_jobs=-1)\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"scores","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"scores.mean()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"MSE = [1 - x for x in k_scores]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"MSE","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# def get_image(path, img_height=28, img_width=28, 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]\n# df_copy = driver_imgs_list.iloc[random_list]\n# image_paths = [TRAIN_DIR+row.classname+'/'+row.img \n#                    for (index, row) in df_copy.iterrows()]\n# image_shapes = [get_image(path).shape for path in image_paths]\n# print(set(image_shapes))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# img_path_list = []\n# label_list = []\n# for 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\n# y_labels_one_hot = to_categorical(label_list, dtype=np.int8)\n# x_img_path = np.array(img_path_list)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# from sklearn.utils import shuffle\n\n# np.save('x_img_path.npy', x_img_path)\n# np.save('y_labels_one_hot.npy', y_labels_one_hot)\n\n# x_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().\n# np.save('y_labels_one_hot_shuffled.npy', y_labels_one_hot_shuffled)\n# np.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.\n# x_img_path_shuffled_numpy = np.array(x_img_path_shuffled)\n\n# X_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\n# print(X_train_filenames.shape) # (3800,)\n# print(y_train.shape)           # (3800, 12)\n\n# print(X_val_filenames.shape)   # (950,)\n# print(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.\n# np.save('X_train_filenames.npy', X_train_filenames)\n# np.save('y_train.npy', y_train)\n\n# np.save('X_val_filenames.npy', X_val_filenames)\n# np.save('y_val.npy', y_val)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# IMG_HEIGHT = 64\n# IMG_WIDTH = 64\n# BATCH_SIZE = 32\n# CHANNEL = 3\n# class 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]\n# train_gen = Img_Generator(X_train_filenames, y_train, BATCH_SIZE)\n# val_gen = Img_Generator(X_val_filenames, y_val, BATCH_SIZE)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# train_gen","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# start_time = time.perf_counter()\n# train_results = []\n# test_results = []\n# # search for an optimal value of k for KNN MOdel\n# k_range = list(range(1,5))\n# k_scores = []\n# for k in k_range:\n#     knn = KNeighborsClassifier(n_neighbors=k, n_jobs=-1, algorithm='ball_tree', leaf_size=40, weights='uniform')\n#     scores = cross_val_score(knn, features_train, target_train, cv=10, scoring='accuracy', n_jobs=-1)\n#     k_scores.append(scores.mean())\n# if DEBUG:\n#     print(k_scores) \n# print(time.perf_counter() - start_time, \"seconds\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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\n# from efficientnet.keras import EfficientNetB5\n# from keras.layers import (Activation, Dropout, Flatten, Dense, GlobalMaxPooling2D,\n#                           BatchNormalization, Input, Conv2D, GlobalAveragePooling2D,concatenate,Concatenate,multiply, LocallyConnected2D, Lambda)\n\n# nb_train_samples = 17943\n# nb_validation_samples = 4481\n\n# IMAGENET_WEIGHTS_HASHES = {\n#     'efficientnet-b5': ('30172f1d45f9b8a41352d4219bf930ee'\n#                         '3339025fd26ab314a817ba8918fefc7d',\n#                         '9d197bc2bfe29165c10a2af8c2ebc675'\n#                         '07f5d70456f09e584c71b822941b1952')\n# }\n# IMAGENET_WEIGHTS_PATH = (\n#     'https://github.com/Callidior/keras-applications/'\n#     'releases/download/efficientnet/')\n\n# eff_net = EfficientNetB5(weights= None, include_top=False, input_shape=(64, 64, 3))\n# in_lay = Input(shape=(64,64,3))\n\n# file_name = \"efficientnet-b5\" + '_weights_tf_dim_ordering_tf_kernels_autoaugment_notop.h5'\n# file_hash = IMAGENET_WEIGHTS_HASHES[\"efficientnet-b5\"][1]\n# weights_path = keras.utils.get_file(\n#             file_name,\n#             IMAGENET_WEIGHTS_PATH + file_name,\n#             cache_subdir='models',\n#             file_hash=file_hash,\n#  )\n# eff_net.load_weights(weights_path)\n# pt_depth = eff_net.get_output_shape_at(0)[-1]\n# pt_features = eff_net(in_lay)\n# bn_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\n# attn_layer = Conv2D(64, kernel_size = (1,1), padding = 'same', activation = 'relu')(Dropout(0.5)(bn_features))\n# attn_layer = Conv2D(16, kernel_size = (1,1), padding = 'same', activation = 'relu')(attn_layer)\n# attn_layer = Conv2D(8, kernel_size = (1,1), padding = 'same', activation = 'relu')(attn_layer)\n# attn_layer = Conv2D(1, kernel_size = (1,1), padding = 'valid', activation = 'sigmoid')(attn_layer)\n\n# mask_features = multiply([attn_layer, bn_features])\n# gap_features = GlobalAveragePooling2D()(mask_features)\n# gap_mask = GlobalAveragePooling2D()(attn_layer)\n# # to account for missing values from the attention model\n# gap = Lambda(lambda x: x[0]/x[1], name = 'RescaleGAP')([gap_features, gap_mask])\n# gap_dr = Dropout(0.25)(gap)\n# dr_steps = Dropout(0.25)(Dense(128, activation = 'relu')(gap_dr))\n# out_layer = Dense(10, activation = 'softmax')(dr_steps)\n# retina_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\n# epochs = 15; batch_size = 32\n# checkpoint = ModelCheckpoint('../working/model_.h5', monitor='val_loss', verbose=1, \n#                              save_best_only=True, mode='min', save_weights_only = True)\n# reduceLROnPlat = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=4, \n#                                    verbose=1, mode='auto', epsilon=0.0001)\n# early = EarlyStopping(monitor=\"val_loss\", \n#                       mode=\"min\", \n#                       patience=9)\n# csv_logger = CSVLogger(filename='../working/training_log.csv',\n#                        separator=',',\n#                        append=True)\n\n# train_generator = train_gen\n# # train_mixup = My_Generator(train_x, train_y, batch_size, is_train=True, mix=False, augment=True)\n# valid_generator = val_gen\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# from keras.callbacks import Callback\n# class 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\n# qwk = 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\n# for i in range(-3,0):\n#     retina_model.layers[i].trainable = True\n\n# retina_model.compile(\n#     loss='categorical_crossentropy',\n#     optimizer=Adam(1e-3),metrics=['accuracy'])\n\n# retina_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\n# from keras.losses import binary_crossentropy, categorical_crossentropy\n# from sklearn.metrics import f1_score, fbeta_score, cohen_kappa_score\n\n# for layer in retina_model.layers:\n#     layer.trainable = True\n# callbacks_list = [checkpoint, csv_logger, reduceLROnPlat, early, qwk]\n# retina_model.compile(\n#             loss='categorical_crossentropy',\n#             optimizer=Adam(lr=1e-4))\n# retina_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}