김성준

code upload

1 +{
2 + "cells": [
3 + {
4 + "cell_type": "code",
5 + "execution_count": 1,
6 + "metadata": {},
7 + "outputs": [
8 + {
9 + "name": "stdout",
10 + "output_type": "stream",
11 + "text": [
12 + "D:/Games/Images/train\n",
13 + "antelope 파일 길이 : 0\n",
14 + "cats 파일 길이 : 0\n",
15 + "chimpanzee 파일 길이 : 0\n",
16 + "cow 파일 길이 : 0\n",
17 + "dogs 파일 길이 : 0\n",
18 + "hippopotamus 파일 길이 : 0\n",
19 + "horse 파일 길이 : 0\n",
20 + "otter 파일 길이 : 0\n",
21 + "raccoon 파일 길이 : 0\n",
22 + "rat 파일 길이 : 0\n",
23 + "rhinoceros 파일 길이 : 0\n",
24 + "squirrel 파일 길이 : 0\n",
25 + "weasel 파일 길이 : 0\n",
26 + "wolf 파일 길이 : 0\n",
27 + "ok 0\n"
28 + ]
29 + }
30 + ],
31 + "source": [
32 + "from PIL import Image\n",
33 + "import os, glob, numpy as np\n",
34 + "from sklearn.model_selection import train_test_split\n",
35 + "caltech_dir = \"D:/Games/Images/train\"\n",
36 + "categories = [\"antelope\", \"cats\", \"chimpanzee\", \"cow\", \"dogs\", \"hippopotamus\",\"horse\",\"otter\",\"raccoon\",\"rat\",\"rhinoceros\",\"squirrel\",\"weasel\",\"wolf\"]\n",
37 + "nb_classes = len(categories)\n",
38 + "print(caltech_dir)\n",
39 + "image_w = 64\n",
40 + "image_h = 64\n",
41 + "\n",
42 + "pixels = image_h * image_w * 3\n",
43 + "\n",
44 + "X = []\n",
45 + "y = []\n",
46 + "\n",
47 + "for idx, cat in enumerate(categories):\n",
48 + " \n",
49 + " #one-hot 돌리기.\n",
50 + " label = [0 for i in range(nb_classes)]\n",
51 + " label[idx] = 1\n",
52 + "\n",
53 + " image_dir = caltech_dir + \"/\" + cat\n",
54 + " files = glob.glob(image_dir+\"/*.jpg\")\n",
55 + " print(cat, \" 파일 길이 : \", len(files))\n",
56 + " for i, f in enumerate(files):\n",
57 + " img = Image.open(f)\n",
58 + " img = img.convert(\"RGB\")\n",
59 + " img = img.resize((image_w, image_h))\n",
60 + " data = np.asarray(img)\n",
61 + "\n",
62 + " X.append(data)\n",
63 + " y.append(label)\n",
64 + "\n",
65 + " if i % 700 == 0:\n",
66 + " print(cat, \" : \", f)\n",
67 + "\n",
68 + "X = np.array(X)\n",
69 + "y = np.array(y)\n",
70 + "#1 0 0 0 이면 airplanes\n",
71 + "#0 1 0 0 이면 buddha 이런식\n",
72 + "\n",
73 + "\n",
74 + "X_train, X_test, y_train, y_test = train_test_split(X, y)\n",
75 + "xy = (X_train, X_test, y_train, y_test)\n",
76 + "np.save(\"./numpy_data/multi_image_data3.npy\", xy)\n",
77 + "\n",
78 + "print(\"ok\", len(y))\n",
79 + "\n"
80 + ]
81 + },
82 + {
83 + "cell_type": "code",
84 + "execution_count": 5,
85 + "metadata": {},
86 + "outputs": [
87 + {
88 + "name": "stderr",
89 + "output_type": "stream",
90 + "text": [
91 + "Using TensorFlow backend.\n"
92 + ]
93 + },
94 + {
95 + "name": "stdout",
96 + "output_type": "stream",
97 + "text": [
98 + "(0,)\n",
99 + "0\n"
100 + ]
101 + }
102 + ],
103 + "source": [
104 + "import os, glob, numpy as np\n",
105 + "from keras.models import Sequential\n",
106 + "from keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout\n",
107 + "from keras.callbacks import EarlyStopping, ModelCheckpoint\n",
108 + "import matplotlib.pyplot as plt\n",
109 + "from keras import optimizers\n",
110 + "import keras.backend.tensorflow_backend as K\n",
111 + "\n",
112 + "import tensorflow as tf\n",
113 + "config = tf.ConfigProto()\n",
114 + "config.gpu_options.allow_growth = True\n",
115 + "session = tf.Session(config=config)\n",
116 + "\n",
117 + "np_load_old = np.load\n",
118 + "np.load = lambda *a,**k: np_load_old(*a, allow_pickle=True, **k)\n",
119 + "X_train, X_test, y_train, y_test = np.load('./numpy_data/multi_image_data3.npy')\n",
120 + "np.load = np_load_old\n",
121 + "print(X_train.shape)\n",
122 + "print(X_train.shape[0])"
123 + ]
124 + },
125 + {
126 + "cell_type": "code",
127 + "execution_count": 6,
128 + "metadata": {},
129 + "outputs": [],
130 + "source": [
131 + "categories = [\"antelope\", \"cats\", \"chimpanzee\", \"cow\", \"dogs\", \"hippopotamus\",\"horse\",\"otter\",\"raccoon\",\"rat\",\"rhinoceros\",\"squirrel\",\"weasel\",\"wolf\"]\n",
132 + "nb_classes = len(categories)\n",
133 + "\n",
134 + "#일반화\n",
135 + "X_train = X_train.astype(float) / 255\n",
136 + "X_test = X_test.astype(float) / 255"
137 + ]
138 + },
139 + {
140 + "cell_type": "code",
141 + "execution_count": null,
142 + "metadata": {},
143 + "outputs": [],
144 + "source": [
145 + "with K.tf_ops.device('/device:GPU:0'):\n",
146 + " model = Sequential()\n",
147 + " model.add(Conv2D(32, (3,3), padding=\"same\", input_shape=X_train.shape[1:], activation='relu'))\n",
148 + " model.add(MaxPooling2D(pool_size=(2,2)))\n",
149 + " model.add(Dropout(0.25))\n",
150 + " \n",
151 + " model.add(Conv2D(64, (3,3), padding=\"same\", activation='relu'))\n",
152 + " model.add(MaxPooling2D(pool_size=(2,2)))\n",
153 + " model.add(Dropout(0.25))\n",
154 + " \n",
155 + " model.add(Flatten())\n",
156 + " model.add(Dense(256, activation='relu'))\n",
157 + " model.add(Dropout(0.5))\n",
158 + " model.add(Dense(nb_classes, activation='softmax'))\n",
159 + " model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n",
160 + " model_dir = './model'\n",
161 + " \n",
162 + " if not os.path.exists(model_dir):\n",
163 + " os.mkdir(model_dir)\n",
164 + " \n",
165 + " model_path = model_dir + '/multi_img_classification.model'\n",
166 + " checkpoint = ModelCheckpoint(filepath=model_path , monitor='val_loss', verbose=1, save_best_only=True)\n",
167 + " early_stopping = EarlyStopping(monitor='val_loss', patience=6)\n",
168 + " model.summary()\n",
169 + " "
170 + ]
171 + },
172 + {
173 + "cell_type": "code",
174 + "execution_count": 46,
175 + "metadata": {},
176 + "outputs": [
177 + {
178 + "name": "stdout",
179 + "output_type": "stream",
180 + "text": [
181 + "Train on 4623 samples, validate on 1541 samples\n",
182 + "Epoch 1/100\n",
183 + "4623/4623 [==============================] - 10s 2ms/step - loss: 13.5012 - acc: 0.1622 - val_loss: 13.5869 - val_acc: 0.1570\n",
184 + "\n",
185 + "Epoch 00001: val_loss improved from inf to 13.58690, saving model to ./model/multi_img_classification.model\n",
186 + "Epoch 2/100\n",
187 + "4623/4623 [==============================] - 2s 468us/step - loss: 13.4753 - acc: 0.1640 - val_loss: 13.5869 - val_acc: 0.1570\n",
188 + "\n",
189 + "Epoch 00002: val_loss did not improve from 13.58690\n",
190 + "Epoch 3/100\n",
191 + "4623/4623 [==============================] - 2s 470us/step - loss: 13.4753 - acc: 0.1640 - val_loss: 13.5869 - val_acc: 0.1570\n",
192 + "\n",
193 + "Epoch 00003: val_loss did not improve from 13.58690\n",
194 + "Epoch 4/100\n",
195 + "4623/4623 [==============================] - 2s 481us/step - loss: 13.4753 - acc: 0.1640 - val_loss: 13.5869 - val_acc: 0.1570\n",
196 + "\n",
197 + "Epoch 00004: val_loss did not improve from 13.58690\n",
198 + "Epoch 5/100\n",
199 + "4623/4623 [==============================] - 2s 471us/step - loss: 13.4753 - acc: 0.1640 - val_loss: 13.5869 - val_acc: 0.1570\n",
200 + "\n",
201 + "Epoch 00005: val_loss did not improve from 13.58690\n",
202 + "Epoch 6/100\n",
203 + "4623/4623 [==============================] - 2s 473us/step - loss: 13.4753 - acc: 0.1640 - val_loss: 13.5869 - val_acc: 0.1570\n",
204 + "\n",
205 + "Epoch 00006: val_loss did not improve from 13.58690\n",
206 + "Epoch 7/100\n",
207 + "4623/4623 [==============================] - 2s 471us/step - loss: 13.4753 - acc: 0.1640 - val_loss: 13.5869 - val_acc: 0.1570\n",
208 + "\n",
209 + "Epoch 00007: val_loss did not improve from 13.58690\n",
210 + "Model: \"sequential_10\"\n",
211 + "_________________________________________________________________\n",
212 + "Layer (type) Output Shape Param # \n",
213 + "=================================================================\n",
214 + "conv2d_22 (Conv2D) (None, 64, 64, 32) 896 \n",
215 + "_________________________________________________________________\n",
216 + "max_pooling2d_22 (MaxPooling (None, 32, 32, 32) 0 \n",
217 + "_________________________________________________________________\n",
218 + "dropout_30 (Dropout) (None, 32, 32, 32) 0 \n",
219 + "_________________________________________________________________\n",
220 + "conv2d_23 (Conv2D) (None, 32, 32, 64) 18496 \n",
221 + "_________________________________________________________________\n",
222 + "max_pooling2d_23 (MaxPooling (None, 16, 16, 64) 0 \n",
223 + "_________________________________________________________________\n",
224 + "dropout_31 (Dropout) (None, 16, 16, 64) 0 \n",
225 + "_________________________________________________________________\n",
226 + "flatten_9 (Flatten) (None, 16384) 0 \n",
227 + "_________________________________________________________________\n",
228 + "dense_17 (Dense) (None, 256) 4194560 \n",
229 + "_________________________________________________________________\n",
230 + "dropout_32 (Dropout) (None, 256) 0 \n",
231 + "_________________________________________________________________\n",
232 + "dense_18 (Dense) (None, 14) 3598 \n",
233 + "=================================================================\n",
234 + "Total params: 4,217,550\n",
235 + "Trainable params: 4,217,550\n",
236 + "Non-trainable params: 0\n",
237 + "_________________________________________________________________\n"
238 + ]
239 + }
240 + ],
241 + "source": [
242 + "\n",
243 + "#데이터셋이 적어서 validation을 그냥 test 데이터로 했습니다. \n",
244 + "#데이터셋이 충분하시면 이렇게 하시지 마시고 validation_split=0.2 이렇게 하셔서 테스트 셋으로 나누시길 권장합니다.\n",
245 + "history = model.fit(X_train, y_train, batch_size=34, epochs=100, validation_data=(X_test, y_test), callbacks=[checkpoint, early_stopping])\n",
246 + "\n"
247 + ]
248 + },
249 + {
250 + "cell_type": "code",
251 + "execution_count": 47,
252 + "metadata": {},
253 + "outputs": [
254 + {
255 + "name": "stdout",
256 + "output_type": "stream",
257 + "text": [
258 + "1541/1541 [==============================] - 0s 173us/step\n",
259 + "정확도 : 0.1570\n"
260 + ]
261 + }
262 + ],
263 + "source": [
264 + "print(\"정확도 : %.4f\" % (model.evaluate(X_test, y_test)[1]))"
265 + ]
266 + },
267 + {
268 + "cell_type": "code",
269 + "execution_count": 42,
270 + "metadata": {
271 + "scrolled": false
272 + },
273 + "outputs": [
274 + {
275 + "data": {
276 + "image/png": "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F7BwYdhWDx9i1ixrIn/zjb1Hx4w5OGiclHR0z501bbAwfo4C8gThjto551jhv0cfhXvugddfB5FTmDLF3v9B3/dxcTYe0a6d9efOm2ebDzmXl1dftSX/mZn2n/eHH9qbMJS+/hquu84SxJlnwn//a/u/h9rRJpkw8zEIFxIlSsDtt9siTwBVYdcum7iUo4QEePttOP54++/shx8KJVYXw2bOtHGAjAxblLNnj31wX3mlDY5t3Xp0j79tm42N1a9vU/dGj7aNscKRHGKAJwgXUr1725idiK2oe+op+Pe/c7lD1aq2RiI93WrNbNuWy8numJWZaXOre/SwcatSpawVGh9vReumT7c3X6VK1ip96CFYtiz/KzszM22B2hlnWFIYMMC6lW64wf77OUZ5gnAhldWteuWV3zF1Kpx11sFxiT/+yOFODRrYlNdVq+zkffsKNWYX5bZts8Rw771wxRXWn/nhhzZoPHeuveF++826KW+6yc6/9VZo3Bhq1LCteHNrXXzyib1xBw6EU06xaawTJkCVKoX6Y0alnHYSisWL7ygXPbLi3LtX9e67VePiVGvUUP3gg1zu9MILtiPdkCGqmZmFEqdqIbym+dzlLy+x9rsPia++sp0K4+JUx43L//ti40bViRNVe/dWLV/e3lfFi6u2bav64IOqkyfruksvVe3SxY5Vrao6ebJqRkboYg+hcP7uyWVHOR+kdmEVH289A127WiuiY0ebFPKvf1lX1CEGD7bprw89ZN0IN98ckZhD6t13be3H/v02xz3HUXv3J++8Y1PkSpSwdQRHMg20alVrEQwcaC3SRYtsoHnWLGtdENiYBuyNOX68rW52h/AuJlcomje3noHhw2HsWCs5s3RpkBMfeAD69IFbboG//tV2zIol6en2IXTjjbYNa5cuNs89M9Pm0M+cGekIo5+q/Qdx4YX2j8LixUe3RiA+3tYc/OtfttHOyJEgYpvVxMVZJUpPDkF5gnCFpkwZGDcO3nvPuoPPPtvywSF7YRcrBkOH2tdp06zGTdmyVhDq/POtlXHPPdZHPHs2rF6d8zLuUBdTC2bPHusHv/NOaN3aFkd162Y/6F/+An//u7UcROyD74kn7IfevTt8McWy9HQbh7r9dujXD+bPt3UyoXTRRVCqFJnFikXtArVo4V1MrtB16gTLl9sC6jvusJmu//d/cNppgRMW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\n",
277 + "text/plain": [
278 + "<Figure size 432x288 with 1 Axes>"
279 + ]
280 + },
281 + "metadata": {
282 + "needs_background": "light"
283 + },
284 + "output_type": "display_data"
285 + }
286 + ],
287 + "source": [
288 + "y_vloss = history.history['val_loss']\n",
289 + "y_loss = history.history['loss']\n",
290 + "\n",
291 + "x_len = np.arange(len(y_loss))\n",
292 + "\n",
293 + "plt.plot(x_len, y_vloss, marker='.', c='red', label='val_set_loss')\n",
294 + "plt.plot(x_len, y_loss, marker='.', c='blue', label='train_set_oss')\n",
295 + "plt.legend()\n",
296 + "plt.xlabel('epochs')\n",
297 + "plt.ylabel('loss')\n",
298 + "plt.grid()\n",
299 + "plt.show()"
300 + ]
301 + },
302 + {
303 + "cell_type": "code",
304 + "execution_count": 43,
305 + "metadata": {
306 + "scrolled": true
307 + },
308 + "outputs": [
309 + {
310 + "name": "stdout",
311 + "output_type": "stream",
312 + "text": [
313 + "i: [0.000 0.000 0.000 1.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000\n",
314 + " 0.000 0.000]\n",
315 + "pre_ans: 3\n",
316 + "해당 antelope1.jpg이미지는 cow로 추정됩니다.\n",
317 + "i: [0.000 0.000 0.000 1.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000\n",
318 + " 0.000 0.000]\n",
319 + "pre_ans: 3\n",
320 + "해당 cat.jpg이미지는 cow로 추정됩니다.\n",
321 + "i: [0.000 0.000 1.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000\n",
322 + " 0.000 0.000]\n",
323 + "pre_ans: 2\n",
324 + "해당 raccoon.jpg이미지는 chimpanzee로 추정됩니다.\n",
325 + "i: [0.000 0.000 0.000 1.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000\n",
326 + " 0.000 0.000]\n",
327 + "pre_ans: 3\n",
328 + "해당 raccoon2.jpg이미지는 cow로 추정됩니다.\n",
329 + "i: [0.000 0.000 0.000 1.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000\n",
330 + " 0.000 0.000]\n",
331 + "pre_ans: 3\n",
332 + "해당 rat.jpg이미지는 cow로 추정됩니다.\n",
333 + "i: [0.000 1.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000\n",
334 + " 0.000 0.000]\n",
335 + "pre_ans: 1\n",
336 + "해당 squirrel.jpg이미지는 cats으로 추정됩니다.\n"
337 + ]
338 + }
339 + ],
340 + "source": [
341 + "from PIL import Image\n",
342 + "import os, glob, numpy as np\n",
343 + "from keras.models import load_model\n",
344 + "\n",
345 + "caltech_dir = \"D:/Games/Images/val2\"\n",
346 + "image_w = 64\n",
347 + "image_h = 64\n",
348 + "\n",
349 + "pixels = image_h * image_w * 3\n",
350 + "\n",
351 + "X = []\n",
352 + "filenames = []\n",
353 + "files = glob.glob(caltech_dir+\"/*.*\")\n",
354 + "for i, f in enumerate(files):\n",
355 + " img = Image.open(f)\n",
356 + " img = img.convert(\"RGB\")\n",
357 + " img = img.resize((image_w, image_h))\n",
358 + " data = np.asarray(img)\n",
359 + " filenames.append(f)\n",
360 + " X.append(data)\n",
361 + "\n",
362 + "X = np.array(X)\n",
363 + "model = load_model('./model/multi_img_classification.model')\n",
364 + "\n",
365 + "prediction = model.predict(X)\n",
366 + "np.set_printoptions(formatter={'float': lambda x: \"{0:0.3f}\".format(x)})\n",
367 + "cnt = 0\n",
368 + "\n",
369 + "#이 비교는 그냥 파일들이 있으면 해당 파일과 비교. 카테고리와 함께 비교해서 진행하는 것은 _4 파일.\n",
370 + "for i in prediction:\n",
371 + " pre_ans = i.argmax() # 예측 레이블\n",
372 + " print(\"i:\",i)\n",
373 + " print(\"pre_ans: \",pre_ans)\n",
374 + " pre_ans_str = ''\n",
375 + " if pre_ans == 0: pre_ans_str = \"antelope\"\n",
376 + " elif pre_ans == 1: pre_ans_str = \"cats\"\n",
377 + " elif pre_ans == 2: pre_ans_str = \"chimpanzee\"\n",
378 + " elif pre_ans == 3: pre_ans_str = \"cow\"\n",
379 + " elif pre_ans == 4: pre_ans_str = \"dogs\"\n",
380 + " elif pre_ans == 5: pre_ans_str = \"hippopotamus\"\n",
381 + " elif pre_ans == 6: pre_ans_str = \"horse\"\n",
382 + " elif pre_ans == 7: pre_ans_str = \"otter\"\n",
383 + " elif pre_ans == 8: pre_ans_str = \"raccooon\"\n",
384 + " elif pre_ans == 9: pre_ans_str = \"rat\"\n",
385 + " elif pre_ans == 10: pre_ans_str = \"rhinoceros\"\n",
386 + " elif pre_ans == 11: pre_ans_str = \"squirrel\"\n",
387 + " elif pre_ans == 12: pre_ans_str = \"weasel\"\n",
388 + " else: pre_ans_str = \"wolf\"\n",
389 + " if i[0] >= 0.8: print(\"해당 \"+filenames[cnt].split(\"\\\\\")[1]+\"이미지는 \"+pre_ans_str+\"로 추정됩니다.\")\n",
390 + " if i[1] >= 0.8: print(\"해당 \"+filenames[cnt].split(\"\\\\\")[1]+\"이미지는 \"+pre_ans_str+\"으로 추정됩니다.\")\n",
391 + " if i[2] >= 0.8: print(\"해당 \"+filenames[cnt].split(\"\\\\\")[1]+\"이미지는 \"+pre_ans_str+\"로 추정됩니다.\")\n",
392 + " if i[3] >= 0.8: print(\"해당 \"+filenames[cnt].split(\"\\\\\")[1]+\"이미지는 \"+pre_ans_str+\"로 추정됩니다.\")\n",
393 + " if i[4] >= 0.8: print(\"해당 \"+filenames[cnt].split(\"\\\\\")[1]+\"이미지는 \"+pre_ans_str+\"로 추정됩니다.\")\n",
394 + " if i[5] >= 0.8: print(\"해당 \"+filenames[cnt].split(\"\\\\\")[1]+\"이미지는 \"+pre_ans_str+\"로 추정됩니다.\")\n",
395 + " if i[6] >= 0.8: print(\"해당 \"+filenames[cnt].split(\"\\\\\")[1]+\"이미지는 \"+pre_ans_str+\"로 추정됩니다.\")\n",
396 + " if i[7] >= 0.8: print(\"해당 \"+filenames[cnt].split(\"\\\\\")[1]+\"이미지는 \"+pre_ans_str+\"로 추정됩니다.\")\n",
397 + " if i[8] >= 0.8: print(\"해당 \"+filenames[cnt].split(\"\\\\\")[1]+\"이미지는 \"+pre_ans_str+\"로 추정됩니다.\")\n",
398 + " if i[9] >= 0.8: print(\"해당 \"+filenames[cnt].split(\"\\\\\")[1]+\"이미지는 \"+pre_ans_str+\"로 추정됩니다.\")\n",
399 + " if i[10] >= 0.8: print(\"해당 \"+filenames[cnt].split(\"\\\\\")[1]+\"이미지는 \"+pre_ans_str+\"로 추정됩니다.\")\n",
400 + " if i[11] >= 0.8: print(\"해당 \"+filenames[cnt].split(\"\\\\\")[1]+\"이미지는 \"+pre_ans_str+\"로 추정됩니다.\")\n",
401 + " if i[12] >= 0.8: print(\"해당 \"+filenames[cnt].split(\"\\\\\")[1]+\"이미지는 \"+pre_ans_str+\"로 추정됩니다.\")\n",
402 + " cnt += 1\n",
403 + " # print(i.argmax()) #얘가 레이블 [1. 0. 0.] 이런식으로 되어 있는 것을 숫자로 바꿔주는 것.\n",
404 + " # 즉 얘랑, 나중에 카테고리 데이터 불러와서 카테고리랑 비교를 해서 같으면 맞는거고, 아니면 틀린거로 취급하면 된다.\n",
405 + " # 이걸 한 것은 _4.py에.\n"
406 + ]
407 + },
408 + {
409 + "cell_type": "code",
410 + "execution_count": null,
411 + "metadata": {},
412 + "outputs": [],
413 + "source": []
414 + }
415 + ],
416 + "metadata": {
417 + "kernelspec": {
418 + "display_name": "project",
419 + "language": "python",
420 + "name": "project"
421 + },
422 + "language_info": {
423 + "codemirror_mode": {
424 + "name": "ipython",
425 + "version": 3
426 + },
427 + "file_extension": ".py",
428 + "mimetype": "text/x-python",
429 + "name": "python",
430 + "nbconvert_exporter": "python",
431 + "pygments_lexer": "ipython3",
432 + "version": "3.6.7"
433 + }
434 + },
435 + "nbformat": 4,
436 + "nbformat_minor": 4
437 +}
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.