File size: 130,774 Bytes
170eafa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "490880a8-d1a4-42cf-8ff8-df4c60bc1235",
   "metadata": {},
   "source": [
    "# Library Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d8b740da-fdc1-46b7-b273-ca1bf85102b5",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "from torch.nn import functional as F\n",
    "\n",
    "import json\n",
    "import random\n",
    "from collections import defaultdict\n",
    "import time\n",
    "import sys\n",
    "import io\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "\n",
    "from transformers import AutoTokenizer \n",
    "from tokenizers.pre_tokenizers import Whitespace\n",
    "import warnings\n",
    "import pickle"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "66923f7a-95d1-44f4-a481-c0d6625798dd",
   "metadata": {},
   "source": [
    "# Setting GPU/CPU device"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0b37a05a-d42f-4795-9e0c-67603a2311a1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CUDA available: True\n",
      "CUDA device count: 8\n",
      "Current CUDA device: 0\n"
     ]
    }
   ],
   "source": [
    "# Check if CUDA is available and print more information\n",
    "print(f\"CUDA available: {torch.cuda.is_available()}\")\n",
    "if torch.cuda.is_available():\n",
    "    print(f\"CUDA device count: {torch.cuda.device_count()}\")\n",
    "    print(f\"Current CUDA device: {torch.cuda.current_device()}\")\n",
    "    device = torch.device(\"cuda\")\n",
    "else:\n",
    "    print(\"CUDA is not available. Using CPU instead.\")\n",
    "    device = torch.device(\"cpu\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cec9d62f-344a-467f-94ad-0c59d3568003",
   "metadata": {},
   "source": [
    "# Using BPE tokenizer from previous assignment"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "5915680d-3173-42ac-a254-9107fabd51f7",
   "metadata": {},
   "outputs": [],
   "source": [
    "class BPETokenizer:\n",
    "    def __init__(self, vocab_size=4000):\n",
    "        self.vocab_size = vocab_size\n",
    "        self.vocab = [\"<|endoftext|>\"]\n",
    "        self.word_freqs = defaultdict(int)\n",
    "        self.merges = {}\n",
    "        self.tokenizer = AutoTokenizer.from_pretrained(\"gpt2\")\n",
    "\n",
    "    def compute_pair_freqs(self,splits):\n",
    "        pair_freqs = defaultdict(int)\n",
    "        for word, freq in self.word_freqs.items():\n",
    "            split = splits[word]\n",
    "            if len(split) == 1:\n",
    "                continue\n",
    "            for i in range(len(split) - 1):\n",
    "                pair = (split[i], split[i + 1])\n",
    "                pair_freqs[pair] += freq\n",
    "        return pair_freqs\n",
    "    \n",
    "    def merge_pair(self,a, b, splits):\n",
    "        for word in self.word_freqs:\n",
    "            split = splits[word]\n",
    "            if len(split) == 1:\n",
    "                continue\n",
    "\n",
    "            i = 0\n",
    "            while i < len(split) - 1:\n",
    "                if split[i] == a and split[i + 1] == b:\n",
    "                    split = split[:i] + [a + b] + split[i + 2 :]\n",
    "                else:\n",
    "                    i += 1\n",
    "            splits[word] = split\n",
    "        return splits\n",
    "\n",
    "    def build_vocab(self, corpus):\n",
    "        for text in corpus:\n",
    "            self.tokenizer.backend_tokenizer.pre_tokenizer = Whitespace()\n",
    "            text= ' Ġ'.join(text.split())\n",
    "            words_with_offsets = self.tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str(text)\n",
    "            new_words = [word for word, offset in words_with_offsets]\n",
    "            for word in new_words:\n",
    "                self.word_freqs[word] += 1\n",
    "\n",
    "        alphabet = []\n",
    "\n",
    "        for word in self.word_freqs.keys():\n",
    "            for letter in word:\n",
    "                if letter not in alphabet:\n",
    "                    alphabet.append(letter)\n",
    "        alphabet.sort()\n",
    "\n",
    "\n",
    "        # Add every unique character to the vocab\n",
    "        for char in alphabet:\n",
    "            if char not in self.vocab:\n",
    "                self.vocab.append(char)\n",
    "\n",
    "        splits = {word: [c for c in word] for word in self.word_freqs.keys()}\n",
    "\n",
    "        while len(self.vocab) < self.vocab_size:\n",
    "            pair_freqs = self.compute_pair_freqs(splits)\n",
    "            best_pair = \"\"\n",
    "            max_freq = None\n",
    "            for pair, freq in pair_freqs.items():\n",
    "                if max_freq is None or max_freq < freq:\n",
    "                    best_pair = pair\n",
    "                    max_freq = freq\n",
    "            if len(best_pair) == 2:\n",
    "                splits = self.merge_pair(best_pair[0],best_pair[1], splits)\n",
    "                self.merges[best_pair] = best_pair[0] + best_pair[1]\n",
    "                self.vocab.append(best_pair[0] + best_pair[1])\n",
    "            else:\n",
    "                break\n",
    "\n",
    "\n",
    "    def tokenize(self,text):\n",
    "        self.tokenizer.backend_tokenizer.pre_tokenizer = Whitespace()\n",
    "        pre_tokenize_result = self.tokenizer._tokenizer.pre_tokenizer.pre_tokenize_str(text)\n",
    "        pre_tokenized_text = [word for word, offset in pre_tokenize_result]\n",
    "        splits = [[l for l in word] for word in pre_tokenized_text]\n",
    "\n",
    "\n",
    "        for word in pre_tokenized_text:\n",
    "            for char in word:\n",
    "                if char not in self.vocab:\n",
    "                    self.vocab.append(char)  \n",
    "\n",
    "        for pair, merge in self.merges.items():\n",
    "            for idx, split in enumerate(splits):\n",
    "                i = 0\n",
    "                while i < len(split) - 1:\n",
    "                    if split[i] == pair[0] and split[i + 1] == pair[1]:\n",
    "                        split = split[:i] + [merge] + split[i + 2 :]\n",
    "                    else:\n",
    "                        i += 1\n",
    "                splits[idx] = split\n",
    "\n",
    "        return sum(splits, [])\n",
    "\n",
    "    def save(self, file_path):\n",
    "        \"\"\"\n",
    "        Save the tokenizer's state to a file.\n",
    "        \"\"\"\n",
    "        state = {\n",
    "            'vocab_size': self.vocab_size,\n",
    "            'vocab': self.vocab,\n",
    "            'word_freqs': dict(self.word_freqs),\n",
    "            'merges': self.merges\n",
    "        }\n",
    "        with open(file_path, 'wb') as f:\n",
    "            pickle.dump(state, f)\n",
    "\n",
    "    @classmethod\n",
    "    def load(cls, file_path):\n",
    "        \"\"\"\n",
    "        Load a tokenizer's state from a file.\n",
    "        \"\"\"\n",
    "        with open(file_path, 'rb') as f:\n",
    "            state = pickle.load(f)\n",
    "        \n",
    "        tokenizer = cls(vocab_size=state['vocab_size'])\n",
    "        tokenizer.vocab = state['vocab']\n",
    "        tokenizer.word_freqs = defaultdict(int, state['word_freqs'])\n",
    "        tokenizer.merges = state['merges']\n",
    "        return tokenizer\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ad2cd41-a4d3-4cfa-bb49-9a30c8e19a43",
   "metadata": {},
   "source": [
    "# Encode Decode function implemenation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "2459246a-5d33-455a-9bab-cd06976c582f",
   "metadata": {},
   "outputs": [],
   "source": [
    "tokenizer_file = \"tokenizer.pkl\"\n",
    "\n",
    "def encode(text):\n",
    "    # Step 1: Encode, decode, and normalize the text\n",
    "    text = text.encode('utf-8').decode('utf-8').lower()\n",
    "    text = 'Ġ'.join(text.split())\n",
    "\n",
    "    # Step 2: Load tokenizer\n",
    "    tokenizer_instance = BPETokenizer.load(tokenizer_file)\n",
    "\n",
    "    # Step 3: Create a dictionary for vocabulary for O(1) lookups\n",
    "    vocab_dict = {token: idx for idx, token in enumerate(tokenizer_instance.vocab)}\n",
    "\n",
    "    # Step 4: Tokenize the text\n",
    "    tokens = tokenizer_instance.tokenize(text)\n",
    "\n",
    "    # Step 5: Generate token IDs efficiently\n",
    "    unknown_token_id = len(tokenizer_instance.vocab) \n",
    "    token_ids = [vocab_dict.get(t, unknown_token_id) for t in tokens]\n",
    "\n",
    "    return token_ids\n",
    "\n",
    "def decode(token_ids):\n",
    "    tokenizer_instance = BPETokenizer.load(tokenizer_file)\n",
    "    tokens = []\n",
    "    for id in token_ids:\n",
    "        if 0 <= id < len(tokenizer_instance.vocab):\n",
    "            tokens.append(tokenizer_instance.vocab[id])\n",
    "        else:\n",
    "            # Handle out-of-vocabulary token IDs\n",
    "            tokens.append('<UNK>')\n",
    "    decoded_string = ''.join(tokens)\n",
    "    decoded_string = decoded_string.replace('Ġ', ' ').strip()\n",
    "    return decoded_string"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d2320fce-43fb-4d28-ba2a-7831ae725c2e",
   "metadata": {},
   "source": [
    "# Data Handling"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "68eeed34-53a0-412a-a86b-2eefea02a46a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Helper function to load JSON data\n",
    "def load_json_data(file_path):\n",
    "    with open(file_path, 'r', encoding='utf-8') as f:\n",
    "        data = json.load(f)\n",
    "    return data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "685df365-cb3b-49a9-93a1-46a3977184d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "def find_space_low_strings(strings, low_bound, up_bound):\n",
    "    result = []\n",
    "    for index, text in enumerate(strings):\n",
    "        total_chars = len(text)\n",
    "        space_count = text.count(' ')\n",
    "\n",
    "        # Calculate percentage if there are non-space characters\n",
    "        if total_chars > space_count:\n",
    "            percentage = (space_count / (total_chars - space_count)) * 100\n",
    "            if percentage > low_bound and percentage < up_bound:\n",
    "                result.append(text)\n",
    "\n",
    "    return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "85778ca0-6cba-4f30-b6b1-55bb11cb17ad",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "24653\n",
      "16555\n"
     ]
    }
   ],
   "source": [
    "# Load English and Amharic data\n",
    "english_data = load_json_data('alpaca_data_cleaned_cleaned_corpus.json')\n",
    "amharic_data = load_json_data('Amharic_cleaned_corpus.json')\n",
    "\n",
    "# Using data samples having longer context\n",
    "long_english_data = [s for s in english_data if len(s) >= 500]\n",
    "long_amharic_data = [s for s in amharic_data if len(s) >= 500]\n",
    "print(len(long_english_data))\n",
    "print(len(long_amharic_data))\n",
    "\n",
    "long_english_data = find_space_low_strings(long_english_data, 17, 22)\n",
    "long_amharic_data = find_space_low_strings(long_amharic_data, 22, 26)\n",
    "\n",
    "\n",
    "# Control how many elements to take from each file\n",
    "num_english_elements = 1000  # Number of elements from English file\n",
    "num_amharic_elements = 1000  # Number of elements from Amharic file\n",
    "\n",
    "\n",
    "random.shuffle(long_english_data)\n",
    "random.shuffle(long_amharic_data)\n",
    "# Slice data from both files as per the desired number of elements\n",
    "english_list = long_english_data[:num_english_elements]\n",
    "amharic_list = long_amharic_data[:num_amharic_elements]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "8e4da812-0fd5-4710-90b5-40763ad6457b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2146699\n"
     ]
    }
   ],
   "source": [
    "# Combine the texts\n",
    "combined_list = english_list  + amharic_list\n",
    "\n",
    "# Shuffle the combined text\n",
    "def shuffle_text(text_list, seed=42):\n",
    "    random.seed(seed)\n",
    "    # Split into blocks of text\n",
    "    random.shuffle(text_list)  # Shuffle the text blocks\n",
    "    return ' '.join(text_list)\n",
    "\n",
    "# Shuffle the combined text\n",
    "text = shuffle_text(combined_list)\n",
    "print(len(text))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "96e58556-d016-441f-a695-ad4349b70ba3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 2.69 ms, sys: 66.9 ms, total: 69.6 ms\n",
      "Wall time: 68.3 ms\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "<timed exec>:3: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "# Encode the entire dataset\n",
    "# data = torch.tensor(encode(text), dtype=torch.long)\n",
    "data = torch.load('tensor_data.pt')\n",
    "\n",
    "# Split into train and validation sets\n",
    "n = int(0.8 * len(data))\n",
    "train_data = data[:n]\n",
    "val_data = data[n:]\n",
    "\n",
    "\n",
    "def get_batch(split):\n",
    "    data = train_data if split == 'train' else val_data\n",
    "    # Making sure we don't try to start at an index that would give us an incomplete sequence\n",
    "    max_index = len(data) - hyperparams['block_size'] - 1\n",
    "    if max_index < 1:\n",
    "        raise ValueError(f\"Not enough data for sequence length {hyperparams['block_size']}\")\n",
    "    \n",
    "    ix = torch.randint(max_index, (hyperparams['block_size'],))\n",
    "    \n",
    "    x = torch.stack([data[i:i+hyperparams['block_size']] for i in ix])\n",
    "    y = torch.stack([data[i+1:i+hyperparams['block_size']+1] for i in ix])\n",
    "    \n",
    "    return x.to(device), y.to(device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "d644ad3e-aedb-480f-8acc-99ea111226d1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Evaluation function\n",
    "@torch.no_grad()\n",
    "def estimate_loss():\n",
    "    out = {}\n",
    "    model.eval()\n",
    "    for split in ['train', 'val']:\n",
    "        losses = torch.zeros(hyperparams['eval_iters'])\n",
    "        for k in range(hyperparams['eval_iters']):\n",
    "            X, Y = get_batch(split)\n",
    "            logits, loss = model(X, Y)\n",
    "            losses[k] = loss.item()\n",
    "        out[split] = losses.mean()\n",
    "    model.train()\n",
    "    return out"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "beaba601-ad27-4f6f-af9c-d4092a9beeec",
   "metadata": {},
   "source": [
    "# Hyperparameters Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "b47ec2f6-1444-4027-8ca8-70ca818bd9e0",
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "These are our hyperparameters. Feel free to change\n",
    "\"\"\"\n",
    "# Hyperparameters\n",
    "hyperparams = {}\n",
    "hyperparams['batch_size'] = 128 # This defines the number of samples processed in one forward/backward pass of the model.\n",
    "hyperparams['block_size'] = 256  # sequence length || This represents the length of the input sequences the model will process.\n",
    "hyperparams['max_iters'] = 3000 # This sets the maximum number of training iterations (or steps) the model will perform.\n",
    "                 # The training will stop after this many iterations, even if other stopping criteria haven't been met.\n",
    "hyperparams['eval_interval'] = 300 # This determines how often the model's performance is evaluated during training.\n",
    "hyperparams['learning_rate'] = 1e-2 # This controls the step size at each iteration while moving toward a minimum of the loss function.\n",
    "hyperparams['eval_iters'] = 200\n",
    "hyperparams['n_embd'] = 512 #  Refers to the dimensionality of the embedding space.\n",
    "hyperparams['n_hidden'] = 1024\n",
    "hyperparams['dropout'] = 0.3 # Dropout is a regularization technique to prevent overfitting."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "8179c773-16ed-4512-80b3-1fcb70f65576",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[' ', '#', '$', '%', '&', '*', '+', '>', '@', '[', '\\\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '°', '²', '³', '¹', '×', 'é', 'ö', '÷', 'λ', 'ሀ', 'ሁ', 'ሂ', 'ሃ', 'ሄ', 'ህ', 'ሆ', 'ለ', 'ሉ', 'ሊ', 'ላ', 'ሌ', 'ል', 'ሎ', 'ሏ', 'ሐ', 'ሑ', 'ሒ', 'ሔ', 'ሕ', 'መ', 'ሙ', 'ሚ', 'ማ', 'ሜ', 'ም', 'ሞ', 'ሟ', 'ሠ', 'ሣ', 'ሥ', 'ሦ', 'ረ', 'ሩ', 'ሪ', 'ራ', 'ሬ', 'ር', 'ሮ', 'ሯ', 'ሰ', 'ሱ', 'ሲ', 'ሳ', 'ሴ', 'ስ', 'ሶ', 'ሷ', 'ሸ', 'ሹ', 'ሺ', 'ሻ', 'ሼ', 'ሽ', 'ሾ', 'ሿ', 'ቀ', 'ቁ', 'ቂ', 'ቃ', 'ቄ', 'ቅ', 'ቆ', 'ቋ', 'በ', 'ቡ', 'ቢ', 'ባ', 'ቤ', 'ብ', 'ቦ', 'ቧ', 'ቨ', 'ቪ', 'ቫ', 'ቬ', 'ቭ', 'ቮ', 'ተ', 'ቱ', 'ቲ', 'ታ', 'ቴ', 'ት', 'ቶ', 'ቷ', 'ቸ', 'ቹ', 'ቺ', 'ቻ', 'ቼ', 'ች', 'ቾ', 'ቿ', 'ኃ', 'ኄ', 'ኅ', 'ኋ', 'ነ', 'ኑ', 'ኒ', 'ና', 'ኔ', 'ን', 'ኖ', 'ኗ', 'ኘ', 'ኙ', 'ኚ', 'ኛ', 'ኜ', 'ኝ', 'ኞ', 'ኟ', 'አ', 'ኡ', 'ኢ', 'ኤ', 'እ', 'ኦ', 'ኧ', 'ከ', 'ኩ', 'ኪ', 'ካ', 'ኬ', 'ክ', 'ኮ', 'ኳ', 'ኸ', 'ወ', 'ዉ', 'ዊ', 'ዋ', 'ዌ', 'ው', 'ዎ', 'ዐ', 'ዑ', 'ዒ', 'ዓ', 'ዔ', 'ዕ', 'ዖ', 'ዘ', 'ዙ', 'ዚ', 'ዛ', 'ዜ', 'ዝ', 'ዞ', 'ዟ', 'ዠ', 'ዡ', 'ዢ', 'ዣ', 'ዤ', 'ዥ', 'ዦ', 'የ', 'ዩ', 'ያ', 'ዬ', 'ይ', 'ዮ', 'ደ', 'ዱ', 'ዲ', 'ዳ', 'ዴ', 'ድ', 'ዶ', 'ዷ', 'ጀ', 'ጁ', 'ጂ', 'ጃ', 'ጄ', 'ጅ', 'ጆ', 'ጇ', 'ገ', 'ጉ', 'ጊ', 'ጋ', 'ጌ', 'ግ', 'ጎ', 'ጓ', 'ጠ', 'ጡ', 'ጢ', 'ጣ', 'ጤ', 'ጥ', 'ጦ', 'ጧ', 'ጨ', 'ጩ', 'ጪ', 'ጫ', 'ጬ', 'ጭ', 'ጮ', 'ጲ', 'ጴ', 'ጵ', 'ጶ', 'ጸ', 'ጹ', 'ጻ', 'ጽ', 'ጾ', 'ጿ', 'ፀ', 'ፁ', 'ፃ', 'ፅ', 'ፆ', 'ፈ', 'ፉ', 'ፊ', 'ፋ', 'ፌ', 'ፍ', 'ፎ', 'ፏ', 'ፐ', 'ፑ', 'ፒ', 'ፓ', 'ፔ', 'ፕ', 'ፖ', '፡', '።', '፣', '፤', '፥', '፦', '–', '‘', '’', '“', '”', '‹', '›', '⁰', '💪', '📢', '🙏', '🧴', '🧼']\n",
      "4000\n"
     ]
    }
   ],
   "source": [
    "\"\"\"\n",
    "Please change this with the tokenizer you have created for your dataset.\n",
    "\"\"\"\n",
    "# Create the vocabulary\n",
    "chars = sorted(list(set(text)))\n",
    "vocab_size = 4000 # check BPETokenizer initialization\n",
    "\n",
    "print(chars)\n",
    "print(vocab_size)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b554e9f4-4420-4adb-9297-758aa85588a8",
   "metadata": {},
   "source": [
    "# Model Class Definition"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "c0a7617c-e65a-40ed-aa74-c716d87be947",
   "metadata": {},
   "outputs": [],
   "source": [
    "class SimpleRNNModel(nn.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.embedding = nn.Embedding(vocab_size, hyperparams['n_embd'])\n",
    "        # print(f\"Embedding layer: {vocab_size} x {n_embd}\")\n",
    "        # self.rnn = nn.RNN(n_embd, n_hidden, batch_first=True)\n",
    "        self.rnn = nn.LSTM(hyperparams['n_embd'], hyperparams['n_hidden'], batch_first=True)\n",
    "        # print(f\"RNN layer: {n_embd} -> {n_hidden}\")\n",
    "        self.fc = nn.Linear(hyperparams['n_hidden'], vocab_size)\n",
    "        # print(f\"Linear layer: {n_hidden} -> {vocab_size}\")\n",
    "        self.dropout = nn.Dropout(hyperparams['dropout'])\n",
    "\n",
    "\n",
    "    def forward(self, idx, targets=None):\n",
    "        B, T = idx.shape\n",
    "        # print(f\"Input shape in forward: {idx.shape}\")\n",
    "        # print(f\"Max token in input: {idx.max()}\")\n",
    "        \n",
    "        embeds = self.embedding(idx)\n",
    "        # print(f\"Embedding output shape: {embeds.shape}\")\n",
    "        \n",
    "        output, _ = self.rnn(embeds)\n",
    "        # print(f\"RNN output shape: {output.shape}\")\n",
    "        \n",
    "        output = self.dropout(output)\n",
    "        logits = self.fc(output)\n",
    "        # print(f\"Logits shape: {logits.shape}\")\n",
    "        \n",
    "        if targets is None:\n",
    "            loss = None\n",
    "        else:\n",
    "            # print(f\"Targets shape: {targets.shape}\")\n",
    "            # print(f\"Max token in targets: {targets.max()}\")\n",
    "            B, T, C = logits.shape\n",
    "            logits = logits.view(B*T, C)\n",
    "            targets = targets.view(B*T)\n",
    "            loss = F.cross_entropy(logits, targets)\n",
    "        \n",
    "        return logits, loss\n",
    "\n",
    "\n",
    "    def generate(self, idx, max_new_tokens):\n",
    "        for _ in range(max_new_tokens):\n",
    "            idx_cond = idx[:, -hyperparams['block_size']:]\n",
    "            embeds = self.embedding(idx_cond)\n",
    "            output, _ = self.rnn(embeds)\n",
    "            logits = self.fc(output[:, -1, :])\n",
    "            probs = F.softmax(logits, dim=-1)\n",
    "            idx_next = torch.multinomial(probs, num_samples=1)\n",
    "            idx = torch.cat((idx, idx_next), dim=1)\n",
    "        return idx\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "045d03c3-87e6-46a4-887b-521da832e208",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "12.447648 M parameters\n"
     ]
    }
   ],
   "source": [
    "\"\"\" Lets get things ready for the training \"\"\"\n",
    "model = SimpleRNNModel().to(device) # Send the model to GPU\n",
    "print(sum(p.numel() for p in model.parameters())/1e6, 'M parameters') # How many parameters we have in our model?\n",
    "\n",
    "# Create an optimizer\n",
    "optimizer = torch.optim.AdamW(model.parameters(), lr=hyperparams['learning_rate'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "65249553-2a6f-4208-a451-88fb2b9b9c17",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train data size: 10100769\n",
      "Validation data size: 2525193\n",
      "Vocabulary size: 4000\n"
     ]
    }
   ],
   "source": [
    "print(f\"Train data size: {len(train_data)}\")\n",
    "print(f\"Validation data size: {len(val_data)}\")\n",
    "print(f\"Vocabulary size: {vocab_size}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "57ca28e4-cb1c-4fd2-a9fb-cfed554cc8c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "def calculate_perplexity(model, data, block_size=hyperparams['block_size'], batch_size=hyperparams['batch_size']):\n",
    "    model.eval()\n",
    "    total_loss = 0\n",
    "    total_tokens = 0\n",
    "\n",
    "    with torch.no_grad():\n",
    "        for i in range(0, len(data) - block_size, block_size):\n",
    "            current_batch_size = batch_size\n",
    "            \n",
    "            # Adjust batch size for the last batch if not enough data\n",
    "            if i + block_size * batch_size > len(data):\n",
    "                current_batch_size = (len(data) - i) // block_size\n",
    "            \n",
    "            x = []\n",
    "            y = []\n",
    "            \n",
    "            # Collect chunks for x and y, ensuring they're consistent\n",
    "            for j in range(0, block_size * current_batch_size, block_size):\n",
    "                x_chunk = data[i+j : i+j+block_size]\n",
    "                y_chunk = data[i+j+1 : i+j+block_size+1]\n",
    "                \n",
    "                # Skip this batch if we have any incomplete chunks\n",
    "                if len(x_chunk) == block_size and len(y_chunk) == block_size:\n",
    "                    x.append(x_chunk)\n",
    "                    y.append(y_chunk)\n",
    "\n",
    "            if len(x) == 0 or len(y) == 0:\n",
    "                continue\n",
    "\n",
    "            x = torch.stack(x).to(model.embedding.weight.device)\n",
    "            y = torch.stack(y).to(model.embedding.weight.device)\n",
    "\n",
    "            logits, _ = model(x)\n",
    "            loss = F.cross_entropy(logits.view(-1, logits.size(-1)), y.view(-1), reduction='sum')\n",
    "            \n",
    "            total_loss += loss.item()\n",
    "            total_tokens += y.numel()\n",
    "\n",
    "    avg_loss = total_loss / total_tokens\n",
    "    perplexity = torch.exp(torch.tensor(avg_loss))\n",
    "\n",
    "    return perplexity.item()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "54863d6a-48bb-4aaa-864f-07ee6849a727",
   "metadata": {},
   "source": [
    "# Training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "04e07290-2a7f-4018-8519-dd8c99c527dd",
   "metadata": {},
   "outputs": [],
   "source": [
    "save_path = 'cp_10k_500char_words_v5/'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "33d5be6f-1c16-48c5-bf62-ff40ff249c00",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initialize variables to track the best model\n",
    "best_val_loss = float('inf')\n",
    "best_model_state = None\n",
    "train_losses = []\n",
    "val_losses = []\n",
    "perplexities = []\n",
    "save_path = '../'\n",
    "for iter in range(hyperparams['max_iters']):\n",
    "    try:\n",
    "        # Evaluation phase\n",
    "        if iter % hyperparams['eval_interval'] == 0:\n",
    "            model.eval()  # Set to evaluation mode for validation\n",
    "            losses = estimate_loss()\n",
    "            train_loss = losses['train']\n",
    "            val_loss = losses['val']\n",
    "            train_losses.append(train_loss)\n",
    "            val_losses.append(val_loss)\n",
    "\n",
    "            # Calculate perplexity\n",
    "            perplexity = calculate_perplexity(model, val_data, hyperparams['block_size'], hyperparams['batch_size'])\n",
    "            perplexities.append(perplexity)\n",
    "\n",
    "            print(f\"Step {iter}: train loss {train_loss:.4f}, val loss {val_loss:.4f}, perplexity {perplexity:.4f}\")\n",
    "\n",
    "            # Save the model and check for overfitting\n",
    "            torch.save(model.state_dict(), f\"{save_path}checkpoint_{iter}.pt\")\n",
    "            if val_loss < best_val_loss:\n",
    "                best_val_loss = val_loss\n",
    "                best_model_state = model.state_dict()\n",
    "                torch.save(best_model_state, f\"{save_path}best_model.pt\")\n",
    "                print(\"New best model saved.\")\n",
    "            \n",
    "            if len(val_losses) > 3 and val_losses[-1] > val_losses[-2] > val_losses[-3]:\n",
    "                print(\"Overfitting detected. Exiting training.\")\n",
    "                break\n",
    "\n",
    "        # Training phase\n",
    "        model.train()  # Set to training mode\n",
    "        print(f\"\\nIteration {iter}:\")\n",
    "        xb, yb = get_batch('train')\n",
    "        \n",
    "        logits, loss = model(xb, yb)\n",
    "        print(f\"Loss: {loss.item()}\")\n",
    "        \n",
    "        optimizer.zero_grad(set_to_none=True)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        \n",
    "    except RuntimeError as e:\n",
    "        print(f\"Error at iteration {iter}: {e}\")\n",
    "        print(\"Last shapes:\")\n",
    "        print(f\"xb shape: {xb.shape}, yb shape: {yb.shape}\")\n",
    "        print(f\"xb max token: {xb.max()}, yb max token: {yb.max()}\")\n",
    "        break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "403799c6-9d99-4eb3-8e4b-9d5474320b28",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Save final training state\n",
    "if best_model_state is not None:\n",
    "    model.load_state_dict(best_model_state)\n",
    "    torch.save(model.state_dict(), f\"{save_path}best_model_final.pt\")\n",
    "    print(\"Best model saved as best_model_final.pt\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "74e4fe82-a31b-4749-b960-e516aa6e2d6c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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9z558mSuuuoqRowYwaZNm1iwYEGF3vHyz500aRJ33nkn/fv3Z+vWrXz++ecVeuAB4uPjCQkJ4b333iMwMBB/f38uvPBCWrVqVenzR40axSWXXMJTTz1FYmIi3bt3Z+HChcybN4+JEydWWCSuJvz6668UFhZWah89ejR//etfef/99xk3bhwbNmwgLi6Ob775hlWrVvHmm286evrvueceMjIyuPTSS4mJiSEpKYkpU6bQo0cPx/z1Tp06MWTIEHr37k1YWBjr16/nm2++YcKECTX6fUREpOYopIuIiFsLDw9n/vz5PProozz99NOEhoZy2223cdlllzF8+HBXlwdA7969WbBgAY899hjPPPMMsbGxTJo0iZ07d55x9XlPT0++//57Hn74YSZPnoyPjw/XXnstEyZMoHv37udUj9ls5rvvvmPixInMmDEDk8nE1VdfzRtvvEHPnj3P6l633norM2fOJDo6mksvvbTCsXHjxpGamsr777/Pzz//TKdOnZgxYwazZs1i6dKlZ133iy++iI+PD++99x5LlizhwgsvZOHChYwcObLCef/85z/Jy8tj5syZfPXVV/Tq1YsffviBJ554osJ5np6efPrppzz55JPcf//9lJaWMnXq1CpDevmf2bPPPstXX33F1KlTiYuL47XXXuPRRx896+9yJj/99FOlRd4A4uLi6NKlC0uXLuWJJ57g008/JTs7m/bt2zN16lTGjRvnOPe2227jgw8+4J133iEzM5OmTZty00038dxzzzmGyT/88MN89913LFy4kKKiIlq2bMmLL77I448/XuPfSUREaobJ7k5dESIiIg3I6NGjtf2ViIiInBXNSRcREakBBQUFFd7v2bOHH3/8kSFDhrimIBEREamX1JMuIiJSA6Kjoxk3bhytW7cmKSmJd999l6KiIjZt2lRp728RERGR09GcdBERkRpwxRVX8MUXX5Camoq3tzf9+vXjpZdeUkAXERGRs6KedBERERERERE3oTnpIiIiIiIiIm5CIV1ERERERETETTS6Oek2m41Dhw4RGBiIyWRydTkiIiIiIiLSwNntdnJycmjWrBlms/O+8kYX0g8dOkRsbKyryxAREREREZFGJjk5mZiYGKfnNLqQHhgYCBh/OEFBQS6uRkRERERERBq67OxsYmNjHXnUmUYX0suHuAcFBSmki4iIiIiISJ2pzpRrLRwnIiIiIiIi4iYU0kVERERERETchEK6iIiIiIiIiJtodHPSRURERERE3IHdbqe0tBSr1erqUqQGeHp6YrFYzvs+CukiIiIiIiJ1rLi4mMOHD5Ofn+/qUqSGmEwmYmJiCAgIOK/7KKSLiIiIiIjUIZvNRkJCAhaLhWbNmuHl5VWtVb/Ffdntdo4dO8bBgwdp27btefWoK6SLiIiIiIjUoeLiYmw2G7Gxsfj5+bm6HKkhTZo0ITExkZKSkvMK6Vo4TkRERERExAXMZsWxhqSmRkPop0JERERERETETSiki4iIiIiIiLgJhXQRERERERFxmbi4ON58801Xl+E2FNJFRERERETkjEwmk9PHc889d073XbduHX/961/Pq7YhQ4YwceLE87qHu9Dq7iIiIiIiInJGhw8fdrz+6quvePbZZ9m9e7ej7eT9we12O1arFQ+PM0fOJk2a1Gyh9Zx60kVERERERFzMbreTX1zqkofdbq9WjU2bNnU8goODMZlMjve7du0iMDCQBQsW0Lt3b7y9vVm5ciX79u3jmmuuISoqioCAAPr27csvv/xS4b6nDnc3mUx89NFHXHvttfj5+dG2bVu+++678/rz/fbbb+ncuTPe3t7ExcXxxhtvVDj+zjvv0LZtW3x8fIiKiuL66693HPvmm2/o2rUrvr6+hIeHM3ToUPLy8s6rHmfUky4iIiIiIuJiBSVWOj37s0s+e8ek4fh51Uw0fOKJJ3j99ddp3bo1oaGhJCcnM2LECP7v//4Pb29vpk+fzqhRo9i9ezctWrQ47X2ef/55Xn31VV577TWmTJnCrbfeSlJSEmFhYWdd04YNG7jxxht57rnnuOmmm1i9ejUPPvgg4eHhjBs3jvXr1/Pwww/z2Wef0b9/fzIyMlixYgVgjB645ZZbePXVV7n22mvJyclhxYoV1f7FxrlQSBcREREREZEaMWnSJC6//HLH+7CwMLp37+54/8ILLzBnzhy+++47JkyYcNr7jBs3jltuuQWAl156ibfeeou1a9dyxRVXnHVN//73v7nssst45plnAGjXrh07duzgtddeY9y4cRw4cAB/f3+uuuoqAgMDadmyJT179gSMkF5aWsqYMWNo2bIlAF27dj3rGs6GQrq7KsyGhOXgGwJxF7u6GhERERERqUW+nhZ2TBruss+uKX369KnwPjc3l+eee44ffvjBEXgLCgo4cOCA0/t069bN8drf35+goCCOHj16TjXt3LmTa665pkLbgAEDePPNN7FarVx++eW0bNmS1q1bc8UVV3DFFVc4htp3796dyy67jK5duzJ8+HCGDRvG9ddfT2ho6DnVUh2ak+6u1n0EX90Kq992dSUiIiIiIlLLTCYTfl4eLnmYTKYa+x7+/v4V3j/22GPMmTOHl156iRUrVrB582a6du1KcXGx0/t4enpW+vOx2Ww1VufJAgMD2bhxI1988QXR0dE8++yzdO/enczMTCwWC4sWLWLBggV06tSJKVOm0L59exISEmqlFlBId19tLjOeE1dAqfMfYBEREREREXe0atUqxo0bx7XXXkvXrl1p2rQpiYmJdVpDx44dWbVqVaW62rVrh8VijCLw8PBg6NChvPrqq/zxxx8kJiayePFiwPgFwYABA3j++efZtGkTXl5ezJkzp9bq1XB3dxXVFfwiID8NDq7VkHcREREREal32rZty+zZsxk1ahQmk4lnnnmm1nrEjx07xubNmyu0RUdH8+ijj9K3b19eeOEFbrrpJtasWcPbb7/NO++8A8D8+fPZv38/gwYNIjQ0lB9//BGbzUb79u35/fff+fXXXxk2bBiRkZH8/vvvHDt2jI4dO9bKdwD1pLut/FIbRyL7G2/2/uraYkRERERERM7Bv//9b0JDQ+nfvz+jRo1i+PDh9OrVq1Y+a+bMmfTs2bPC48MPP6RXr158/fXXfPnll3Tp0oVnn32WSZMmMW7cOABCQkKYPXs2l156KR07duS9997jiy++oHPnzgQFBbF8+XJGjBhBu3btePrpp3njjTe48sora+U7AJjstbl2vBvKzs4mODiYrKwsgoKCXF3Oab2zdC97Fn7Ef7zehejucN9yV5ckIiIiIiI1oLCwkISEBFq1aoWPj4+ry5Ea4ux/17PJoepJd1P94yNYaStb2v/wFshLc21BIiIiIiIiUusU0t1Ul2ZBFHpHsMNm7MXHviWuLUhERERERERqnUK6m/KwmLmwdRjLbWX7A+7TvHQREREREZGGTiHdjfWLj2CZI6Qvhsa1fICIiIiIiEijo5DuxvrHh7PB1o58uzfkHoEj211dkoiIiIiIiNQihXQ31j4qkAB/f36zle3BpyHvIiIiIiIiDZpCuhszm030ax1+Yl669ksXERERERFp0BTS3dxF8SeF9ANroDjPtQWJiIiIiIhIrVFId3P948PZb48mxR4B1mJIWu3qkkRERERERKSWKKS7udYR/kQF+bDM2tVo0JB3ERERERGpx4YMGcLEiRNdXYbbUkh3cyaTif7xESy3dTcatHiciIiIiIi4wKhRo7jiiiuqPLZixQpMJhN//PHHeX/OtGnTCAkJOe/71FcK6fVAv/hwVts6Y8UMaX9CZrKrSxIRERERkUbm7rvvZtGiRRw8eLDSsalTp9KnTx+6devmgsoaFoX0eqB/fDjZ+LPFFm807Fvs2oJERERERKRm2e3GItGueNjt1SrxqquuokmTJkybNq1Ce25uLrNmzeLuu+8mPT2dW265hebNm+Pn50fXrl354osvavSP6sCBA1xzzTUEBAQQFBTEjTfeyJEjRxzHt2zZwiWXXEJgYCBBQUH07t2b9evXA5CUlMSoUaMIDQ3F39+fzp078+OPP9ZofefLw9UFyJnFhPrRIsyPZVnd6GXeYwx5732Hq8sSEREREZGaUpIPLzVzzWf/8xB4+Z/xNA8PD8aOHcu0adN46qmnMJlMAMyaNQur1cott9xCbm4uvXv35h//+AdBQUH88MMP3H777cTHx3PBBRecd6k2m80R0JctW0ZpaSnjx4/npptuYunSpQDceuut9OzZk3fffReLxcLmzZvx9PQEYPz48RQXF7N8+XL8/f3ZsWMHAQEB511XTVJIryf6x4ezfH03/s63sH8pWEvBov/5RERERESk7tx111289tprLFu2jCFDhgDGUPfrrruO4OBggoODeeyxxxznP/TQQ/z88898/fXXNRLSf/31V7Zu3UpCQgKxsbEATJ8+nc6dO7Nu3Tr69u3LgQMHePzxx+nQoQMAbdu2dVx/4MABrrvuOrp2NRbmbt269XnXVNOU8uqJfvHhfL0unlyTPwGFWXBoI8Se/w+5iIiIiIi4AU8/o0fbVZ9dTR06dKB///588sknDBkyhL1797JixQomTZoEgNVq5aWXXuLrr78mJSWF4uJiioqK8POr/mc4s3PnTmJjYx0BHaBTp06EhISwc+dO+vbtyyOPPMI999zDZ599xtChQ7nhhhuIjzemDj/88MM88MADLFy4kKFDh3Lddde53Tx6zUmvJ/rFh2PDzPLSzkaD5qWLiIiIiDQcJpMx5NwVj7Jh69V199138+2335KTk8PU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WSIiIiIiInIOFNLrOZPJRL/4cHLx41BgV6NRQ95FRERERETqJYX0BqB8yPsKWzejQUPeRURERERE6iWF9AagPKR/ndnWaEhYDtYSF1YkIiIiIiIi50IhvQFoEeZH8xBftpTGUeIdCkXZcHC9q8sSERERERGRs6SQ3gCUz0u3YWZPQB+jcZ/mpYuIiIiIiNQ3CukNRPmQ90VFnY0GLR4nIiIiIiJS7yikNxD9ykL6l+ltjIZDmyA/w4UViYiIiIiIyNlSSG8gooN9aR3hz2F7GDnB7QA77F/i6rJERERERETkLCikNyDlvelbfXobDXu1FZuIiIiIiEh9opDegPSPjwDg+9yORsO+X8Fud2FFIiIiIiIicjYU0huQi1qHATA7vQV2Dx/IOQzHdrm4KhEREREREakuhfQGJDzAmw5NAynCi2NhZVuxaZV3ERERERGRekMhvYEpH/K+zqOn0aD90kVEREREROoNhfQGpny/9FmZ7YyGpNVQUuDCikRERERERKS6FNIbmAtah2E2wdKMMKwB0VBaaAR1ERERERERcXsK6Q1MkI8nXWNCABMHQvsZjfu0FZuIiIiIiEh9oJDeAJUPeV9p72Y0aPE4ERERERGRekEhvQHq19oI6Z8fa40dExzbCVkpLq5KREREREREzkQhvQHqExeKp8XEriwPiqN6GI37l7i0JhERERERETkzhfQGyM/Lg56xoQDsCbzAaNSQdxEREREREbenkN5A9Subl76wqIvRsH8J2KwurEhERERERETORCG9gSpfPO6rQ5HYvYOg4Dgc2uzaokRERERERMQphfQGqkeLEHw8zRzJs5LbrL/RqK3YRERERERE3JpCegPl7WGhb1wYAFt9+hiN+zQvXURERERExJ0ppDdg5fPSv8/taDQkr4XCLBdWJCIiIiIiIs4opDdg/eMjAPgh2RN7eBuwWyFhuYurEhERERERkdNRSG/AujQLItDbg+zCUtKjLjYaNS9dRERERETEbSmkN2AeFjMXtjbmpa+z9DAa9/4KdrvrihIREREREZHTUkhv4PqVDXmfc7w1mD0hMwky9ru4KhEREREREamKQnoDV75f+soDBdhiLzIa92qVdxEREREREXfk0pA+efJk+vbtS2BgIJGRkYwePZrdu3dX+/ovv/wSk8nE6NGja6/Ieq59VCBh/l7kF1s5FN7PaNS8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",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA+UAAAIjCAYAAABlBbqXAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABwZklEQVR4nO3dd3xUVf7/8feUzGTSJiSkQugJHURUBFFwRQGxKwqigKjfdVdXXctafmLHvuquvYIFy+piLyygYkOkhSJIDT0hQEjvM/f3R8iYMQFDCLkzk9fz8ZjHzNx75t7PJBnCO+fccyyGYRgCAAAAAAAtzmp2AQAAAAAAtFaEcgAAAAAATEIoBwAAAADAJIRyAAAAAABMQigHAAAAAMAkhHIAAAAAAExCKAcAAAAAwCSEcgAAAAAATEIoBwAAAADAJIRyAAAOYvPmzbJYLJoxY4Zv29133y2LxdKo11ssFt19993NWtPw4cM1fPjwZj1msGro+9PcJk+erE6dOh2x4wMAWjdCOQAgZJx11lmKiIhQUVHRAdtMmDBBDodDe/fubcHKDt3q1at19913a/PmzWaX4vPNN9/IYrH4bmFhYerSpYsmTpyoTZs2mV1eiyktLdXdd9+tb775xuxSAAAhgFAOAAgZEyZMUFlZmT744IMG95eWluqjjz7SqFGjFB8f3+Tz3HHHHSorK2vy6xtj9erVuueeexoM5f/73//0v//974ie/2CuvfZavfHGG3rxxRc1ZswYvfvuuzr22GO1c+dO02o6kl566SWtXbvW97y0tFT33HMPoRwA0CwI5QCAkHHWWWcpOjpab731VoP7P/roI5WUlGjChAmHdR673a7w8PDDOsbhcDgccjgcpp3/xBNP1CWXXKLLLrtMTz31lB577DHl5eXptddeO+xjl5SUNEOFzSssLExOp9PsMgAAIYpQDgAIGS6XS+edd57mzZun3NzcevvfeustRUdH66yzzlJeXp5uuukm9e3bV1FRUYqJidHo0aO1fPnyPzxPQ9eUV1RU6O9//7sSEhJ859i+fXu9127ZskV//etf1b17d7lcLsXHx2vs2LF+PeIzZszQ2LFjJUknn3yyb7h4bc9sQ9eU5+bm6vLLL1dSUpLCw8PVv3//eiG59vrrxx57TC+++KK6du0qp9OpY489VosWLfrD930gf/rTnyRJWVlZvm1ffPGFTjzxREVGRio6OlpjxozRL7/84ve6yZMnKyoqShs3btTpp5+u6Oho3x9Mhg8frj59+mjJkiUaMmSIXC6XOnfurOeff75RNf3666+64IILFBcXp/DwcB1zzDH6+OOPfftzc3OVkJCg4cOHyzAM3/YNGzYoMjJSF110kV+dtdeUb968WQkJCZKke+65x/e9ufvuuzV9+nRZLBYtW7asXj0PPPCAbDabduzY0aj6AQCtB6EcABBSJkyYoOrqav3nP//x256Xl6fZs2fr3HPPlcvl0qZNm/Thhx/qjDPO0OOPP66bb75ZK1eu1LBhw5o0DPuKK67Qk08+qdNOO00PPfSQwsLCNGbMmHrtFi1apB9//FHjxo3Tv//9b1111VWaN2+ehg8frtLSUknSSSedpGuvvVaSdPvtt+uNN97QG2+8oZ49ezZ47rKyMg0fPlxvvPGGJkyYoEcffVRut1uTJ0/Wv/71r3rt33rrLT366KP685//rPvvv1+bN2/Weeedp6qqqkN+35K0ceNGSfJdEvDGG29ozJgxioqK0sMPP6ypU6dq9erVGjp0aL3h+NXV1Ro5cqQSExP12GOP6fzzz/ft27dvn04//XQNHDhQjzzyiNq3b6+//OUvevXVVw9azy+//KLjjz9ea9as0a233qp//vOfioyM1DnnnOO7tCExMVHPPfec5s+fr6eeekqS5PV6NXnyZEVHR+vZZ59t8NgJCQl67rnnJEnnnnuu73tz3nnn6YILLpDL5dLMmTPrvW7mzJkaPny42rVr14ivKACgVTEAAAgh1dXVRkpKijF48GC/7c8//7whyZg9e7ZhGIZRXl5ueDwevzZZWVmG0+k07r33Xr9tkozp06f7tt11111G3V+hmZmZhiTjr3/9q9/xLr74YkOScdddd/m2lZaW1qt5wYIFhiTj9ddf92177733DEnG119/Xa/9sGHDjGHDhvmeP/nkk4Yk48033/Rtq6ysNAYPHmxERUUZhYWFfu8lPj7eyMvL87X96KOPDEnGJ598Uu9cdX399deGJOPVV181du/ebezcudP47LPPjE6dOhkWi8VYtGiRUVRUZMTGxhpXXnml32tzcnIMt9vtt33SpEmGJOPWW29t8D1KMv75z3/6tlVUVBhHHXWUkZiYaFRWVvq9p7rfn1NOOcXo27evUV5e7tvm9XqNIUOGGOnp6X7nGT9+vBEREWGsW7fOePTRRw1JxocffujXZtKkSUbHjh19z3fv3l3v+1r3eKmpqX4/W0uXLq1XIwAAtegpBwCEFJvNpnHjxmnBggV+vbJvvfWWkpKSdMopp0iSnE6nrNaaX4Mej0d79+5VVFSUunfvrqVLlx7SOT///HNJ8vVu17r++uvrtXW5XL7HVVVV2rt3r7p166bY2NhDPm/d8ycnJ2v8+PG+bWFhYbr22mtVXFys+fPn+7W/6KKL1KZNG9/zE088UZIaPYP6lClTlJCQoNTUVI0ZM0YlJSV67bXXdMwxx2jOnDnKz8/X+PHjtWfPHt/NZrNp0KBB+vrrr+sd7y9/+UuD57Hb7frzn//se+5wOPTnP/9Zubm5WrJkSYOvycvL01dffaULL7xQRUVFvvPv3btXI0eO1Pr16/2GkD/99NNyu9264IILNHXqVF166aU6++yzG/V1aMjEiRO1c+dOv/c5c+ZMuVwuv1EAAADUIpQDAEJO7XXJtRO+bd++Xd99953GjRsnm80mqWao8hNPPKH09HQ5nU61bdtWCQkJWrFihQoKCg7pfFu2bJHValXXrl39tnfv3r1e27KyMt15551KS0vzO29+fv4hn7fu+dPT031/ZKhVO9x9y5Ytfts7dOjg97w2oO/bt69R57vzzjs1Z84cffXVV1qxYoV27typSy+9VJK0fv16STXXmSckJPjd/ve//9W71t9ut6t9+/YNnic1NVWRkZF+2zIyMiTpgEvFbdiwQYZhaOrUqfXOf9ddd0mSXw1xcXH697//rRUrVsjtduvf//53o74GB3LqqacqJSXFN4Td6/Xq7bff1tlnn63o6OjDOjYAIDTZzS4AAIDmNnDgQPXo0UNvv/22br/9dr399tsyDMNv1vUHHnhAU6dO1ZQpU3TfffcpLi5OVqtV119/vbxe7xGr7W9/+5umT5+u66+/XoMHD5bb7ZbFYtG4ceOO6Hnrqv3DxO8ZdSY8O5i+fftqxIgRDe6rfQ9vvPGGkpOT6+232/3/61F3xEJzqD3/TTfdpJEjRzbYplu3bn7PZ8+eLanmjxLbt29XbGxsk89vs9l08cUX66WXXtKzzz6rH374QTt37tQll1zS5GMCAEIboRwAEJImTJigqVOnasWKFXrrrbeUnp6uY4891rf//fff18knn6xXXnnF73X5+flq27btIZ2rY8eO8nq92rhxo1/veN21reued9KkSfrnP//p21ZeXq78/Hy/dr+f3f2Pzr9ixQp5vV6/gPvrr7/69reU2tECiYmJBwzujbVz506VlJT49ZavW7dOknyzof9ely5dJNUM32/M+b/88ku9/PLL+sc//qGZM2dq0qRJWrhwYb0/HtT1R9+biRMn6p///Kc++eQTffHFF0pISDjgHwgAAGD4OgAgJNX2it95553KzMystza5zWar1zP83nvvNWnJqtGjR0tSvaHPTz75ZL22DZ33qaeeksfj8dtWG0R/H9YbcvrppysnJ0fvvvuub1t1dbWeeuopRUVFadiwYY15G81i5MiRiomJ0QMPPNDgbO67d+9u9LGqq6v1wgsv+J5XVlbqhRdeUEJCggYOHNjgaxITEzV8+HC98MILys7OPuj58/PzdcUVV+i4447TAw88oJdffllLly7VAw88cNC6IiIifK9vSL9+/dSvXz+9/PLL+u9//6tx48YdNOQDAFo3fkMAAEJS586dNWTIEH300UeSVC+Un3HGGbr33nt12WWXaciQIVq5cqVmzpzp62k9FEcddZTGjx+vZ599VgUFBRoyZIjmzZunDRs21Gt7xhln6I033pDb7VavXr20YMECzZ0717ecWN1j2mw2PfzwwyooKJDT6dSf/vQnJSYm1jvm//3f/+mFF17Q5MmTtWTJEnXq1Envv/++fvjhBz355JMtei1zTEyMnnvuOV166aU6+uijNW7cOCUkJGjr1q367LPPdMIJJ+jpp59u1LFSU1P18MMPa/PmzcrIyNC7776rzMxMvfjiiwoLCzvg65555hkNHTpUffv21ZVXXqkuXbpo165dWrBggbZv3+5bi/66667T3r17NXfuXNlsNo0aNUpXXHGF7r//fp199tnq379/g8d3uVzq1auX3n33XWVkZCguLk59+vRRnz59fG0mTpyom266SZIYug4AOCh6ygEAIas2iB933HH1riO+/fbbdeONN2r27Nm67rrrtHTpUn322WdKS0tr0rleffVVXXvttfryyy/1j3/8Q1VVVfrss8/qtfvXv/6liRMnaubMmbrxxhuVnZ2tuXPnKioqyq9dcnKynn/+eeXm5uryyy/X+PHjtXr16gbP7XK59M0332jChAl67bXXdOONNyovL0/Tp0/Xdddd16T3czguvvhizZs3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AEeIK8ym1feONOW8h+rTTz9VVFSUqqqq5PV6dfHFF+uCCy7QjBkzlJGR4de2oqJC8fHxvucOh0P9+vWrd8z+/fv7ArokDR48WMXFxdq2bZs6duzo13blypXyeDx/eK4bb7xRH374oZ5++ml98cUXfvsa64orrtCLL76of/zjH9q1a5e++OILffXVV4d8nENFKA8Qt/53pVbuKNDzlxytUX1SzC4HAAAAwBFisVgOexh5Szn55JP13HPPyeFwKDU1VXa7Xe+++65sNpuWLFkim80/6NftVXa5XLJYLId1/uLi4kadKzc3V+vWrZPNZtP69es1atSoQz7XxIkTdeutt2rBggX68ccf1blzZ5144omHVX9jBMdPQiuQnhSllTsKtG5XsUb1MbsaAAAAAJAiIyPVrVs3v20DBgyQx+NRbm5uk0Lr8uXLVVZW5psR/aefflJUVJTS0tLqtW3suaZMmaK+ffvq8ssv15VXXqkRI0aoZ8+eDbZ1OBzyeDz1tsfHx+ucc87R9OnTtWDBAl122WWH/N6aglAeILonRUuS1u0qMrkSAAAAADiwjIwMTZgwQRMnTtQ///lPDRgwQLt379a8efPUr18/jRkz5qCvr6ys1OWXX6477rhDmzdv1l133aVrrrmmweXSGnOuZ555RgsWLNCKFSuUlpamzz77TBMmTNBPP/0kh8NR75idOnVSVlaWMjMz1b59e0VHR8vpdEqqGcJ+xhlnyOPxaNKkSc3zBfsDTPQWIDL2h/L1u4pNrgQAAAAADm769OmaOHGibrzxRnXv3l3nnHOOFi1apA4dOvzha0855RSlp6frpJNO0kUXXaSzzjpLd999d5PO9euvv+rmm2/Ws88+6+tpf/bZZ7Vnzx5NnTq1weOdf/75GjVqlE4++WQlJCTo7bff9u0bMWKEUlJSNHLkSKWmph7aF6WJLEZTFqsLIoWFhXK73SooKFBMTIzZ5RzQ9n2lGvrw1wqzWbT63lEKs/H3EgAAACDYlZeXKysrS507d1Z4OBM6T548Wfn5+frwww/NLqVBxcXFateunaZPn67zzjvvoG0P9r09lBxK8gsQ7WJdinTYVOUxtHlPidnlAAAAAECr4fV6lZubq/vuu0+xsbE666yzWuzchPIAYbFY1M13XTlD2AEAAACgpWzdulVJSUl666239Oqrr8pub7np15joLYBkJEZp+bZ8rdtVpDFiWTQAAAAAoWXGjBlml9CgTp06yawru+kpDyC+yd5ymYEdAAAAAFoDQnkAyUhm+DoAAAAQikJ8fu1Wqbm+p4TyAJKRFCVJ2rynRBXV9RezBwAAABBcwsLCJEmlpaUmV4LmVvs9rf0eNxXXlAeQ5JhwRTvtKqqoVtaeEvVIDtwl3AAAAAD8MZvNptjYWOXm5kqSIiIiZLFYTK4Kh8MwDJWWlio3N1exsbGy2WyHdTxCeQCxWCxKT4rS0q35WrermFAOAAAAhIDk5GRJ8gVzhIbY2Fjf9/ZwEMoDTEZStJZuzdf6XUz2BgAAAIQCi8WilJQUJSYmqqqqyuxy0AzCwsIOu4e8FqE8wKT71ionlAMAAAChxGazNVuQQ+hgorcAUzvZ23pmYAcAAACAkEcoDzDd9/eUb95bovIqZmAHAAAAgFBGKA8wCdFOuV1h8hrSpt0lZpcDAAAAADiCCOUBxmKx+Iawc105AAAAAIQ2QnkAYrI3AAAAAGgdCOUBKCOxtqecyd4AAAAAIJQRygNQxv6e8vW59JQDAAAAQCgjlAeg2uHrW/NKVVbJDOwAAAAAEKoI5QGobZRDbSLCZBjSxt0MYQcAAACAUEUoD0A1M7Az2RsAAAAAhDpCeYCqDeVrCeUAAAAAELII5QGqdq3y9czADgAAAAAhi1AeoFirHAAAAABCH6E8QNUOX9++r0wlFdUmVwMAAAAAOBII5QEqLtKhtlEOSdKGXIawAwAAAEAoIpQHsPREhrADAAAAQCgjlAew7sk1oXw9PeUAAAAAEJII5QEsff8M7Gtz6CkHAAAAgFBEKA9gtZO9rWf4OgAAAACEJEJ5AMvYf035zoJyFZVXmVwNAAAAAKC5EcoDmDsiTInRTklcVw4AAAAAoYhQHuAYwg4AAAAAoYtQHuBqJ3tbt4uecgAAAAAINYTyAFfbU85a5QAAAAAQegjlAe634ev0lAMAAABAqCGUB7ja4es5heUqKGMGdgAAAAAIJYTyABcTHqYUd7gkJnsDAAAAgFBDKA8C6b7ryhnCDgAAAAChhFAeBDISa2dgp6ccAAAAAEIJoTwI+CZ7yyWUAwAAAEAoIZQHAdYqBwAAAIDQRCgPArXXlO8uqtC+kkqTqwEAAAAANBdCeRCIctrVLtYlievKAQAAACCUEMqDREbtEPZchrADAAAAQKgglAcJ32Rv9JQDAAAAQMgglAeJ39YqJ5QDAAAAQKgglAeJ2uHr65mBHQAAAABCBqE8SHRLrAnle0sqtbe4wuRqAAAAAADNgVAeJCIcdnWIi5DEeuUAAAAAECoI5UHENwM715UDAAAAQEgglAcRJnsDAAAAgNBiaij/9ttvdeaZZyo1NVUWi0Uffvihb19VVZVuueUW9e3bV5GRkUpNTdXEiRO1c+dO8wo2GZO9AQAAAEBoMTWUl5SUqH///nrmmWfq7SstLdXSpUs1depULV26VLNmzdLatWt11llnmVBpYEhP3N9TnlskwzBMrgYAAAAAcLjsZp589OjRGj16dIP73G635syZ47ft6aef1nHHHaetW7eqQ4cOLVFiQOmWGCWrRcovrdLu4golRoebXRIAAAAA4DCYGsoPVUFBgSwWi2JjYw/YpqKiQhUVvy0ZVlhY2AKVtYzwMJs6xEVo895Srd9VTCgHAAAAgCAXNBO9lZeX65ZbbtH48eMVExNzwHYPPvig3G6375aWltaCVR55TPYGAAAAAKEjKEJ5VVWVLrzwQhmGoeeee+6gbW+77TYVFBT4btu2bWuhKltGd0I5AAAAAISMgB++XhvIt2zZoq+++uqgveSS5HQ65XQ6W6i6lpfuW6ucGdgBAAAAINgFdCivDeTr16/X119/rfj4eLNLMl1GnZ5ywzBksVhMrggAAAAA0FSmhvLi4mJt2LDB9zwrK0uZmZmKi4tTSkqKLrjgAi1dulSffvqpPB6PcnJyJElxcXFyOBxmlW2qLgmRslktKiqv1q7CCiW7mewNAAAAAIKVqaF88eLFOvnkk33Pb7jhBknSpEmTdPfdd+vjjz+WJB111FF+r/v66681fPjwliozoDjtNnWMj9Cm3SVat6uIUA4AAAAAQczUUD58+HAZhnHA/Qfb15plJEb7QvlJGQlmlwMAAAAAaKKgmH0d/jL2T/a2nsneAAAAACCoEcqDUEZyzWRva1kWDQAAAACCGqE8CNXOwL4ht5gh/gAAAAAQxAjlQahTfKTsVouKK6q1s6Dc7HIAAAAAAE1EKA9CDrtVndtGSqpZrxwAAAAAEJwI5UGqdgj7ekI5AAAAAAQtQnmQSt8/A/s6ZmAHAAAAgKBFKA9S9JQDAAAAQPAjlAcp31rlucXyepmBHQAAAACCEaE8SHWMj5TDZlVppUc78svMLgcAAAAA0ASE8iAVZrOqSwIzsAMAAABAMCOUB7H0/deVM9kbAAAAAAQnQnkQy0jcf105PeUAAAAAEJQI5UHM11OeSygHAAAAgGBEKA9itTOwb2AGdgAAAAAISoTyINYxPlIOu1XlVV5t21dqdjkAAAAAgENEKA9iNqtF3RJqesvX5jCEHQAAAACCDaE8yNUOYV+fywzsAAAAABBsCOVB7rdl0egpBwAAAIBgQygPchmsVQ4AAAAAQYtQHuRqh69v3F0sDzOwAwAAAEBQIZQHubQ2EQoPs6qy2qste0vMLgcAAAAAcAgI5UHOarWoW2JNbzlD2AEAAAAguBDKQ0AGk70BAAAAQFAilIcAQjkAAAAABCdCeQjwrVXO8HUAAAAACCqE8hCQnljTU75pT7GqPF6TqwEAAAAANBahPAS0i3UpwmFTlcdgBnYAAAAACCKE8hBgtVqUzgzsAAAAABB0COUhIp3J3gAAAAAg6BDKQ0TtZG+EcgAAAAAIHoTyEPHbsmgMXwcAAACAYEEoDxG1oXzznhJVVjMDOwAAAAAEA0J5iEhxhyvaaVe111DWHmZgBwAAAIBgQCgPERaLRd24rhwAAAAAggqhPIRkJNYMYV9PKAcAAACAoEAoDyHpSaxVDgAAAADBhFAeQjJYqxwAAAAAggqhPIR0T94/A/veEpVXeUyuBgAAAADwRwjlISQx2qmYcLu8hrRpNzOwAwAAAECgI5SHEIvF4hvCvj6XIewAAAAAEOgI5SEmnevKAQAAACBoEMpDTAYzsAMAAABA0CCUhxjf8HV6ygEAAAAg4BHKQ0ztWuVb8kpVVskM7AAAAAAQyAjlISYhyqnYiDAZhrRxN0PYAQAAACCQEcpDTN0Z2JnsDQAAAAACG6E8BDHZGwAAAAAEB0J5CGKyNwAAAAAIDoTyEJSeuH/4ei6hHAAAAAACGaE8BNUOX9+WV6bSymqTqwEAAAAAHAihPATFRzkVH+mQJG3I5bpyAAAAAAhUhPIQVbte+dochrADAAAAQKAilIeo7rWTvdFTDgAAAAABi1AeotJZqxwAAAAAAh6hPET9tiwaPeUAAAAAEKgI5SGqdgb2HfllKq5gBnYAAAAACESE8hAVG+FQQrRTkrSeIewAAAAAEJAI5SGstrecIewAAAAAEJgI5SEsPbHmuvK19JQDAAAAQEAilIew7snMwA4AAAAAgYxQHsIYvg4AAAAAgY1QHsK67R++nlNYroKyKpOrAQAAAAD8nqmh/Ntvv9WZZ56p1NRUWSwWffjhh377Z82apdNOO03x8fGyWCzKzMw0pc5g5XaFKTkmXJK0IZch7AAAAAAQaEwN5SUlJerfv7+eeeaZA+4fOnSoHn744RauLHSk7x/Cvo4h7AAAAAAQcOxmnnz06NEaPXr0AfdfeumlkqTNmze3UEWhJyMpWt+t38NkbwAAAAAQgEwN5UdCRUWFKioqfM8LCwtNrMZ8Gb6eckI5AAAAAASakJvo7cEHH5Tb7fbd0tLSzC7JVOlJtcuiMXwdAAAAAAJNyIXy2267TQUFBb7btm3bzC7JVOmJNT3lu4sqlF9aaXI1AAAAAIC6Qi6UO51OxcTE+N1as+jwMLWLdUmitxwAAAAAAk3IhXLUl8515QAAAAAQkEyd6K24uFgbNmzwPc/KylJmZqbi4uLUoUMH5eXlaevWrdq5c6ckae3atZKk5ORkJScnm1JzMMpIitY3a3drPaEcAAAAAAKKqT3lixcv1oABAzRgwABJ0g033KABAwbozjvvlCR9/PHHGjBggMaMGSNJGjdunAYMGKDnn3/etJqDUe115QxfBwAAAIDAYmpP+fDhw2UYxgH3T548WZMnT265gkJUhm8GdnrKAQAAACCQcE15K9Btf0/53pJK7S2u+IPWAAAAAICWQihvBSKddqXFMQM7AAAAAAQaQnkrkZFYM4R9fS5D2AEAAAAgUBDKW4l0risHAAAAgIBDKG8lMpKYgR0AAAAAAg2hvJWonYF9/a6ig854DwAAAABoOYTyVqJrQpQsFmlfaZV2MwM7AAAAAAQEQnkr4XLY1CEuQpK0niHsAAAAABAQCOWtSHoik70BAAAAQCAhlLci3ZOZ7A0AAAAAAgmhvBWpO9kbAAAAAMB8hPJWpO7wdWZgBwAAAADzEcpbkS4JkbJapMLyauUWMQM7AAAAAJiNUN6KhIfZ1Ck+UhKTvQEAAABAICCUtzLpSTWTva3NIZQDAAAAgNkI5a3Mb5O9MQM7AAAAAJiNUN7K1Ibydbn0lAMAAACA2QjlrUxtKN+wq5gZ2AEAAADAZITyVqZz20jZrRYVVVQru6Dc7HIAAAAAoFUjlLcyDrtVndoyAzsAAAAABAJCeSuUsX8GdiZ7AwAAAABzEcpbofTEmuvK19JTDgAAAACmIpS3Qr8ti0YoBwAAAAAzEcpbId/w9dxieb3MwA4AAAAAZiGUt0Kd2kYqzGZRaaVHO/LLzC4HAAAAAFotQnkrFGazqkvb2t5yhrADAAAAgFkI5a1U+v4h7OuYgR0AAAAATEMob6VqJ3tjrXIAAAAAMA+hvJXK8PWUE8oBAAAAwCyE8lYqfX9P+QZmYAcAAAAA0xDKW6mOcRFy2Kwqr/Jq275Ss8sBAAAAgFaJUN5K2W1WdU1ksjcAAAAAMBOhvBWrva48c9s+kysBAAAAgNaJUN6KjeiZJEl6d9E2lVd5TK4GAAAAAFofQnkrNrpPstrFurSnuFIfZe4wuxwAAAAAaHUI5a2Y3WbV5CGdJEkvf5clw2AWdgAAAABoSYTyVu6i49IU5bRrfW6x5q/bbXY5AAAAANCqEMpbuZjwMF10bJqkmt5yAAAAAEDLIZRDl53QSVaL9P2GPVqTXWh2OQAAAADQajQplE+fPl2lpaXNXQtM0r5NhEb3TZFEbzkAAAAAtKQmhfJbb71VycnJuvzyy/Xjjz82d00wwZUndpEkfbx8h3ILy02uBgAAAABahyaF8h07dui1117Tnj17NHz4cPXo0UMPP/ywcnJymrs+tJCj0mJ1TMc2qvIYem3BZrPLAQAAAIBWoUmh3G6369xzz9VHH32kbdu26corr9TMmTPVoUMHnXXWWfroo4/k9Xqbu1YcYVec2FmSNHPhVpVWVptcDQAAAACEvsOe6C0pKUlDhw7V4MGDZbVatXLlSk2aNEldu3bVN9980wwloqWc2itZHeIilF9apf8u2W52OQAAAAAQ8pocynft2qXHHntMvXv31vDhw1VYWKhPP/1UWVlZ2rFjhy688EJNmjSpOWvFEWazWjTlhE6SpFe+z5LXa5hbEAAAAACEuCaF8jPPPFNpaWmaMWOGrrzySu3YsUNvv/22RowYIUmKjIzUjTfeqG3btjVrsTjyxh6TpphwuzbvLdXcNbvMLgcAAAAAQpq9KS9KTEzU/PnzNXjw4AO2SUhIUFYWy2sFm0inXRcP6qjn52/Uy99n6bTeyWaXBAAAAAAhq0k95cOGDdPRRx9db3tlZaVef/11SZLFYlHHjh0PrzqYYvKQTrJbLfo5K08rtuebXQ4AAAAAhKwmhfLLLrtMBQUF9bYXFRXpsssuO+yiYK5kd7jO7J8qSXr5O0Y7AAAAAMCR0qRQbhiGLBZLve3bt2+X2+0+7KJgvsuH1iyP9tnKbO3ILzO5GgAAAAAITYd0TfmAAQNksVhksVh0yimnyG7/7eUej0dZWVkaNWpUsxeJltennVuDu8Rrwaa9eu3Hzbr99J5mlwQAAAAAIeeQQvk555wjScrMzNTIkSMVFRXl2+dwONSpUyedf/75zVogzHPlSZ21YNNevb1wq/72p26KDg8zuyQAAAAACCmHFMrvuusuSVKnTp100UUXKTw8/IgUhcAwPCNRXRIitWl3if6zeLtvSDsAAAAAoHk06ZrySZMmEchbAavVoiuGdpEkvfp9lqo9XpMrAgAAAIDQ0uhQHhcXpz179kiS2rRpo7i4uAPeEDrOO7qd4iId2pFfptm/7DK7HAAAAAAIKY0evv7EE08oOjra97ih2dcResLDbLrk+I7697z1eum7TTq9bzLfewAAAABoJhbDMAyziziSCgsL5Xa7VVBQoJiYGLPLCUq7iyp0wsNfqbLaq//+ZbAGdmQ0BAAAAAAcyKHk0CZdUz5jxowGt1dXV+u2225ryiERwBKinTr3qHaSpJe+zTK5GgAAAAAIHU0K5ddee63Gjh2rffv2+batXbtWgwYN0ttvv91sxSFwXH5izczrs1fnaMveEpOrAQAAAIDQ0KRQvmzZMm3fvl19+/bVnDlz9Mwzz+joo49Wjx49tHz58uauEQEgIylawzISZBjS9B82m10OAAAAAISEJoXyrl276ocfftB5552nUaNG6e9//7tefvllzZw5U263u7lrRIC4Yn9v+X8Wb1NBaZXJ1QAAAABA8GtSKJekzz77TO+8844GDx6s2NhYvfLKK9q5c2dz1oYAM7RbW/VIjlZppUdvL9pqdjkAAAAAEPSaFMr//Oc/a+zYsbrlllv03XffacWKFXI4HOrbt6/+85//NHeNCBAWi0WXD63pLZ/xw2ZVVntNrggAAAAAgluTQvkPP/yghQsX6sYbb5TFYlFycrI+//xz3XvvvZoyZUqjj/Ptt9/qzDPPVGpqqiwWiz788EO//YZh6M4771RKSopcLpdGjBih9evXN6VkNJOzjkpVQrRTOYXl+nxlttnlAAAAAEBQa1IoX7Jkifr3719v+9VXX60lS5Y0+jglJSXq37+/nnnmmQb3P/LII/r3v/+t559/XgsXLlRkZKRGjhyp8vLyppSNZuC02zRpcEdJ0kvfbVKIL3MPAAAAAEdUk0K50+nUxo0bdccdd2j8+PHKzc2VJH3xxReqrq5u9HFGjx6t+++/X+eee269fYZh6Mknn9Qdd9yhs88+W/369dPrr7+unTt31utRR8uaMKijwsOs+mVnoX7alGd2OQAAAAAQtJoUyufPn6++fftq4cKFmjVrloqLiyVJy5cv11133dUshWVlZSknJ0cjRozwbXO73Ro0aJAWLFhwwNdVVFSosLDQ74bm1SbSoQsGtpckvfzdJpOrAQAAAIDg1aRQfuutt+r+++/XnDlz5HA4fNv/9Kc/6aeffmqWwnJyciRJSUlJftuTkpJ8+xry4IMPyu12+25paWnNUg/8TTmhsywWad6vudq4u9jscgAAAAAgKDUplK9cubLBIeeJiYnas2fPYRd1OG677TYVFBT4btu2bTO1nlDVJSFKp/So+YPJK99nmVwNAAAAAASnJoXy2NhYZWfXn3l72bJlateu3WEXJUnJycmSpF27dvlt37Vrl29fQ5xOp2JiYvxuODKuPLFmebT/LtmuvJJKk6sBAAAAgODTpFA+btw43XLLLcrJyZHFYpHX69UPP/ygm266SRMnTmyWwjp37qzk5GTNmzfPt62wsFALFy7U4MGDm+UcODzHdY5T33ZuVVR79eZPW8wuBwAAAACCTpNC+QMPPKAePXooLS1NxcXF6tWrl0466SQNGTJEd9xxR6OPU1xcrMzMTGVmZkqqmdwtMzNTW7dulcVi0fXXX6/7779fH3/8sVauXKmJEycqNTVV55xzTlPKRjOzWCy6Yn9v+esLNqu8ymNyRQAAAAAQXCzGYSw0vXXrVq1atUrFxcUaMGCA0tPTD+n133zzjU4++eR62ydNmqQZM2bIMAzdddddevHFF5Wfn6+hQ4fq2WefVUZGRqPPUVhYKLfbrYKCAoayHwFVHq9OeuRrZReU65Hz++nCY5lYDwAAAEDrdig59LBCeTAglB95L367UQ98/qsykqI0+/qTZLFYzC4JAAAAAExzKDnU3tiD3nDDDY0u4PHHH290WwS/i47toH/NXa91u4r17fo9GpaRYHZJAAAAABAUGh3Kly1b1qh29JK2Pm5XmC46toNe/SFLL3+3iVAOAAAAAI3U6FD+9ddfH8k6EOQuO6GTZvyYpe/W79GvOYXqkcylAgAAAADwR5o0+3pd27Zt07Zt25qjFgSxtLgIje6TIkl65bssk6sBAAAAgODQpFBeXV2tqVOnyu12q1OnTurUqZPcbrfuuOMOVVVVNXeNCBKX718e7aPMncotKje5GgAAAAAIfE0K5X/729/04osv6pFHHtGyZcu0bNkyPfLII3rllVd07bXXNneNCBJHd2ijgR3bqNLj1RsLtphdDgAAAAAEvCYtieZ2u/XOO+9o9OjRfts///xzjR8/XgUFBc1W4OFiSbSW9cXKbP1l5lK1iQjTj7eeIpfDZnZJAAAAANCiDiWHNqmn3Ol0qlOnTvW2d+7cWQ6HoymHRIg4rXey0uJc2ldapf8u3W52OQAAAAAQ0JoUyq+55hrdd999qqio8G2rqKjQtGnTdM011zRbcQg+NqtFU06oubb81e+z5PUe8kAMAAAAAGg1Gr0kWl3Lli3TvHnz1L59e/Xv31+StHz5clVWVuqUU07Reeed52s7a9as5qkUQePCY9L0+Jx12rSnRF/9mqsRvZLMLgkAAAAAAlKTQnlsbKzOP/98v21paWnNUhCCX6TTrosHddAL8zfppe82EcoBAAAA4AAOOZQbhqF77rlHCQkJcrlcR6ImhIDJQzrple+ytDArTyu3F6hve7fZJQEAAABAwDnka8oNw1C3bt20fTuTeOHAUtwundEvRZL08vebTK4GAAAAAALTIYdyq9Wq9PR07d2790jUgxByxYldJEmfrcjWzvwyk6sBAAAAgMDTpNnXH3roId18881atWpVc9eDENKnnVvHd4lTtdfQaz9uNrscAAAAAAg4FsMwDnnNqjZt2qi0tFTV1dVyOBz1ri3Py8trtgIP16Es2o7mN2/NLl3+2mJFh9u14LZTFOVs0tyCAAAAABA0DiWHNikhPfnkk015GVqhk7snqktCpDbtLtF/Fm3TlKGdzS4JAAAAAAJGk3rKgwk95eabuXCL/t8Hq9S+jUvzbz5ZNqvF7JIAAAAA4Ig5lBzapGvKJWnjxo264447NH78eOXm5kqSvvjiC/3yyy9NPSRC1HkD2qtNRJi27yvT7F9yzC4HAAAAAAJGk0L5/Pnz1bdvXy1cuFCzZs1ScXGxJGn58uW66667mrVABD+Xw6ZLj+8oSXr5O5ZHAwAAAIBaTQrlt956q+6//37NmTNHDofDt/1Pf/qTfvrpp2YrDqHjksEd5bBZtXRrvpZs2Wd2OQAAAAAQEJoUyleuXKlzzz233vbExETt2bPnsItC6EmMDtc5A1IlSa98T285AAAAAEhNDOWxsbHKzs6ut33ZsmVq167dYReF0HT50C6SpC9X5WhbXqnJ1QAAAACA+ZoUyseNG6dbbrlFOTk5slgs8nq9+uGHH3TTTTdp4sSJzV0jQkT35GidlJEgryH9a956s8sBAAAAANM1KZQ/8MAD6tmzpzp06KDi4mL16tVLJ510koYMGaI77rijuWtECPnbn7rJYpHeX7Jdn62oP9oCAAAAAFoT+6E09nq9evTRR/Xxxx+rsrJSl156qc4//3wVFxdrwIABSk9PP1J1IkQc2ylOfx3eVc98vVG3zlqhfu3dSouLMLssAAAAADDFIfWUT5s2TbfffruioqLUrl07vfXWW3r//fd14YUXEsjRaNePyNDAjm1UVF6tv729TFUer9klAQAAAIApDimUv/7663r22Wc1e/Zsffjhh/rkk080c+ZMeb2EKjRemM2qf407SjHhdmVuy9c//7fO7JIAAAAAwBSHFMq3bt2q008/3fd8xIgRslgs2rlzZ7MXhtDWvk2EHrmgnyTp+fkb9e263SZXBAAAAAAt75BCeXV1tcLDw/22hYWFqaqqqlmLQuswqk+KLj2+oyTphv9kKreo3OSKAAAAAKBlHdJEb4ZhaPLkyXI6nb5t5eXluuqqqxQZGenbNmvWrOarECHt/43pqUWb8/RrTpFueHe5Xp9ynKxWi9llAQAAAECLOKSe8kmTJikxMVFut9t3u+SSS5Samuq3DWis8DCbnr54gFxhNn2/YY+e/3aj2SUBAAAAQIuxGIZhmF3EkVRYWCi3262CggLFxMSYXQ4O4D+Ltukf/10hm9Wi//x5sAZ2bGN2SQAAAADQJIeSQw+ppxw4UsYe015n9U+Vx2vo2reXqaCUeQoAAAAAhD5COQKCxWLRtHP7qENchHbkl+nWWSsU4oM4AAAAAIBQjsARHR6mpy8eoDCbRV+sytHMhVvNLgkAAAAAjihCOQJKv/axumVUD0nSvZ+u1q85hSZXBAAAAABHDqEcAWfKCZ11cvcEVVZ7dc1by1RaWW12SQAAAABwRBDKEXCsVoseG9tfidFObcgt1r2frDa7JAAAAAA4IgjlCEjxUU49Oe4oWSzSO4u26ePlO80uCQAAAACaHaEcAWtI17b628ndJEm3z1qprXtLTa4IAAAAAJoXoRwB7dpT0nVspzYqrqjW395eqspqr9klAQAAAECzIZQjoNltVv1r3AC5XWFavr1Aj/1vrdklAQAAAECzIZQj4KXGuvTIBf0kSS9+u0lfr801uSIAAAAAaB6EcgSFkb2TNWlwR0nSjf9Zrl2F5SZXBAAAAACHj1COoHHb6T3VMyVGeSWV+vu7mfJ4DbNLAgAAAIDDQihH0AgPs+npiwcowmHTjxv36rlvNphdEgAAAAAcFkI5gkrXhCjde3YfSdITc9dr0eY8kysCAAAAgKYjlCPonH90O507oJ08XkPXvb1M+aWVZpcEAAAAAE1CKEfQsVgsuu+cPuoUH6GdBeW65b8rZBhcXw4AAAAg+BDKEZSinHY9ffHRCrNZNPuXXXrzpy1mlwQAAAAAh4xQjqDVp51bt43uKUm677M1Wr2z0OSKAAAAAODQEMoR1C47oZNO6ZGoymqvrnl7qUorq80uCQAAAAAajVCOoGaxWPTo2P5KinFq0+4S3fXRL2aXBAAAAACNRihH0IuLdOhf4wbIapHeW7JdHy7bYXZJAAAAANAohHKEhOO7xOtvf0qXJP2/D1Zq854SkysCAAAAgD9GKEfI+Nufuum4znEqqfTomreXqqLaY3ZJAAAAAHBQhHKEDLvNqn+NO0qxEWFataNQj3y51uySAAAAAOCgCOUIKSlulx67oL8k6ZXvszRvzS6TKwIAAACAAyOUI+SM6JWky07oJEm66b3lyikoN7cgAAAAADgAQjlC0q2je6h3aoz2lVbpuneWyeM1zC4JAAAAAOohlCMkOe02PTV+gCIcNi3MytMzX28wuyQAAAAAqIdQjpDVJSFK95/TR5L05Nx1Wrhpr8kVAQAAAIA/QjlC2nlHt9d5R7eT15AmT1+kjzJ3mF0SAAAAAPgEfCgvKirS9ddfr44dO8rlcmnIkCFatGiR2WUhiNx3dh+d0C1eZVUeXfdOpu78aBVrmAMAAAAICAEfyq+44grNmTNHb7zxhlauXKnTTjtNI0aM0I4d9HiicSKddr0+ZZCuObmbJOn1BVt04Qs/aUd+mcmVAQAAAGjtLIZhBOy01GVlZYqOjtZHH32kMWPG+LYPHDhQo0eP1v333/+HxygsLJTb7VZBQYFiYmKOZLkIAvPW7NLf381UYXm12kSE6clxAzQsI8HssgAAAACEkEPJoQHdU15dXS2Px6Pw8HC/7S6XS99//32Dr6moqFBhYaHfDah1Ss8kfXbtierTrma5tMnTf9aTc9fJy5JpAAAAAEwQ0KE8OjpagwcP1n333aedO3fK4/HozTff1IIFC5Sdnd3gax588EG53W7fLS0trYWrRqBLi4vQ+1cN0fjjOsgwpCfnrtfkGYuUV1JpdmkAAAAAWpmAHr4uSRs3btSUKVP07bffymaz6eijj1ZGRoaWLFmiNWvW1GtfUVGhiooK3/PCwkKlpaUxfB0Nen/Jdv2/D1aqotqrdrEuPTPhaB2VFmt2WQAAAACCWMgMX5ekrl27av78+SouLta2bdv0888/q6qqSl26dGmwvdPpVExMjN8NOJALBrbXh1efoE7xEdqRX6axz/+oNxZsVoD/rQoAAABAiAj4UF4rMjJSKSkp2rdvn2bPnq2zzz7b7JIQInqmxOjjvw3VyN5JqvIYmvrRL7r+3UyVVlabXRoAAACAEBfww9dnz54twzDUvXt3bdiwQTfffLPCw8P13XffKSws7A9fz+zraCzDMPTyd1l66Mtf5fEaSk+M0nOXDFS3xCizSwMAAAAQREJq+HpBQYGuvvpq9ejRQxMnTtTQoUM1e/bsRgVy4FBYLBZdeVIXvXXFICVEO7U+t1hnP/29Pl2x0+zSAAAAAISogO8pP1z0lKMpcovK9be3lmlhVp4k6bITOum20T3lsAf837EAAAAAmCykesoBMyRGh2vmFYN01bCukqTpP2zWuBcXKLugzOTKAAAAAIQSQjlwAHabVbeO7qEXLx2o6HC7lm7N1xn//l4/bNhjdmkAAAAAQgShHPgDp/VO1qd/G6qeKTHaW1KpS19ZqKe/Wi+vN6Sv/AAAAADQAgjlQCN0jI/UB38doguPaS+vIT32v3W64vXFyi+tNLs0AAAAAEGMUA40UniYTY9c0F+PnN9PTrtVX/2aqzOe+l4rtxeYXRoAAACAIEUoBw7Rhcem6b9/GaIOcRHavq9M5z/3o95auFUhvpABAAAAgCOAUA40QZ92bn3yt6Ea0TNJlR6vbv9gpW58b7nKKj1mlwYAAAAgiBDKgSZyu8L04qUDdcuoHrJapFlLd+jcZ39Q1p4Ss0sDAAAAECQI5cBhsFot+svwrnrzikFqG+XQrzlFOuup7/XlqmyzSwMAAAAQBAjlQDMY0rWtPrv2RB3bqY2KKqp11ZtLNe2z1aryeM0uDQAAAEAAI5QDzSQpJlxvXXm8rjyxsyTppe+yNOHlhdpbXGFyZQAAAAACFaEcaEZhNqv+35heev6SoxXltOvnrDyd9fQPWr2z0OzSAAAAAAQgQjlwBIzqk6IPrx6iTvER2pFfs2zaFyu5zhwAAACAP0I5cIR0S4zWR1cP1YnpbVVW5dFfZi7Vk3PXyetlPXMAAAAANQjlwBHkjgjT9MnH6rITOkmSnpy7Xle/tVSlldXmFgYAAAAgIBDKgSPMbrPqrjN76+Hz+yrMZtEXq3J0/nMLtH1fqdmlAQAAADAZoRxoIRcd20FvX3m82kY5tCa7UGc//YMWbc4zuywAAAAAJiKUAy3omE5x+uiaoeqVEqO9JZW6+KWf9M7PW80uCwAAAIBJCOVAC2sX69L7fxmsMX1TVOUxdOuslbr7419U7fGaXRoAAACAFkYoB0wQ4bDr6YsH6MZTMyRJM37crEnTf1Z+aaXJlQEAAABoSYRywCQWi0V/OyVdz18yUBEOm37YsFdnP/OD1u8qMrs0AAAAAC2EUA6YbFSfZM366xC1b+PSlr2lOvfZHzVvzS6zywIAAADQAgjlQADokRyjj68ZqkGd41RcUa0rXl+s577ZKMMwzC4NAAAAwBFEKAcCRFykQ29eMUgTBnWQYUgPf/mrrn83U+VVHrNLAwAAAHCEEMqBABJms2rauX113zl9ZLNa9FHmTl34wgLlFJSbXRoAAACAI4BQDgSgS4/vqDcuP06xEWFasb1AZz39vZZt3Wd2WQAAAACaGaEcCFBDurbVx1cPVfekaOUWVeiiF3/SrKXbzS4LAAAAQDMilAMBrEN8hP771yEa0TNJldVe3fCf5Xrw8zXyeJkADgAAAAgFhHIgwEU57Xrx0oG65uRukqQXvt2ky19bpMLyKpMrAwAAAHC4COVAELBaLbppZHc9NX6AwsOs+mbtbp3zzA/atLvY7NIAAAAAHAZCORBEzuyfqvf+PEQp7nBt2l2ic575Qd+u2212WQAAAACaiFAOBJm+7d366JoTdHSHWBWWV2vy9J/1yvdZMgyuMwcAAACCDaEcCEKJ0eF6+/+O1wUD28trSPd9ulr/eH+FKqo9ZpcGAAAA4BAQyoEg5bTb9OgF/TT1jF6yWqT3lmzXxS8t1O6iCrNLAwAAANBIhHIgiFksFl0+tLOmX3acosPtWrJln0b/6zu9sWAzveYAAABAECCUAyFgWEaCPrr6BHVNiNSe4gpN/egX/emx+frPom2q9njNLg8AAADAAViMEJ8dqrCwUG63WwUFBYqJiTG7HOCIqqj26D+LtumprzYod/8w9s5tI3X9iHSd0S9VNqvF5AoBAACA0HcoOZRQDoSg8iqP3vxpi579ZqPySiolSRlJUbrh1AyN7J0si4VwDgAAABwphPI6COVozYorqvXaj5v1wvyNKiyvliT1aRejG0/truHdEwjnAAAAwBFAKK+DUA5IBWVVeuW7TXrl+yyVVNZMAHd0h1jddFp3DenW1uTqAAAAgNBCKK+DUA78Jq+kUi/M36jXFmxWeVXNBHBDusbrxtMyNLBjnMnVAQAAAKGBUF4HoRyoL7ewXM98vUFv/bxVVZ6afwJO7p6gG0/rrj7t3CZXBwAAAAQ3QnkdhHLgwLbvK9XTX23Qe0u2y+Ot+adgVO9k/f3UDHVPjja5OgAAACA4EcrrIJQDf2zznhL9a956fZi5Q4YhWSzSWf1Tdf2IDHVuG2l2eQAAAEBQIZTXQSgHGm/9riI9MXedPl+ZI0myWS06/+h2+tuf0pUWF2FydQAAAEBwIJTXQSgHDt2qHQV6Ys46zfs1V5IUZrNo3LEddM2fuikpJtzk6gAAAIDARiivg1AONN3Srfv0+P/W6fsNeyRJTrtVEwd31FXDuio+ymlydQAAAEBgIpTXQSgHDt+CjXv1z/+t1eIt+yRJEQ6bppzQWVee2EXuiDCTqwMAAAACC6G8DkI50DwMw9C36/fon/9bqxXbCyRJ0eF2/d+JXXTZ0M6KctpNrhAAAAAIDITyOgjlQPMyDENzVu/S43PW6decIkmS2xWmcwe00wUD27POOQAAAFo9QnkdhHLgyPB6DX22MltPzFmnTXtKfNt7psRo7MD2OmdAO8VFOkysEAAAADAHobwOQjlwZHm8hr5bv1vvLdmuOb/sUqXHK6lmxvYRPZM09pj2Oik9QXab1eRKAQAAgJZBKK+DUA60nPzSSn2UuVPvLdmmVTsKfdsTo5069+h2GjswTd0So0ysEAAAADjyCOV1EMoBc6zJLtR7i7frw8wdyiup9G0f0CFWFx6TpjP6pSg6nJnbAQAAEHoI5XUQygFzVVZ79dWvuXpv8TZ9s263PN6af3LCw6wa3SdFYwe21/Fd4mW1WkyuFAAAAGgehPI6COVA4MgtKtcHS3fovSXbtSG32Le9fRuXzj+6vS4Y2F5pcREmVggAAAAcPkJ5HYRyIPAYhqHMbfl6b8l2fZK5U0UV1b59Q7rGa+wx7TWqd4pcDpuJVQIAAABNQyivg1AOBLaySo9m/5Kj95Zs048b96r2X6Rop11n9E/RBQPTdHSHWFksDG8HAABAcCCU10EoB4LH9n2l+u+SHXp/6TZtyyvzbe+aEKkLBqbp/KPbKTEm3MQKAQAAgD9GKK+DUA4EH6/X0MKsPL23eJs+X5Wt8qqatc9tVouGZSRo7MD2OqVnkhx21j4HAABA4CGU10EoB4JbUXmVPluRrfeWbNeSLft82+MiHRp3bJomDu6kZDe95wAAAAgchPI6COVA6Ni4u1jvL9muWUu3a1dhhSTJbrXojH4punxoF/Vt7za5QgAAAIBQ7odQDoSeao9Xc9fk6tXvs/Tz5jzf9mM7tdHlQzvr1F7JsrHuOQAAAExyKDk0oC/I9Hg8mjp1qjp37iyXy6WuXbvqvvvuU4j/HQHAH7DbrBrVJ1n/uWqwPrlmqM4d0E52q0WLNu/TVW8u1bBHv9bL321SYXmV2aUCAAAABxXQPeUPPPCAHn/8cb322mvq3bu3Fi9erMsuu0zTpk3Ttdde26hj0FMOtA67Csv1xoItmrlwi/aV1oTxKKddY49pr8lDOqljfKTJFQIAAKC1CJnh62eccYaSkpL0yiuv+Ladf/75crlcevPNNxt1DEI50LqUVXr0YeYOvfp9ltbnFkuSLBbp1J5JunxoZx3XOY41zwEAAHBEhczw9SFDhmjevHlat26dJGn58uX6/vvvNXr06AO+pqKiQoWFhX43AK2Hy2HT+OM66H9/P0mvTTlOwzISZBjS/1bv0kUv/qQznvpes5ZuV2W11+xSAQAAgMDuKfd6vbr99tv1yCOPyGazyePxaNq0abrtttsO+Jq7775b99xzT73t9JQDrdf6XUWa/uNmzVq63bfmeUK0UxOP76gJx3dUXKTD5AoBAAAQSkJm+Po777yjm2++WY8++qh69+6tzMxMXX/99Xr88cc1adKkBl9TUVGhiooK3/PCwkKlpaURygFoX0ml3vp5q15fsNm3pJrTbtW5A9ppytDOykiKNrlCAAAAhIKQCeVpaWm69dZbdfXVV/u23X///XrzzTf166+/NuoYXFMO4Pcqq736YlW2Xvk+Syu2F/i2n5jeVlOGdtaw9ARZWVINAAAATXQoOdTeQjU1SWlpqaxW/8vebTabvF6uBQXQdA67VWcf1U5n9U/V4i379Or3WZr9S46+W79H363fo64JkbrshM46/+j2cjlsZpcLAACAEBbQofzMM8/UtGnT1KFDB/Xu3VvLli3T448/rilTpphdGoAQYLFYdGynOB3bKU7b8kr12o+b9e6ibdq4u0R3fLhKj/1vrcYf10GTBndSsjvc7HIBAAAQggJ6+HpRUZGmTp2qDz74QLm5uUpNTdX48eN15513yuFo3MRMDF8HcCiKyqv03uLtmvHjZm3NK5Uk2a0WjemXoikndFb/tFhzCwQAAEDAC5lrypsDoRxAU3i8huau2aVXv8/Swqw83/b0xCiN7pOs0X1T1CM5mjXPAQAAUA+hvA5COYDDtWpHgV79IUufLs9Wpee3OS06t43UqD7JOr1Pivq0iyGgAwAAQBKh3A+hHEBzKSyv0ldrcvX5ymzNX7dbFdW/BfT2bVy+HvSj2scyezsAAEArRiivg1AO4EgoqajW12tz9cXKHH31a67Kqjy+fckx4TU96H1TNLBjG9kI6AAAAK0KobwOQjmAI62s0qP563bri1XZmrcmV8UV1b59baOcGtUnSaf3SdFxneNkt1kPciQAAACEAkJ5HYRyAC2pvMqjHzbs0ecrczRndY4Ky38L6HGRDp3WK0mj+6ZoSNd4hRHQAQAAQhKhvA5COQCzVFZ7tWDTXn2xMlv/W71LeSWVvn0x4Xad2itZp/dN1tD0tnLabSZWCgAAgOZEKK+DUA4gEFR7vPo5K0+fr8rWl6t2aU9xhW9flNOuU3omanSfFA3LSJDLQUAHAAAIZoTyOgjlAAKNx2toyZZ9+nxltr5claOcwnLfPleYTX/qkajRfZN1cvdERTrtJlYKAACApiCU10EoBxDIvF5Dmdvz9cXKbH2xKkfb95X59jntVg3LSNCInkk6KSNBye5wEysFAABAYxHK6yCUAwgWhmFo1Y5Cfb4qW1+szNbmvaV++zOSojQsI0EnZSTo2E5xCg9jmDsAAEAgIpTXQSgHEIwMw9CvOUX6clWO5q/brRXb8+Wt8691eJhVx3eJ10npNSG9a0KkLBbWQwcAAAgEhPI6COUAQkF+aaW+37BH367brfnrdmtXYYXf/naxLp2UkaBhGW01pFtbxYSHmVQpAAAACOV1EMoBhBrDMLRuV7G+Xbdb367frYVZeaqs9vr226wWDUiL9Q1179vOLauVXnQAAICWQiivg1AOINSVVXr0U9ZeXy/6pt0lfvvbRITpxP3D3E9Kb6vEGCaMAwAAOJII5XUQygG0Ntv3lerbdTVD3X/YsEdFFdV++3skR2tYRoKGZSRoYKc2ctqZMA4AAKA5EcrrIJQDaM2qPF5lbsuvGeq+brdW7ChQ3X/1XWE2De4a7xvq3ik+ggnjAAAADhOhvA5COQD8Jq+kUt+t313Tk75+t3YX+U8Ylxbn0knpCTquc5z6tHOrc3wk16MDAAAcIkJ5HYRyAGiYYRhak12kb9fX9KIv2pynKo//r4QIh029UmLUOzVGvdu51Ts1RumJ0XLYrSZVDQAAEPgI5XUQygGgcUoqqvXTpr36bv0erdier9XZhSqv8tZr57BZlZEcpT6pbl9Y75kcI5eDa9MBAAAkQrkfQjkANI3Ha2jT7mL9srNQq3YU1NzvLFBReXW9tlaL1DUhSn3296b3TnWrV2qM3C7WSwcAAK0PobwOQjkANB/DMLR9X5lfSF+1o1B7iisabN8hLkK9U2PUp11NSO+T6lZCtLOFqwYAAGhZhPI6COUAcOTlFpbX61Hfvq+swbaJ0U6/HvXeqTFq38bFrO8AACBkEMrrIJQDgDnySyu1en9Arw3sm/aUqKHfOm5XmLomRCopJlxJMeFKjHEqKdr/cYzLTnAHAABBgVBeB6EcAAJHSUW1fs0p9OtVX7erqN6s7w1x2q37Q7tTidH7w/r+50n7nyfGhCvaSXgHAADmOpQcam+hmgAAUKTTroEd4zSwY5xvW2W1V+t2FWlbXql2FZZrV1GFdhWWK7ewQrlF5dpVWKGCsipVVHu1Na9UW/NKD3oOV5itJrjHhCsxuk5wjwlXYnS4b1+Uk1+BAADAfPyPBABgKofdqj7t3OrTzn3ANuVVHuUWVmhXUU1Yrwnv/sF9V2G5isqrVVbl0ea9pdq89+DhPdJhU/s2EToqLVYDOsRqQIc26pYYJZuVXnYAANByGL4OAAgZZZUev5C+q7BcuUUVyi3cv21/kC+uqL+sm1QT1PvXhvS0NjqqQ6zaRjFbPAAAODRcU14HoRwA8HslFdXaVViuDbnFytyWr2Vb87V8e75KKz312naIi9gf0mN1VIc26pUSI4fdakLVAAAgWBDK6yCUAwAaw+M1tG5XkZZtzdeyrfu0bFu+NuQW12vnsFvVJzVGAzq08Q17T3WHM7kcAADwIZTXQSgHADRVQVmVVmzP9wvq+aVV9dolRjv3X5teE9T7tXcrwsG0LQAAtFaE8joI5QCA5mIYhjbvLa0J6FvzlbktX2uyC1Xt9f9VarNa1D0p2teTPqBDrDrHR8rKJHIAALQKhPI6COUAgCOprNKjVTsLfEF92dZ85RSW12sXE27XUR3aqF87t9LiXEpxu5Qa61JqbDi96gAAhBhCeR2EcgBAS8suKFPm1nwt21Yz7H3F9gJVVHsP2D42IkypdUJ6aqxLKe5wtYut2ZYY7ZTdxuRyAAAEC0J5HYRyAIDZqjxe/ZpdpGXb9mlNdpGyC8q0M79MO/PLD7g8W11Wi5QcE66U2DrB3e3/ODYijMnmAAAIEITyOgjlAIBAVlhepZ35ZcrOL9eO/Jqwnl1Q8zi7oGb7769Zb4grzKaU2P29626XUvb3uNeE95rH4WG2FnhHAADgUHIoF7EBAGCimPAwxSSHqUdyw7+wPV5De4orfD3rO/PLtLNOT3t2QZn2FFeqrMqjTbtLtGl3yQHPlRTjVPs2EWrfxqW02vu4mvsUt4v11wEAMAE95QAABLnyKo9yCmoC+479Pe11H+/YV6ayKs9Bj1E7RL42tLeP8w/vKe5wrmsHAKCR6CkHAKAVCQ+zqVPbSHVqG9ngfsMwlFdSqe37yrR9X5m27SvV9n2l2pZXpu37SrV9X5kqqr3aWVCunQXl+nlz/WPYrBaluMNrAnubiHo97Ukx4bKx5BsAAIeMUA4AQIizWCyKj3IqPsqp/mmx9fYbhqHdxRW/hfa80v2Pa+537CtTpcfr2y/l1TtGmM2i1FhXTWiPjVC7Ni6F2awyZKh2TJ7Xa8iQZBjybTf2n7/+tv3b/fbXbPfuP+Bv+397bWxEmJLdLqXEhCslNlwpbpfaMAkeACCAEcoBAGjlLBaLEqPDlRgdrqM7tKm33+utCe11w/q2vDJtz6+535lfpiqPoS17S7Vlb6mkvS3/Jg7CYbcqxR1eM4O9O1zJ+ye/q3nuUrI7XPGRDlnp6QcAmIBQDgAADspqtSgpJlxJMeE6plP9/R6voV2F5XVCe83M8dVeQxZJFotktVhU01ldc++3XfL1ZNfss8hq2f94/379frvfcWoeG4a0r7RS2QXlyikoV3ZBufYUV6iy2lvnDwYNC7PVvMcUd01Qrwnvv4X4FHe42kY5GaIPAGh2hHIAAHBYbFbL/jXTXRpkdjG/U1HtUW5hhbILamaqrw3rOfufZxeUa3dxhao8Rp3h+fsaPJZ9/x8nkmsD+/7HCdFOxUc6FR/lUHykQ20iHQpjUjwAQCMRygEAQMhy2m1Ki4tQWlzEAdtUebzKLapQzv6QXhvcs+s831VYs178jv2z2v+RmHC74qOciot0KC6yJqzXPm5bd3tUzb3TzhryANBaEcoBAECrFmazql2sS+1iXQdsU+3xak9xpa+3fWdBuS/E7ymu0N7iSuWVVGpfaaW8hlRYXq3C8mpl7TnwuvF1RTnt9QJ8fJTztzAfVWd7pFMuByEeAEIFoRwAAOAP2G1W37D1g/F4DRWUVSmv5Legvrek5j6vpFJ7iit8j/eWVGpfSaWqvYaKK6pVXFGtrXkHvu7drx6rRVarRXarRbY69zWPrbJaJbvV6ttntVhkt+1vY9nfzmaRzWqVzSLZrNbfHeO3x7XPLRaLqr1eebySx+tVtdeQx2vU3HsMeYw6z71eVXtqnvu2e2r3e33tvL72de+98nqlaq9XVotF7dq41CEuQh3jI9QxLlId4msed4iLUISD/8oCCH4Ww6hdqCQ0Hcqi7QAAAC3JMAwVllVrb0nFwQN88W/bKz1es8sOGAnRTnWMi1DH+Mia0L4/rHeMj2QpPACmOpQcyp8XAQAATGKxWOSOCJM7IkxdEv64vWHU9KqXVHhqeqA9+3uWjZqe5mqP4XvsqXOr7b3+fS/3gXqsvQ28xmvot150W21vuvWAvfa1PfW2hvb5eunrPq/fQ1/lMbQtr1Rb95ZqS16Jtuwt1da8mpn0C8qqtLuoQruLKrR4S/3J+aKd9jq96vtDe1yEOraNVHJMODPpAwgY9JQDAAAg6OSXVtYsdZdXqq17S+o8LlVOYflBX+uwWdU+zuXrZfcNj4+PUPs2EQoP45p9AIeHnnIAAACEtNgIh2IjHOqfFltvX3mVR9vySrV5b6m27C3x9a5vzSvV9n2lqvR4tWl3iTbtLpG0u97rrZaaCQBrbhbZbVY5bFbZbRaF2WpGBzjsNfcHaxfma29VmN2iMGtNW7vNUq9dhMOuKKddkc6a+yinXVHhdkU6bczOD4Q4QjkAAABCSniYTelJ0UpPiq63z+M1tDO/TFvzSrV5b0nN0Pg6Pe4llR55Dami2quK6sC4fj/MZqkX2CP3h/YoR214tyvKaVOUM0yRTpuiw+2KdNRsjw7/7bVOu5Vr7YEAQygHAABAq2GzWnxr15/Qra3fvtqJ9yqqPar01MwgX+Xxqmr/fbXXq8rqmuv4/bZ7jN+1r9lXXfvYa6iquuZa/pp29V9bWlntmy+gqLxaJRXVKqvySJKqPIb2lVZpX2nVYb9/u9XiC+hxkQ61jXIoIdpZc4tyKiE63Pe8bZRDUU57QIf4Ko9XeSWVNfMLFFdoT1GF9hTXPN9TXHOrqPYqJtyuGFeYYsLDFOOy779v6Lld0eFhctitZr81tCKEcgAAAEC/TbwnhZldiiSp2uNVSaVHJRU1Ib1o/31xeW2Ar96/nJ5HxRVVKqnw1Dwvr1ZJpX+7ksqagF+9f9m+grIq7cgv+8MawsOsdQJ7bXgP94X23wK8s9muxa/2eLW35LdgvXt/0P7tce2tZkWCI8EVZqsX1n8f4qMbCPS1bQj1OBSEcgAAACAA2W1WuV1WuV2H/0cCj9eo0xtfraLyau0rrfTNYF/b07y7Tk9zcUW1yqu82pZXpm15fxzgY8LtfiHdvwe+5mYY8gXqugH7t8eV2ldaqUOZitpmtezv9f+thz8hqu4fC6wqLK9WYVlVnfsqFZZV77+vUtH+7UUV1ZKksiqPyqo82lVY0aSvd6TDpnZtXGrfJkLt27j23yJ89yzZd3CGYaiwvFq5heXaVVihXYXl2lVUrtzCCuUUlKtdG5emntHL7DKbDaEcAAAACHE2q0XR+3t3G6u0slp7iiq1u7i8TnCv9Avxe/Y/rvR4awJvebU27i457HqtFik+ylkvaLetE7bbRtdsaxPhkLWZlrjzeA0Vl9eE9YIGwvtBQ315zb0klVR6tG5XsdbtKm7wPBEOmy+gp/0usLdv41JsCIf20srq34J2YU3Q3lVYrpzax0U128urDjynQ4/k+vNFBDNCOQAAAIB6Ihx2dYivWe/9YGqvxa/taffd/y685xZVyGJRTaCuHfreQNBuuz9om7GWvM1acwmDOyJMaU14vcdrqLiiWnuLK7Qjv0zb95Vp+77S/fc1j3cVVqj0D0J7pMN2wF72QA3tFdUe5RZWKLeoTu92YYVy9wfu2gBeOxqhMdyuMCXFOJUUE77/VvM4rc3BfyaDDeuUAwAAAEALKa/yaKcvsNcN7TX3uUV/PGS+odCe7A6XxVLzhwGP11C115C39t4wVO3Zf79/v9/NqL+t7us9Xq88hmru67Sp8hjaU1wTwA9lIsIIh03JMeFK3B+yax7/FrqTomv2Ndc8BWZgnXIAAAAACEDhYTZ1SYhSl4SoBvc3JrSXVHq0dleR1u4qauHqD85ht9YE6+ianm3/0P1bj3eUkxhaF18NAAAAAAgQTQ3tOYXlsqhmCL7NapF9//1vN6tsFtXcW3+7t1utslosstssNfdWi6y/e73dajlgm/gop5L393K7XYE3rD4YEMoBAAAAIEj8UWhH8GEBPQAAAAAATEIoBwAAAADAJIRyAAAAAABMQigHAAAAAMAkAR/KO3XqJIvFUu929dVXm10aAAAAAACHJeBnX1+0aJE8Ho/v+apVq3Tqqadq7NixJlYFAAAAAMDhC/hQnpCQ4Pf8oYceUteuXTVs2DCTKgIAAAAAoHkEfCivq7KyUm+++aZuuOGGAy5KX1FRoYqKCt/zwsLClioPAAAAAIBDEvDXlNf14YcfKj8/X5MnTz5gmwcffFBut9t3S0tLa7kCAQAAAAA4BBbDMAyzi2iskSNHyuFw6JNPPjlgm4Z6ytPS0lRQUKCYmJiWKBMAAAAA0IoVFhbK7XY3KocGzfD1LVu2aO7cuZo1a9ZB2zmdTjmdzhaqCgAAAACApgua4evTp09XYmKixowZY3YpAAAAAAA0i6AI5V6vV9OnT9ekSZNktwdN5z4AAAAAAAcVFKF87ty52rp1q6ZMmWJ2KQAAAAAANJug6HY+7bTTFETz0QEAAAAA0ChB0VMOAAAAAEAoIpQDAAAAAGASQjkAAAAAACYJimvKD0ftteiFhYUmVwIAAAAAaA1q82dj5kYL+VBeVFQkSUpLSzO5EgAAAABAa1JUVCS3233QNhYjxKc193q92rlzp6Kjo2WxWBr1msLCQqWlpWnbtm2KiYk5whUCgYvPAsDnAJD4HAC1+CygsQzDUFFRkVJTU2W1Hvyq8ZDvKbdarWrfvn2TXhsTE8OHDRCfBUDicwBIfA6AWnwW0Bh/1ENei4neAAAAAAAwCaEcAAAAAACTEMob4HQ6ddddd8npdJpdCmAqPgsAnwNA4nMA1OKzgCMh5Cd6AwAAAAAgUNFTDgAAAACASQjlAAAAAACYhFAOAAAAAIBJCOUAAAAAAJiEUN6AZ555Rp06dVJ4eLgGDRqkn3/+2eySgCZ58MEHdeyxxyo6OlqJiYk655xztHbtWr825eXluvrqqxUfH6+oqCidf/752rVrl1+brVu3asyYMYqIiFBiYqJuvvlmVVdX+7X55ptvdPTRR8vpdKpbt26aMWPGkX57QJM89NBDslgsuv76633b+BygtdixY4cuueQSxcfHy+VyqW/fvlq8eLFvv2EYuvPOO5WSkiKXy6URI0Zo/fr1fsfIy8vThAkTFBMTo9jYWF1++eUqLi72a7NixQqdeOKJCg8PV1pamh555JEWeX/AH/F4PJo6dao6d+4sl8ulrl276r777lPdua/5HKDFGfDzzjvvGA6Hw3j11VeNX375xbjyyiuN2NhYY9euXWaXBhyykSNHGtOnTzdWrVplZGZmGqeffrrRoUMHo7i42NfmqquuMtLS0ox58+YZixcvNo4//nhjyJAhvv3V1dVGnz59jBEjRhjLli0zPv/8c6Nt27bGbbfd5muzadMmIyIiwrjhhhuM1atXG0899ZRhs9mML7/8skXfL/BHfv75Z6NTp05Gv379jOuuu863nc8BWoO8vDyjY8eOxuTJk42FCxcamzZtMmbPnm1s2LDB1+ahhx4y3G638eGHHxrLly83zjrrLKNz585GWVmZr82oUaOM/v37Gz/99JPx3XffGd26dTPGjx/v219QUGAkJSUZEyZMMFatWmW8/fbbhsvlMl544YUWfb9AQ6ZNm2bEx8cbn376qZGVlWW89957RlRUlPGvf/3L14bPAVoaofx3jjvuOOPqq6/2Pfd4PEZqaqrx4IMPmlgV0Dxyc3MNScb8+fMNwzCM/Px8IywszHjvvfd8bdasWWNIMhYsWGAYhmF8/vnnhtVqNXJycnxtnnvuOSMmJsaoqKgwDMMw/vGPfxi9e/f2O9dFF11kjBw58ki/JaDRioqKjPT0dGPOnDnGsGHDfKGczwFai1tuucUYOnToAfd7vV4jOTnZePTRR33b8vPzDafTabz99tuGYRjG6tWrDUnGokWLfG2++OILw2KxGDt27DAMwzCeffZZo02bNr7PRu25u3fv3txvCThkY8aMMaZMmeK37bzzzjMmTJhgGAafA5iD4et1VFZWasmSJRoxYoRvm9Vq1YgRI7RgwQITKwOaR0FBgSQpLi5OkrRkyRJVVVX5/cz36NFDHTp08P3ML1iwQH379lVSUpKvzciRI1VYWKhffvnF16buMWrb8LlBILn66qs1ZsyYej+rfA7QWnz88cc65phjNHbsWCUmJmrAgAF66aWXfPuzsrKUk5Pj93Psdrs1aNAgv89CbGysjjnmGF+bESNGyGq1auHChb42J510khwOh6/NyJEjtXbtWu3bt+9Iv03goIYMGaJ58+Zp3bp1kqTly5fr+++/1+jRoyXxOYA57GYXEEj27Nkjj8fj958uSUpKStKvv/5qUlVA8/B6vbr++ut1wgknqE+fPpKknJwcORwOxcbG+rVNSkpSTk6Or01Dn4nafQdrU1hYqLKyMrlcriPxloBGe+edd7R06VItWrSo3j4+B2gtNm3apOeee0433HCDbr/9di1atEjXXnutHA6HJk2a5PtZbujnuO7PeWJiot9+u92uuLg4vzadO3eud4zafW3atDki7w9ojFtvvVWFhYXq0aOHbDabPB6Ppk2bpgkTJkgSnwOYglAOtBJXX321Vq1ape+//97sUoAWtW3bNl133XWaM2eOwsPDzS4HMI3X69UxxxyjBx54QJI0YMAArVq1Ss8//7wmTZpkcnVAy/jPf/6jmTNn6q233lLv3r2VmZmp66+/XqmpqXwOYBqGr9fRtm1b2Wy2ejPu7tq1S8nJySZVBRy+a665Rp9++qm+/vprtW/f3rc9OTlZlZWVys/P92tf92c+OTm5wc9E7b6DtYmJiaF3EKZbsmSJcnNzdfTRR8tut8tut2v+/Pn697//LbvdrqSkJD4HaBVSUlLUq1cvv209e/bU1q1bJf32s3yw/wclJycrNzfXb391dbXy8vIO6fMCmOXmm2/WrbfeqnHjxqlv37669NJL9fe//10PPvigJD4HMAehvA6Hw6GBAwdq3rx5vm1er1fz5s3T4MGDTawMaBrDMHTNNdfogw8+0FdffVVvGNXAgQMVFhbm9zO/du1abd261fczP3jwYK1cudLvl8+cOXMUExPj+8/d4MGD/Y5R24bPDQLBKaecopUrVyozM9N3O+aYYzRhwgTfYz4HaA1OOOGEestirlu3Th07dpQkde7cWcnJyX4/x4WFhVq4cKHfZyE/P19Llizxtfnqq6/k9Xo1aNAgX5tvv/1WVVVVvjZz5sxR9+7dGbIL05WWlspq9Y9ANptNXq9XEp8DmMTsmeYCzTvvvGM4nU5jxowZxurVq43/+7//M2JjY/1m3AWCxV/+8hfD7XYb33zzjZGdne27lZaW+tpcddVVRocOHYyvvvrKWLx4sTF48GBj8ODBvv21S0GddtppRmZmpvHll18aCQkJDS4FdfPNNxtr1qwxnnnmGZaCQkCrO/u6YfA5QOvw888/G3a73Zg2bZqxfv16Y+bMmUZERITx5ptv+to89NBDRmxsrPHRRx8ZK1asMM4+++wGl4IaMGCAsXDhQuP777830tPT/ZaCys/PN5KSkoxLL73UWLVqlfHOO+8YERERLAWFgDBp0iSjXbt2viXRZs2aZbRt29b4xz/+4WvD5wAtjVDegKeeesro0KGD4XA4jOOOO8746aefzC4JaBJJDd6mT5/ua1NWVmb89a9/Ndq0aWNEREQY5557rpGdne13nM2bNxujR482XC6X0bZtW+PGG280qqqq/Np8/fXXxlFHHWU4HA6jS5cufucAAs3vQzmfA7QWn3zyidGnTx/D6XQaPXr0MF588UW//V6v15g6daqRlJRkOJ1O45RTTjHWrl3r12bv3r3G+PHjjaioKCMmJsa47LLLjKKiIr82y5cvN4YOHWo4nU6jXbt2xkMPPXTE3xvQGIWFhcZ1111ndOjQwQgPDze6dOli/L//9//8li7jc4CWZjEMwzCzpx4AAAAAgNaKa8oBAAAAADAJoRwAAAAAAJMQygEAAAAAMAmhHAAAAAAAkxDKAQAAAAAwCaEcAAAAAACTEMoBAAAAADAJoRwAAAAAAJMQygEACBKbN2+WxWJRZmbmET/XjBkzFBsbe8TPAwBAa0coBwCgGUyePFkWi6XebdSoUWaX9oc6deqkJ5980m/bRRddpHXr1h3xc2dlZeniiy9WamqqwsPD1b59e5199tn69ddfJbXsHyIAADCD3ewCAAAIFaNGjdL06dP9tjmdTpOqOTwul0sul+uInqOqqkqnnnqqunfvrlmzZiklJUXbt2/XF198ofz8/CN6bgAAAgU95QAANBOn06nk5GS/W5s2bSRJF198sS666CK/9lVVVWrbtq1ef/11SdKXX36poUOHKjY2VvHx8TrjjDO0cePGA56voSHmH374oSwWi+/5xo0bdfbZZyspKUlRUVE69thjNXfuXN/+4cOHa8uWLfr73//u690/0LGfe+45de3aVQ6HQ927d9cbb7zht99isejll1/Wueeeq4iICKWnp+vjjz8+YP2//PKLNm7cqGeffVbHH3+8OnbsqBNOOEH333+/jj/+eElS586dJUkDBgyQxWLR8OHDfa9/+eWX1bNnT4WHh6tHjx569tlnfftqe9jfeecdDRkyROHh4erTp4/mz59/wHoAADADoRwAgBYwYcIEffLJJyouLvZtmz17tkpLS3XuuedKkkpKSnTDDTdo8eLFmjdvnqxWq84991x5vd4mn7e4uFinn3665s2bp2XLlmnUqFE688wztXXrVknSrFmz1L59e917773Kzs5WdnZ2g8f54IMPdN111+nGG2/UqlWr9Oc//1mXXXaZvv76a79299xzjy688EKtWLFCp59+uiZMmKC8vLwGj5mQkCCr1ar3339fHo+nwTY///yzJGnu3LnKzs7WrFmzJEkzZ87UnXfeqWnTpmnNmjV64IEHNHXqVL322mt+r7/55pt14403atmyZRo8eLDOPPNM7d27t/FfQAAAjjQDAAActkmTJhk2m82IjIz0u02bNs0wDMOoqqoy2rZta7z++uu+14wfP9646KKLDnjM3bt3G5KMlStXGoZhGFlZWYYkY9myZYZhGMb06dMNt9vt95oPPvjA+KNf77179zaeeuop3/OOHTsaTzzxhF+b3x97yJAhxpVXXunXZuzYscbpp5/uey7JuOOOO3zPi4uLDUnGF198ccBann76aSMiIsKIjo42Tj75ZOPee+81Nm7c6Nv/+/dcq2vXrsZbb73lt+2+++4zBg8e7Pe6hx56yLe/qqrKaN++vfHwww8fsB4AAFoaPeUAADSTk08+WZmZmX63q666SpJkt9t14YUXaubMmZJqesU/+ugjTZgwwff69evXa/z48erSpYtiYmLUqVMnSfL1ajdFcXGxbrrpJvXs2VOxsbGKiorSmjVrDvmYa9as0QknnOC37YQTTtCaNWv8tvXr18/3ODIyUjExMcrNzT3gca+++mrl5ORo5syZGjx4sN577z317t1bc+bMOeBrSkpKtHHjRl1++eWKiory3e6///56w/0HDx7se2y323XMMcfUqxkAADMx0RsAAM0kMjJS3bp1O+D+CRMmaNiwYcrNzdWcOXPkcrn8Zmc/88wz1bFjR7300ktKTU2V1+tVnz59VFlZ2eDxrFarDMPw21ZVVeX3/KabbtKcOXP02GOPqVu3bnK5XLrgggsOeMzDFRYW5vfcYrH84fD76OhonXnmmTrzzDN1//33a+TIkbr//vt16qmnNti+9hKAl156SYMGDfLbZ7PZDqN6AABaHj3lAAC0kCFDhigtLU3vvvuuZs6cqbFjx/pC7N69e7V27VrdcccdOuWUU9SzZ0/t27fvoMdLSEhQUVGRSkpKfNt+v3TYDz/8oMmTJ+vcc89V3759lZycrM2bN/u1cTgcB7ymu1bPnj31ww8/1Dt2r169/uBdHxqLxaIePXr43pPD4ZAkv/qSkpKUmpqqTZs2qVu3bn632onhav3000++x9XV1VqyZIl69uzZrDUDAHA46CkHAKCZVFRUKCcnx2+b3W5X27Ztfc8vvvhiPf/881q3bp3fJGlt2rRRfHy8XnzxRaWkpGjr1q269dZbD3q+QYMGKSIiQrfffruuvfZaLVy4UDNmzPBrk56erlmzZunMM8+UxWLR1KlT6/Vcd+rUSd9++63GjRsnp9PpV2+tm2++WRdeeKEGDBigESNG6JNPPtGsWbP8ZnI/VJmZmbrrrrt06aWXqlevXnI4HJo/f75effVV3XLLLZKkxMREuVwuffnll2rfvr3Cw8Pldrt1zz336Nprr5Xb7daoUaNUUVGhxYsXa9++fbrhhht853jmmWeUnp6unj176oknntC+ffs0ZcqUJtcMAECzM/uidgAAQsGkSZMMSfVu3bt392u3evVqQ5LRsWNHw+v1+u2bM2eO0bNnT8PpdBr9+vUzvvnmG0OS8cEHHxiG0fCkZx988IHRrVs3w+VyGWeccYbx4osv+k30lpWVZZx88smGy+Uy0tLSjKefftoYNmyYcd111/naLFiwwOjXr5/hdDp9r21oErlnn33W6NKlixEWFmZkZGT4TVpnGIZfrbXcbrcxffr0Br9mu3fvNq699lqjT58+RlRUlBEdHW307dvXeOyxxwyPx+Nr99JLLxlpaWmG1Wo1hg0b5ts+c+ZM46ijjjIcDofRpk0b46STTjJmzZrl97V66623jOOOO85wOBxGr169jK+++qrBWgAAMIvFMH53MRoAAECQ27x5szp37qxly5bpqKOOMrscAAAOiGvKAQAAAAAwCaEcAAAAAACTMHwdAAAAAACT0FMOAAAAAIBJCOUAAAAAAJiEUA4AAAAAgEkI5QAAAAAAmIRQDgAAAACASQjlAAAAAACYhFAOAAAAAIBJCOUAAAAAAJjk/wO2ay6WV36dOAAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot training and validation losses\n",
    "plt.figure(figsize=(12, 6))\n",
    "plt.plot(list(range(300, 300*len(perplexities),300)), train_losses[1:], label=\"Train Loss\")\n",
    "plt.plot(list(range(300, 300*len(perplexities),300)), val_losses[1:], label=\"Val Loss\")\n",
    "plt.xlabel(\"Evaluation Step\")\n",
    "plt.ylabel(\"Loss\")\n",
    "plt.title(\"Training and Validation Loss\")\n",
    "plt.legend()\n",
    "plt.show()\n",
    "\n",
    "# Plot perplexity curve\n",
    "plt.figure(figsize=(12, 6))\n",
    "plt.plot(list(range(300, 300*len(perplexities),300)), perplexities[1:], label=\"Perplexity\")\n",
    "plt.xlabel(\"Evaluation Step\")\n",
    "plt.ylabel(\"Perplexity\")\n",
    "plt.title(\"Validation Perplexity\")\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b268064f-d464-42b0-a210-d369c17a6dbe",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Generate step values, incremented by 300\n",
    "steps_ = list(range(0, 300 * len(train_losses), 300))\n",
    "train_losses = [round(float(t.item()), 3) for t in train_losses]\n",
    "val_losses = [round(float(t.item()), 3) for t in val_losses]\n",
    "\n",
    "# Create a DataFrame\n",
    "df = pd.DataFrame({\n",
    "    'step': steps_,\n",
    "    'training_loss': train_losses,\n",
    "    'val_loss': val_losses\n",
    "})\n",
    "\n",
    "# Save to CSV\n",
    "df.to_csv(f'{save_path}loss_values.csv', index=False)\n",
    "\n",
    "\n",
    "# Create a DataFrame\n",
    "perplexity_df = pd.DataFrame({\n",
    "    'step': steps_,\n",
    "    'perplexity': [round(float(t), 3) for t in perplexities]\n",
    "})\n",
    "\n",
    "# Save to CSV\n",
    "perplexity_df.to_csv(f'{save_path}perplexity.csv', index=False)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "93b25e22-2b08-43b2-9be3-d776a7d2e9bd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<|endoftext|>ብ<UNK><UNK><UNK><UNK>ir ተ<UNK>ers<UNK><UNK><UNK><UNK>ዥ<UNK>ዊ<UNK><UNK><UNK><UNK> ऊर्जाጢ<UNK>कर<UNK><UNK><UNK>ፀ<UNK> to adቄ<UNK><UNK><UNK>त्र<UNK><UNK><UNK><UNK><UNK><UNK>ाव<UNK><UNK><UNK> ई<UNK><UNK><UNK><UNK>ቶकृ<UNK><UNK><UNK><UNK>ጠ<UNK><UNK><UNK><UNK><UNK><UNK>मे<UNK>ग्रस–ኗ<UNK><UNK><UNK><UNK><UNK><UNK><UNK>ङ्<UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK>ኅ<UNK><UNK><UNK><UNK><UNK>ं<UNK>ዌ<UNK><UNK>ऊ<UNK><UNK><UNK>ive<UNK> re<UNK><UNK><UNK><UNK>ख्या दि य<UNK><UNK><UNK><UNK><UNK> कम<UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK>el<UNK><UNK><UNK><UNK>ntन्त<UNK><UNK><UNK><UNK><UNK><UNK> प्रभाव<UNK><UNK><UNK><UNK>ኗ<UNK>नं मह<UNK><UNK><UNK>का helpलऽ<UNK><UNK><UNK><UNK><UNK>enत<UNK><UNK><UNK><UNK><UNK>u<UNK><UNK><UNK>ou<UNK><UNK><UNK>ኢ<UNK> परमाणुial<UNK><UNK><UNK><UNK>ሩ<UNK> त<UNK> गर्नुहोस्<UNK>ሺ<UNK><UNK> प्रदूषण<UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK> compleदा<UNK><UNK><UNK> जेकरा<UNK><UNK>चार<UNK> बहु<UNK><UNK>g<UNK><UNK><UNK><UNK><UNK>ፊ<UNK><UNK>ar<UNK><UNK>ue<UNK><UNK><UNK><UNK><UNK>ፓ<UNK>क्त<UNK><UNK>o<UNK>कर<UNK>all<UNK><UNK>ge<UNK><UNK> ነው<UNK><UNK><UNK><UNK><UNK>न्त्र<UNK>के<UNK>५जा<UNK><UNK>ሁ<UNK>ोन<UNK><UNK><UNK><UNK><UNK><UNK> सा रा man<UNK><UNK>q<UNK><UNK><UNK>ዷred<UNK><UNK><UNK><UNK> व<UNK>द्य<UNK><UNK><UNK><UNK><UNK><UNK>ation<UNK><UNK><UNK> चार्ल्<UNK>ब्<UNK><UNK><UNK><UNK>ेलैनो ले n<UNK><UNK><UNK>रि<UNK><UNK><UNK>le एक<UNK><UNK> कुर्व<UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK>द्ध<UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK>ጭ<UNK>π<UNK><UNK> እና<UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK> or<UNK><UNK><UNK><UNK><UNK>ूल<UNK><UNK><UNK>हीኪ<UNK>unनो<UNK>ቋ<UNK><UNK>ቨ<UNK><UNK>ॉअ<UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK>terक्ष<UNK><UNK><UNK><UNK>as<UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK>ኑ<UNK>क्<UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK> or<UNK>ig<UNK><UNK><UNK> ይህ<UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK>हरूकोጃ<UNK> by<UNK> can<UNK><UNK><UNK><UNK>usqu<UNK><UNK>b<UNK><UNK><UNK><UNK><UNK><UNK>सी<UNK><UNK><UNK>नां<UNK><UNK><UNK><UNK> እንደnd<UNK> p<UNK><UNK>ፋ<UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK>e<UNK> क्षी cीकरण<UNK><UNK><UNK><UNK>\n"
     ]
    }
   ],
   "source": [
    "# Generate from the model\n",
    "context = torch.zeros((1, 1), dtype=torch.long, device=device)\n",
    "print(decode(model.generate(context, max_new_tokens=500)[0].tolist()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "a3c2c224-2886-4dd4-92c7-ba02276659f2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "once upon a time<UNK>ሩ<UNK><UNK><UNK><UNK>इ<UNK>प्त<UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK><UNK> केरऽ मिैत<UNK><UNK> न्यू<UNK><UNK><UNK> घ<UNK>द्ध<UNK>ld<UNK><UNK>ूर्ण<UNK><UNK><UNK><UNK><UNK> in<UNK><UNK> बी fने<UNK>]<UNK><UNK><UNK>ከ<UNK>ide<UNK>एकोage<UNK><UNK>ሃ<UNK><UNK>थ<UNK><UNK>सी<UNK><UNK>र्<UNK><UNK><UNK><UNK><UNK>ስተ<UNK>हरूको<UNK>ቼ<UNK><UNK><UNK><UNK><UNK><UNK><UNK>ሪያनि<UNK> कऱil गर्द<UNK>म् ओ<UNK><UNK><UNK><UNK>\n"
     ]
    }
   ],
   "source": [
    "context = torch.tensor(encode(\"Once upon a time\"), dtype=torch.long, device=device).unsqueeze(0)\n",
    "print(decode(model.generate(context, max_new_tokens=100)[0].tolist()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "ad862a6f-983d-4624-86eb-9f039f32f541",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "የተመጣጠነ እና የተመጣጠነ ምግብ ይመገቡ፡ ምግብዎ የተለያዩ አትክልትና ፍራፍሬ፣ ዘንበል ያደርገዋል፣ አዳዲስ እድሎችን አልፈለች እና እራስዎን በተናጋሪ ጊዜ ማሸነፍ እችላለሁ። ቦ ኤን ኤን ኤን እንደ ጥቁር እንቅስቃሴዎች ቀደም ካልሆኑ አስከፊ መስኮችን ያሰሳሰሉ እና ከትይዩ ስፋት የሚቆጣጠርበት\n"
     ]
    }
   ],
   "source": [
    "context = torch.tensor(encode(\"የተመጣጠነ እና የተመጣጠነ ምግብ ይመገቡ፡ ምግብዎ የተለያዩ አትክልትና ፍራፍሬ፣ ዘንበል\"), dtype=torch.long, device=device).unsqueeze(0)\n",
    "print(decode(model.generate(context, max_new_tokens=100)[0].tolist()))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2f82abb2-c403-48c4-9320-0ede28c3270d",
   "metadata": {},
   "source": [
    "# Loading the save model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "481d8579-91d2-4b87-bb02-c4c8f1e8b4eb",
   "metadata": {},
   "outputs": [],
   "source": [
    "model_path = f'{save_path}best_model.pt'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "2139ea0d-4509-4c6c-9128-cd20ef04967b",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_968398/955188772.py:2: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n",
      "  model.load_state_dict(torch.load(model_path))\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "SimpleRNNModel(\n",
       "  (embedding): Embedding(4000, 512)\n",
       "  (rnn): LSTM(512, 1024, batch_first=True)\n",
       "  (fc): Linear(in_features=1024, out_features=4000, bias=True)\n",
       "  (dropout): Dropout(p=0.3, inplace=False)\n",
       ")"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model = SimpleRNNModel()\n",
    "model.load_state_dict(torch.load(model_path))\n",
    "model.to(device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "2bca6f75-6ccf-4cec-9f69-c481483182b8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "once upon a time elaborate on adventure related to an image used in its blood and on another started to create a train during different parts of the needs to provide example the relationship can be a lot of compress focused on the other and job re\n"
     ]
    }
   ],
   "source": [
    "context = torch.tensor(encode(\"Once upon a time\"), dtype=torch.long, device=device).unsqueeze(0)\n",
    "print(decode(model.generate(context, max_new_tokens=100)[0].tolist()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ccb40a93-a1d7-4bde-8032-042883676fd7",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}