{"cells":[{"metadata":{"_uuid":"84f5cc55-1dd7-458e-be12-22b6a2f774ea","_cell_guid":"4c593fd1-7b84-4681-96bf-689abefd7e64","trusted":true},"cell_type":"code","source":"'''\n# 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\nfor 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 20GB 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\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#!git clone https://github.com/google-research/simclr.git","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true},"cell_type":"code","source":"'''\nimport matplotlib.pyplot as plt\n\nplt.figure()\ntrain_sample = plt.imread('/kaggle/input/cassava-leaf-disease-classification/train_images/1000015157.jpg')\nplt.subplot(121)\nplt.imshow(train_sample)\ntest_sample = plt.imread('/kaggle/input/cassava-leaf-disease-classification/test_images/2216849948.jpg')\nplt.subplot(122)\nplt.imshow(test_sample)\nprint(train_sample.shape)\nprint(test_sample.shape)\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nplt.figure()\nsample = Image.open('/kaggle/input/cassava-leaf-disease-classification/train_images/1000015157.jpg')\nplt.subplot(121)\nplt.imshow(sample)\nsample_resize = sample.resize((600, 600))\nplt.subplot(122)\nplt.imshow(sample_resize)\n'''","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"データの集計"},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nimport pandas as pd\n\ntrain = pd.read_csv('../input/cassava-leaf-disease-classification/train.csv')\ntrain.head()\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#train.label.value_counts()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"label count\n* 0: 1087\n* 1: 2189\n* 2: 2386\n* 3: 13158\n* 4: 2577"},{"metadata":{"trusted":true},"cell_type":"code","source":"#!python /kaggle/working/simclr/tf2/run.py --train_mode=pretrain --train_batch_size=256 --train_epochs=1 --dataset=cifar10 --image_size=32 --resnet_depth=18 --model_dir=/kaggle/working/simclr/tf2/cache --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* 上のセルの実行でGPUのRAMは15.2GB/15.9GB使用しておりかなりギリギリ\n* CPUもGPUも使用率100%になっていた"},{"metadata":{},"cell_type":"markdown","source":"# **入力の形式**"},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nimport tensorflow_datasets as tfds\nimport tensorflow as tf\nbuilder = tfds.builder('cifar10', data_dir='/kaggle/working/data')\nbuilder.download_and_prepare()\nprint('num_train_examples:', builder.info.splits['train'].num_examples)\nprint('num_eval_examples: ', builder.info.splits['test'].num_examples)\nprint('num_classes: ', builder.info.features['label'].num_classes)\ndataset = builder.as_dataset(as_supervised=True) # これにより辞書型ではなくなる\ntrain_dataset, test_dataset = dataset['train'], dataset['test']\nassert isinstance(train_dataset, tf.data.Dataset)\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#print(train_dataset)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\ndef map_fn(image, label):\n      \"\"\"Produces multiple transformations of the same batch.\"\"\"\n      print(type(image))\n      label = tf.one_hot(label, 10)\n      return image, label\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#train_dataset = train_dataset.map(map_fn)\n#train_dataset","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **cassavaのデータを上の形式に合わせる**"},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nimport pandas as pd\n\ntrain = pd.read_csv('../input/cassava-leaf-disease-classification/train.csv')\ntrain.head()\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#from sklearn.model_selection import train_test_split\n#train, test = train_test_split(train, stratify=train['label'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#train","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#test","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nall_image_paths = list(train['image_id'])\nall_image_paths = ['../input/cassava-leaf-disease-classification/train_images/' + str(path) for path in all_image_paths]\nall_image_labels = list(train['label'])\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#print(all_image_paths[:5])\n#print(all_image_labels[:5])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nimport tensorflow as tf\ndef preprocess_image(image):\n  image = tf.image.decode_jpeg(image, channels=3)\n  image = tf.image.resize(image, [600, 600])\n  image = tf.cast(image, tf.uint8)\n  #image /= 255.0  # normalize to [0,1] range\n  return image\n\ndef load_and_preprocess_image(path):\n  image = tf.io.read_file(path)\n  return preprocess_image(image)\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\npath_ds = tf.data.Dataset.from_tensor_slices(all_image_paths)\nimage_ds = path_ds.map(load_and_preprocess_image, num_parallel_calls=tf.data.experimental.AUTOTUNE)\nlabel_ds = tf.data.Dataset.from_tensor_slices(tf.cast(all_image_labels, tf.int64))\nimage_label_ds = tf.data.Dataset.zip((image_ds, label_ds))\nprint(image_label_ds)\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nBATCH_SIZE = 32\nimage_count = len(all_image_paths)\nds = image_label_ds.shuffle(buffer_size=image_count)\nds = ds.repeat()\nds = ds.batch(BATCH_SIZE)\n'''\n# `prefetch`を使うことで、モデルの訓練中にバックグラウンドでデータセットがバッチを取得できます。\n#ds = image_label_ds.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)\n#print(ds)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 画像をnormalizeしないと表示できない\n'''\nimport matplotlib.pyplot as plt\n\nplt.figure(figsize=(6,6))\nfor n,image in enumerate(image_ds.take(2)):\n  plt.subplot(1,2,n+1)\n  plt.imshow(image)\nplt.show()\n'''","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **辞書型でなくても動くかの確認**"},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\ndef map_fn(image, label):\n      \"\"\"Produces multiple transformations of the same batch.\"\"\"\n      print(type(image))\n      label = tf.one_hot(label, 4)\n      return image, label\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#ds = ds.map(map_fn)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#ds","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"そもそもcifar10も辞書型ではなくなることが判明したので大丈夫"},{"metadata":{},"cell_type":"markdown","source":"# CassavaデータでSimCLRを検証(12/21)"},{"metadata":{"trusted":true},"cell_type":"code","source":"#!git clone https://github.com/ta9ryuWalrus/simclr.git","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#!python /kaggle/working/simclr/tf2/run.py --train_mode=pretrain --train_batch_size=32 --train_epochs=5 --resnet_depth=18 --model_dir=/kaggle/working/trained_model --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* 上記の設定でGPUのメモリーは15.2GB/15.9GB使う\n* GPU使用率の上限に関わらずメモリの使用量は一定なので、無駄な読み込みが発生していそう(?)\n* またGPU使用率は0~100%で周期的に変動しているので、iterationの切れ目とかCPUの処理が律速になってしまっている可能性がある(CPU使用率は常に150%前後(←?))\n* CPUのメモリやDiskはほとんど使われていない\n* batch size32は動く(48は動かない)\n* batch size32だと15分くらいで1epochが終わる\n* 試しに5epochやってみたが精度は向上せず->pretrainなのでそれは問題ない(寧ろlabelを一切使わずに60%くらい当ててるのすごい)\n* contrast accがどれくらい上がるまで学習すべきなのか？5epochでは15%程度しか当てられていない"},{"metadata":{"trusted":true},"cell_type":"code","source":"#!python /kaggle/working/simclr/tf2/run.py --mode=train_then_eval --train_mode=finetune --train_batch_size=32 --train_epochs=10 --resnet_depth=18 --model_dir=/kaggle/working/trained_model --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* top1 accuracy: 0.61\n* top5 accuracy: 1.0(5classなので当たり前)\n\n* trainとtestの分け方とlabeledとunlabeledの分け方が違うっぽい。\n* train:testを1:9にしたら上記のようになったが、eval時に全体の9割を占めるtestのlabel情報を使ってfine-tuningしてしまっている気がする\n* labeledとunlabeledの分け方はどこで決めている？\n* ↑data.pyの_input_fnにあるbuilder.as_dataset(as_supervised=True)が怪しい気がする->as_supervisedは辞書型からimageとlabelのtupleに変換しているだけ"},{"metadata":{},"cell_type":"markdown","source":"# ***log***\n* pretrain5epochでaccが60％くらいになり\n* finetuning10epochで70%弱くらいまで上昇"},{"metadata":{},"cell_type":"markdown","source":"# データの使い方の方針\n* trainとtestに分ける(7:3とか)\n* pretrainではlabelは使わないのでtrainをそのまま使う\n* fine-tuningの際にlabelを使うが、ここではsemi-supervisedの性能を検証したいので、trainのうち10%程度のみをfine-tuningに使う\n\nこういう感じ？\n* あくまでもSimCLRはself-supervisedの手法なので、pretrainのところしかちゃんと記述されていない感\n* その後はsemi-supervisedとして使うも、別のデータに対してsupervisedでfine-tuningするも、各々の自由という感じか？"},{"metadata":{},"cell_type":"markdown","source":"# ***課題***\n* 学習済みモデルの保存方法\n* /kaggle/working/の下にモデルを保存するようにはなっているが、notebookを再起動すると消えてしまう"},{"metadata":{},"cell_type":"markdown","source":"# ***学習率とoptimizerを変更してみる***"},{"metadata":{"trusted":true},"cell_type":"code","source":"#!python /kaggle/working/simclr/tf2/run.py --learning_rate=1e-3 --optimizer=adam --train_mode=pretrain --train_batch_size=32 --train_epochs=40 --resnet_depth=18 --model_dir=/kaggle/working/trained_model --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* 10epochの学習でcontrast accが26.6%まで向上した\n* supervised accは相変わらず61%程度\n* 15epoch学習すると、contrast accが41.6%、supervised accが61.4%\n* 上のコードでpretrainしたモデルがtrained_modelに保存されている"},{"metadata":{"trusted":true},"cell_type":"code","source":"#!python /kaggle/working/simclr/tf2/run.py --learning_rate=1e-3 --optimizer=adam --mode=train_then_eval --train_mode=finetune --train_batch_size=32 --train_epochs=10 --resnet_depth=18 --model_dir=/kaggle/working/trained_model --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* 15epochのpretrainの後に20epochのfine-tuning\n* 学習データに対する正解率は66.2%でテストデータに対する正解率は62.0%(あまり学習できていない？)"},{"metadata":{},"cell_type":"markdown","source":"## 1/13"},{"metadata":{"trusted":true},"cell_type":"code","source":"#! git clone https://github.com/ta9ryuWalrus/simclr.git","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* 40epoch pretrainしたところ、contrast accが0.745、supervised accが0.621となった\n* 学習済みモデルを保存できた"},{"metadata":{},"cell_type":"markdown","source":"* 40epoch事前学習したモデルを読み込んでfinetuningしてみる\n* inputディレクトリにdatasetとして学習済みモデルをloadしているが、permissionの関係でここから直接読み込んでfinetuningすることができなかったので、一度outputの方に学習済みモデルをコピーしてからfinetuningしている"},{"metadata":{"trusted":true},"cell_type":"code","source":"#! cp -r ../input/trained-model/trained_model /kaggle/working/trained_model","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"40epoch事前学習したやつをさらに追加で30epoch事前学習する\n-> 古いモデルは削除されるようなコードになっていたので、残したければ古いやつと新しく保存するやつを別ディレクトリに残す必要がありそう(ここを書き換えるのは面倒)"},{"metadata":{"trusted":true},"cell_type":"code","source":"#!python /kaggle/working/simclr/tf2/run.py --learning_rate=1e-3 --optimizer=adam --train_mode=pretrain --train_batch_size=32 --train_epochs=70 --resnet_depth=18 --model_dir=/kaggle/working/trained_model --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"fine-tuning"},{"metadata":{"trusted":true},"cell_type":"code","source":"#! python /kaggle/working/simclr/tf2/run.py --learning_rate=1e-3 --optimizer=adam --mode=train_then_eval --train_mode=finetune --train_batch_size=32 --train_epochs=10 --pretrain_steps=19188 --resnet_depth=18 --model_dir=/kaggle/working/trained_model --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* 学習率やepoch数などを変えてもaccが0.622から全然変わらないのでfinetuningされていない可能性\n* logを読むに学習済みモデルの読み込みは正しく行われていそう\n* global step=19188というのがpretrainから引き継がれていて、finetuningのtrain_steps=469を上回ってしまっていることから学習が行われずにいる。\n* -> finetuning時のepoch数はpretrainのepoch数+finetuningのepoch数として指定する？->結局finetuningのデータ数が少なくstep数が小さく見積もられるのでこれではダメ\n* -> 書き換えた。--pretrainでpretrainで学習したstep数を指定することで、train_stepsを正しく計算できる。--train_epochsのところはfinetuningを行うepoch数を指定する。\n* とりあえず期待通りに動くことは確認できた\n* 40epochのpretrainのあと10epochのfinetuningをしたときの精度は0.628程度(finetuning途中のtrainデータに対する精度は0.68くらい)"},{"metadata":{},"cell_type":"markdown","source":"### pretrainを少し短めにした場合 ###"},{"metadata":{"trusted":true},"cell_type":"code","source":"#! python /kaggle/working/simclr/tf2/run.py --learning_rate=1e-4 --optimizer=adam --train_mode=pretrain --train_batch_size=32 --train_epochs=10 --resnet_depth=18 --model_dir=/kaggle/working/trained_model2 --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* lr=1e-4、epoch=10でpretrain\n* contrast_acc=0.170、supervised_acc=0.614"},{"metadata":{"trusted":true},"cell_type":"code","source":"#! python /kaggle/working/simclr/tf2/run.py --learning_rate=1e-4 --optimizer=adam --mode=train_then_eval --train_mode=finetune --train_batch_size=32 --train_epochs=10 --pretrain_steps=4681 --resnet_depth=18 --model_dir=/kaggle/working/trained_model2 --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* 10epochのfine-tuning\n* acc=0.614\n* supervisedデータの割合が10%なのが問題設定として難しすぎる可能性"},{"metadata":{},"cell_type":"markdown","source":"* supervised ratio=50%の場合を試してみる\n* supervised ratioはpretrainには関係ないので、すでに40epoch学習済みのモデルを使用する"},{"metadata":{"trusted":true},"cell_type":"code","source":"#! cp -r ../input/trained-model/trained_model /kaggle/working/trained_model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#! python /kaggle/working/simclr/tf2/run.py --learning_rate=1e-3 --optimizer=adam --mode=train_then_eval --train_mode=finetune --train_batch_size=32 --train_epochs=10 --supervised_ratio=0.5 --pretrain_steps=19188 --resnet_depth=18 --model_dir=/kaggle/working/trained_model --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* lr=1e-3\n* supervised_ratio=0.5\n* epochs=10\n* 上記の設定でfinetuningしてaccは0.628(supervised_ratio=0.1の時と変わってない)"},{"metadata":{},"cell_type":"markdown","source":"# 1/20"},{"metadata":{},"cell_type":"markdown","source":"70epoch学習したモデルでfine-tuningをしてみる。\n\n事前学習時の性能は、\n* contrast_acc: 0.815\n* supervised_acc: 0.628"},{"metadata":{"trusted":true},"cell_type":"code","source":"#! git clone https://github.com/ta9ryuWalrus/simclr.git\n#! cp -r ../input/trained-model/trained_model /kaggle/working/trained_model\n#! cp -r ../input/trained-model/trained_model /kaggle/working/trained_model70epochs # 古いやつはここに保管する","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#! python /kaggle/working/simclr/tf2/run.py --learning_rate=1e-3 --optimizer=adam --mode=train_then_eval --train_mode=finetune --train_batch_size=32 --train_epochs=10 --pretrain_steps=33228 --resnet_depth=18 --model_dir=/kaggle/working/trained_model --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"70epochの事前学習の後、10epochのfinetuningをした結果\n* accuracy: 0.639"},{"metadata":{},"cell_type":"markdown","source":"# 画像サイズを小さくする(600->400)"},{"metadata":{"trusted":true},"cell_type":"code","source":"#! git clone https://github.com/ta9ryuWalrus/simclr.git\n#! cp -r ../input/trained-model/trained_small_model /kaggle/working/trained_small_model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#!python /kaggle/working/simclr/tf2/run.py --learning_rate=1e-3 --optimizer=adam --train_mode=pretrain --train_batch_size=64 --train_epochs=40 --resnet_depth=18 --model_dir=/kaggle/working/trained_small_model --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"40epochの事前学習\n* contrast_acc = 0.641\n* supervised_acc = 0.630"},{"metadata":{"trusted":true},"cell_type":"code","source":"#! python /kaggle/working/simclr/tf2/run.py --learning_rate=1e-3 --optimizer=adam --mode=train_then_eval --train_mode=finetune --train_batch_size=64 --train_epochs=10 --pretrain_steps=9360 --resnet_depth=18 --model_dir=/kaggle/working/trained_small_model --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"40epochの事前学習->10epochのfine-tuning\n* accuracy = 0.643"},{"metadata":{},"cell_type":"markdown","source":"# 1/25\nk-foldで評価"},{"metadata":{"trusted":true},"cell_type":"code","source":"! git clone https://github.com/ta9ryuWalrus/simclr.git","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* seed=0\n* 5-foldの1つめ\n* この設定だと20epochくらいでcontrast accが92%くらいに収束する"},{"metadata":{"trusted":true},"cell_type":"code","source":"#! python /kaggle/working/simclr/tf2/run.py --learning_rate=1e-4 --seed=0 --fold=4 --optimizer=adam --train_mode=pretrain --train_batch_size=64 --train_epochs=40 --resnet_depth=18 --model_dir=/kaggle/working/trained_model_seed0_fold4 --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"! cp -r ../input/trained-model/trained_model_seed0_fold4 /kaggle/working/trained_model_seed0_fold4","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"! python /kaggle/working/simclr/tf2/run.py --learning_rate=1e-4 --seed=0 --fold=4 --optimizer=adam --mode=train_then_eval --train_mode=finetune --train_batch_size=64 --train_epochs=40 --pretrain_steps=10947 --resnet_depth=18 --model_dir=/kaggle/working/trained_model_seed0_fold4 --eval_split=test --use_tpu=False","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"10epochのfinetuningで\n* loss 0.00245\n* acc 0.614"},{"metadata":{"trusted":true},"cell_type":"code","source":"! rm -r /kaggle/working/simclr","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## データの分布をチェック"},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nimport numpy as np\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split, StratifiedKFold\n\ndf = pd.read_csv('/kaggle/input/cassava-leaf-disease-classification/train.csv')\nkf = StratifiedKFold(n_splits=5, shuffle=True, random_state=0)\nfor train_idx, test_idx in kf.split(df['image_id'], df['label']):\n  train_df = df.iloc[train_idx]\n  test_df = df.iloc[test_idx]\n  train_labels = np.array(train_df['label'])\n  labeled_idx, _ = train_test_split(train_labels, train_size=0.1, random_state=0)\n  labeled_df = train_df.iloc[labeled_idx]\n  print()\n  print('labeled train set:')\n  print(labeled_df['label'].value_counts())\n  print()\n  print('test set:')\n  print(test_df['label'].value_counts())\n'''","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}