{"nbformat": 4, "cells": [{"cell_type": "markdown", "source": ["### Work flow for Porto Seguro\u2019s Safe Driver Prediction\n", "* Feature transformation\n", "* algorithme spot check"], "metadata": {"_cell_guid": "606314dc-8860-4d15-ace6-9bcc4a685b51", "_uuid": "746d1f52cf511395efeb193e32d1bd1250ae1609"}}, {"cell_type": "code", "outputs": [], "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 in \n", "\n", "import numpy as np # linear algebra\n", "import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n", "\n", "from sklearn.model_selection import cross_val_score,StratifiedKFold\n", "\n", "\n", "from lightgbm import LGBMClassifier\n", "from xgboost import XGBClassifier\n", "from catboost import CatBoostClassifier\n", "from sklearn.ensemble import RandomForestClassifier\n", "from rgf.sklearn import RGFClassifier\n", "\n", "# Input data files are available in the \"../input/\" directory.\n", "# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n", "\n", "from subprocess import check_output\n", "print(check_output([\"ls\", \"../input\"]).decode(\"utf8\"))\n", "\n", "\n", "# Any results you write to the current directory are saved as output."], "metadata": {"_uuid": "be84cc89f209f6700f4429fe4e096ff1f864c12f", "_cell_guid": "e591ad62-449a-42e6-95cc-dad68f2eeaad", "_kg_hide-input": true}, "execution_count": 1}, {"cell_type": "markdown", "source": ["## Loading data"], "metadata": {"_cell_guid": "d42be291-2dcf-41ae-908b-944e1b9b3f4a", "_uuid": "e9a0af7b96c239ca2f091241aa70c52cb80d92db"}}, {"cell_type": "code", "outputs": [], "source": ["trainData = pd.read_csv('../input/train.csv',na_values=[-1,-1.0])\n", "testData = pd.read_csv('../input/test.csv',na_values=[-1,-1.0])"], "metadata": {"collapsed": true, "_cell_guid": "2aa62334-267d-47dd-99d0-92200a48f7bf", "_uuid": "4fa3cd734f6e385eedf0af0739a03315877ba328"}, "execution_count": 2}, {"cell_type": "markdown", "source": ["## preprocessing\n", "merging two dataframes into one"], "metadata": {"_cell_guid": "42a7be49-a313-49a7-9767-9c4197516023", "_uuid": "0d6c2ef41b1e8259eb62d50f5055e03dc9ce1d72"}}, {"cell_type": "code", "outputs": [], "source": ["trainData['dset'] = 'train'\n", "testData['dset'] = 'test'\n", "combined = pd.concat([trainData, testData], ignore_index=True)"], "metadata": {"collapsed": true, "_cell_guid": "5e723218-dcea-4842-9331-7467c7a51dc0", "_uuid": "56f7bbd1bcc3793399960487177e6786f263124d"}, "execution_count": 3}, {"cell_type": "markdown", "source": ["feature modification based on EDA"], "metadata": {"_cell_guid": "ffc68461-42d6-4f7b-9fb7-f6f84a7f9add", "_uuid": "68a8f1730507cb09fee48284f557fc67d9ac2cf5"}}, {"cell_type": "code", "outputs": [], "source": ["  # ps_ind_01 \n", "    # mergering but had good roc without merging\n", "#combined['ps_ind_01_merged_cat'] = 1\n", "#combined.loc[combined.ps_ind_01 < 2 ,'ps_ind_01_merged_cat'] = 0\n", "#combined.loc[combined.ps_ind_01 > 2 ,'ps_ind_01_merged_cat'] = 2\n", "\n", "  # ps_ind_02_cat \n", "    # only NA imputation\n", "combined['ps_ind_02_cat'].fillna(4,inplace=True)\n", "\n", "  # ps_ind_03 \n", "    # not improved with binning. possible entropy based binning couldnt find a good package\n", "#combined['ps_ind_03_merged_cat'] = 1\n", "#combined.loc[combined.ps_ind_01 < 2 ,'ps_ind_03_merged_cat'] = 0\n", "#combined.loc[combined.ps_ind_01 > 4 ,'ps_ind_03_merged_cat'] = 2\n", "\n", "  #ps_ind_04_cat\n", "combined['ps_ind_04_cat'].fillna(1,inplace=True)\n", "\n", "  #ps_ind_05_cat : category 5 has lesser count, may be merged to two cat\n", "combined['ps_ind_05_cat'].fillna(2,inplace=True)\n", "\n", "  #ps_ind_06/06/08/09/10/11/12/13/16/17/18_bin \n", "    # 10,11,12,13 has very less count on one category\n", "    \n", "  #ps_ind_14 \n", "    # binning possible\n", "combined['ps_ind_14_binned'] = combined['ps_ind_14']\n", "combined.loc[combined.ps_ind_14 > 0 ,'ps_ind_14_binned'] = 1\n", "\n", "  #ps_ind_15 \n", "    # better roc without any modification\n", "#combined['ps_ind_15_binned'] = combined['ps_ind_15']\n", "#combined.loc[combined.ps_ind_15 < 3 ,'ps_ind_15_binned'] = 0\n", "#combined.loc[combined.ps_ind_15 > 8 ,'ps_ind_15_binned'] = 2\n", "#combined.loc[(combined.ps_ind_15 > 2) & (combined.ps_ind_15 < 9) ,'ps_ind_15_binned'] = 1\n", "\n", "  #ps_reg_01\n", "combined['ps_reg_01'] = combined['ps_reg_01']*10\n", "\n", "  #ps_reg_02\n", "combined['ps_reg_02'] = combined['ps_reg_02']*10\n", "\n", "  #ps_reg_01_02\n", "combined['ps_reg_01_02'] = combined['ps_reg_01']*combined['ps_reg_02']    \n", "  #ps_reg_03\n", "    # NA 8%\n", "    # outlier removing\n", "combined['ps_reg_03'].fillna(combined['ps_reg_03'].median(skipna=True),inplace=True)\n", "combined['ps_reg_03_mod'] = combined['ps_reg_03']\n", "combined.loc[combined.ps_reg_03_mod < 0.25 ,'ps_reg_03_mod'] = 0.25\n", "combined.loc[combined.ps_reg_03_mod > 2.25 ,'ps_reg_03_mod'] = 2.25\n", "combined['ps_reg_03_mod'] = np.log(combined['ps_reg_03_mod']*100)\n", "\n", "  #ps_car_01_cat\n", "    # NA merged cat 9\n", "combined['ps_car_01_cat'].fillna(9,inplace=True)\n", "combined.loc[combined.ps_car_01_cat < 4 ,'ps_car_01_cat'] = 3\n", "\n", "  #ps_car_02_cat\n", "    # NA merged cat 9\n", "combined['ps_car_02_cat'].fillna(1,inplace=True)\n", "\n", "  #ps_car_03_cat\n", "    # 80% NA\n", "\n", "  #ps_car_04_cat\n", "    # 3,4,5,6,7 has low counts\n", "combined.loc[(combined.ps_car_04_cat < 8) & (combined.ps_car_04_cat >2) ,'ps_car_04_cat'] = 3    \n", "\n", "  #ps_car_05_cat\n", "    # 50% NA    \n", "combined['ps_car_05_cat'].fillna(2,inplace=True)\n", "\n", "  #ps_car_06_cat\n", "    # 17 categories\n", "    # some are having very low count\n", "combined.loc[combined.ps_car_06_cat == 5,'ps_car_06_cat'] = 2\n", "combined.loc[combined.ps_car_06_cat == 8,'ps_car_06_cat'] = 2\n", "combined.loc[combined.ps_car_06_cat == 12,'ps_car_06_cat'] = 2\n", "combined.loc[combined.ps_car_06_cat == 13,'ps_car_06_cat'] = 2\n", "combined.loc[combined.ps_car_06_cat == 16,'ps_car_06_cat'] = 2\n", "combined.loc[combined.ps_car_06_cat == 17,'ps_car_06_cat'] = 2\n", "\n", "  #ps_car_07_cat\n", "    # 2% NA\n", "combined['ps_car_07_cat'].fillna(0,inplace=True)\n", "combined['ps_car_07_bin'] = combined['ps_car_07_cat'] # renaming to bin\n", "\n", "  #ps_car_08_cat\n", "combined['ps_car_08_bin'] = combined['ps_car_08_cat'] # renaming to bin\n", "\n", "  #ps_car_09_cat\n", "    # NA 569/877\n", "    # one category having low count\n", "combined['ps_car_09_cat'].fillna(1,inplace=True)\n", "combined.loc[combined.ps_car_09_cat == 4,'ps_car_09_cat'] = 1\n", "\n", "  #ps_car_10_cat\n", "    # cat 2 has very low count\n", "combined.loc[combined.ps_car_10_cat==2,'ps_car_10_cat'] = 1\n", "combined['ps_car_10_bin'] = combined['ps_car_10_cat']\n", "\n", "  #ps_car_11_cat\n", "    # too many categories\n", "\n", "  #ps_car_11\n", "    # better to try with category option\n", "combined['ps_car_11'].fillna(1,inplace=True)\n", "\n", "  #ps_car_12\n", "    # NA changed with mean\n", "combined['ps_car_12'].fillna(combined['ps_car_12'].median(skipna=True),inplace=True)\n", "combined.loc[combined.ps_car_12>0.75,'ps_car_12'] = 0.75\n", "combined.loc[combined.ps_car_12<0.2828,'ps_car_12'] = 0.2828\n", "\n", "  #ps_car_13\n", "combined.loc[combined.ps_car_13>2,'ps_car_13'] = 2\n", "\n", "  #ps_car_14\n", "combined['ps_car_14'].fillna(combined['ps_car_14'].median(skipna=True),inplace=True)\n", "combined.loc[combined.ps_car_14<0.275,'ps_car_14'] <- 0.275\n", "combined.loc[combined.ps_car_14>0.575,'ps_car_14'] <- 0.575\n", "\n", "  #ps_car_15\n", "combined['ps_car_15'] = round(combined['ps_car_15']**2,0)"], "metadata": {"collapsed": true, "_cell_guid": "d396d1ea-2dda-4aed-a7e5-30458e0385d9", "_uuid": "a25319d01fff3d05376157d4fc44c99e27cc6342"}, "execution_count": 4}, {"cell_type": "markdown", "source": ["Selected features during EDA"], "metadata": {"_cell_guid": "498be7fb-be8a-4247-995c-fd129bfbc088", "_uuid": "348a0490d17997eb874ddd83dfe05ca69acb75d5"}}, {"cell_type": "code", "outputs": [], "source": ["trainFeatures = [\n", "    \"ps_ind_01\",\n", "    \"ps_ind_02_cat\", \n", "    \"ps_ind_03\",\n", "    \"ps_ind_04_cat\",     \n", "    \"ps_ind_05_cat\",      # cat 5 has very low count\n", "    \"ps_ind_06_bin\", \n", "    \"ps_ind_07_bin\", \n", "    \"ps_ind_08_bin\", \n", "    \"ps_ind_09_bin\",    \n", "    #\"ps_ind_10_bin\",     # non-zero variance \n", "    #\"ps_ind_11_bin\",     # non-zero variance \n", "    #\"ps_ind_12_bin\",     # non-zero variance \n", "    #\"ps_ind_13_bin\",     # non-zero variance\n", "    \"ps_ind_14_binned\",  # one category dominates the count, # from the feature importance\n", "    \"ps_ind_15\",\n", "    \"ps_ind_16_bin\", \n", "    \"ps_ind_17_bin\", \n", "    \"ps_ind_18_bin\",      \n", "    \n", "    \"ps_reg_01\",\n", "    \"ps_reg_02\",\n", "    \"ps_reg_01_02\",\n", "    #\"ps_reg_03\",\n", "    \"ps_reg_03_mod\",\n", "    \n", "    \"ps_car_01_cat\", \n", "    \"ps_car_02_cat\",     \n", "    #\"ps_car_03_cat\",     # 80% NA \n", "    \"ps_car_04_cat\", \n", "    \"ps_car_05_cat\",\n", "    \"ps_car_06_cat\",      # saw slight drop in auc. but feature importance is good\n", "    \"ps_car_07_bin\",      # rename as bin variable from cat due to two category\n", "    \"ps_car_08_bin\",     # rename as bin variable from cat due to two category # from the feature importance\n", "    \"ps_car_09_cat\", \n", "    \"ps_car_10_bin\",     # merge and rename as bin but accuracy dropped little # from the feature importance\n", "    #\"ps_car_11_cat\",     # too many categories when introduce accuracy went down\n", "    \"ps_car_11\",         \n", "    \"ps_car_12\", \n", "    \"ps_car_13\",\n", "    \"ps_car_14\",\n", "    \"ps_car_15\",\n", "    \"ps_calc_01\", \n", "    \"ps_calc_02\",\n", "    \"ps_calc_03\", \n", "    \"ps_calc_04\",\n", "    \"ps_calc_05\",        \n", "    \"ps_calc_06\",\n", "    \"ps_calc_07\", \n", "    \"ps_calc_08\",\n", "    \"ps_calc_09\", \n", "    \"ps_calc_10\",\n", "    \"ps_calc_11\", \n", "    \"ps_calc_12\",\n", "    \"ps_calc_13\",        \n", "    \"ps_calc_14\",\n", "    \"ps_calc_15_bin\",    # from feature importance after introducing calc\n", "    \"ps_calc_16_bin\",    # from feature importance after introducing calc\n", "    \"ps_calc_17_bin\",    # from feature importance after introducing calc\n", "    \"ps_calc_18_bin\",    # from feature importance after introducing calc\n", "    \"ps_calc_19_bin\",    # from feature importance after introducing calc\n", "    \"ps_calc_20_bin\",    # from feature importance after introducing calc\n", "]"], "metadata": {"collapsed": true, "_cell_guid": "b68a64d3-a927-4250-8335-42b97f92f018", "_uuid": "64b4d367ca81709033473b4f649d39a9a5157a49"}, "execution_count": 5}, {"cell_type": "markdown", "source": ["preaparing train and test set for model building"], "metadata": {"_cell_guid": "390e6aba-fbfb-44b7-801c-b90a073cfec0", "_uuid": "e7a928bf727f46478405fdf664ffec521c222f55"}}, {"cell_type": "code", "outputs": [], "source": ["id_test = combined.loc[combined.dset=='test','id'].values\n", "target_train = combined.loc[combined.dset=='train','target'].values\n", "\n", "trainSet = combined.loc[combined.dset=='train',trainFeatures]\n", "testSet = combined.loc[combined.dset=='test',trainFeatures]\n", "\n", "cat_features = [a for a in trainSet.columns if a.endswith('cat')]\n", "for column in cat_features:\n", "    trainSet[column]=trainSet[column].astype('category')\n", "    testSet[column]=testSet[column].astype('category')\n", "\n", "temp = pd.get_dummies(trainSet[cat_features])\n", "trainSet = pd.concat([trainSet,temp],axis=1)\n", "trainSet.drop(np.asarray(cat_features),axis=1,inplace=True)\n", "\n", "temp = pd.get_dummies(testSet[cat_features])\n", "testSet = pd.concat([testSet,temp],axis=1)\n", "testSet.drop(np.asarray(cat_features),axis=1,inplace=True)"], "metadata": {"collapsed": true, "_cell_guid": "80d64d25-446a-4bed-8c84-91b54af27d8a", "_uuid": "07879e4ae7c8f914ab759783bedc15a6ec5ac56b"}, "execution_count": 6}, {"cell_type": "markdown", "source": ["## LightGBM"], "metadata": {"_cell_guid": "70d3172c-b7ba-4a7c-a27e-5ac7d3ac911d", "_uuid": "42826b6d09423e0fb4e492fb615f6b2f9ebae373"}}, {"cell_type": "code", "outputs": [], "source": ["# parameters\n", "lgb_params = {}\n", "lgb_params['n_estimators'] = 500      # n_estimators (int, optional (default=10)) \u2013 Number of boosted trees to fit.\n", "lgb_params['learning_rate'] = 0.02    # learning_rate (float, optional (default=0.1)) \u2013 Boosting learning rate.\n", "lgb_params['colsample_bytree'] = 0.8  # colsample_bytree (float, optional (default=1.)) \u2013 Subsample ratio of columns when constructing each tree.\n", "lgb_params['subsample'] = 0.8         # subsample (float, optional (default=1.)) \u2013 Subsample ratio of the training instanc\n", "lgb_params['subsample_freq'] = 2     # subsample_freq (int, optional (default=1)) \u2013 Frequence of subsample, <=0 means no enable.\n", "lgb_params['max_bin'] = 32            # max_bin (int, optional (default=255)) \u2013 Number of bucketed bin for feature values.\n", "lgb_params['min_child_samples'] = 20  # min_child_samples (int, optional (default=20)) \u2013 Minimum number of data need in a child(leaf).\n", "lgb_params['random_state'] = 100\n", "lgb_params['n_jobs'] = 2\n", "\n", "# Model building\n", "lgb_model = LGBMClassifier(**lgb_params)\n", "cv_results = cross_val_score(lgb_model, trainSet, target_train, cv=StratifiedKFold(2), scoring='roc_auc',verbose=1)\n", "print(cv_results)\n"], "metadata": {"collapsed": true, "_cell_guid": "1a31a957-7720-406c-b454-57378b045251", "_uuid": "9db1335a60c69a87516c86fe2b0478f86a28bdd1"}, "execution_count": null}, {"cell_type": "markdown", "source": ["## XGBoost"], "metadata": {"_cell_guid": "de67c93d-0445-4aff-be6a-a44645dbb43e", "_uuid": "1cecf3f87361d46c778cd53842f5a4c37f04a36e"}}, {"cell_type": "code", "outputs": [], "source": ["# parameters\n", "xgb_params = {}\n", "xgb_params['objective'] = 'binary:logistic'\n", "xgb_params['learning_rate'] = 1\n", "xgb_params['n_estimators'] = 200\n", "xgb_params['max_depth'] = 4\n", "xgb_params['subsample'] = 0.9\n", "xgb_params['colsample_bytree'] = 0.9\n", "xgb_params['min_child_weight'] = 10\n", "xgb_params['scale_pos_weight'] = 0.5\n", "xgb_params['n_jobs'] = 2\n", "xgb_params['gamma']=1\n", "xgb_params['reg_alpha']=0\n", "xgb_params['reg_lambda']=1\n", "# Model building\n", "xgb_model = XGBClassifier(**xgb_params)\n", "cv_results = cross_val_score(xgb_model, trainSet, target_train, cv=2, scoring='roc_auc',verbose=1)\n", "print(cv_results)"], "metadata": {"collapsed": true, "_cell_guid": "e6db5663-9b0e-4fef-a940-31401a5a96b0", "_uuid": "89d38fcd176e99049154c31a046aa3aec8fba8da"}, "execution_count": null}, {"cell_type": "markdown", "source": ["## catBoost"], "metadata": {"_cell_guid": "805b380d-9b6e-4428-853e-aa256c2e36e2", "_uuid": "866aa17c92d6b8e17ba9b4c08eb17f17c094b2c1"}}, {"cell_type": "code", "outputs": [], "source": ["#CatBoost params initial\n", "cat_params = {}\n", "cat_params['iterations'] = 100\n", "cat_params['depth'] = 8\n", "cat_params['rsm'] = 0.95\n", "cat_params['learning_rate'] = 0.03\n", "cat_params['l2_leaf_reg'] = 3.5  \n", "cat_params['border_count'] = 8\n", "cat_params['gradient_iterations'] = 4\n", "cat_params['n_jobs'] = 2\n", "\n", "# Model building\n", "catBoost_model = CatBoostClassifier(**cat_params)\n", "cv_results = cross_val_score(catBoost_model, trainSet, target_train, cv=2, scoring='roc_auc',verbose=1)\n", "print(cv_results)"], "metadata": {"collapsed": true, "_cell_guid": "c44033c3-cb00-4a78-9c32-759a5c753f4f", "_uuid": "45e9f16df8a68eb67a72e3b1b37e0b7e48e1e88b"}, "execution_count": null}, {"cell_type": "markdown", "source": ["## Random Forest"], "metadata": {"_cell_guid": "6b6c4989-1cbf-4da9-82e4-debec91420ea", "_uuid": "050bc2209ce953188c1292ab0ee13a35101edaa2"}}, {"cell_type": "code", "outputs": [], "source": ["rf_params ={}\n", "rf_params['n_estimators'] = 1000 # The number of trees in the forest.\n", "rf_params['min_samples_split'] = 50  #The minimum number of samples required to split an internal node:\n", "rf_params['n_jobs'] = 2\n", "\n", "# Model building\n", "rf_model = RandomForestClassifier(**rf_params)\n", "cv_results = cross_val_score(rf_model, trainSet, target_train, cv=2, scoring='roc_auc',verbose=1)\n", "print(cv_results)"], "metadata": {"collapsed": true, "_cell_guid": "fc194e23-c6ce-4fea-be15-e7ad4d5fdb76", "_uuid": "77ba4b1c6f9762236aa2517228626f5620622947"}, "execution_count": null}, {"cell_type": "markdown", "source": ["## RegularizedGreedyForest"], "metadata": {"_cell_guid": "0b86761c-fd57-4dd0-aa31-becd5c05665d", "_uuid": "27e2b89f9319a7a062f58b52b803159b59cb5d3d"}}, {"cell_type": "code", "outputs": [], "source": ["rgf_params ={}\n", "rgf_params['max_leaf'] = 1000 \n", "rgf_params['algorithm'] = \"RGF_Sib\"\n", "rgf_params['test_interval'] = 100\n", "rgf_params['n_jobs'] = 2\n", "\n", "# Model building\n", "rgf_model = RGFClassifier(**rgf_params)\n", "cv_results = cross_val_score(rgf_model, trainSet, target_train, cv=2, scoring='roc_auc',verbose=1)\n", "print(cv_results)"], "metadata": {"collapsed": true, "_cell_guid": "cfc0fcd5-094c-4666-81dc-81770486f57e", "_uuid": "d622b4fcadc03df6c25b43c21e1c736ce519f1cf"}, "execution_count": null}, {"cell_type": "markdown", "source": ["## ANN"], "metadata": {"collapsed": true, "_cell_guid": "9c86e1c7-1249-4078-b80e-c3bc5b299056", "_uuid": "a409e3f34dbac61fa4ecf6105b0d11a10233b918"}}, {"cell_type": "code", "outputs": [], "source": ["from sklearn.model_selection import train_test_split\n", "X_train, X_test, y_train, y_test = train_test_split(trainSet, target_train, test_size = 0.2, random_state = 0)\n", "\n", "# Feature Scaling\n", "from sklearn.preprocessing import StandardScaler\n", "sc = StandardScaler()\n", "X_train = sc.fit_transform(X_train)\n", "X_test = sc.transform(X_test)\n", "\n", "# Importing the Keras libraries and packages\n", "from keras.models import Sequential\n", "from keras.layers import Dense\n", "\n", "# Initialising the ANN\n", "classifier = Sequential()\n", "\n", "# Adding the input layer and the first hidden layer\n", "classifier.add(Dense(units = 92, kernel_initializer = 'uniform', activation = 'relu', input_dim = 92))\n", "\n", "# Adding the second hidden layer\n", "classifier.add(Dense(units = 92, kernel_initializer = 'uniform', activation = 'relu'))\n", "\n", "# Adding the third hidden layer\n", "classifier.add(Dense(units = 92, kernel_initializer = 'uniform', activation = 'relu'))\n", "\n", "# Adding the output layer\n", "classifier.add(Dense(units = 1, kernel_initializer = 'uniform', activation = 'sigmoid'))\n", "\n", "# Compiling the ANN\n", "classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])\n", "\n", "# Fitting the ANN to the Training set\n", "classifier.fit(X_train, y_train, batch_size = 32, epochs = 10)\n", "\n", "# Part 3 - Making predictions and evaluating the model\n", "\n", "# Predicting the Test set results\n", "y_pred = classifier.predict(X_test)\n", "y_pred = (y_pred > 0.5)\n", "\n", "# Making the Confusion Matrix\n", "from sklearn.metrics import confusion_matrix\n", "cm = confusion_matrix(y_test, y_pred)"], "metadata": {}, "execution_count": 8}, {"cell_type": "code", "outputs": [], "source": [], "metadata": {"collapsed": true}, "execution_count": null}], "nbformat_minor": 1, "metadata": {"language_info": {"mimetype": "text/x-python", "pygments_lexer": "ipython3", "version": "3.6.3", "name": "python", "nbconvert_exporter": "python", "codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py"}, "kernelspec": {"name": "python3", "display_name": "Python 3", "language": "python"}}}