tdickson17 commited on
Commit
7807765
·
1 Parent(s): 0f9dcb8

added project back

Browse files
Files changed (1) hide show
  1. pal_project.ipynb +475 -0
pal_project.ipynb ADDED
@@ -0,0 +1,475 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "id": "initial_id",
6
+ "metadata": {
7
+ "collapsed": true,
8
+ "ExecuteTime": {
9
+ "end_time": "2025-08-10T15:22:21.391963Z",
10
+ "start_time": "2025-08-10T15:22:21.389220Z"
11
+ }
12
+ },
13
+ "source": [
14
+ "# import pandas as pd\n",
15
+ "# import torch\n",
16
+ "# from transformers import T5Tokenizer\n",
17
+ "# import pandas as pd\n",
18
+ "# from torch.utils.data import DataLoader, TensorDataset\n",
19
+ "# device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
20
+ "# \n",
21
+ "# import numpy as np\n",
22
+ "# from transformers import T5Tokenizer\n"
23
+ ],
24
+ "outputs": [],
25
+ "execution_count": 12
26
+ },
27
+ {
28
+ "metadata": {},
29
+ "cell_type": "markdown",
30
+ "source": "",
31
+ "id": "18d7838a0a2b47f0"
32
+ },
33
+ {
34
+ "metadata": {
35
+ "ExecuteTime": {
36
+ "start_time": "2025-08-10T15:22:21.416790Z"
37
+ }
38
+ },
39
+ "cell_type": "code",
40
+ "source": "# df = pd.read_parquet(\"press_releases_all_with_CAP_issues.parquet\")",
41
+ "id": "3318aa3e574f90cf",
42
+ "outputs": [],
43
+ "execution_count": null
44
+ },
45
+ {
46
+ "metadata": {},
47
+ "cell_type": "code",
48
+ "source": "# df = df[['title', 'text']]",
49
+ "id": "f3816d3ecce5a8e0",
50
+ "outputs": [],
51
+ "execution_count": null
52
+ },
53
+ {
54
+ "metadata": {},
55
+ "cell_type": "code",
56
+ "source": "# df = df.head(10000)",
57
+ "id": "2cc68e87814bc931",
58
+ "outputs": [],
59
+ "execution_count": null
60
+ },
61
+ {
62
+ "metadata": {},
63
+ "cell_type": "code",
64
+ "source": "# df['title'].fillna('', inplace=True)",
65
+ "id": "8f3c1efe99f9dcdf",
66
+ "outputs": [],
67
+ "execution_count": null
68
+ },
69
+ {
70
+ "metadata": {},
71
+ "cell_type": "code",
72
+ "source": "# df['title'] = df['title'].replace('', 'No Title') ",
73
+ "id": "3d4322138b08d0f5",
74
+ "outputs": [],
75
+ "execution_count": null
76
+ },
77
+ {
78
+ "metadata": {},
79
+ "cell_type": "code",
80
+ "source": "# print(df.isna().sum())",
81
+ "id": "393b3b45b339c991",
82
+ "outputs": [],
83
+ "execution_count": null
84
+ },
85
+ {
86
+ "metadata": {},
87
+ "cell_type": "code",
88
+ "source": "# df.to_parquet('press_releases_consolidated.parquet', engine='pyarrow')",
89
+ "id": "4561d51aa9a63bba",
90
+ "outputs": [],
91
+ "execution_count": null
92
+ },
93
+ {
94
+ "metadata": {
95
+ "ExecuteTime": {
96
+ "end_time": "2025-08-10T15:39:06.429249Z",
97
+ "start_time": "2025-08-10T15:39:06.123602Z"
98
+ }
99
+ },
100
+ "cell_type": "code",
101
+ "source": [
102
+ "import pandas as pd\n",
103
+ "df = pd.read_parquet('press_releases_consolidated.parquet')"
104
+ ],
105
+ "id": "3f9ca20cb8190e2a",
106
+ "outputs": [],
107
+ "execution_count": 1
108
+ },
109
+ {
110
+ "metadata": {
111
+ "ExecuteTime": {
112
+ "end_time": "2025-08-10T15:39:14.393933Z",
113
+ "start_time": "2025-08-10T15:39:12.502613Z"
114
+ }
115
+ },
116
+ "cell_type": "code",
117
+ "source": [
118
+ "import torch\n",
119
+ "from torch.utils.data import Dataset, DataLoader, random_split\n",
120
+ "import torch\n",
121
+ "from transformers import T5Tokenizer\n",
122
+ "\n",
123
+ "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
124
+ "\n",
125
+ "tokenizer = T5Tokenizer.from_pretrained('t5-small')\n",
126
+ "\n",
127
+ "# modify accordingly\n",
128
+ "MAX_TARGET_LENGTH = 128\n",
129
+ "MAX_INPUT_LENGTH = 512\n",
130
+ "\n",
131
+ "class SummarizationDataset(Dataset):\n",
132
+ " def __init__(self, dataframe, tokenizer, max_input_length=MAX_INPUT_LENGTH, max_target_length=MAX_TARGET_LENGTH):\n",
133
+ " self.data = dataframe\n",
134
+ " self.tokenizer = tokenizer\n",
135
+ " self.max_input_length = max_input_length\n",
136
+ " self.max_target_length = max_target_length\n",
137
+ "\n",
138
+ " def __len__(self):\n",
139
+ " return len(self.data)\n",
140
+ " \n",
141
+ " def __getitem__(self, idx):\n",
142
+ " text = self.data.iloc[idx]['text']\n",
143
+ " title = self.data.iloc[idx]['title']\n",
144
+ " \n",
145
+ " \n",
146
+ " # tokenize\n",
147
+ " text_to_token = self.tokenizer(text, padding='max_length', truncation=True, max_length=self.max_input_length, return_tensors='pt')\n",
148
+ " title_to_token = self.tokenizer(title, padding='max_length', truncation=True, max_length=self.max_target_length, return_tensors='pt')\n",
149
+ " \n",
150
+ " \n",
151
+ " input_ids = text_to_token['input_ids'].squeeze(0) \n",
152
+ " attention_mask = text_to_token['attention_mask'].squeeze(0) \n",
153
+ " labels = title_to_token['input_ids'].squeeze(0) \n",
154
+ " labels[labels == self.tokenizer.pad_token_id] = -100 \n",
155
+ " \n",
156
+ " return {\n",
157
+ " 'input_ids': input_ids,\n",
158
+ " 'attention_mask': attention_mask,\n",
159
+ " 'labels': labels \n",
160
+ " }\n",
161
+ "\n",
162
+ "dataset = SummarizationDataset(df, tokenizer)\n",
163
+ "\n",
164
+ "\n",
165
+ "train_size = int(0.8 * len(dataset))\n",
166
+ "val_size = len(dataset) - train_size\n",
167
+ "train_dataset, val_dataset = random_split(dataset, [train_size, val_size])\n",
168
+ "\n",
169
+ "train_dataloader = DataLoader(train_dataset, batch_size=8, shuffle=True)\n",
170
+ "val_dataloader = DataLoader(val_dataset, batch_size=8)\n",
171
+ "\n"
172
+ ],
173
+ "id": "22604924094a8cd3",
174
+ "outputs": [
175
+ {
176
+ "name": "stderr",
177
+ "output_type": "stream",
178
+ "text": [
179
+ "You are using the default legacy behaviour of the <class 'transformers.models.t5.tokenization_t5.T5Tokenizer'>. This is expected, and simply means that the `legacy` (previous) behavior will be used so nothing changes for you. If you want to use the new behaviour, set `legacy=False`. This should only be set if you understand what it means, and thoroughly read the reason why this was added as explained in https://github.com/huggingface/transformers/pull/24565\n"
180
+ ]
181
+ }
182
+ ],
183
+ "execution_count": 3
184
+ },
185
+ {
186
+ "metadata": {
187
+ "ExecuteTime": {
188
+ "end_time": "2025-08-10T21:47:41.277658Z",
189
+ "start_time": "2025-08-10T15:39:15.673627Z"
190
+ }
191
+ },
192
+ "cell_type": "code",
193
+ "source": [
194
+ "import torch\n",
195
+ "from transformers import T5ForConditionalGeneration\n",
196
+ "from torch.optim import Adam\n",
197
+ "from torch.utils.data import DataLoader\n",
198
+ "from sklearn.model_selection import train_test_split\n",
199
+ "import evaluate\n",
200
+ "\n",
201
+ "model = T5ForConditionalGeneration.from_pretrained('t5-small')\n",
202
+ "optimizer = Adam(model.parameters(), lr=5e-5)\n",
203
+ "\n",
204
+ "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
205
+ "model.to(device)\n",
206
+ "\n",
207
+ "rouge = evaluate.load(\"rouge\")\n",
208
+ "\n",
209
+ "def train():\n",
210
+ " model.train()\n",
211
+ " total_loss = 0\n",
212
+ " for batch in train_dataloader:\n",
213
+ " input_ids = batch['input_ids'].to(device)\n",
214
+ " attention_mask = batch['attention_mask'].to(device)\n",
215
+ " labels = batch['labels'].to(device)\n",
216
+ "\n",
217
+ " outputs = model(input_ids=input_ids, attention_mask=attention_mask, labels=labels)\n",
218
+ " loss = outputs.loss\n",
219
+ " total_loss += loss.item()\n",
220
+ "\n",
221
+ " loss.backward()\n",
222
+ " optimizer.step()\n",
223
+ " optimizer.zero_grad()\n",
224
+ "\n",
225
+ " return total_loss / len(train_dataloader)\n",
226
+ "\n",
227
+ "def evaluate():\n",
228
+ " model.eval()\n",
229
+ " total_loss = 0\n",
230
+ " all_preds = []\n",
231
+ " all_labels = []\n",
232
+ " \n",
233
+ " with torch.no_grad():\n",
234
+ " for batch in val_dataloader:\n",
235
+ " input_ids = batch['input_ids'].to(device)\n",
236
+ " attention_mask = batch['attention_mask'].to(device)\n",
237
+ " labels = batch['labels'].to(device)\n",
238
+ "\n",
239
+ " outputs = model(input_ids=input_ids, attention_mask=attention_mask, labels=labels)\n",
240
+ " total_loss += outputs.loss.item()\n",
241
+ " \n",
242
+ " try:\n",
243
+ " summary_ids = model.generate(\n",
244
+ " input_ids=input_ids,\n",
245
+ " attention_mask=attention_mask,\n",
246
+ " max_length=MAX_TARGET_LENGTH,\n",
247
+ " num_beams=8,\n",
248
+ " early_stopping=True\n",
249
+ " )\n",
250
+ " \n",
251
+ " summary_ids = summary_ids[0] if len(summary_ids) > 0 else torch.tensor([tokenizer.pad_token_id])\n",
252
+ " \n",
253
+ " preds = tokenizer.decode(summary_ids.cpu(), skip_special_tokens=True, clean_up_tokenization_spaces=True)\n",
254
+ " labels_decoded = tokenizer.decode(\n",
255
+ " labels[0].masked_select(labels[0] != -100).cpu(), \n",
256
+ " skip_special_tokens=True,\n",
257
+ " clean_up_tokenization_spaces=True\n",
258
+ " )\n",
259
+ " \n",
260
+ " all_preds.append(preds if preds else \" \")\n",
261
+ " all_labels.append(labels_decoded if labels_decoded else \" \")\n",
262
+ " \n",
263
+ " except Exception as e:\n",
264
+ " print(f\"Error during generation: {e}\")\n",
265
+ " all_preds.append(\" \")\n",
266
+ " all_labels.append(\" \")\n",
267
+ " continue\n",
268
+ "\n",
269
+ " all_preds = [p if p.strip() else \" \" for p in all_preds]\n",
270
+ " all_labels = [l if l.strip() else \" \" for l in all_labels]\n",
271
+ " \n",
272
+ " rouge_result = rouge.compute(predictions=all_preds, references=all_labels)\n",
273
+ " \n",
274
+ " return total_loss / len(val_dataloader), rouge_result\n",
275
+ "\n",
276
+ "\n",
277
+ "epochs = 15\n",
278
+ "best_val_loss = float('inf')\n",
279
+ "\n",
280
+ "for epoch in range(epochs):\n",
281
+ " print(f\"Epoch {epoch + 1}/{epochs}\")\n",
282
+ "\n",
283
+ " train_loss = train()\n",
284
+ " print(f\"Training Loss: {train_loss:.4f}\")\n",
285
+ "\n",
286
+ " val_loss, rouge_result = evaluate()\n",
287
+ " print(f\"Validation Loss: {val_loss:.4f}\")\n",
288
+ " print(f\"ROUGE Scores: {rouge_result}\")\n",
289
+ "\n",
290
+ " if val_loss < best_val_loss:\n",
291
+ " best_val_loss = val_loss\n",
292
+ " model.save_pretrained(f\"best_model_epoch_{epoch + 1}\")\n",
293
+ " tokenizer.save_pretrained(f\"best_model_epoch_{epoch + 1}\")\n"
294
+ ],
295
+ "id": "2041549aaa86af9f",
296
+ "outputs": [
297
+ {
298
+ "name": "stdout",
299
+ "output_type": "stream",
300
+ "text": [
301
+ "Epoch 1/15\n",
302
+ "Training Loss: 2.3327\n",
303
+ "Validation Loss: 1.9963\n",
304
+ "ROUGE Scores: {'rouge1': 0.21808722374319384, 'rouge2': 0.1182736024791169, 'rougeL': 0.19976099496233557, 'rougeLsum': 0.19920689338385827}\n",
305
+ "Epoch 2/15\n",
306
+ "Training Loss: 2.1164\n",
307
+ "Validation Loss: 1.9190\n",
308
+ "ROUGE Scores: {'rouge1': 0.24314444230564494, 'rouge2': 0.14001878402499457, 'rougeL': 0.2237854024840728, 'rougeLsum': 0.22246462572576908}\n",
309
+ "Epoch 3/15\n",
310
+ "Training Loss: 2.0179\n",
311
+ "Validation Loss: 1.8727\n",
312
+ "ROUGE Scores: {'rouge1': 0.23564530968156083, 'rouge2': 0.13669895563342216, 'rougeL': 0.21725589526977998, 'rougeLsum': 0.2151015219135301}\n",
313
+ "Epoch 4/15\n",
314
+ "Training Loss: 1.9257\n",
315
+ "Validation Loss: 1.8389\n",
316
+ "ROUGE Scores: {'rouge1': 0.23937899093803855, 'rouge2': 0.13888041555479988, 'rougeL': 0.21854222551451663, 'rougeLsum': 0.21721511685962552}\n",
317
+ "Epoch 5/15\n",
318
+ "Training Loss: 1.8781\n",
319
+ "Validation Loss: 1.8102\n",
320
+ "ROUGE Scores: {'rouge1': 0.2412030325505815, 'rouge2': 0.1373245465699872, 'rougeL': 0.22158876960762192, 'rougeLsum': 0.21964406824128718}\n",
321
+ "Epoch 6/15\n",
322
+ "Training Loss: 1.8266\n",
323
+ "Validation Loss: 1.8030\n",
324
+ "ROUGE Scores: {'rouge1': 0.24693945766624123, 'rouge2': 0.13859814431515555, 'rougeL': 0.22609207133571282, 'rougeLsum': 0.22456133662136685}\n",
325
+ "Epoch 7/15\n",
326
+ "Training Loss: 1.7831\n",
327
+ "Validation Loss: 1.7842\n",
328
+ "ROUGE Scores: {'rouge1': 0.24995693123364204, 'rouge2': 0.13730760003890233, 'rougeL': 0.22966043449504253, 'rougeLsum': 0.22839320529835103}\n",
329
+ "Epoch 8/15\n",
330
+ "Training Loss: 1.7398\n",
331
+ "Validation Loss: 1.7843\n",
332
+ "ROUGE Scores: {'rouge1': 0.24797510003323764, 'rouge2': 0.13919083038634567, 'rougeL': 0.22646443435896133, 'rougeLsum': 0.22558282591894607}\n",
333
+ "Epoch 9/15\n",
334
+ "Training Loss: 1.7068\n",
335
+ "Validation Loss: 1.7860\n",
336
+ "ROUGE Scores: {'rouge1': 0.25390876204792084, 'rouge2': 0.13814393342112263, 'rougeL': 0.231234438215985, 'rougeLsum': 0.2311260176829176}\n",
337
+ "Epoch 10/15\n",
338
+ "Training Loss: 1.6779\n",
339
+ "Validation Loss: 1.7854\n",
340
+ "ROUGE Scores: {'rouge1': 0.25411363403331366, 'rouge2': 0.14468888317851958, 'rougeL': 0.2354872641812709, 'rougeLsum': 0.23342210178892542}\n",
341
+ "Epoch 11/15\n",
342
+ "Training Loss: 1.6413\n",
343
+ "Validation Loss: 1.7642\n",
344
+ "ROUGE Scores: {'rouge1': 0.2679774072064855, 'rouge2': 0.14667787569965263, 'rougeL': 0.24705660369839066, 'rougeLsum': 0.2454144686019869}\n",
345
+ "Epoch 12/15\n",
346
+ "Training Loss: 1.6075\n",
347
+ "Validation Loss: 1.7712\n",
348
+ "ROUGE Scores: {'rouge1': 0.268361111086107, 'rouge2': 0.15128550708369404, 'rougeL': 0.24768429614360232, 'rougeLsum': 0.24575241584538624}\n",
349
+ "Epoch 13/15\n",
350
+ "Training Loss: 1.5857\n",
351
+ "Validation Loss: 1.7618\n",
352
+ "ROUGE Scores: {'rouge1': 0.28096384664011065, 'rouge2': 0.1595810134136424, 'rougeL': 0.2575870112336856, 'rougeLsum': 0.25663783533294626}\n",
353
+ "Epoch 14/15\n",
354
+ "Training Loss: 1.5552\n",
355
+ "Validation Loss: 1.7620\n",
356
+ "ROUGE Scores: {'rouge1': 0.2833173462582747, 'rouge2': 0.1648174970170761, 'rougeL': 0.2615026211543109, 'rougeLsum': 0.2600381314435784}\n",
357
+ "Epoch 15/15\n",
358
+ "Training Loss: 1.5316\n",
359
+ "Validation Loss: 1.7716\n",
360
+ "ROUGE Scores: {'rouge1': 0.2782139285308772, 'rouge2': 0.1606118164438922, 'rougeL': 0.2581515139790868, 'rougeLsum': 0.2571149575053421}\n"
361
+ ]
362
+ }
363
+ ],
364
+ "execution_count": 4
365
+ },
366
+ {
367
+ "metadata": {},
368
+ "cell_type": "code",
369
+ "source": "",
370
+ "id": "c8d5f56240932910",
371
+ "outputs": [],
372
+ "execution_count": null
373
+ },
374
+ {
375
+ "metadata": {},
376
+ "cell_type": "code",
377
+ "source": "",
378
+ "id": "3cecb16d8154a783",
379
+ "outputs": [],
380
+ "execution_count": null
381
+ },
382
+ {
383
+ "metadata": {
384
+ "ExecuteTime": {
385
+ "end_time": "2025-08-11T23:22:29.491880Z",
386
+ "start_time": "2025-08-11T23:22:28.364057Z"
387
+ }
388
+ },
389
+ "cell_type": "code",
390
+ "source": [
391
+ "import torch\n",
392
+ "from transformers import AutoModelForSeq2SeqLM, AutoTokenizer\n",
393
+ "\n",
394
+ "model_id = \"tdickson17/Text_Summarization\"\n",
395
+ "\n",
396
+ "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
397
+ "\n",
398
+ "tok = AutoTokenizer.from_pretrained(model_id, use_fast=True)\n",
399
+ "model = AutoModelForSeq2SeqLM.from_pretrained(model_id).to(device)\n",
400
+ "\n",
401
+ "def generate_summary(\n",
402
+ " text,\n",
403
+ " model=model,\n",
404
+ " tokenizer=tok,\n",
405
+ " device=device,\n",
406
+ " max_new_tokens=128,\n",
407
+ " min_new_tokens=20,\n",
408
+ " num_beams=4\n",
409
+ "):\n",
410
+ " # T5 often uses a task prefix; keep if your model expects it\n",
411
+ " if not text.lower().startswith(\"summarize:\"):\n",
412
+ " text = \"summarize: \" + text\n",
413
+ "\n",
414
+ " inputs = tokenizer(text, return_tensors=\"pt\", truncation=True).to(device)\n",
415
+ "\n",
416
+ " with torch.no_grad():\n",
417
+ " out_ids = model.generate(\n",
418
+ " **inputs,\n",
419
+ " max_new_tokens=max_new_tokens, \n",
420
+ " min_new_tokens=min_new_tokens,\n",
421
+ " num_beams=num_beams,\n",
422
+ " no_repeat_ngram_size=3,\n",
423
+ " early_stopping=True\n",
424
+ " )\n",
425
+ "\n",
426
+ " return tokenizer.decode(out_ids[0], skip_special_tokens=True)\n",
427
+ "\n",
428
+ "input_text = (\n",
429
+ " \"At Susquehanna, we approach quantitative finance with a deep commitment to scientific rigor and innovation. Our research leverages vast and diverse datasets, applying cutting-edge machine learning to uncover actionable insights and driving data-informed decisions from predictive modeling to strategic execution. Today, Susquehanna has over 3,000 employees in 17+ global locations. While we have grown in size and expanded our reach, our collaborative culture and love for gaming remains.\"\n",
430
+ ")\n",
431
+ "print(\"Summary:\", generate_summary(input_text))\n"
432
+ ],
433
+ "id": "add7d5e5d17e708b",
434
+ "outputs": [
435
+ {
436
+ "name": "stdout",
437
+ "output_type": "stream",
438
+ "text": [
439
+ "Summary: quantitative finance is driven by scientific rigor and innovation. Susquehanna has over 3,000 employees.\n"
440
+ ]
441
+ }
442
+ ],
443
+ "execution_count": 15
444
+ },
445
+ {
446
+ "metadata": {},
447
+ "cell_type": "code",
448
+ "outputs": [],
449
+ "execution_count": null,
450
+ "source": "",
451
+ "id": "976fd3465f63b737"
452
+ }
453
+ ],
454
+ "metadata": {
455
+ "kernelspec": {
456
+ "display_name": "Python 3",
457
+ "language": "python",
458
+ "name": "python3"
459
+ },
460
+ "language_info": {
461
+ "codemirror_mode": {
462
+ "name": "ipython",
463
+ "version": 2
464
+ },
465
+ "file_extension": ".py",
466
+ "mimetype": "text/x-python",
467
+ "name": "python",
468
+ "nbconvert_exporter": "python",
469
+ "pygments_lexer": "ipython2",
470
+ "version": "2.7.6"
471
+ }
472
+ },
473
+ "nbformat": 4,
474
+ "nbformat_minor": 5
475
+ }