ml-finance-python
python scripts for finance machine learning
git clone https://9o.is/git/ml-finance-python.git
04_bonus_translation.ipynb
(85249B)
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": null,
6 "metadata": {
7 "slideshow": {
8 "slide_type": "skip"
9 }
10 },
11 "outputs": [],
12 "source": [
13 "from notebook.services.config import ConfigManager\n",
14 "cm = ConfigManager()\n",
15 "cm.update('livereveal', {\n",
16 " 'width': 1280,\n",
17 " 'height': 800,\n",
18 " 'scroll': True\n",
19 "})"
20 ]
21 },
22 {
23 "cell_type": "markdown",
24 "metadata": {
25 "slideshow": {
26 "slide_type": "slide"
27 }
28 },
29 "source": [
30 "## Imports & Config"
31 ]
32 },
33 {
34 "cell_type": "code",
35 "execution_count": 39,
36 "metadata": {
37 "slideshow": {
38 "slide_type": "fragment"
39 }
40 },
41 "outputs": [],
42 "source": [
43 "import tensorflow as tf\n",
44 "from sklearn.model_selection import train_test_split\n",
45 "from pathlib import Path\n",
46 "import sys\n",
47 "from os import environ\n",
48 "from inspect import getfile, currentframe\n",
49 "from os.path import join, dirname, abspath\n",
50 "from gensim.models import Word2Vec, KeyedVectors\n",
51 "import pandas as pd\n",
52 "import numpy as np\n",
53 "from numpy.linalg import norm\n",
54 "from numpy.random import permutation\n",
55 "from sklearn.manifold import TSNE\n",
56 "import matplotlib.pyplot as plt\n",
57 "from matplotlib.ticker import FuncFormatter\n",
58 "\n",
59 "plt.style.use('ggplot')"
60 ]
61 },
62 {
63 "cell_type": "code",
64 "execution_count": 2,
65 "metadata": {
66 "slideshow": {
67 "slide_type": "slide"
68 }
69 },
70 "outputs": [],
71 "source": [
72 "def batches(l, n):\n",
73 " \"\"\" Yield successive n-sized chunks from l.\"\"\"\n",
74 " for i in range(0, len(l), n):\n",
75 " yield l[i:i + n]"
76 ]
77 },
78 {
79 "cell_type": "code",
80 "execution_count": 41,
81 "metadata": {
82 "slideshow": {
83 "slide_type": "fragment"
84 }
85 },
86 "outputs": [],
87 "source": [
88 "LANGUAGES = ['en', 'es']\n",
89 "translation_path = Path('translation')\n",
90 "if not translation_path.exists():\n",
91 " translation_path.mkdir(parents=True, exist_ok=True)"
92 ]
93 },
94 {
95 "cell_type": "markdown",
96 "metadata": {
97 "slideshow": {
98 "slide_type": "slide"
99 }
100 },
101 "source": [
102 "## Load word2vec Models"
103 ]
104 },
105 {
106 "cell_type": "code",
107 "execution_count": 6,
108 "metadata": {
109 "slideshow": {
110 "slide_type": "fragment"
111 }
112 },
113 "outputs": [],
114 "source": [
115 "model, words, vectors = {}, {}, {}\n",
116 "for language in LANGUAGES:\n",
117 " file_name = 'word2vec/word_vectors/vectors_{}.bin'.format(language)\n",
118 " model[language] = KeyedVectors.load_word2vec_format(file_name,\n",
119 " binary=True,\n",
120 " unicode_errors='ignore')\n",
121 " words[language] = model[language].index2word\n",
122 " vectors[language] = model[language].vectors\n",
123 " vectors[language] /= norm(vectors[language], axis=1).reshape(-1, 1)"
124 ]
125 },
126 {
127 "cell_type": "markdown",
128 "metadata": {
129 "slideshow": {
130 "slide_type": "slide"
131 }
132 },
133 "source": [
134 "## Translate Top 10k English Terms"
135 ]
136 },
137 {
138 "cell_type": "code",
139 "execution_count": 7,
140 "metadata": {
141 "slideshow": {
142 "slide_type": "fragment"
143 }
144 },
145 "outputs": [],
146 "source": [
147 "to_translate = words['en'][:10000]\n",
148 "pd.Series(to_translate).to_csv(translation_path / 'words_en.txt', index=False)"
149 ]
150 },
151 {
152 "cell_type": "code",
153 "execution_count": 8,
154 "metadata": {
155 "slideshow": {
156 "slide_type": "fragment"
157 }
158 },
159 "outputs": [
160 {
161 "data": {
162 "text/plain": [
163 "10000"
164 ]
165 },
166 "execution_count": 8,
167 "metadata": {},
168 "output_type": "execute_result"
169 }
170 ],
171 "source": [
172 "translated = pd.Series((translation_path / 'words_es.txt').read_text().split('\\n'))\n",
173 "translated.count()"
174 ]
175 },
176 {
177 "cell_type": "code",
178 "execution_count": 9,
179 "metadata": {
180 "slideshow": {
181 "slide_type": "slide"
182 }
183 },
184 "outputs": [
185 {
186 "data": {
187 "text/html": [
188 "<div>\n",
189 "<style scoped>\n",
190 " .dataframe tbody tr th:only-of-type {\n",
191 " vertical-align: middle;\n",
192 " }\n",
193 "\n",
194 " .dataframe tbody tr th {\n",
195 " vertical-align: top;\n",
196 " }\n",
197 "\n",
198 " .dataframe thead th {\n",
199 " text-align: right;\n",
200 " }\n",
201 "</style>\n",
202 "<table border=\"1\" class=\"dataframe\">\n",
203 " <thead>\n",
204 " <tr style=\"text-align: right;\">\n",
205 " <th></th>\n",
206 " <th>en</th>\n",
207 " <th>es</th>\n",
208 " </tr>\n",
209 " </thead>\n",
210 " <tbody>\n",
211 " <tr>\n",
212 " <th>0</th>\n",
213 " <td></s></td>\n",
214 " <td></ s></td>\n",
215 " </tr>\n",
216 " <tr>\n",
217 " <th>1</th>\n",
218 " <td>the</td>\n",
219 " <td>el</td>\n",
220 " </tr>\n",
221 " <tr>\n",
222 " <th>2</th>\n",
223 " <td>of</td>\n",
224 " <td>de</td>\n",
225 " </tr>\n",
226 " <tr>\n",
227 " <th>3</th>\n",
228 " <td>and</td>\n",
229 " <td>y</td>\n",
230 " </tr>\n",
231 " <tr>\n",
232 " <th>4</th>\n",
233 " <td>in</td>\n",
234 " <td>en</td>\n",
235 " </tr>\n",
236 " </tbody>\n",
237 "</table>\n",
238 "</div>"
239 ],
240 "text/plain": [
241 " en es\n",
242 "0 </s> </ s>\n",
243 "1 the el\n",
244 "2 of de\n",
245 "3 and y\n",
246 "4 in en"
247 ]
248 },
249 "execution_count": 9,
250 "metadata": {},
251 "output_type": "execute_result"
252 }
253 ],
254 "source": [
255 "matches = pd.DataFrame({'en': to_translate, 'es': translated})\n",
256 "matches.head()"
257 ]
258 },
259 {
260 "cell_type": "code",
261 "execution_count": 10,
262 "metadata": {
263 "slideshow": {
264 "slide_type": "slide"
265 }
266 },
267 "outputs": [],
268 "source": [
269 "word2id = {}\n",
270 "for language in LANGUAGES:\n",
271 " word2id[language] = {w: i for i, w in enumerate(words[language])}"
272 ]
273 },
274 {
275 "cell_type": "code",
276 "execution_count": 11,
277 "metadata": {
278 "slideshow": {
279 "slide_type": "fragment"
280 }
281 },
282 "outputs": [
283 {
284 "data": {
285 "text/plain": [
286 "'Missing: 13.17%'"
287 ]
288 },
289 "execution_count": 11,
290 "metadata": {},
291 "output_type": "execute_result"
292 }
293 ],
294 "source": [
295 "matches['es_id'] = matches.es.map(word2id['es'])\n",
296 "'Missing: {:.2%}'.format(matches.es_id.isnull().sum()/len(matches))"
297 ]
298 },
299 {
300 "cell_type": "code",
301 "execution_count": 12,
302 "metadata": {
303 "slideshow": {
304 "slide_type": "fragment"
305 }
306 },
307 "outputs": [
308 {
309 "data": {
310 "text/html": [
311 "<div>\n",
312 "<style scoped>\n",
313 " .dataframe tbody tr th:only-of-type {\n",
314 " vertical-align: middle;\n",
315 " }\n",
316 "\n",
317 " .dataframe tbody tr th {\n",
318 " vertical-align: top;\n",
319 " }\n",
320 "\n",
321 " .dataframe thead th {\n",
322 " text-align: right;\n",
323 " }\n",
324 "</style>\n",
325 "<table border=\"1\" class=\"dataframe\">\n",
326 " <thead>\n",
327 " <tr style=\"text-align: right;\">\n",
328 " <th></th>\n",
329 " <th>en</th>\n",
330 " <th>en_id</th>\n",
331 " <th>es</th>\n",
332 " <th>es_id</th>\n",
333 " </tr>\n",
334 " </thead>\n",
335 " <tbody>\n",
336 " <tr>\n",
337 " <th>0</th>\n",
338 " <td>the</td>\n",
339 " <td>1</td>\n",
340 " <td>el</td>\n",
341 " <td>2</td>\n",
342 " </tr>\n",
343 " <tr>\n",
344 " <th>1</th>\n",
345 " <td>of</td>\n",
346 " <td>2</td>\n",
347 " <td>de</td>\n",
348 " <td>1</td>\n",
349 " </tr>\n",
350 " <tr>\n",
351 " <th>2</th>\n",
352 " <td>and</td>\n",
353 " <td>3</td>\n",
354 " <td>y</td>\n",
355 " <td>5</td>\n",
356 " </tr>\n",
357 " <tr>\n",
358 " <th>3</th>\n",
359 " <td>in</td>\n",
360 " <td>4</td>\n",
361 " <td>en</td>\n",
362 " <td>4</td>\n",
363 " </tr>\n",
364 " <tr>\n",
365 " <th>4</th>\n",
366 " <td>to</td>\n",
367 " <td>5</td>\n",
368 " <td>a</td>\n",
369 " <td>6</td>\n",
370 " </tr>\n",
371 " </tbody>\n",
372 "</table>\n",
373 "</div>"
374 ],
375 "text/plain": [
376 " en en_id es es_id\n",
377 "0 the 1 el 2\n",
378 "1 of 2 de 1\n",
379 "2 and 3 y 5\n",
380 "3 in 4 en 4\n",
381 "4 to 5 a 6"
382 ]
383 },
384 "execution_count": 12,
385 "metadata": {},
386 "output_type": "execute_result"
387 }
388 ],
389 "source": [
390 "matches = matches.dropna().reset_index().rename(columns={'index': 'en_id'}).sort_index(1)\n",
391 "matches.es_id = matches.es_id.astype(int)\n",
392 "matches.head()"
393 ]
394 },
395 {
396 "cell_type": "code",
397 "execution_count": 13,
398 "metadata": {
399 "slideshow": {
400 "slide_type": "slide"
401 }
402 },
403 "outputs": [
404 {
405 "name": "stdout",
406 "output_type": "stream",
407 "text": [
408 "<class 'pandas.core.frame.DataFrame'>\n",
409 "RangeIndex: 8683 entries, 0 to 8682\n",
410 "Data columns (total 4 columns):\n",
411 "en 8683 non-null object\n",
412 "en_id 8683 non-null int64\n",
413 "es 8683 non-null object\n",
414 "es_id 8683 non-null int64\n",
415 "dtypes: int64(2), object(2)\n",
416 "memory usage: 271.4+ KB\n"
417 ]
418 }
419 ],
420 "source": [
421 "matches.info()"
422 ]
423 },
424 {
425 "cell_type": "markdown",
426 "metadata": {
427 "slideshow": {
428 "slide_type": "slide"
429 }
430 },
431 "source": [
432 "## Learn Translation Matrix"
433 ]
434 },
435 {
436 "cell_type": "markdown",
437 "metadata": {
438 "slideshow": {
439 "slide_type": "fragment"
440 }
441 },
442 "source": [
443 "### Model Settings"
444 ]
445 },
446 {
447 "cell_type": "code",
448 "execution_count": 14,
449 "metadata": {
450 "slideshow": {
451 "slide_type": "fragment"
452 }
453 },
454 "outputs": [],
455 "source": [
456 "BATCH_SIZE = 100\n",
457 "TRAIN_SIZE = 5000\n",
458 "EARLY_STOP = 5\n",
459 "SOURCE_DIM = vectors['en'].shape[1]\n",
460 "TARGET_DIM = vectors['es'].shape[1]"
461 ]
462 },
463 {
464 "cell_type": "markdown",
465 "metadata": {
466 "slideshow": {
467 "slide_type": "slide"
468 }
469 },
470 "source": [
471 "### Train & Test Sets for Source & Target Embeddings"
472 ]
473 },
474 {
475 "cell_type": "code",
476 "execution_count": 15,
477 "metadata": {
478 "slideshow": {
479 "slide_type": "fragment"
480 }
481 },
482 "outputs": [],
483 "source": [
484 "source_id = matches.en_id.values\n",
485 "source_train = vectors['en'][source_id[:TRAIN_SIZE]]\n",
486 "source_test = vectors['en'][source_id[TRAIN_SIZE:]]\n",
487 "\n",
488 "target_id = matches.es_id.values\n",
489 "target_train = vectors['es'][target_id[:TRAIN_SIZE]]\n",
490 "target_test = vectors['es'][target_id[TRAIN_SIZE:]]"
491 ]
492 },
493 {
494 "cell_type": "markdown",
495 "metadata": {
496 "slideshow": {
497 "slide_type": "slide"
498 }
499 },
500 "source": [
501 "### TensorFlow Graph"
502 ]
503 },
504 {
505 "cell_type": "code",
506 "execution_count": 16,
507 "metadata": {
508 "slideshow": {
509 "slide_type": "fragment"
510 }
511 },
512 "outputs": [],
513 "source": [
514 "tf.logging.set_verbosity(tf.logging.INFO)\n",
515 "\n",
516 "with tf.name_scope('inputs'):\n",
517 " s = tf.placeholder(tf.float32, shape=[None, SOURCE_DIM], name='source')\n",
518 " t_ = tf.placeholder(tf.float32, shape=[None, TARGET_DIM], name='target')\n",
519 "\n",
520 "with tf.name_scope('parameters'):\n",
521 " T = tf.Variable(\n",
522 " tf.random_normal([SOURCE_DIM, TARGET_DIM]),\n",
523 " name='translation_matrix'\n",
524 " )\n",
525 " tf.summary.histogram('histogram', T)\n",
526 "\n",
527 "with tf.name_scope('inference'):\n",
528 " t = tf.matmul(s, T, name='projection')\n",
529 " # Regularized L2 Loss\n",
530 " loss = tf.nn.l2_loss(t - t_, name='l2_loss') + .01 * tf.nn.l2_loss(T)\n",
531 "\n",
532 "with tf.name_scope('training'):\n",
533 " optimizer = tf.train.AdamOptimizer()\n",
534 " train = optimizer.minimize(loss)"
535 ]
536 },
537 {
538 "cell_type": "markdown",
539 "metadata": {
540 "slideshow": {
541 "slide_type": "slide"
542 }
543 },
544 "source": [
545 "### Run TensorFlow Model"
546 ]
547 },
548 {
549 "cell_type": "code",
550 "execution_count": 17,
551 "metadata": {
552 "slideshow": {
553 "slide_type": "fragment"
554 }
555 },
556 "outputs": [],
557 "source": [
558 "with tf.Session().as_default() as sess:\n",
559 " tf.global_variables_initializer().run()\n",
560 "\n",
561 " test_loss = np.inf\n",
562 " early_stop = 0\n",
563 " losses = []\n",
564 " \n",
565 " while True:\n",
566 " s_train, s_test, t_train, t_test = train_test_split(source_train, \n",
567 " target_train, \n",
568 " test_size=0.2,\n",
569 " random_state=42)\n",
570 " \n",
571 " for idx in batches(permutation(s_train.shape[0]), BATCH_SIZE):\n",
572 " train.run(feed_dict={s: s_train[idx], t_: t_train[idx]})\n",
573 " \n",
574 " loss_ = sess.run(loss, feed_dict={s: s_test, t_: t_test})\n",
575 " losses.append(loss_)\n",
576 " \n",
577 " if loss_ < test_loss:\n",
578 " test_loss = loss_\n",
579 " early_stop = 0\n",
580 " else:\n",
581 " early_stop += 1\n",
582 " if early_stop == EARLY_STOP:\n",
583 " break\n",
584 " \n",
585 " translation_matrix = T.eval(sess)"
586 ]
587 },
588 {
589 "cell_type": "markdown",
590 "metadata": {
591 "slideshow": {
592 "slide_type": "slide"
593 }
594 },
595 "source": [
596 "### Review Results"
597 ]
598 },
599 {
600 "cell_type": "code",
601 "execution_count": 18,
602 "metadata": {
603 "slideshow": {
604 "slide_type": "fragment"
605 }
606 },
607 "outputs": [
608 {
609 "data": {
610 "image/png": "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\n",
611 "text/plain": [
612 "<Figure size 432x288 with 1 Axes>"
613 ]
614 },
615 "metadata": {},
616 "output_type": "display_data"
617 }
618 ],
619 "source": [
620 "ax = pd.Series(losses).plot(title='L2 Loss', logy=True)\n",
621 "ax.set_xlabel('Epochs');"
622 ]
623 },
624 {
625 "cell_type": "code",
626 "execution_count": 19,
627 "metadata": {
628 "slideshow": {
629 "slide_type": "fragment"
630 }
631 },
632 "outputs": [
633 {
634 "data": {
635 "text/plain": [
636 "(300, 300)"
637 ]
638 },
639 "execution_count": 19,
640 "metadata": {},
641 "output_type": "execute_result"
642 }
643 ],
644 "source": [
645 "translation_matrix.shape"
646 ]
647 },
648 {
649 "cell_type": "markdown",
650 "metadata": {
651 "slideshow": {
652 "slide_type": "slide"
653 }
654 },
655 "source": [
656 "### Evaluate Translation Accuracy"
657 ]
658 },
659 {
660 "cell_type": "code",
661 "execution_count": 22,
662 "metadata": {
663 "slideshow": {
664 "slide_type": "fragment"
665 }
666 },
667 "outputs": [],
668 "source": [
669 "def get_accuracy(source, target, translation):\n",
670 " source_projection = np.dot(source, translation)\n",
671 " similarity = np.dot(source_projection, target.T)\n",
672 " \n",
673 " # Sort descending by index from left to right\n",
674 " nearest_neighbors = np.fliplr(similarity.argsort(axis=1)) \n",
675 " \n",
676 " # Get ranking of correct prediction\n",
677 " _, rank = np.where(nearest_neighbors == np.arange(target.shape[0]).reshape(-1, 1))\n",
678 " return pd.Series(data=rank).add(1), nearest_neighbors"
679 ]
680 },
681 {
682 "cell_type": "markdown",
683 "metadata": {
684 "slideshow": {
685 "slide_type": "slide"
686 }
687 },
688 "source": [
689 "#### Train Accuracy"
690 ]
691 },
692 {
693 "cell_type": "code",
694 "execution_count": 31,
695 "metadata": {
696 "slideshow": {
697 "slide_type": "fragment"
698 }
699 },
700 "outputs": [],
701 "source": [
702 "ranking, nn_train = get_accuracy(source_train, target_train, translation_matrix)\n",
703 "train_accuracy = ranking.value_counts().sort_index()\n",
704 "train_precision = train_accuracy.cumsum().div(len(ranking)).iloc[:10]\n",
705 "train_precision = train_precision.to_frame('Train: n={:,d}'.format(len(ranking)))"
706 ]
707 },
708 {
709 "cell_type": "markdown",
710 "metadata": {
711 "slideshow": {
712 "slide_type": "slide"
713 }
714 },
715 "source": [
716 "#### Test Accuracy"
717 ]
718 },
719 {
720 "cell_type": "code",
721 "execution_count": 32,
722 "metadata": {
723 "slideshow": {
724 "slide_type": "fragment"
725 }
726 },
727 "outputs": [],
728 "source": [
729 "ranking, nn_test = get_accuracy(source_test, target_test, translation_matrix)\n",
730 "test_accuracy = ranking.value_counts().sort_index()\n",
731 "test_precision = test_accuracy.cumsum().div(len(ranking)).iloc[:10].iloc[:10]\n",
732 "test_precision = test_precision.to_frame('Test: n={:,d}'.format(len(ranking)))"
733 ]
734 },
735 {
736 "cell_type": "markdown",
737 "metadata": {
738 "slideshow": {
739 "slide_type": "slide"
740 }
741 },
742 "source": [
743 "#### Plot Results"
744 ]
745 },
746 {
747 "cell_type": "code",
748 "execution_count": 34,
749 "metadata": {
750 "slideshow": {
751 "slide_type": "fragment"
752 }
753 },
754 "outputs": [
755 {
756 "data": {
757 "image/png": "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O+2Yn1eSJEmSNHLFXHsS0rTuJLY09358mPCmn7E10NAI4yYQ5pwO9Y1Q38jY0+aze+BfRkmMyIDnGyu3sb61/YQ+56z6Km5cPPF5P2716tXceeed3HHHHZSXl/OBD3yAO+64gxkzZtDa2trT0rR7925qa2v55je/2e8Ez6c+9SnOO+88LrvsskOee926dfzLv/wLe/bsYenSpbzxjW+krKyMa665hgMHDhxy/8c+9jGWLFkCwCc/+Ul++MMfUl9fTzabPexzxxh53eteR0tLC6985Su56aabSKfT3HrrrVxyySWMGTOGOXPm8OlPf7rncc/1vJIkSZKk4enw4U0zsXXn8whvzoD6cVDfSGhoTD6uG0eoTB/2e1Y0NsIIOSk3IgOeweS+++7jj3/8I1dddRUA7e3tNDU1sXTpUp566ik+8pGPcNlll7F06dLDPv6DH/zgEZ972bJlVFZW0tjYSF1dHTt37mTChAn86Ec/es66PvShD/GhD32Iz372s9x+++3cfPPN/a7n83lWrlzJj3/8Y6qqqnjNa17DWWedxaJFi/jOd77Dr371K6ZOncott9zCl7/8Zd7znvcc0/NKkiRJkoaeo4Y3LUk71TGHNw2NhPrG3iCn4thm1o50IzLgOZ6TNidLjJHrr7+eD3zgA4dc+9WvfsVdd93Ft771LX72s5/xd3/3d8/rufu2b5WVlZHP5wGO6QRPt+uuu44bb7zxkCCmqamJCy64oKc165JLLuHRRx+loqKCiooKpk+fDsDVV1/NN77xjUO+15GeV5IkSZI0uPSENy19Tts8n/CmcSJh7vyDwpskwDG8OXFGZMAzmFx44YW84x3v4MYbb6ShoYGWlhYOHDhAVVUV6XSaq6++mlmzZvH+978fgLFjx7J///4X9D2f6wTPunXrmD17NgA///nPmTNnDgArV67ku9/9Lp/5zGe45JJL+PrXv86BAweoqKjg97//Pe95z3toampi9erVtLS00NDQwH333cfcuXOP+rySJEmSpNI4NLzpHl78HOFNdW0S2BjeDBoGPCV2+umn85d/+Zdcf/31xBgpLy/nU5/6FGVlZfzVX/0VMUZCCPzP/5lM/c5kMvz1X/91z5Dlz3zmM0ecwXO8br31VjZs2EAqlWLatGncdtttAGzatImqqiogGar81re+lauuuopUKsXy5cu5+OKLAXjf+97HK1/5SioqKpg6dSqf+9znjvq8kiRJkqQT74jhTZ/hxYY3w4dr0nXMPvrRj3LDDTcwb968Af2+Q+nPzlWX0snn+0w6+XyfSQPD95peiOcOb5qh7TDdH93hTX0xsCkOKh6u4c1weJ+5Jl0n3Mc//vFSlyBJkiRJw17MtScbpVqPM7zpPnnTE96ML4Y6wyu8UX8GPJIkSZIkDZD+4U3zYTdPGd7oeIyYgGeYtqKNCP7ZSZIkSRoKDhveHLR56sjhTaPhjV6QERPwpFIp8vk85eUj5iUPC/l8nlQqVeoyJEmSJI1wJyS8mTe/d86N4Y1OsBGTdlRVVdHe3k4ulyOE55xNpEEgxkgqlerZ3CVJkiRJJ0PM52F3C+zckYQ3LTuS8Kb4Oy07jrJt6uDwpnvblOGNBtaICXhCCIwaNarUZUiSJEmSBlCMEfbuTk7YHCnA2d0CB4+GGD02aZVqGE+Yc1oS3jSMN7zRoDViAh5JkiRJ0vAT29uKp2yKgc1hghzynf0fVF4BDeOhoZFwxtm9QU59I4wbn5zCqfKAgIYWAx5JkiRJ0qAU851QnHHTt10qdrdNHW7uTUhBXUMS3syYA2dfkHxcDHRoGA9jaxzdoWHHgEeSJEmSNOBioQD7dvcJbQ6ee9MMe1oPbZ0aU50ENT1zb8b3CXDGQ209weU6GoH8u16SJEmSdMLFA2294U3rDtjZDK19T9/sPLR1qrKyN7BZcE4S2NQ3EsaN7/162iUs0uEY8EiSJEmSnpee1qmeEzfF0zd9594cOEzrVH1DEtjMnAvnvjiZe9PdNlU/HsZW2zolHScDHkmSJElSj1goJFunDmqZ6hlg3LID9uw6tHVqbE3SOjV+EmHegt5hxd0BTm0DoaysNC9KGgEMeCRJkiRpBIlt+3uCmp52qb4BTmsz5PP9H1SZ7t06tXBxsjJ8XHHrVHcbVTpdmhckCTDgkSRJkqRhI3Z29oQ0ceeOQ4Oc1mY40Nb/QakU1I1L2qVmzYNFS3qHFnevDR891tYpaZAz4JEkSZKkISAWCklrVDGo6Q5w+q4PZ8+uQx9YXZsENRMmE047s/ckTneAU1dPSNk6JQ11BjySJEmSVGIxxmQoccuhJ256ApzWndB1UOtUuqq3RWrarCSw6Te4eByh0tYpaSQw4JEkSZKkkyx2dhTbpXoDmz1te+na8ix0t1K1H+j/oLKyYutUI+GU05IBxg3jCcV14TSMh9FjbJ2SBBjwSJIkSdILEgtdsHtX78mb1v7bp2jZkWylOkiutj4JcCZNIZxx9qFzb2rqbJ2SdMwMeCRJkiTpCGKM0Lb/oE1TO2BnM7EY5LBrJ3R19X9gelRyymbceML02f3n3jQ0Qn0j45sm09zcXJoXJmnYMeCRJEmSNGLFjlwy2+bguTd9NlCRa+//oLJyqC+2Ts0949C5Nw2NMMrWKUkDy4BHkiRJ0rAUC12wq/WQTVP9VoYfpnWK2voktGmaRph/TjLAeNz4niAnaZ1KDfwLkqSjMOCRJEmSNOTEGGH/3t7QprW5Z1hxT4CzaycUCv0fOGp079apmXN7Bxd3n76pG0eoqCjJa5KkF8KAR5IkSdKgE3O5ww4rjt1tUy3N0JHr/6Dy8t52qXkLDjv3JoweU5oXJEknmQGPJEmSpAEVu7pgd0v/dqmeAcbFz/ft7f+gEKCmPglqpswgLFgM4xqLK8OLAU51ra1TkkYsAx5JkiRJJ0yMMQlnWnccOcBpbYF4cOvUmN52qVnzelaFJwFOI9SPI5TbOiVJR2LAI0mSJOmYxVx7n2HFxVap1u4gJ/mYjo7+Dyqv6G2ROnVh/9apYoATRo0uzQuSpGHCgEeSJEkSADGfL7ZOHWbuTffa8P2HaZ2qrU9O3kydCWedlwQ53W1TDeOT1ilXhkvSSWXAI0mSJI0ASevUnv7tUgcHOLtbD22dGj22t3Vqzmm9G6i6A5y6BlunJGkQMOCRJEmShoHYfuDQWTc7+2ydat0JnYdrnSq2SJ1xdm+QU5x/Q30joWpUaV6QJOl5MeCRJEmShoi4fy9s20zcvhm2bYHtm4nbNsOOrdC2r//NIZW0To0bT5h+Cpx9Qf+V4Q3jYWyNrVOSNEwY8EiSJEmDSGzbB9u2FEOczUmIs31L8nHfECeEJKSZOJkw60JomNA/wKltIJT7474kjRT+E1+SJEkaYPFAW+/pm+JpnLi9+PG+PkOMQ0jWhU+cTDjvpTBhMmFCE0ycDI2TCBXOvpEkJQx4JEmSpJMgtrfB9i3EYitVT2vV9i2wd3f/m+sbYUIT4dyX9IY4EybDhEmEisrSvABJ0pBiwCNJkiQdp5hrTwKbPqdx4rYtsGNLspGqr7qGJLw5+0UwvokwsRjijG8ipNOleQGSpGHDgEeSJEk6ipjLJYFNd3izvc9JnF0t/W+urU9O4ixYlPw+cXLxJE4TIV1VmhcgSRoRDHgkSZI04sXODti+tTe82VYcbLx9S7JuvK/q2mQmzhnnQLGVKjmN00SoGl2aFyBJGvEMeCRJkjQixM5OaN7ab814z0mc1maIsffmsTVJiHPqQpjYHeIU26lGjyndi5Ak6QgMeCRJkjRsxHwnNG/rt5WqZ8V4SzPEQu/NY6qTUzdzz0jaqCZOJnS3U40ZW7oXIUnScTDgkSRJ0pAS83nYub3/YOPudqrm7f1DnFFjksDmlNPgxZNhYlMS4kycTBhTXboXIUnSCWbAI0mSpEEndnX1CXGSrVTdYQ7N26DQJ8SpGpW0UM2cC+df1NtONWEyjK0mhFCy1yFJ0kAx4JEkSVJJxEIX7NwB27cUT+B0n8jZkoQ4Xfnem9NVyUmcabNh8Uv7DDaeDNW1hjiSpBHPgEeSJEknTSwUkgHGPVup+szEad4K+T4hTmU62Uo1ZQbh3AuSEKfYTkVNnSGOJElHYcAjSZKkFyQWCrBrZ/EkTp/tVNs2w46tkO/svbmiMglxmqYSzjq/d7DxxCaobTDEkSTpOBnwSJIk6TnFGGFXS58QZ3PvivEdW6Cjo/fm8goYPykJbxYu7h1sPGEy1DUQUqnSvRBJkoYpAx5JkiT1iO1tdDz+MIUn/9Q74Lg7yOnI9d5YXg6NxRDnjLP7DDZugvpGQxxJkgaYAY8kSdIIFvfvhTWPE9c8RnzyMdj4FK3dG6rKypIQZ0IT4bQzewcbj2+CceMJqbLSFi9JknoY8EiSJI0gcXcrFMOcuOYx2PQ0xJicyJk1j3Dlq6k993z2jKqGcRMIZYY4kiQNBQY8kiRJw1jcuYP45KqeUIdtm5ILlWmYczph0RLCvPlJuFNRCUC6sZHQ3FzCqiVJ0vNlwCNJkjRMxBiT4cdrHoPuEzo7tycXR42BuWcQLlxOmDsfpp9CKPdHQUmShgv/rS5JkjRExUIBNm9MgpwnViW/79mVXKyuhbnzCcuvTU7oTJnuzBxJkoYxAx5JkqQhInZ1wcZ1xDWrknarNY9D277kYn0j4fSzYN58wtwFMGkKIYTSFixJkgaMAY8kSdIgFTs7YcMa4pPF0zlrV0PuQHJxQhPhnAtg3oLkhM64CQY6kiSNYAY8kiRJg0TMtcNTq3tXlq97AvKdycUpMwgvvqR4QucMQt240hYrSZIGFQMeSZKkEolt+2Dtn3pXlj+9Frq6IKRg+mzCxS8jnDof5pxBGFtT6nIlSdIgZsAjSZI0QOLe3T3ryuOTq+DZDRAjlJXDrLmEy1+ZtFudcjph1OhSlytJkoYQAx5JkqSTJLY0919ZvuWZ5EJlJcw+jfBnr00CnVmnEtLp0hYrSZKGNAMeSZKkEyDGCDu29gY6T66C5m3JxapRSZvViy9NAp0ZpxDKK0pbsCRJGlYMeCRJko5DjBE2P0Ncs6r3hM6uluTi2GqYO59w2Z8lK8unzSSkykpbsCRJGtYMeCRJko5BLHRub/IbAAAgAElEQVTBMxuIa1YlG67WPA779iQX6xoIc+f3riyfNJWQSpW2YEmSNKIY8EiSJB1GzHfChrW9K8uf+hMcaEsujp9EOPO84sry+cnnIZS2YEmSNKIZ8EiSJAExl4P1T/SuLF+3Gjo6kotN0wjnXdQT6ISGxtIWK0mSdBADHkmSNCLFA23w1J+ITxZbrjasha48hADTZhEuvCJpt5pzBqGmrtTlSpIkHZUBjyRJGhHivj2w5vHeEzob10EsQFkZzJhDWHZNMdA5nTB6bKnLlSRJel4MeCRJ0rAUd+0krnm8d8PVpqeTCxWVMPtUwsszSaAz+1RCuqq0xUqSJL1ABjySJGnIizFC87YkyOkOdLZvSS6mR8Gc0wjnXUiYtwBmziVUVJS2YEmSpBPMgEeSJA05MUbYuom4ZlVvoNPSnFwcPTYZhrz0quSEzrTZhLKy0hYsSZJ0khnwSJKkQS8WumDTxt6ByGseg727k4s1dcnJnCuLK8snTyekUqUtWJIkaYAZ8EiSpEEn5vOw8SnimseSQGft49C2P7k4bgJh/rnJKZ15C2BCEyGE0hYsSZJUYgY8kiSp5GJnB6x/Mtlw9eQqeGo1dOSSi5OmEBYtSQKdufMJ4yaUtlhJkqRByIBHkiQNuNh+AJ5aXVxZvgrWPwn5PIQAU2YQlixL5ufMm0+oqS91uZIkSYOeAY8kSTrp4v59sPbxYqDzGDy9FgoFSKVgxhzCpVcngc6c0wljqktdriRJ0pBjwCNJkk64mM8ngc4jDxL/9EfY9DTECOXlMGse4cpXJ4HOKacSqkaXulxJkqQhz4BHkiSdEHHvbuKjD8GjK4mP/RccaEsCnbnzCde8Pgl0Zs0jVFSWulRJkqRhx4BHkiQdlxgjbNpA/OODxEdXwronklM6tfWERUsIZ54Hp59FqBpV6lIlSZKGPQMeSZJ0zGJHDlY/Qnx0JfGRB6GlObkwYw7hz15LOOs8mDabkEqVtlBJkqQRxoBHkiQdVWxp7g10Vv8ROjogXQVnnJ2EOgsXE+oaSl2mJEnSiGbAI0mS+omFLli/hvjISuKjD8Iz65MLjRMJL708ab2at4BQUVHaQiVJktTDgEeSJBEPtMHjf0jm6ax6CPbuTlaYzzmd8Oo3ExYuhqZphBBKXaokSZIOw4BHkqQRKm7bnKwxf+RBWPMYdHXB6LGEBYvgzMWEBecSxlSXukxJkiQdAwMeSZJGiJjPw9rHi6HOSti2KbkweTph+bVJ69XsUwllZaUtVJIkSc+bAY8kScNY3Lub+OhD8MiDxMf/AAfaoLwcTjuTcOnLkwHJ4yeVukxJkiS9QAY8kiQNIzFGeHZDckrn0ZWw7gmIEWobCItfSjhzMZx2FqFqVKlLlSRJ0glkwCNJ0hAXO3Kw+pHe1qvW5uTCzLmEq1+XhDrTZhNSqdIWKkmSpJPGgEeSpCEotuxI1pg/8iA88Qh0dEC6Cs44m3DN65LWq9r6UpcpSZKkAWLAI0nSEBALXbB+TW+o8+z65ELjRMKFVySndOYuIFRUlLZQSZIklYQBjyRJg1Rs2w+P/yFpvVr1X7B3N6RSMOcMwqvfnGy9mjSVEEKpS5UkSVKJDVjAk8lkbgZuBCLwKPAW4KvAUmB38bY3Z7PZhzOZzKuAvwFagGuz2ezOTCZzCvDJbDZ7/UDVLEnSQItbNxEfLZ7SWfMYdHXBmGrCgnPhzPMI888ljBlb6jIlSZI0yAxIwJPJZKYA7wPOyGazBzKZTBZ4bfHy+7PZ7L8e9JD3AucB1wGvB74I3Ap8eCDqlSRpoMR8J6x5vLf1avvm5MKUGYTLryUsPA9mn0ooKyttoZIkSRrUBrJFqxwYlclkOoHRwOaj3FsA0sX7OjOZzIXA1mw2u+bklylJ0skV9+4mPvoQPPIg8fE/wIE2KK+A0xYSll2dDEhunFjqMiVJkjSEhBjjgHyjTCbzF8AngAPAL7LZ7A2ZTOZbwIuBHPBr4IPZbDaXyWSWA58iCYHeAPwAeG02m205yvO/A3gHQDabXdTR0XEyX450WOXl5eTz+VKXIQ1rQ/F9FmMkv2EtuZW/o2Pl7+hc8zjESKq+kfTil1C5eAnpMxcTqkaVulQJGJrvM2ko8r0mnXzD4X1WWVkJ8JxDFwck4MlkMvXAD4HrgV0kgc2/koQ6W4FK4B+Bp7LZ7N8c9Ng3AQ3A74G/BlqBv8hms21H+ZZx8+ajHRCSTo7Gxkaam5tLXYY0rA2V91nM5WD1I8mA5EdXQmux5plzCWeelwxInj7bAckalIbK+0wa6nyvSSffcHifTZ48GY4h4BmoFq1lwPpsNrsDIJPJ/D/gJdls9jvF67lMJvNNkgCnRyaTGQ28GbgC+AnJTJ5XAzcAXx+Y0iVJOjaxZUfvLJ3Vj0BnB6RHwfyzCa94PWHBIkJtfanLlCRJ0jA0UAHPRuCCYmBzALgMWJnJZJqy2eyWTCYTgGuBVQc97v3AF7LZbGcmkxlFsoGrQDKbR5KkkoqFLli/Jjml88iD8OyG5ML4SYSLriCcuRjmLiBUVJS0TkmSJA1/AxLwZLPZ+zOZzL8C/wXkgT+QtGStyGQy40mOGj0M3NT9mEwmMxk4P5vNfrz4pS8CD5K0eF07EHVLknSw2LYfHv9DsfXqIdi3B1IpmHMG4dVvSVqvJk2x9UqSJEkDasCGLA8wZ/CoJIZDf6c02JXifRa3buo9pbP2cejqgjHVhIWLYOFiwvxzCWPGDmhN0snkv8+kgeF7TTr5hsP7bLDN4JEkaciI+U5Y83jvPJ3txf9pMGUG4fJrk1M6s08lpMpKW6gkSZJUZMAjSRIQ9+wirnooCXQe+wO0H4DyCjjtTMKyawhnLiaMm1DqMiVJkqTDMuCRJI1IMUZ4Zn3vGvP1T0KMUNdAOO/C5JTO6WcR0lWlLlWSJEl6TgY8kqQRI+ZysPqR3lCntdiPPWse4ZrXJaHOtNkOSJYkSdKQY8AjSRrW4s4dxEcfJD6yElY/Ap0dkB4F888hvOIGwsJzCTX1pS5TkiRJekEMeCRJw0osdMH6Nb1br57dkFwYP4lw0RXJKZ258wkVFSWtU5IkSTqRDHgkSUNebNtPfOwP8MiDxFUPwb49kEolQc5r3kJYeB5MmmLrlSRJkoYtAx5J0pAUt27qPaWz9nHo6oKx1YQFi+DM8wjzzyGMHlvqMiVJkqQBYcAjSRoSYoyw9k/s/dEf6Lr/Xti+JbkwZQbh8lcmrVez5xFSZaUtVJIkSSoBAx5J0qAWD7QRf/8b4t0rYPNG2ioq4dSFhGWvIJy5mDBuQqlLlCRJkkrOgEeSNCjFjeuI96wg3n8P5NphxhzCf3sv46+8lp379pe6PEmSJGlQMeCRJA0asbODuPJ3xHtWwFOroaKScP6FhKUvI8yaC0CoGgUGPJIkSVI/BjySpJKL27cQ772T+Ltfwb69MHEKIfM2wksuJYypLnV5kiRJ0qBnwCNJKolY6IJHVlK4ZwWs+q9krfnZLyJ18cvgtDNdaS5JkiQ9DwY8kqQBFXe3En/7S+K9d0JLM9Q1EK5+HeHCywn140pdniRJkjQkGfBIkk66GCM8+Rjx7p8R//Cf0NUFp59F6vob4czzCeX+60iSJEl6IfyJWpJ00sS2/cT//E0yNHnLMzB6LOGSPyMsvZIwaUqpy5MkSZKGDQMeSdIJFzc+Rby7uOK8Iwcz5xLe/D7C4gsJ6XSpy5MkSdIw0tkV2dvRxZ72PHtyXezNdbGn+GvGhDwXTBwZ0cfIeJWSpJMudnYQH/wt8e6fwfonobKScP5SwsVXEWbMKXV5kiRJGgK6CpF9Hb0BTU9g097Fnlz+0K/numjrLBzx+V48s4sLJk4cwFdQOgY8kqQXJG7fTLznTuLvfg3798KkKYTrbyS8+FLCmLGlLk+SJEklEmNkf2eBvbkudh8U0PQ9ZZOEN13szeXZ11EgHuH5qsoDNekyqtPl1KTLmFxdSU26rPi1MmqqyoqfJ9fHVpbRNHE8zc3NA/q6S8WAR5L0vMWuLnj0QQq/WQGP/wHKypIV50uvcsW5JEnSMBRjpD0fe0KawwU03SFN31M2hSOkNeWp0BPO1KTLmFWfpiY9+pCQpqYY3FRXlpEuTw3six5iDHgkSccs7moh/vYXxHt/Aa3NUDeOcM3rCRcuJ9S54lySJGmo6OgqHCacOUIbVPGeziOkNalAcoKm+GtKTSWnp8v7fa2mzwmb6nQZo8pT/k/BE8yAR5J0VDFGeOLRZGjyw79PVpyfcQ6p170DzjyPUFZW6hIlSZJGtHwh9jlRk+8JbvqdsjnohE17/kiNUFBdmeppgxo/poJTGqp626DSh56wGV2ZImVYU3IGPJKkw4pt+5IV53evgK3PJivOL7uacNGVhImTS12eJEnSsFSIkX0dBfbk8uxtPzSg6RvS7C6GOPuPMmR4VHmK2qoknKmrKmN6bWVvQFN1cGiTzK0pSxnWDEUGPJKkfuLTTxHv/hnxgXuTFeez5hHe8heExS8lVLriXJIk6VjFGGnrLBxmsHD+MK1Rya99HUeeW1NZ1n9uzcRxlVRXHdQG1XfocLqMijLn1owUBjySJGJHjrjyt8lpnfVPQmWa8KKlhKVXEWacUuryJEmSSi7GSK4r9glmDjNsuDuw6bMxquuIQ4bpaYOqSZcxoy59aBtUVXm/0MYhwzoaAx5JGsHits3Ee1YkK87b9sGkqYTXvoPw4osJo11xLkmSRqZcvsDG3TnWt+ZY39rOhtYcT+/KHbEVKhWgurI3nGmqqeDUdFXPnJrDDRt2yLBONAMeSRphYlcX/PEBCvesgMcfhrIywjkvJlx8Fcxb4A8akiRpxIgx0nIgz4bWYpizKwlzNu/t6GmTqipPMbMuzUUzaxg/pqLfNqjuAGeMQ4Y1CBjwSNIIEXftJN73S+K9P4ddO6GhkfCKGwgvXU6oayh1eZIkSSdVZ1dk057eUznrd+XY0JpjT66r554JY8qZWV/FS6ZXM7u+ipn1aSaOrTC80ZBgwCNJw1iMEVY/QuHuFfDw76FQgPnnkLrhJli42BXnkiRpWNqT62JDa3tvi9WuHM/szpEvdlhVpALT69KcP3UsM+vSzK6vYkZ9mrGV/mykocuAR5KGobh/H/E/f028507YugnGVBOWvYKw9ArCBFecS5Kk4aGrENmyr6O3xao4L2fngXzPPfVVZcysr+KcpjHMKp7KmVJd6SpwDTsGPJI0jMQNa4h3ryA+eC90dMDsUwlvvZmweAmhorLU5UmSJB23ts4unm7Nsa41x4Zdyemcjbty5IprqlIBptWkWTBxNDPr0z0tVnVV/mevRgb/TpekIS7mcsSV9yUrzjesgXQV4YJLkhXn02eXujxJkqTnJcbI9v2dhww+3rqvs+eesZUpZtZXcfmcOmbVp5lVX8W02koqylwjrpHLgEeShqi4dRPxnjuJ//EraNsPTdMIr3tHEu6MHlPq8iRJkp5T33Xk3TNz+q4jD0BTdQWzG6q4bHZtT4tV4+hyN39KBzHgkaQhJObzvSvO//RHKCsnnFtccT53vj/oSJKkQSnGSGt7Mvh4XZ8wp/868sCMuiounFnTcypnem2aURWeypGOhQGPJA0BsXUn8b6fE+/7BexqgYbxhGvfQLhwOaGmvtTlSZIk9cgXIs/uzrFhV//Bx7v7rCMfP7p3HXl3mOM6cumFMeCRpEEqFgrJivN7VsDD90OMMP9cUm94NyxcREi5xlOSJJXW3lxXzxry9cVTOc/s7iBfPJaTrCOvZPGUsT1Bzsy6NGPT/hwjnWgGPJI0yMT9+4j/8etkaPL2zTC2hrD8WsLSKwnjJ5W6PEmSNAJ1FSJb93X2b7HalWNnW+868ro+68hn1iVhzpQa15FLA8WAR5IGibh+DfGenxEfuA86O+CU0whXX09Y5IpzSZI0cNo6u3h6V653i1VrO08ftI58ak0lCyYk68hn1Vcxqy5N3Sj/81IqJd+BklRCMZcjPnAP8Z474em1yYrzF19KuPgqwrRZpS5PkiQNYzFGduzP96wh726x6ruOfExlill1aS6fU9cT5kyrraTSdeTSoGPAI0klELc8S7xnBfE/70pWnE+ZQXj9TYQLLiaMGl3q8iRJ0jDT0VVg464ONuzqbbHasCvH/o7edeST+qwj7w5zXEcuDR0GPJI0QJIV5/dTuHsFrH4kWXG+6CWEpVfB3DP84UmSJJ0QrQfyPZur1rfmWL+rnU17Dl5HnubCGTU9s3Jm1LmOXBrqDHgk6SSLLc3E+36RrDjf3QLjJhBe+UbCS5e54lySJB23fCGyaU9HT2tV9+Dj3e2968gbR5czqz7Ni6dVJ6dy6qqYVO06cmk4MuCRpJMgFgrwpz8mp3UeeSBZcb5gEamL/xwWnOuKc0mS9Lzsy3X1zMrpbrHa2GcdeXkqML22ksWTk3XkM+vTzKyrotp15NKIYcAjSSdQ3LcnWXF+z52wfUuy4vyKVxIuvMIV55Ik6TkVYmTr3s5DBh8391lHXltVxqy6NFefWt8zK2dKTSXlriOXRjQDHkl6gWKMsP5J4t0riCt/m6w4n3MG4ZrXE859CaGiotQlSpKkQaito4vVOw4k83J29a4jb8/3riOfUlPJGRNGM6su3RPm1LuOXNJh+E8GSTpOMddOfOBe4t0rYONTkB5FWHIZYelVhKkzS12eJEkaJLoKkc17O3h6V46nd+XYuDv5feveTopzjxlTkWJmfZplp9QlLVZ1VUyvcx25pGNnwCNJz1Pc8kxyWuc/fwMHiivOb3gX4YKlhCpXnEuSNFLFGNmxP58EObtzbCwGOs/u6Z2VkwrQVF3JzLoqXj6/iQnpLmbVVTF+jOvIJb0wBjySdAxivpP4h/uJ96yAJx6F8nLCoiWEi6+CU073BzJJkkaY3e35Q07kbNzVwYF8oeeextHlzKhLc+7kMUyvTTOjLs3U2t5TOY2NjTQ3N5fqJUgaZgx4JOkoYssO4r0/J/72l7C7FRonEq77b8mK8+raUpcnSZJOsrbOLp7Z3VEMcHI9p3P6riKvTpcxoy7NpbNrmF6XBDnTa9OMqXSDlaSBY8AjSQeJhQI8/jCFe1bAHx8EIixcTOril8H8cwgpe+ElSRpuOrsKbNpTDHJ2d/D0rnae3tXB9v2dPfekywLT69KcN2Vsz4mcGXVp6qrKPM0rqeQMeCSpKO7bQ/zdr5M2rB1bobqWcOV1hIuuIDROLHV5kiTpBCjEyLZ9nT3tVd0tVpv3dNBVnHhcFmBqTZpTG6tYPqc2CXJq00wYW0HKIEfSIGXAI2lEizHCuid6V5znO2HefMK1byCc+2JCuSvOJUkaimKMtBzI9zuNs7EY5nR0JznApLEVTK9L86Kp1T0nciZXV1JRZpAjaWgx4JE0IsUYib+/m/jLf4dn1kPVKMKFy5MV51NmlLo8SZL0POzLdfUMOu4+kbNxV469Hb0Dj+uryphel+bKuXU9M3Km1aYZVWHrtaThwYBH0ogTc+3E//u/iQ/cA1NnEt7wbsKLlhKqRpW6NEmSdBS5fIFni3Ny+g493nkg33PP6IoU02vTvGR6TRLk1FUyozZNTZX/6SNpePOfcpJGlLh9C4Wv3Aabnk7asK56tUOTJUkaZLoKkS17O3o2VnUHOVv3dVIodldVpAJTaytZOGk0M2rTPdurGkeXO/BY0ohkwCNpxIiPPkThG/8LCKTe91HCgnNLXZIkSSNajJHmtnz/Ezm7czyzu4N8MclJBZg0tpIZdVVcNLN3DXnT2ErKUgY5ktTNgEfSsBcLBeLPssQffQ+mzCT17lsI4yeVuixJkkaU3e35PvNxOthQDHQO5Hvn5IwbXc7MujRnTxrD9Lo0M+vSTKmpJF3uaVtJei4GPJKGtdi2n8I/fRb++EAyZ+eN7yGk06UuS5KkYetAZ6FnyHHfFqtd7V0991RXpphRl+aS2TVMr02CnGl1acZWlpWwckka2gx4JA1bcdNGCl/+JOzcRnjtOwiXvtyefEmSTpDOrsimPbniGvLe7VXb9nX23JMuC0yvS7No8tieFeTT69LUV5X572RJOsEMeCQNS3Hlbyl86wuQriL1l7cS5s0vdUmSJA1JhRjZtq/zkBM5m/Z00FUceFwWYEpNJXPHVbFsdm1PkDNxbAUpgxxJGhAGPJKGldjVRfy3bxN//v/glNNI3fQ/CHXjSl2WJEmDXoyR1vau3iCnZ15Ojlx3kgNMHFvB9No050+tToKc2kqm1KSpKDPIkaRSMuCRNGzEvXsofP3v4U9/JFx8FeH6GwnlFaUuS5KkQWdfRxfP7Molg477zMvZ29E78LiuqozpdWkun1vXs4Z8Wm0loyuckyNJg5EBj6RhIT69lsKXb4M9uwhvfh+pJctKXZIkSSWXyxfYtKd3Y9XG3Umos7Mt33PPqPIU0+vSvGR6DdPrKplem8zKqa3yPxUkaSjxn9qShrzC735N/M6XoaaO1Ac/TZgxp9QlSZI0oLoKkS37kmHHyWmc5OOt+zooFLurylOBabWVLJgwunfgcW2a8WPKHXgsScOAAY+kISvmO4n/8g3i3Svg9LNIvf2vCdW1pS5LkqST6kBngQ272lnfmmNdS/L707tydBaTnAA0VVcwoy7NhTOre9qrJldXUpYyyJGk4cqAR9KQFFt3Uvjap+Gp1YQrriO88o2EMmcCSJKGl13t+Z4QZ11r8vvmPR10jzyurkwxq6GKl82rY2Z9FTPq0kytqSRdnipp3ZKkgWfAI2nIiU8+loQ7uXZS7/wAYfFLS12SJEkvSPcq8nWt7axv6Q1zWg70zsqZMKacWfVVXDSjhlkNaWbXV9E42vYqSVLCgEfSkBFjJN71E+IP/gnGTST1l7cSpkwvdVmSJD0vnV2RZ3b3hjjrWtrZsCtHW2eywSoVYFpNmjMnjWZ2fRWz6tPMqq+iOu1JVUnSkRnwSBoSYi5H/M7/Jv7+bjjrfFJvvZkwekypy5Ik6ajaOrtY35pjfWs764onc57ZnSNf3EaeLgvMrK9i6cwaZjckYc702rQtVpKk582AR9KgF3dsTVagb9pAeMUNhJe9hpDyB19J0uDScqB7Xk4764onc7bu6+y5XpsuY1ZDFec0jWFWfRWzG9I0jXXwsSTpxDDgkTSoxVUPUfj6PwCR1Hv/P8LCRaUuSZI0whViZMvezn5hzvrWdna1d/XcM2lsBbPqq7hsdm3PyZyGUc7LkSSdPAY8kgalWCgQV/wr8Y5/hikzSL3rFsKEplKXJUkaYTq7Cjy9q6M4Lydps9qwq532fLLHqizA9Lo0504ey+z6ZPDxzPo0YyqdlyNJGlgGPJIGnXigjcI/fQ4e/j3h/KWEN/05IV1V6rIkScPcvo4u1vcZfLyuNcezu3N0FXeSV5WnmF2f5rJT6nrCnGm1lVSU2TYsSSo9Ax5Jg0rc8gyFL38Stm8hXH8j4bKrPc4uSTqhYozs7JmXkww+XteSY/v+3nk59VVlzG6o4rwpxZM5DVVMHFtByn8nSZIGKQMeSYNG/K//oPBPn4fKymQF+qkLSl2SJGmI6ypENu/t6BfmrG/NsSfXOy9ncnUFc8dVccXc5GTOrPoq6kf5Y7IkaWjx31ySSi4Wuoj//h3iih/CrHmkbvogoaGx1GVJkoaYXL7A07t6Q5x1Le1s2JWjo9hjVZ4KzKir5PypY5ldX8Xs+jQz6tOMrnBejiRp6DPgkVRScd8eCl//X/D4w4SLriS89u2EiopSlyVJGuT25LqKQ497T+Zs2tNBoTgvZ0xFiln16eKpnCTMmVqbptyV5JKkYcqAR/r/2bvvODvrOu//r+tMzfRJJm3SqSGQEJLQRCD0gApSvERULKzKWnZ1dXX77r3eq66r6723v3tVEPtaLgl2E0AgFBFJo3dIAskkmdTp/Xx/f5whBAQygZm5zsy8no9HHiQnE/POw7kg5z2f7+er1IRNT5P92uehaTfRlR8lc+q5aUeSJOWZEAI72npze3L2m8zZ2d6772MmjCvkkPElnDyjMlfmjC9hUnmRO9wkSWOKBY+kVGTvvoXwg69BRRWZT/870ZzD044kSUpZXzawubm7/warXJmzYU8nrd1ZACJgWlUx8yaWMWd87harObUlVJf6V1pJkvyvoaRhFXp7CMl1hNt+C0fOJ/PBvyaqqkk7liRpmHX2Ztm47warXJmzaW8XPf1nrIoLImbVlHDKzCrm9N9iNaumhNJCrySXJOnlWPBIGjZh7y6yX/93ePoxonMvJrrkSqICF1tK0mi3t7N339Gq5ydzGpq76V+XQ0VxhkNqS3nTkbW5Mqe2lGlVxRS4L0eSpAGz4JE0LMKTj5D9xr9DZwfRB/+azPGnph1JkjTIQghsa+3pX36cO171zJ4udne8sC9nUnkhc2pLOW3WC5M5dWWF7suRJOl1suCRNKRCCIRVvyX85JswYRKZT/wr0bRZaceSJL1OPX2B55peKHE29E/mtPfk9uVkIphRVcKCyWUcMj63K2dObSmVJU5uSpI0FCx4JA2Z0N1F+MF/E/5wGyw4nsxVnyAqq0g7liTpILX39O23LydX5jzb1E1v/76ckoKI2bWlnD67al+ZM7O6hBL35UiSNGwseCQNibBze+4K9Oc2EF14BdGbYqKMf9GXpHwWQmB3Ry9PbtzNfRt37pvM2drSs+9jqkoKOKS2hAvn1jKntpRDakuYWum+HEmS0mbBI2nQhUfWk73mS5DNkvnoPxAtOD7tSJKkl+jszfLs3tzNVRv7v23a00lL/5XkAFMqiphTW8KZc6r3TeaMH+e+HEmS8pEFj6RBE0IgrFxO+NkPoH4GmQ//LdGk+rRjSdKYlg2B7a09/QVOf5GzNzeV8/wtVqWFETOrSzh5ZiWza0pZMGsS4zOdlBe7L0eSpJHCgkfSoAid7WS//V+w7g9Ex59K9J6PEZWUph1LknYlqtMAACAASURBVMaU1q6+/SZyOtm4p4tnm7ro7M1VOREwtbKIWTWlnD67mlm1JcyuKWFyRRGZ/aZy6uqq2bmz5xV+F0mSlI8seCS9bmHrZrL//TlobCCKryI6+0LH9yVpCPVmA1uau9m4p/NFR6x2tb9wHXllcYZZtaWcfWgNs2pyRc7MmhJKXXwsSdKoZMEj6XUJ6+8h+62vQFFx7gr0uQvSjiRJo0YIgT2dfWzc07nviNWmpi6ea+qit39VTmEGplWVcMykMmbXlDC7toRZNe7KkSRprLHgkfSahGwf4Rc/JPz2pzD7cDJ//jdE4yemHUuSRqyu3izPNvUvPd7zwlROS1ffvo+ZMK6Q2bUlHDe1fN9UzrSqEooKLHIkSRrrLHgkHbTQ2kz22i/DI+uJTj2X6B0fJCoqTjuWJI0I2RBo7F96vHHvC4XO1pbufUuPSwoiZtaUcNL0in0TObNqSqkqcemxJEl6eRY8kg5KePZpsv/9eWjaTfTuj5A57by0I0lS3mrt7ttX4GzqX3y8aW83nf3nqyJgSmURs2pKOG127gar2bV/uvRYkiTpQCx4JA1Y9p7bCN/7f1BRRebTXyCac0TakSQpL/RmAw3N3ftN5OR25uzcb+lxRXGG2TUlnHVoNbNrclM5M6tLGFfk0mNJkvT6WfBIOqDQ20v46bcIt/4ajjiGzIc+TVRVk3YsSRp2IQT2dvbljlftd4PVc03d9GZzB6wKIpheVcK855ce15Qwq7aECS49liRJQ8iCR9KrCk17yH793+GpR4jOuYjo0vcSFbgDQtLo19Wb5bmmbjbu3e8Gq71dNO239Hj8uEJm15SwcEo5s2tdeixJktJjwSPpFYWnHyP7tS9ARxvRBz5F5oTT0o4kSYMuGwI72nr225OT+7a1pZv+oRyKCyJm1ZRw/PSKfcerZteUUFXqX6UkSVJ+8G8lkv5ECIFw+wrCj78J4+vIfPyfiabPSTuWJL1ubc8vPd7v9qpNe7vo6F96DDClIrf0+I2zKvuPWJUyuaKIgoxTOZIkKX9Z8Eh6kdDdRfifrxPuvgXmLyFz1V8RlVekHUuSDkpfNrClpZtNe54vc3L7chrbXlh6XN6/9PjMQ6qY1X971YzqYsqKPIYqSZJGHgseSfuEXY25I1mbniJ6y+VEb76cKOPtLpLy296O3hcmcvZ2snFPbulxz35Lj6dVFTO3rozzDi/Zd8Sqrsylx5IkafSw4JEEQHjkPrLX/gf09ZH56D8QHXtC2pEk6UW6+/qXHvdfQf78UaumzheWHtf2Lz1eMKU8d7yqtoTpVcUUFVhWS5Kk0c2CRxrjQgiEG28g3PB9mDqdzIf/jmhyfdqxJI1hIQQa23peWHjcvyen4SVLj2dWl3D8tBeWHs+qKaHapceSJGmMGra/BcVx/Angz4AAPAi8D5gK/BiYAKwF3p0kSXccxx8DPgQ8C7y1/7U3ApcmSfKJ4cosjXahs53sd/4vrL2baMkbid7zMaLScWnHkjSGtPf07bcn54V/tvf86dLjN8ys7L+KvJQpLj2WJEl6kWEpeOI4ngb8BTAvSZKOOI4T4HLgAuArSZL8OI7jrwNXAV8D3gksAP4OOC+O418D/wi8YzjySmNB2LaZ7H9/HrZtIXrb+4jOeau7KCQNmb5sYGtL976JnOeLnMa2nn0fU16UYVZNCUvnVPVfQ17KzBqXHkuSJA3EcM4xFwLj4jjuAcqArcCZwBX9P/9d4F/IFTwRUNT/cT3Au4AVSZLsHsa80qgV7ruH7Lf+DxQUkvnE/yI66ti0I0kahTbs6WTVhmYe3N7Gs3tfWHqc6V96fGRdKecdVsPsWpceS5IkvV7DUvAkSbIljuMvkTty1QHcRO5I1t4kSZ6/r3QzMK3/+/8fcA/wMPB74BfAea/2e8Rx/EHgg/2/H3V1dYP9x5AOqLCwMK8/90JfH20/uY62n36HwsPmUvPpz1EwcUrasaSDku/P2Vi3o7WLmx7fwY2PNvL0rnYKMhEL66s4YXYdh9aVcWhdObNqyygpdOlxPvM5k4aHz5o09MbScxaFEIb8N4njuBZYDrwd2Av8FLge+JckSQ7r/5gZ5KZ0jnnJr/0n4AEgC1wJPAd8MkmSLK8sNDQ0DPqfQzqQuro6du7cmXaMlxXaWsh+88vw0DqiU84meufVREXFaceSDlo+P2djVUdPlj8818KqDU08sK2dABwxoZSlc6p546xKFx+PQD5n0vDwWZOG3mh4zurr6yF30ulVDdffuM4GNiRJsgMgjuMbgFOAmjiOC/uneKYDW/b/RXEc1wMnJEnyr3Ec307uSNc/AGcBNw9TdmnEC89tIPu1z8PunUTv/jDRqed5DELS69KXDdy/rY1VG5q557kWuvoCkyuKeNsxE1g6p5ppVRbIkiRJw2m4Cp5ngZPiOC4jd0TrLGANcBtwGbmbtN5D7ijW/j4L/FP/98eRu4ErS243j6QByP7xdsL3vgplFWT++nNEh85NO5KkESqEwIY9Xaza0MQdG5vZ09lHeXGGpXOqWTqniqMmjrM8liRJSslw7eD5YxzH1wPrgF5gPXAN8Bvgx3Ec/+/+1657/tfEcXxc/69d1//SD8ldr/4c8MXhyC2NZKG3l3D9twm3/AqOOJrMhz5NVFWbdixJI9DO9h5u39DMqg1NPNvUTWEGFtdXsHROFUumVVBc4D4dSZKktA3LDp4UuINHqciX852heQ/Zb3wRnniY6OwLiS59L1GhOzA0OuTLczbatff08YdnW/pvwcrt1Tmy7vm9OlVUlXh1+WjmcyYND581aeiNhucs33bwSBom4enHyH79C9DeSnTVX5E5aWnakSSNEH3ZwH1b+/fqbG6huy8wpaKIeP4Els6upt69OpIkSXnLgkcaJUIIhDtuJPzoGqidQOZv/oNoxpy0Y0nKcyEEntnTxW0bmrhzYzN7O/uoKM5w5iG5vTpz69yrI0mSNBJY8EijQOjpJvzwG4S7boZjFpH5s08SlVemHUtSHtvR1sPtG3N7dZ7r36uzZFoFS+dUs6S+nCL36kiSJI0oFjzSCBd27chdgb7pKaI3v53oLZcTZdyNIelPtff0cXf/Xp2H+vfqzK0bx9XHT+aNs6qodK+OJEnSiGXBI41g4dH7yV7zH9DXS+Yjf0+08MS0I0nKM7379uo08cfNrfv26lw+v47T51QxtdK9OpIkSaOBBY80AoUQCDf9nLD8uzBlGpkP/y3RlOlpx5KUJ0IIPLW7k1UbmrlzYzNNXX1UFmc465Bqls6p5si6UvfqSJIkjTIDKnjiOP5L4H+SJBnZd4tJo0Do7CB896uENXfB4jeQee9fEJWWpR1LUh5obO3h9o1NrNrQzObmbgozEcdPq+CMOVUsqq+gqMBSR5IkabQa6ATPmcC/xXG8Cvg+8PMkSbqGLJWklxW2N5D978/B1s1El72X6NyL/Sq8NMa1dT+/V6eJhxo7AJg3cRwfPmEKp8yspMK9OpIkSWPCgAqeJEkuiuN4AnA58HHg63EcLwe+lyTJHUMZUFJOuP9estf9JxQUkPn4vxDNW5h2JEkp6c0G1je0cduGJlZvye3Vqa8s4ooFdSydU8XkCvfqSJIkjTVRCOGgf1EcxwvITfIcAzwHXAv8V5IkrYMb7zULDQ0NaWfQGFRXV8fOnYN7kjFks4Rf/Zjw6x/DzENz+3YmTBrU30MaSYbiORsJnt+rc9uGZu56fq9OSQGnzqpk6ZxqjpjgXh0NnrH6nEnDzWdNGnqj4Tmrr68HOOBf9A5qyXIcx2cB7wIuAtYAXwSeBf4SWAGcerBBJb2y0Naam9p5cA3RG84ieufVRMUlaceSNIy2t3Zz+8ZmVm1oZktzN0WZiOOnV7B0ThWLprpXR5IkSTkDXbL8JXLHs5qA7wH/kCTJlv1+/h5gz5AklMaosHljbt/O7p25Yuf08/3qvDRGtO63V+fh/r06R08ax1uPmsIbZlZSUexeHUmSJL3YQCd4SoGLkyRZ/XI/mSRJTxzHSwYvljS2Ze+9g/Ddr8K4cjKf+jeiw45KO5KkIdbTF1i3tZVVG5pZvbmVnmxgWlUx7zy2jtNnu1dHkiRJr26gBc/ngfb9X4jjuBYYlyRJA0CSJI8NcjZpzAl9fYTl3yHc/As4bB6Zqz9DVF2bdixJQySEwBO7Olm1oYk7N7XQ0tVHVUkB5x5ewxlzqjhsvHt1JEmSNDADLXh+DryfFx/Dmg58EzhxsENJY1Fo3kv2mv+Axx8kOustRJe9j6jwoNZkSRohtrd2s2pDbq9OQ0tur84J0ys4Y041x9WXU5ix1JEkSdLBGei7xyOTJHlw/xeSJHkwjuO5Q5BJGnPCM4+T/fq/Q1sz0VWfIHPSGWlHkjTIWrv6+H3/Xp1HduT26hwzaRyXzMvt1Sl3r44kSZJeh4EWPI1xHB+WJMlTz78Qx/FhwK6hiSWNHdk7biT86BtQPZ7MZ75INPOQtCNJGiQ9fYF1Da3ctqGZ1Vta6c0GplcV8+5jJ3La7ComVRSlHVGSJEmjxEALnm8By+M4/nvgGeBQ4LPkjmhJeg1CTw/hR98g3HkTHH0cmQ98iqi8Mu1Ykl6nEAKP78zt1bnr2dxenerSAs4/vIalc6o5dHyJe3UkSZI06AZa8HwB6AG+BMwAniNX7vznEOWSRrWwe0fuSNaGJ4guiIkuegdRxuMZ0ki2taWb2zc0s2pjE1tbeiguiDhxegVL51SzcKp7dSRJkjS0BlTwJEmSBf6j/5uk1yE8/iDZb3wRerrJ/PnfEi06Oe1Ikl6jlq4+7tqUW5b82M4OIuCYyWVcdvQE3jCzkrIii1tJkiQNjwFf0RPHcTFwJFAH7PsyZJIktw5BLmnUCSEQbv4FYfl3YFI9mQ//HdHU6WnHknSQevqyrGloY9WGJtZsaaM3G5hRXcy7F07k9NlVTCx3r44kSZKG34AKnjiO3wj8FCgBqoBmoJLcUS03wkoHELo6Cd/9KmH1nbDoZDLv+0ui0rK0Y0kaoBACj+3sYNWGZu7a1Exrd5aa0gIuOCK3V+eQWvfqSJIkKV0DneD5CvDFJEm+EsfxniRJxsdx/E9A+xBmk0aF0NhA9r8/Dw3PEV1yJdGyS30jKI0QW1u6WbWhiVUbmtnWmturc9KMSs6YU8WxU8opcK+OJEmS8sRAC54jgP96yWtfADaQW7ws6WWEB1aT/eZ/QiZD5uP/TDTvuLQjSTqA5n17dZp4fGcnETB/Shlvn1/HSTMq3KsjSZKkvDTQgqeJ3NGsvcDWOI7nAbuAiqEKJo1kIZsl/CYh/OpHMGNObply3eS0Y0l6BT19WVZvaWXVhmbWNrTSm4VZ1SW8Z+FETptTRV2Ze3UkSZKU3wZa8NwAXAD8EPgWcBu5a9OvH6Jc0ogV2lvJXvcVeGA10clnEL3rw0TFJWnHkvQSIQQe3dG/V+fZZtq6s9SWFvCmI2pZOqeaOe7VkSRJ0ggy0GvSP77f978Ux/E95JYs3zhUwaSRqHfT02Q/9xnYtZ3oiquJlp7vG0QpzzQ0d3PbhiZu39jM9tYeSgoiTp5Ryenu1ZEkSdIIdsCCJ47jAuAJYF6SJF0ASZLcNdTBpJEmu/oudn/vq1BSSuZT/0Z02Ly0I0nq19zZy52bWli1oYkndnWSiWDB5DLeMb+Ok2ZUMq4ok3ZESZIk6XU5YMGTJElfHMd9QCnQNfSRpJEnbHqacM0XKZq7gL6r/oqoZnzakaQxr3v/vTpbWukLMLumhPceN5HTZlcxwb06kiRJGkUGuoPn/wBJHMefAzYD4fmfSJLkmaEIJo0kYcX1MK6cmn/8MrvbO9KOI41Z2RB4tLGD2zY0cfezLbT1ZKkdV8hb5o7njDlVzK4tTTuiJEmSNCQGWvD8f/3/POclrwfA+2I1poVtWwjr7iY6/zIyZeVgwSMNu83NXax6ppnbNzbT2NZDaWHESTMqOWNONfMnl7lXR5IkSaPeQJcsu5xAegXhpp9BYRHRWW9OO4o0pjR19nLnpmZWbWjmyf69OsdOKeedx+b26pQW+p8uSZIkjR0DneCR9DLCnl2Eu28lOvVcoqratONIo15Xb5ZbntjBrx7YzLqGNvoCzKkt4f2LJnHq7CrGj/M/a5IkSRqbBvQ34TiO72S/vTv7S5LktEFNJI0g4Xe/hJAlOvetaUeRRq2tLd2sa2hjbUMrD25vp7svMGFcIRcdNZ6lc6qZVVOSdkRJkiQpdQP9Uuc3X/LjKcBVwA8GN440coS2VsLtK4mWnEo0cUracaRRo6s3y8ON7axtaGNdQysNLT0ATK0s4pzDajh33jRmlPa4V0eSJEnaz0B38Hz3pa/Fcbwc+Dbwr4MdShoJwqrfQlcH0fmXpB1FGvEamrtZt7WVdQ1t+6Z0igsi5k8u401H1rK4voKplcUA1NXVsHPnzpQTS5IkSfnl9Swr2AIsGKwg0kgSuroIt/wK5i8hmj4n7TjSiNPVm+XB7e2sa2hlbUMb21pzUzr1lUWce1gNi+vLOXpSGSUuSpYkSZIGZKA7eN7/kpfKgEuAewY9kTQChLt/By1NZM6/LO0o0ogQQqChpWdfofNw4wtTOgsml3Hh3PEsqi/fN6UjSZIk6eAMdILn3S/5cRtwN/CVwY0j5b/Q20u48Wdw2FFEh89LO46Ut56f0lnbkDt69fyUzrSqYs47vIbF9RUcPWkcxQVO6UiSJEmv10B38Jwx1EGkkSKsuRN2NZJ5x4fSjiLllRACW5q7c8uRt7bx8PZ2erKBkoKIBVPKuOio8SyuL2dyhVM6kiRJ0mAb6BGtK4H7kiR5YL/XjgUWJEny/aEKJ+WbkM0SViyHabNg/uK040ip6+zN8sC2tv5rzNtobMtN6UyvKuaCI2pYVF/BPKd0JEmSpCE30CNanwUWvuS154BfAhY8GjseXAsNzxJd9QmijG9YNfaEENjc3N1f6LTycGMHvdlAaWHEginlXDIvt0vHKR1JkiRpeA204KkCml/yWhNQM7hxpPyWXXk9TJhEtOTUtKNIw6ajJ8sD23NTOusaWmls6wVgRnUxbz6ylkX15cybOI4ip3QkSZKk1Ay04HkEuBRI9nvtYuDRQU8k5anw5CPw1KNE7/ggUeFAHx1p5Akh8FxT977lyI/saKc3C6WFGY6dUsalR5ezaGoFkyqK0o4qSZIkqd9A36V+BvhtHMdvB54GDgPOAi4YqmBSvsmuuB4qq4lOOSftKNKga+/p44Ft7fumdHa056Z0ZlWX8JYjc8eujppYRlFBlHJSSZIkSS9noLdo3RXH8THAFcAM4F7gL5MkeW4ow0n5ImzeAA+uIXrru4hKStKOI71uIQQ27e1i3dbc0atH+6d0xhVmOHZqGfH8Co6bWs7Ecqd0JEmSpJFgoLdolQBbkyT5wn6vFcVxXJIkSdeQpZPyRFhxA5SMI1rq0JpGrvaePu7f2p47erW1jV3PT+nUlHDh3NyUztw6p3QkSZKkkWigR7RuBj4N3LPfa4uBLwBLBzmTlFfCjm2E1XcSnXMRUXlF2nGkAXt+Smdt/7GrR3d00BegrCi3S2fR/AoW1ZdTV+aUjiRJkjTSDbTgmQ/88SWv3QscO7hxpPwTbvo5FGSIzrkw7SjSAbV193H/tjbWNrSxvqGNXR25KZ05tSW89ajxLK6v4MiJ4yjMOKUjSZIkjSYDLXiagMnAtv1emwy0DXoiKY+E5j2E3/+O6OQziWompB1H+hMhBDbs6cotR97aymP9UzrlRRmOnVrO4vpyjptazgSndCRJkqRRbaAFz3Lgh3Ec/wXwDHAo8J+8+Np0adQJt/waenuIzr047SjSPq3dfdy/NTels25rG3v2m9K5eN4EFtWXc2SdUzqSJEnSWDLQgufvgS+TO5ZVAnQC3wb+bohySakLHe2E234Li04mmjIt7Tgaw56f0lnb0Mq6hjYe29lBNkB5cYaFU/qndOorGD9uoP9KlyRJkjTaDPSa9E7gI3EcfxSoA3YmSRLiOM4MaTopReGOldDRRub8y9KOojGotauP+/bt0mllT2cfAIeOL+HSeRNYXF/OEXXjKHBKR5IkSRIDn+ABIEmSAOyI43h+HMdXAu8E6ockmZSi0NNNuPkXMG8h0azD0o6jMSAbAs/s7mJdQytrG9p4YlduSqeiOMPCqeUsrq/guKnl1DqlI0mSJOllDPidQhzHE4ErgPeQuz3rLuAvhyiXlKrwh1uhaQ+Zq/4q7SgaxVq6+li/NXeF+fqtbezdN6VTymVH53bpHDHBKR1JkiRJB/aqBU8cx0XAhcB7gfOAp4AfAbOAtyVJ0jjUAaXhFrJ9hJU3wOzDYe6CtONoFMmGwNO7O1nXkDt69WT/lE5lcYbjplawqL6c4+rLqSl1SkeSJEnSwTnQu4jtQBb4DvDPSZKsA4jj+MNDnEtKTVj7B9ixjcxl7yWKnJzQ69Pc1cf6/uXI67e20dTVRwQcNqGUtx0zgcX1FRw2vtQpHUmSJEmvy4EKngeANwInAk/GcbwhSZI9Qx9LSkcIgbDyepgyDRaelHYcjUDZEHhq1/NTOq08uauTAFSWFHDc1P4br6aWU+2UjiRJkqRB9KrvMJIkWRrH8SzgSuBTwP+N4/gmoBwoGoZ80vB65D549hmi93yMKOMlcRqY5s5e1m1t2zel09w/pXP4hFLePn8Ci5zSkSRJkjTEDvgl5CRJNgGfBT4bx/EbyZU9WeD+OI6/lSTJp4c4ozRssiuuh5oJRCcuTTuK8lhfNvDU7k7W9h+9eqp/Sqe6pIBFU8tzu3SmllPllI4kSZKkYXKw16TfBdwVx/FfABeTK3ukUSE88zg8/iDR295PVOSAml5sb2cv6xv6p3S2tdHSP6VzRF0ply+oY3F9OYeOLyXj3iZJkiRJKXhNX15OkqST3G1aPxrcOFJ6siuWQ1kF0WnnpR1FeaAvG3hy1wtTOk/vfmFKZ3F9OYvrK1g4tZyqkoK0o0qSJEnSayt4pNEmbH0O7ruH6M2XE5WOSzuOUrK34/ldOq3ct7WNlu4smQiOmDCOKxbUsai+gkPGlzilI0mSJCnvWPBIQFh5AxQXE5355rSjaBj1ZQNP7OxgbUMb67a28vTuLgBqSgs4fnoFi6bmpnQqndKRJEmSlOcseDTmhd07CH9cRbT0AqLKqrTjaBiEELh9YzPfXb+D3R29ZCI4sm4c7zy2jsX1FcypdUpHkiRJ0sgyoIInjuNPJkny5Ze8FgHXJUny/iFJJg2TcPMvAIjOuSjlJBoOT+3q5No123lsZweHTyjlqsWTWDilnAqndCRJkiSNYAOd4LkyjuO9SZJcB/vKne8Dk4YsmTQMQmsz4Y4biU44jWiCn86jWVNnLz+4fwc3P9VEVWkBHztpCmceUu2kjiRJkqRRYaAFzzJgVRzHLcBycrdnlQNvGapg0nAIt/4GuruIzrs07SgaIn3ZwIon9/DDB3bS2ZPlLXNruXx+HeXFTuxIkiRJGj0GVPAkSbI1juPzgNuAjwE7gYuSJOkdynDSUApdnYRbfw3HnkA0bWbacTQEHtjWxrVrtvNsUzfHTinjz5ZMZmZ1SdqxJEmSJGnQvWLBE8fxy+3WuQG4AvgBuWNbJEnyraEKJw2lcOeN0NZC5vzL0o6iQdbY2sO31zdy97MtTCov4m9Pm8aJ0yuIPI4lSZIkaZR6tQmed7/C648Bl/d/PwAWPBpxQm8P4aZfwBHHEB06N+04GiRdvVl+9shulj+yC4B3LqjjoqPGU1KYSTmZJEmSJA2tVyx4kiQ5YziDSMMp/PEO2LOTzJUfSTuKBkEIgT8818K31zXS2NbLKTMred+iSUwsL0o7miRJkiQNi4EuWSaO40rgcGBLkiTbhy6SNLRCNktYuRymz4GjF6UdR6/Ts3u7uHbtdh7Y1s6smhL+99lTmT+5PO1YkiRJkjSsDljwxHFcBXwFOAl4GJgRx/F24F1JkrQOcT5p8N1/L2zbTPSBT7mTZQRr7e7jxw/s5DdP7KGsKMMHl0xm2eE1FGT8/1SSJEnS2POqBU8cx0XATcB3kyS5ar/XPwb8C/CpOI5PTpLkD0OaUhokIQSyK66HiVOIFp+Sdhy9Bn3ZwC3PNPH9+3bQ0tXHeYfX8M4FdVSVDnggUZIkSZJGnQO9I/oIcE+SJF+L4/jv9vv4EuBNcRx/BvhKHMf/kiTJyqEMKg2KJx6CDU8QvfPPiQoK0k6jg/TYjg6uWbOdp3d3Mm/iOD6wZDKHjC9NO5YkSZIkpe5AV8tcAfy//u+XAqcAO4AlwC+TJOkD/h74qyFLKA2i7IrroaqG6JSz0o6ig7C7o5ev3N3AZ27axJ6OXj55Sj2fO2em5Y4kSZIk9TvQBM+cJEme7P/+24DjkyRpjeP4B8AdwGf6//mTIcwoDYqw6Wl4eD3RJe8hKipOO44GoKcv8KvHd/OTB3fRmw1cdvQELjt6AuOKvPZckiRJkvZ3oIKnM47jCUmS7AIqgAlAK1AHTOz/mGKgZ+giSoMjrFwO48qITl+WdhQNwNotrXxzbSMNLd0cP62CqxZPYmqlxZwkSZIkvZwDFTy/B84FfgR8CbgrjuPfA28A/r3/Y84A7h2yhNIgCNsbCGvvJlp2MVGZV2jns60t3Vy3djurt7RRX1nMPy2dzuJpFWnHkiRJkqS8dqCC58vAd+M4/nWSJP8Vx/HNwNHA/0qS5NE4jsuBfwM+OtRBpdcj3PQzKCggOuvCtKPoFXT0ZPnpQzv5xWN7KMxEvOe4ibzlyPEUFXjtuSRJkiQdyKsWPEmSrI7j+GvAqjiO/zxJknuBRwDiOD4OuAb4fpIkdw59VOm1CXt3E+6+heiUs4mqa9OOo5cIIXDHxma+s34Huzt6OWNOFVceN4nx47z2XJIkSZIG6oDvoJIk+Wocxw8CX4jjeAawHZgMbAX+PkmSm4Y4o/S6hN/9EvqyROdeMd4nGAAAIABJREFUnHYUvcQzuzu5Zs12Ht3RwaHjS/nMqdOYO3Fc2rEkSZIkacQZ0JfIkyRZRW6KpwQYD+xOkqRrKINJgyG0txJuX0G05BSiSVPTjqN+zZ29/OD+ndz01F6qSgr46IlTOOvQajKRx7EkSZIk6bV41YInjuMy4B+AY4B1wOeTJNk6HMGkwRBu+y10dhAtuzTtKAL6soGVT+7lfx7YQUdPljcfWcvlC+qoKC5IO5okSZIkjWgHmuD5f8ASYAVwGblr0j821KGkwRC6uwi3/AqOWUw085C044x5D25v49o1jWza28WCKWV8YPFkZtaUpB1LkiRJkkaFAxU8y4BFSZJsjeP4q8AdWPBohAi/vwVamsic7/ROmna09fDtdY38/tkWJpUX8TenTuOkGRVEHseSJEmSpEFzoIKn/PkjWUmSPBfHcfUwZJJet9DXR7jxBjh0Lhx+dNpxxqSu3iw/f3Q31z+8C4B3LKjj4qPGU1KYSTmZJEmSJI0+Byp4CuM4PgOIXuHHJEly61CFk16rsOYu2NVI5vIPOCkyzEII3LO5lW+tbaSxrYdTZlby3uMmMamiKO1okiRJkjRqHajgaQS+td+Pd73kxwFwuYnySgiBsOJ6mDoDFhyfdpwx5bmmLq5ds537t7Uzq7qEz541gwVTytOOJUmSJEmj3qsWPEmSzB6mHNLgeWgtbNlE9L6PE2U8DjQc2rr7+PGDO/nN43soLcrwwSWTWXZ4DQUZp6ckSZIkaTgcaIJHGnGyK66H8XVEJ5yWdpRRLxsCtz7TxPfu20FzZx/nHlbDO4+to7rUf7VIkiRJ0nDyXZhGlfDUI/DkI0SXf4Co0E/vofT4zg6uXbOdJ3d1MrduHP98xmQOHV+adixJkiRJGpN8B6xRJbtiOVRUEb3x3LSjjFp7Onr53n2N3PpMM7XjCvnEG6Zy+uwql1lLkiRJUooseDRqhM0b4YHVRBddQVRSknacUaenL/CbJ3bz4wd20ZPNcum88Vx2zATKigrSjiZJkiRJY54Fj0aNcOMNUFJKdMab0o4y6qxraOWbaxvZ0tzNkvpyrlo8mfqq4rRjSZIkSZL6WfBoVAg7txPuvYPorLcQlVemHWfU2NrSzbfWNXLv5lbqK4v4x6XTWTKtIu1YkiRJkqSXsODRqBBu+jlEGaKzL0o7yqjQ2Zvlpw/t4ueP7qYwE/GehRN5y9xaigq8dl6SJEmS8pEFj0a80LyXcNfNRCctJRpfl3acES2EwJ2bWvjOukZ2dfSydE4VVy6cyISyorSjSZIkSZJehQWPRrxw66+ht4fovEvSjjKibdjTyTWrt/PIjg4OHV/CX59az1ETy9KOJUmSJEkaAAsejWiho51w22/guJOIpk5PO86I1NzVxw/v38GNT+2loriAj5w4hbMOqaYg47XnkiRJkjRSWPBoRAt33AjtbWSWXZZ2lBGnLxu48am9/M/9O2jvyXLBEbW8Y34dFSVeey5JkiRJI40Fj0as0NNDuPkXcNSxRHMOTzvOiPLw9nauXbudDXu6mD+5jA8smcysmpK0Y0mSJEmSXqNhKXjiOD4S+Ml+Lx0C/BNQA3wA2NH/+t8lSfLbOI5PAb4GdAPvSJLkyTiOa4AEWJYkSXY4ciu/hXtug6bdZN7/8bSjjBg72nr47vpG7tzUwsSyQj5zaj0nz6gkijyOJUmSJEkj2bAUPEmSPA4sBIjjuADYAvwMeB/wlSRJvvSSX/JJ4AJgNnB1/4//Afic5Y4AQraPsPIGmHUYHHVs2nHyXndflp8/upvrH9pFAC6fP4FL5k2gpNBrzyVJkiRpNEjjiNZZwNNJkmyK4/iVPqYHKOv/1hPH8aHAjCRJVg1PROW99fdAYwOZqz/j9MmrCCFw7+ZWrlvXyPbWHk6eUcn7Fk1kckVx2tEkSZIkSYMojYLncuBH+/34o3EcXwmsAT6ZJMke4PPA94AO4N3Al8hN8EiEEMiuWA6T6uG4k9KOk7c2N3XxzbWNrN/axozqYv71rBkcO6U87ViSJEmSpCEwrAVPHMfFwIXA3/a/9DXgs0Do/+eXgfcnSXIfcFL/rzkN2ApEcRz/hNx0zyeTJNn+kv/tDwIfBEiShLq6uqH/AykVXfevZu+mp6j88N9QNmly2nFepLCwMPXPvbauXr5973Mk9zUwrjDDx08/hIvnT6GwwONYGh3y4TmTRjufM2l4+KxJQ28sPWfDPcFzPrDu+XJm/5ImjuNrgV/v/8FxHEfkJncuB74KfJrcXp6/AP5+/49NkuQa4Jr+H4adO3cOzZ9Aqev78XVQM562Y46nPc/+f66rqyOtz71sCNz2TBPfu28HTZ19nH1oNe9eOJHq0kL27tmdSiZpKKT5nEljhc+ZNDx81qShNxqes/r6+gF93HB/Sf8d7Hc8K47jqfv93MXAQy/5+CuB3yZJspvcPp5s/7eyIc6pPBU2PAGPPUB0zkVERUVpx8kbT+zs4NM3buL/3rONyRXF/MeyWXz0pKlUl6ZxClOSJEmSNNyG7d1fHMflwDnAh/Z7+YtxHC8kd0Rr4/4/F8dxGfBe4Nz+l/4T+C25q9OvGPrEykfZlcuhrJzotPPSjpIX9nb08r37dnDLM03Ulhbw8ZOncvqcKjIunpYkSZKkMSUKIaSdYSiEhoaGtDNokIWtm8n+80eILngbmbe+K+04L2u4xv96s4HfPL6HHz+4k+6+LBfOHc/bjplAWVHBkP/eUtpGw5itlO98zqTh4bMmDb3R8Jz1H9E64FfxPb+hESPceAMUFRGd9Za0o6Tqvq1tXLtmO5ubu1lcX85ViyczrcprzyVJkiRpLLPg0YgQdu8k3LOK6LTziCqr046Tim0t3XxrXSN/3NzK1Moi/nHpdJZMq0g7liRJkiQpD1jwaEQIv/sFhCzRuW9NO8qw6+zNsvzhXfzskd0UZODdCydy0dxairz2XJIkSZLUz4JHeS+0NhPuuJHohNOI6ianHWfYhBD4/bMtfHtdIzvbezl9dhXvOW4iE8q8PUySJEmS9GIWPMp74bbfQlcn0bJL044ybDbu6eTaNdt5qLGDQ2pL+OQp9cybVJZ2LEmSJElSnrLgUV4LXZ2EW38Fx55ANG1W2nGGXEtXHz98YAcrn9xLeXEBHz5hCmcfWk1BxmvPJUmSJEmvzIJHeS3cdTO0tpAZ5dM7fdnATU/t5X8e2Elbdx/nH17DOxZMpLLEa88lSZIkSQdmwaO8FXp7CTf9DA6fR3TYUWnHGTKPNLZzzZrtbNjTxTGTy/jA4knMri1NO5YkSZIkaQSx4FHeCvfeAbt3knnXh9OOMiR2tffwnfU7uGNjM3VlhXz6jfW8YWYlUeRxLEmSJEnSwbHgUV4K2Sxh5XKYNguOWZx2nEHV05flF4/u4acP76QvC2+fP4FL502gpNBrzyVJkiRJr40Fj/LTA6th63NEf/bJUTPREkJg9ZZWrlvbyLbWHk6aUcH7F01ickVx2tEkSZIkSSOcBY/yTgiB7IrroW4y0ZI3ph1nUGxu7uK6NY2s29rG9Kpi/teZM1g4tTztWJIkSZKkUcKCR/nniYfhmceJ3nk1UcHIvkWqvaeP5MFd/Orx3RQXZLhq8SQuOKKWQq89lyRJkiQNIgse5Z3syuuhsproDWelHeU1y4bAqg3NfG99I3s7+zjr0GrevXAiNaU+cpIkSZKkwee7TeWV8Owz8NA6oovfTVRcknac1+TJXR1cu2Y7j+/s5IgJpfz90ukcPmFc2rEkSZIkSaOYBY/ySli5HErHES09P+0oB21vZy/X/u5JfvPwdqpLC/jLk6eydE4VmVGyJFqSJEmSlL8seJQ3QuNWwprfE537VqKyirTjHJTtrd18csVG2nsDFx01nrfPn0BZ0cjeHyRJkiRJGjkseJQ3wk0/g4IM0dkXph3loF27ppGebOA7VyykKnSkHUeSJEmSNMZk0g4gAYSmPYTf30L0hrOIasanHeeg/HFzC6u3tHL5/DoOmeDV55IkSZKk4WfBo7wQfvdL6OsjOu/itKMclK7eLN9cs52Z1cW8Ze7IKqYkSZIkSaOHBY9SF9rbCLevIFpyCtGk+rTjHJSfPrSLxrZerj5+CoUZlylLkiRJktJhwaPUhdtXQEc70bJL0o5yUDY3d/GzR3exdE4VR08uSzuOJEmSJGkMs+BRqkJ3V+541tHHEc08NO04AxZC4JrV2ykpyPC+4yalHUeSJEmSNMZZ8ChV4e5boXkvmfMvSzvKQfn9sy3cv62ddx47kZpxXkYnSZIkSUqXBY9SE/r6clejzzkCjjgm7TgD1t7Tx3VrGzl0fAnLDq9JO44kSZIkSRY8Sk9Y+3vYsY3M+ZcRRSNnQfGPH9jJno7cYuUCFytLkiRJkvKABY9SEUIgrFgOU6bDsSekHWfANu7p5FeP7+Hcw2o4om5c2nEkSZIkSQIseJSWh9bB5g1Eyy4lyoyMT8MQAt9YvZ2K4gLetXBi2nEkSZIkSdpnZLyz1qiTXXk9jK8jOvG0tKMM2G0bmnlkRwfvOW4iVSUFaceRJEmSJGkfCx4Nu/DUo/DEw0TnvJWosCjtOAPS2tXHd9Y1cmTdOM48pDrtOJIkSZIkvYgFj4ZdduVyKK8kOvXctKMM2A/u30FLdx9/fsJkMiNoIbQkSZIkaWyw4NGwCluehfvvJTrzzUQlpWnHGZAnd3Ww8sm9vOmIWubUjozMkiRJkqSxxYJHwyrcuByKS4jOfFPaUQakLxv4+r3bqRlXyBXH1qUdR5IkSZKkl2XBo2ETdjUS7r2D6LTziCqq0o4zIDc9tZendnfy/kWTKCtysbIkSZIkKT9Z8GjYhJt+DkB0zkUpJxmYvZ29fP/+HcyfXMapsyrTjiNJkiRJ0iuy4NGwCC1NhLtuIjpxKdH4iWnHGZDvrt9BV2+WDx0/mcjFypIkSZKkPGbBo2ERbv019PQQLbsk7SgD8khjO7c+08RFc8czo7ok7TiSJEmSJL0qCx4NudDZTrj1N7DwRKKpM9KOc0B92cDXV29nYlkh8XwXK0uSJEmS8p8Fj4ZcuOMmaG8ls+zStKMMyK8f38OmvV382ZLJlBb6iEiSJEmS8p/vXjWkQk8P4eafw5HziQ45Mu04B7SrvYcfPrCTxfXlnDi9Iu04kiRJkiQNiAWPhlT44yrYu5vM+ZelHWVAvrWukWwIfHCJi5UlSZIkSSOHBY+GTMj2EW68AWYeAvMWph3ngO7b2sZdm1q49OgJTKksTjuOJEmSJEkDZsGjobP+j7BtC9Gyy/J+GqanL8s3Vm9nSkURl8wbn3YcSZIkSZIOigWPhkQIgeyK62HSVKLFJ6cd54B+/uhuGlq6+dDxkyku8LGQJEmSJI0svpPV0HjsAdj0FNF5lxBlCtJO86q2t3aTPLSLk2dUsqjexcqSJEmSpJHHgkdDIrvieqgeT3TymWlHOaBvrm0kE8FViyelHUWSJEmSpNfEgkeDLmx8Eh69n+icC4mKitKO86ru3dzCvZtbefv8OiaW53dWSZIkSZJeiQWPBl125XIYV0502rK0o7yqrt4s165pZEZ1MRfOdbGyJEmSJGnksuDRoArbtsC6PxCdcQHRuLK047yq6x/eRWNbD1cfP4XCTH7f8iVJkiRJ0qux4NGgCjf9DAqLiM56c9pRXtWW5m5ueGQ3S2dXcczk/C6iJEmSJEk6EAseDZqwZxfh7luJTjmbqKo27TivKITANau3UVwQ8d5FLlaWJEmSJI18FjwaNOF3v4CQJTr3rWlHeVV3P9vCfdvaedexE6kdV5h2HEmSJEmSXjcLHg2K0NZCuP1GouNPJZo4Je04r6i9p4/r1jZySG0Jyw6vSTuOJEmSJEmDwoJHgyLc9lvo6iBadmnaUV7VTx7cxa6OXq4+YQoFLlaWJEmSJI0SFjx63UJXF+GWX8H8JUTTZ6cd5xVt2tvFLx/bzbmHVXNk3bi040iSJEmSNGgsePS6hd/fDK3NZM6/LO0oryiEwNfv3UZ5cQHvXuhiZUmSJEnS6GLBo9cl9PYSbvo5HHYU0eHz0o7zim7b0MwjOzp4z8KJVJUUpB1HkiRJkqRBZcGj1yWsuRN2NZJZlr/TO61dfXxnfSNH1o3jrEOr044jSZIkSdKgs+DRaxayWcKK5TBtFsxfnHacV/SD+3fQ0tXH1cdPJhO5WFmSJEmSNPpY8Oi1e3ANNDxLtOwSokx+fio9tauTlU/u5YIjajlkfGnacSRJkiRJGhL5+a5ceS+EQHbF9TBhEtHxp6Ud52X1ZQNfX72NmtICrlhQl3YcSZIkSZKGjAWPXpsnH4GnHyM672KigvxcWnzz03t5clcn71s0ifLi/MwoSZIkSdJgsODRa5JduRwqq4necHbaUV5WU2cv379vB/Mnl3Ha7Kq040iSJEmSNKQseHTQwuYN8OAaorPeQlRSknacl/Xd9Tvo6MnyweMnE7lYWZIkSZI0ylnw6KCFFTdAyTiipRekHeVlPdrYzi3PNHHRUeOZWZ2fBZQkSZIkSYPJgkcHJezYRlh9J9Hpy4jKK9KO8ydyi5W3U1dWyNvnu1hZkiRJkjQ2WPDooISbfgYFGaJzLkw7ysv6zRN72Li3iz9bPJnSQj+9JUmSJEljg++ANWCheQ/hrt8RnXwmUc2EtOP8iV3tPfzw/p0sri/npBn5N10kSZIkSdJQseDRgIXf/Qr6eonOuyTtKC/rO+t20JsNfGCJi5UlSZIkSWOLBY8GJLS3EVb9lmjRG4gm16cd50/cv62NOzY1c9nRE5haWZx2HEmSJEmShpUFjwYk3LESOtqJzr807Sh/oqcv8I3V25lSUcQlR49PO44kSZIkScPOgkcHFHq6Cb/7JcxbSDTrsLTj/IlfPLqbLc3dfHDJZIoL/JSWJEmSJI09vhvWAYU/3ApNe8gsy7/pncbWHn7y0E5OnlHB4mkuVpYkSZIkjU0WPHpVoa+PsPIGmH04zF2Qdpw/8c2124mAqxZPTjuKJEmSJEmpseDRqwrr7oYd28icf2ne3Uy1Zksrf9zcytvn1zGxvCjtOJIkSZIkpcaCR68ohEBYcT1MmQYLT0o7zot09Wa5Zs12plcVc+FcFytLkiRJksY2Cx69sofXw3MbiJZdSpTJr0+V6x/exfbWHq4+YTJFBfk1WSRJkiRJ0nDLr3ftyivZlcuhZgLRiaenHeVFGpq7ueGR3Zw+u4r5k8vTjiNJkiRJUuosePSywtOPweMPEp37VqLC/NlvE0LgmjXbKS6IeN+iSWnHkSRJkiQpL1jw6GVlV94AZRVEp56bdpQXufu5FtZvbeOKBXXUjitMO44kSZIkSXnBgkd/Imx9Du67h+jMNxOVjks7zj4dPVmuW9PInNoSLjiiNu04kiRJkiTlDQse/YmwYjkUFxOd+ea0o7zITx7cya6OXq4+fgoFGRcrS5IkSZL0PAsevUjYtYNw7+1Ep55HVFmVdpx9nt3bxS8f283Zh1Yzd2L+TBVJkiRJkpQPLHj0IuHmnwMQnfPWlJO8IITA11dvo6wow3sWTkw7jiRJkiRJeceCR/uElmbCnTcRnXA60YT8KVJWbWjm4cYOrjxuElWlLlaWJEmSJOmlLHi0T7jt19DdRbTskrSj7NPa3ce31zdyxIRSzj60Ou04kiRJkiTlJQseARA6Owi3/gYWnkhUPzPtOPv88P4dtHT18ecnTCETuVhZkiRJkqSXY8Ej/v/27j3I0rK+E/j39PTMMFeGuXMTUCbIJQ63MSqKIijDakQkeaLGqHgBKtnETblJZbOp3cq6lVi12WRNdiuiJgQ3xvgIiJdwUTBEjQozXAICgiIIOEzP9Nzvt373j25XQiJGmD5vn9OfTxXVp985p55vV5+nZs6X9/29SdJ87YvJjm0ZWHlx21H+v4c37s4N39mcC5bNy/PnH9J2HAAAAJiwFDyk2b8vzRc/m/zMKem84IVtx0mSjDRNPnz72sydPiVvXT5x5gEBAADARKTgIc1t/5BsGs7ABRPn7J2bH96ShzbsziWnL87saVPajgMAAAATmoJnkmtGRtLceE1y1HHJyae3HSdJsnX3/nz8rnU5ZfGMvPLYuW3HAQAAgAlPwTPZ3X1bsvYH6VxwcToTZIjxVXevz859I7lsxdIJkwkAAAAmMgXPJNY0TUZuvCZZtDSdM85qO06S5IH1O3Pzw1vyhhfOz/PmTW87DgAAAPQEBc9k9uC9ySMPpXP+m9KZ0v6cmwMjTa5YNZQFMwfzSz+7sO04AAAA0DMUPJPYyA3XJHPnpfOyV7cdJUly/UOb8simPXnPGYszY6q3JgAAAPxb+RQ9STXffzi5/650zrswnanT2o6Tjbv25xP/NJzTDp+Vlx49p+04AAAA0FMUPJNUc8PVyYyZ6bxyZdtRkiRX3rku+0eaXLZiicHKAAAA8FNS8ExCzdCaNHd+PZ1XXZDOzFltx8k9a3fkK49uzZtOnp/D57R/NhEAAAD0GgXPJNTcdG0yZTCdc9/QdpTsOzA6WHnJ7Km5+KQFbccBAACAnqTgmWSazRvSfOPL6Zx1bjqHHtZ2nHzu2xvzxNa9ufTMJZk+6O0IAAAAz4ZP1JNMc/PnkgMj6Zz/prajZP2OffnUvcP5uaNm58wjZ7cdBwAAAHqWgmcSaXZsT3PrjemseHk6i5a2HScfu2MoSfKeM5a0nAQAAAB6m4JnEmluvT7ZsyudlRe3HSWrf7A933x8e8rPLszi2VPbjgMAAAA9TcEzSTR796S55fPJKWekc/RxrWbZs38kH109lKPmTsuFL5zfahYAAADoB4PdWKSUckKSTz3l0POT/JckHx87fmySR5OUWuumUsrFSf5bko1J3lhr3VBKeUGSP6i1/lI3Mveb5h9vTrZtycAF7Z+9c+39G7J2+7584NyjM3VKp+04AAAA0PO6cgZPrfXBWuuptdZTk5yRZGeSzyT5nSS31FqXJbll7Psk+fUkK5JckeStY8f+e5Lf60beftPs35/mps8kL3hhsuzkVrM8uW1vrrlvY84+Zm5etHRWq1kAAACgX7Rxida5SR6utX4/yYVJrho7flWSN449HkkyPcnMJPtKKa9IsrbW+p1uh+0HzeqvJRvWZWDlxel02jtjpmmafGTVUAYHOrnkjMWt5QAAAIB+05VLtJ7mzUk+OfZ4Sa31ybHHa5P88HZKf5jk5iRrkrwtyafHXvdjlVIuTXJpktRas3DhwoMcuzc1TZONX7ouzdHHZcGrL0hnoL2xS7d+dzh3Prkj7zv7uPzM0e3fxWs8DA4Oeu/BOLPPYPzZZ9Ad9hqMv8m0zzpN03RtsVLKtIyWNifXWodKKZtrrfOe8uebaq2HPe01b08yP8k3k/zHJJuSvK/WuvMZlmrWrFlz8H+AHtTcsyojf/aBdN71mxl46Tmt5di1byS/9oXvZe70KfmfK4/NlIH+nL2zcOHCDA8Ptx0D+pp9BuPPPoPusNdg/PXDPjviiCOS5Cd+iO726RwXJLmz1jo09v1QKeXwJBn7uu6pTy6lzEzyziT/J8nvJ3lHkq8l+eVuBe51Izdck8xflM6KV7Sao35rOBt27s9lK5b0bbkDAAAAbel2wfOW/OjyrCT5XEZLm4x9/ezTnv9bSf601rovyYwkTUbn88wc55x9ofnO/cl370/ntRelM9jG1XijHtuyJ599YGPOe8GhOXGRXx0AAAAcbF371F9KmZXkNUkue8rhDyappZR3J/l+kvKU5x+R5MW11t8fO/RnSVYl2ZwfDWPmGYzceE0ye246L39NaxmapskVt6/NjKkDefupi1rLAQAAAP2sqzN4umjSz+Bpnng0I7//G+lc+NYMvP4Z51OPq1sf2ZI/+fqT+dUXL835y+b95Bf0uH64vhMmOvsMxp99Bt1hr8H464d9NlFn8NAlzY3XJNMPSeec17WWYfveA7nyznVZtuCQvOb4Q1vLAQAAAP1OwdOHmvVr06z6ajpnn5/OrDmt5fibe4azdc+BXL5iaQY6BisDAADAeFHw9KHmS9clnYF0zruwtQzf27g7Nzy0KSuXzcvxCw5pLQcAAABMBgqePtNs3Zzmazen89Jz0pm/sJUMI02TP799beZMn5JfXm6wMgAAAIw3BU+faW75QrJ/XzrnX9Rahpsf3pKHNuzOJactzuxpU1rLAQAAAJOFgqePNLt2prn175LTXprO0qNaybB19/58/K51OXnxjLzquLmtZAAAAIDJRsHTR5qv3JTs3JGBlRe3luHjd6/Pjn0juWzF0nQMVgYAAICuUPD0iWbfvjRf+mxy4vJ0jlvWSoYHh3flSw9vyRteOD/HzJveSgYAAACYjBQ8faL5xpeTLRtbO3vnwMjoYOUFMwbz5p9tZ7gzAAAATFYKnj7QjBxIc9O1yTHHJycubyXDDd/ZlEc27cm7z1ycGVO9rQAAAKCbfBLvB3d+I1n3ZAYuuLiVuTebdu3PJ/5pOKcePisvO3pO19cHAACAyU7B0+OapsnIDdckS45MTntJKxmuvHNd9h5octmZSwxWBgAAgBYoeHrdA3cnjz2czvkXpTMwpevL3zu0I//w6Na86aT5OWLutK6vDwAAACh4et7IDdck8+an85Jzur72vgNNrlg1lCWzp+YXTl7Q9fUBAACAUQqeHtY88lDy7XvSec2F6Uyd2vX1P//tjXl8y96894wlmT7orQQAAABt8am8h43ccHUyc1Y6Z5/f9bXX79iXv713OD931OysOGp219cHAAAAfkTB06OaJx9P7vpmOue8Lp1DZnZ9/b+4YyhNkvecsaTrawMAAAD/nIKnRzU3XZtMm5bOuT/f9bXvXLM933h8e37plIVZPLv7l4YBAAAA/5yCpwc1G9en+eY/pHPWa9KZc2hX1957YCRXrBrKkXOn5cIT53d1bQAAAOBfp+DpQc2XPpc0I+mcf1HX1772vo1Zu31fLlsea5azAAAOmUlEQVSxJFOndLq+PgAAAPAvKXh6TLN9a5qv3pTOi1+ZzoLFXV37yW17c/V9G/KKY+Zk+dJZXV0bAAAA+PEUPD2m+fvrkz2701n5pu6u2zT56OqhDA50csnp3S2WAAAAgGem4OkhzZ7dab78+WT5i9M58piurv3NJ7bnjjU78pYXLcyCmQYrAwAAwESi4OkhzVe/mGzfloGVF3d13d37R/Kx1UM5dt70vP6Ew7q6NgAAAPCTKXh6RLN/X5ovXZcsOymd40/s6tqfunc4wzv35/IVSzJlwGBlAAAAmGgUPD2iuf0rycbhDFzwC11d9/Ete/LZBzbm3OcfmhMXz+zq2gAAAMC/jYKnBzQjI2luvDY56tjklDO6t27T5IpVQ5kxdSDvOG1R19YFAAAAfjoKnl5wz+3Jk4+ns/LidDrdu0TqK49uzb1DO/O25Yty6CGDXVsXAAAA+OkoeCa4pmkycv3VycIl6Zz58q6tu2PvgVx557osW3BIXnv8vK6tCwAAAPz0FDwT3UP3JY88lM75F6UzZUrXlv3kPcPZvPtALjNYGQAAACY8Bc8EN3LDp5M5h6bzsnO7tub3Nu7O3z20KSuXzcuyBTO6ti4AAADw7Ch4JrDmsYeT++5K57w3pDNtelfWHGmafHjVUOZMm5K3LTdYGQAAAHqBgmcCa268NjlkRjqvuqBra97y8JY8OLwr7zx9cWZP794lYQAAAMCzp+CZoJp1a9Ks/sd0XnlBOjNnd2XNrXsO5Kq71+ekRTNyznFzu7ImAAAA8NwpeCao5qbrkilT0jnvDV1b86/vXp8de0cHK3fzduwAAADAc6PgmYCazRvTfP3mdF52bjrz5ndlzQeHd+WL392cnz/hsBx72CFdWRMAAAA4OBQ8E9H3H06mTkvn/Dd2ZbkDI02uWLU2h80YzJtftLArawIAAAAHz2DbAfiXOstXZOB/XJXO9O7cOevG72zOwxv35LdefkRmTjVYGQAAAHqNM3gmqG6VO5t37c8n/ml9Tl06M2c9b05X1gQAAAAOLgXPJHflXeuy50CTS1csNVgZAAAAepSCZxL71tDO3PrI1lx04vwcOXda23EAAACAZ0nBM0ntHxusvHjW1PziKQvajgMAAAA8BwqeSerz396Yx7bszXvPXJzpg94GAAAA0Mt8sp+Ehnfuy9/eO5wVR87Oi48yWBkAAAB6nYJnEvqLO9ZlpEnee+bitqMAAAAAB4GCZ5K5c832fP2xbfnFUxZkyWyDlQEAAKAfKHgmkb0HRvKR1UM5Ys60XHTi/LbjAAAAAAeJgmcS+cz9G/Pktn25bMWSTJ3iVw8AAAD9wqf8SWLttr25+r4NOet5c3Lq4bPajgMAAAAcRAqeSaBpmnx09VAGOp28+wyDlQEAAKDfKHgmgduf2J7Va3bkrS9amAUzp7YdBwAAADjIFDx9bvf+kXx09VCOOXR6XnfCYW3HAQAAAMaBgqfPffpbG7J+5/5c/uIlGRzotB0HAAAAGAcKnj72xJY9ue6BDXn18+fmpMUz244DAAAAjBMFT59qmiZXrBrK9MGBvOM0g5UBAACgnyl4+tRXv78t9wztzK8sX5R5hwy2HQcAAAAYRwqePrRz34H85Z3rcvz8Q/La4+e1HQcAAAAYZwqePvQ39wxn867RwcpTDFYGAACAvqfg6TOPbNqdv3twU85fNi/LFsxoOw4AAADQBQqePjLSNPnw7UOZPW1K3rZ8UdtxAAAAgC5R8PSRL39vS749vCvvPG1R5kyf0nYcAAAAoEsUPH1i254Duequ9Tlx0Yyc8/xD244DAAAAdJGCp0/837vXZ/veA7l8xZIMdAxWBgAAgMlEwdMHHhrelS9+d3Nef8JhOfawQ9qOAwAAAHSZgqfHHRhp8uFVazNvxmDe8qKFbccBAAAAWqDg6XE3fXdzHt64J+8+fXFmTjVYGQAAACYjBU8P27xrf/767vVZvnRmXn7MnLbjAAAAAC1R8PSwv7prXfYcGMmlK5akY7AyAAAATFoKnh5139DO/P0jW/PGExfkqLnT244DAAAAtEjB04P2jw1WXjxrMOWUBW3HAQAAAFqm4OlBX3hwYx7bsjfvOXNJpg/6FQIAAMBkpx3oMcM79+WT92zIiiNn5eeOMlgZAAAAUPD0nL+8Y11GmibvPXNJ21EAAACACULB00PuenJH/vGxbfnFkxdkyexpbccBAAAAJggFT4/Yd2AkH1m1NkfMmZqLTprfdhwAAABgAlHw9IjP3L8xa7bty6UrlmbqFL82AAAA4Ec0BT1gaPvefPq+DTnreXNy2uGz2o4DAAAATDAKnh7w0dVDGegk7zpjcdtRAAAAgAlIwTPB3fbEtqz6wY685UULs3Dm1LbjAAAAABOQgmcC27N/JB9bPZTnHTotrz/BYGUAAADgX6fgmcDqtzZk3Y79uXzF0gwOdNqOAwAAAExQCp4J6omte3LdAxtyznFzc/KSmW3HAQAAACYwBc8E1DRNrlg1lOlTBvLO0wxWBgAAAJ6ZgmcC+vrj23LP2p355eWLMm/GYNtxAAAAgAlOwTMBnXb4rLzztEVZuWxe21EAAACAHuD0kAlo5tQpueikBW3HAAAAAHqEM3gAAAAAepyCBwAAAKDHKXgAAAAAepyCBwAAAKDHKXgAAAAAepyCBwAAAKDHKXgAAAAAepyCBwAAAKDHKXgAAAAAepyCBwAAAKDHKXgAAAAAepyCBwAAAKDHKXgAAAAAepyCBwAAAKDHKXgAAAAAepyCBwAAAKDHKXgAAAAAetxgtxYqpcxL8rEkpyRpkrwryflJ3ptk/djTfrfWen0p5awkf55kb5K31Fq/M/b6mmRlrXWkW7kBAAAAJrquFTxJPpTkxlrrL5RSpiWZmdGC509qrX/0tOe+P8m/S3JsksvHvv+9JH+g3AEAAAD457pS8JRSDk1ydpJ3JkmtdW+SvaWUH/eSfRktgGYm2VdKeUGSo2utt457WAAAAIAe060zeI7L6GVYV5ZSlie5I8n7xv7s35dS3p5kdZL311o3JfnDJB9PsivJryT5o4yewfNjlVIuTXJpktRas3DhwvH4OeAZDQ4Oeu/BOLPPYPzZZ9Ad9hqMv8m0zzpN04z7IqWUM5N8M8lZtdbbSikfSrI1yf9OMpzRmTwfSHJ4rfVdT3vt2UkuyuhMng9k9Oye99dah55hyWbNmjUH/weBn2DhwoUZHh5uOwb0NfsMxp99Bt1hr8H464d9dsQRRyRJ5yc9r1tn8DyR5Ila621j31+d5HeeWtKUUj6a5AtPfVEppZPRM3fenOTPkvx2Rufy/EaS/zz+sQEAAAAmvq7cJr3WujbJ46WUE8YOnZvk/lLK4U952kVJvvW0l749yfW11o0ZncczMvbfzHGODAAAANAzunkXrV9P8omxO2h9L8klSf60lHJqRi/RejTJZT98cillZkaHMr927NAfJ7k+o7dOf+tPWmzsFCboOu89GH/2GYw/+wy6w16D8TdZ9llXZvDAZFFKWV1rPbPtHNDP7DMYf/YZdIe9BuNvMu2zrlyiBQAAAMD4UfAAAAAA9DgFDxxcH2k7AEwC9hmMP/sMusNeg/E3afaZGTwAAAAAPc4ZPAAAAAA9TsEDAAAA0OMG2w4Ava6UcnSSjydZkqRJ8pFa64faTQX9qZQyJcnqJD+otb6+7TzQj0op85J8LMkpGf177V211m+0mwr6SynlN5O8J6N77N4kl9Rad7ebCnpfKeUvk7w+ybpa6yljx+Yn+VSSY5M8mqTUWje1lXE8OYMHnrv9Sd5faz0pyUuS/Fop5aSWM0G/el+SB9oOAX3uQ0lurLW+MMny2HNwUJVSjkzyG0nOHPsAOiXJm9tNBX3jr5KsfNqx30lyS611WZJbxr7vSwoeeI5qrU/WWu8ce7wto/8QPrLdVNB/SilHJXldRs8sAMZBKeXQJGcn+YskqbXurbVubjcV9KXBJDNKKYNJZiZZ03Ie6Au11q8k2fi0wxcmuWrs8VVJ3tjVUF2k4IGDqJRybJLTktzWchToR/8ryW8nGWk7CPSx45KsT3JlKeWuUsrHSimz2g4F/aTW+oMkf5TksSRPJtlSa/1iu6mgry2ptT459nhtRkdr9CUFDxwkpZTZSa5J8h9qrVvbzgP9pJTyw2up72g7C/S5wSSnJ/nzWutpSXakj09lhzaUUg7L6BkFxyU5IsmsUsrb2k0Fk0Ottcno7Ku+pOCBg6CUMjWj5c4naq3Xtp0H+tBZSd5QSnk0yd8meXUp5a/bjQR96YkkT9Raf3gm6tUZLXyAg+e8JI/UWtfXWvcluTbJy1rOBP1sqJRyeJKMfV3Xcp5xo+CB56iU0snorIIHaq1/3HYe6Ee11v9Uaz2q1npsRgdRfrnW6v92wkFWa12b5PFSygljh85Ncn+LkaAfPZbkJaWUmWP/jjw3hpnDePpckneMPX5Hks+2mGVcuU06PHdnJfmVJPeWUu4eO/a7tdbrW8wEAM/Wryf5RCllWpLvJbmk5TzQV2qtt5VSrk5yZ0bvxnpXko+0mwr6Qynlk0lelWRhKeWJJP81yQeT1FLKu5N8P0lpL+H46jRN315+BgAAADApuEQLAAAAoMcpeAAAAAB6nIIHAAAAoMcpeAAAAAB6nIIHAAAAoMcpeAAAfgqllEdLKee1nQMA4KkUPAAAAAA9TsEDAAAA0OMG2w4AANCrSiknJrk+ye/WWj/Zdh4AYPJS8AAAPAullNOTXJfkV2utX2g7DwAwublECwDgp/eKJJ9L8nblDgAwESh4AAB+epcn+Xqt9da2gwAAJAoeAIBn4/Ikzyul/EnbQQAAEgUPAMCzsS3JyiRnl1I+2HYYAAAFDwDAs1Br3ZzkNUkuKKV8oO08AMDk1mmapu0MAAAAADwHzuABAAAA6HEKHgAAAIAep+ABAAAA6HEKHgAAAIAep+ABAAAA6HEKHgAAAIAep+ABAAAA6HEKHgAAAIAe9/8AW1knWDEUZU4AAAAASUVORK5CYII=\n",
758 "text/plain": [
759 "<Figure size 1152x648 with 1 Axes>"
760 ]
761 },
762 "metadata": {},
763 "output_type": "display_data"
764 }
765 ],
766 "source": [
767 "result = pd.concat([train_precision, test_precision], axis=1)\n",
768 "ax = result.plot(title='P@K Accuracy', figsize=(16,9))\n",
769 "ax.set_xlabel('k')\n",
770 "ax.set_ylabel('P@k Accuracy')\n",
771 "ax.yaxis.set_major_formatter(FuncFormatter(lambda y, _: '{:.0%}'.format(y)))\n",
772 "\n",
773 "plt.tight_layout()\n",
774 "plt.gcf().savefig('assets/translation_accuracy.png', dpi=300);"
775 ]
776 },
777 {
778 "cell_type": "markdown",
779 "metadata": {
780 "slideshow": {
781 "slide_type": "slide"
782 }
783 },
784 "source": [
785 "#### View Translations"
786 ]
787 },
788 {
789 "cell_type": "code",
790 "execution_count": 35,
791 "metadata": {
792 "slideshow": {
793 "slide_type": "fragment"
794 }
795 },
796 "outputs": [
797 {
798 "name": "stdout",
799 "output_type": "stream",
800 "text": [
801 " 0 1 2 3 4\n",
802 "en \n",
803 "the el el la de de\n",
804 "of de de el el la\n",
805 "and y y de de con\n",
806 "in en en de de y\n",
807 "to a a para que directamente\n",
808 "a un un el el que\n",
809 "was era estaba es es es\n",
810 "is es es es existe existe\n",
811 "for para además además además además\n",
812 "on en en de de el\n"
813 ]
814 }
815 ],
816 "source": [
817 "top_5_preds = pd.DataFrame(nn_train[:, :5], index=matches.en.iloc[:TRAIN_SIZE])\n",
818 "\n",
819 "for col in top_5_preds.columns:\n",
820 " top_5_preds[col] = top_5_preds[col].map(matches.es.to_dict())\n",
821 "print(top_5_preds.head(10))"
822 ]
823 },
824 {
825 "cell_type": "code",
826 "execution_count": 36,
827 "metadata": {
828 "slideshow": {
829 "slide_type": "fragment"
830 }
831 },
832 "outputs": [],
833 "source": [
834 "with pd.HDFStore(translation_path / 'results.h5') as store:\n",
835 " store.put('translation_matrix', pd.DataFrame(translation_matrix))\n",
836 " store.put('top_5_preds', top_5_preds)\n",
837 " store.put('accuracy', result)"
838 ]
839 },
840 {
841 "cell_type": "markdown",
842 "metadata": {
843 "slideshow": {
844 "slide_type": "slide"
845 }
846 },
847 "source": [
848 "### Visualize Bilingual Vector Space in `tensorboard`"
849 ]
850 },
851 {
852 "cell_type": "markdown",
853 "metadata": {
854 "slideshow": {
855 "slide_type": "fragment"
856 }
857 },
858 "source": [
859 "#### Embeddings"
860 ]
861 },
862 {
863 "cell_type": "code",
864 "execution_count": 37,
865 "metadata": {
866 "slideshow": {
867 "slide_type": "fragment"
868 }
869 },
870 "outputs": [
871 {
872 "name": "stdout",
873 "output_type": "stream",
874 "text": [
875 "<class 'pandas.core.frame.DataFrame'>\n",
876 "RangeIndex: 5000 entries, 0 to 4999\n",
877 "Columns: 300 entries, 0 to 299\n",
878 "dtypes: float32(300)\n",
879 "memory usage: 5.7 MB\n"
880 ]
881 }
882 ],
883 "source": [
884 "LIMIT = 2500\n",
885 "source_projection = np.dot(source_test, translation_matrix)\n",
886 "projector_data = pd.DataFrame(np.vstack((source_projection[:LIMIT], \n",
887 " target_test[:LIMIT])))\n",
888 "projector_data.to_csv(translation_path / 'embeddings.tsv', index=False, sep='\\t', header=None)\n",
889 "projector_data.info()"
890 ]
891 },
892 {
893 "cell_type": "markdown",
894 "metadata": {
895 "slideshow": {
896 "slide_type": "slide"
897 }
898 },
899 "source": [
900 "#### Meta Data"
901 ]
902 },
903 {
904 "cell_type": "code",
905 "execution_count": 38,
906 "metadata": {
907 "slideshow": {
908 "slide_type": "fragment"
909 }
910 },
911 "outputs": [
912 {
913 "name": "stdout",
914 "output_type": "stream",
915 "text": [
916 "<class 'pandas.core.frame.DataFrame'>\n",
917 "RangeIndex: 5000 entries, 0 to 4999\n",
918 "Data columns (total 2 columns):\n",
919 "language 5000 non-null object\n",
920 "word 5000 non-null object\n",
921 "dtypes: object(2)\n",
922 "memory usage: 78.2+ KB\n"
923 ]
924 }
925 ],
926 "source": [
927 "labels = pd.melt(matches.iloc[TRAIN_SIZE:TRAIN_SIZE+LIMIT].loc[:, ['en', 'es']],\n",
928 " var_name='language', \n",
929 " value_name='word')\n",
930 "labels.to_csv(translation_path / 'meta_data.tsv', index=False, sep='\\t')\n",
931 "labels.info()"
932 ]
933 },
934 {
935 "cell_type": "markdown",
936 "metadata": {},
937 "source": [
938 "## Resources\n",
939 "\n",
940 "- [Exploiting similarities among languages for machine translation](https://arxiv.org/pdf/1309.4168)"
941 ]
942 }
943 ],
944 "metadata": {
945 "celltoolbar": "Slideshow",
946 "kernelspec": {
947 "display_name": "Python 3",
948 "language": "python",
949 "name": "python3"
950 },
951 "language_info": {
952 "codemirror_mode": {
953 "name": "ipython",
954 "version": 3
955 },
956 "file_extension": ".py",
957 "mimetype": "text/x-python",
958 "name": "python",
959 "nbconvert_exporter": "python",
960 "pygments_lexer": "ipython3",
961 "version": "3.6.8"
962 },
963 "toc": {
964 "base_numbering": 1,
965 "nav_menu": {},
966 "number_sections": true,
967 "sideBar": true,
968 "skip_h1_title": false,
969 "title_cell": "Table of Contents",
970 "title_sidebar": "Contents",
971 "toc_cell": false,
972 "toc_position": {
973 "height": "900px",
974 "left": "1536px",
975 "top": "302.5px",
976 "width": "212px"
977 },
978 "toc_section_display": true,
979 "toc_window_display": true
980 }
981 },
982 "nbformat": 4,
983 "nbformat_minor": 2
984 }