TIF_E41211115_lstm-quiz-gen.../question_generation/question_generation_model.i...

957 lines
138 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "02cbdb19",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import json\n",
"import random\n",
"import tensorflow as tf\n",
"from tensorflow.keras.preprocessing.text import Tokenizer\n",
"from tensorflow.keras.preprocessing.sequence import pad_sequences\n",
"from tensorflow.keras.models import Model, load_model\n",
"from tensorflow.keras.layers import (\n",
" Input,\n",
" LSTM,\n",
" Dense,\n",
" Embedding,\n",
" Bidirectional,\n",
" Concatenate,\n",
" Dropout,\n",
")\n",
"from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping\n",
"from sklearn.model_selection import train_test_split\n",
"import matplotlib.pyplot as plt\n",
"import re\n",
"from rouge_score import rouge_scorer\n",
"from nltk.translate.bleu_score import sentence_bleu\n"
]
},
{
"cell_type": "code",
"execution_count": 60,
"id": "f9c0af74",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"total context 661\n",
"total question 1212\n"
]
}
],
"source": [
"# Load data\n",
"with open(\"../dataset/stable_qg_qa_train_dataset.json\", \"r\") as f:\n",
" data = json.load(f)\n",
"\n",
"\n",
"# Preprocessing function\n",
"def preprocess_text(text):\n",
" \"\"\"Melakukan preprocessing teks dasar\"\"\"\n",
" text = text.lower()\n",
" text = re.sub(r\"\\s+\", \" \", text).strip()\n",
"\n",
" return text\n",
"\n",
"\n",
"# Persiapkan data untuk model prediksi pertanyaan\n",
"def prepare_question_prediction_data(data):\n",
" \"\"\"Siapkan data untuk model prediksi pertanyaan\"\"\"\n",
" contexts = []\n",
" tokens_list = []\n",
" ner_list = []\n",
" srl_list = []\n",
" questions = []\n",
" q_types = []\n",
"\n",
" for item in data:\n",
" \n",
" for qa in item[\"qas\"]:\n",
" if qa[\"question\"] == \"\":\n",
" continue\n",
" context = preprocess_text(item[\"context\"])\n",
" contexts.append(context)\n",
" token = [preprocess_text(token) for token in item[\"tokens\"]]\n",
" tokens_list.append(token)\n",
" ner_list.append(item[\"ner\"])\n",
" srl_list.append(item[\"srl\"])\n",
" questions.append(preprocess_text(qa[\"question\"]))\n",
" q_types.append(qa[\"type\"])\n",
" # Tidak mengambil jawaban (answer) sebagai input\n",
" print(\"total context \", len(data))\n",
" print(\"total question \", len(questions))\n",
" return contexts, tokens_list, ner_list, srl_list, questions, q_types\n",
"\n",
"\n",
"contexts, tokens_list, ner_list, srl_list, questions, q_types = (\n",
" prepare_question_prediction_data(data)\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 43,
"id": "952f71da",
"metadata": {},
"outputs": [],
"source": [
"# Tokenizer untuk teks (context, question)\n",
"max_vocab_size = 10000\n",
"tokenizer = Tokenizer(num_words=max_vocab_size, oov_token=\"<OOV>\")\n",
"all_texts = contexts + questions + [\" \".join(item) for item in tokens_list]\n",
"tokenizer.fit_on_texts(all_texts)\n",
"vocab_size = len(tokenizer.word_index) + 1\n",
"\n",
"# Encoding untuk NER\n",
"ner_tokenizer = Tokenizer(oov_token=\"<OOV>\")\n",
"ner_tokenizer.fit_on_texts([\" \".join(ner) for ner in ner_list])\n",
"ner_vocab_size = len(ner_tokenizer.word_index) + 1\n",
"\n",
"# Encoding untuk SRL\n",
"srl_tokenizer = Tokenizer(oov_token=\"<OOV>\")\n",
"srl_tokenizer.fit_on_texts([\" \".join(srl) for srl in srl_list])\n",
"srl_vocab_size = len(srl_tokenizer.word_index) + 1\n",
"\n",
"# Encoding untuk tipe pertanyaan\n",
"q_type_tokenizer = Tokenizer()\n",
"q_type_tokenizer.fit_on_texts(q_types)\n",
"q_type_vocab_size = len(q_type_tokenizer.word_index) + 1\n",
"\n",
"\n",
"# Konversi token, ner, srl ke sequences\n",
"def tokens_to_sequences(tokens, ner, srl):\n",
" \"\"\"Konversi token, ner, dan srl ke sequences\"\"\"\n",
" token_seqs = [tokenizer.texts_to_sequences([\" \".join(t)])[0] for t in tokens]\n",
" ner_seqs = [ner_tokenizer.texts_to_sequences([\" \".join(n)])[0] for n in ner]\n",
" srl_seqs = [srl_tokenizer.texts_to_sequences([\" \".join(s)])[0] for s in srl]\n",
" return token_seqs, ner_seqs, srl_seqs\n",
"\n",
"\n",
"# Sequences\n",
"context_seqs = tokenizer.texts_to_sequences(contexts)\n",
"question_seqs = tokenizer.texts_to_sequences(questions)\n",
"token_seqs, ner_seqs, srl_seqs = tokens_to_sequences(tokens_list, ner_list, srl_list)\n",
"\n",
"# Menentukan panjang maksimum untuk padding\n",
"max_context_len = max([len(seq) for seq in context_seqs])\n",
"max_question_len = max([len(seq) for seq in question_seqs])\n",
"max_token_len = max([len(seq) for seq in token_seqs])\n",
"\n",
"\n",
"# Pad sequences untuk memastikan semua input sama panjang\n",
"def pad_all_sequences(context_seqs, token_seqs, ner_seqs, srl_seqs, question_seqs):\n",
" \"\"\"Padding semua sequences\"\"\"\n",
" context_padded = pad_sequences(context_seqs, maxlen=max_context_len, padding=\"post\")\n",
" token_padded = pad_sequences(token_seqs, maxlen=max_token_len, padding=\"post\")\n",
" ner_padded = pad_sequences(ner_seqs, maxlen=max_token_len, padding=\"post\")\n",
" srl_padded = pad_sequences(srl_seqs, maxlen=max_token_len, padding=\"post\")\n",
" question_padded = pad_sequences(\n",
" question_seqs, maxlen=max_question_len, padding=\"post\"\n",
" )\n",
" return (\n",
" context_padded,\n",
" token_padded,\n",
" ner_padded,\n",
" srl_padded,\n",
" question_padded,\n",
" )\n",
"\n",
"\n",
"# Encode tipe pertanyaan\n",
"q_type_indices = []\n",
"for q_type in q_types:\n",
" q_type_idx = q_type_tokenizer.word_index.get(q_type, 0)\n",
" q_type_indices.append(q_type_idx)\n",
"\n",
"# Konversi ke numpy array\n",
"q_type_indices = np.array(q_type_indices)\n",
"\n",
"# One-hot encode tipe pertanyaan\n",
"q_type_categorical = tf.keras.utils.to_categorical(\n",
" q_type_indices, num_classes=q_type_vocab_size\n",
")\n",
"\n",
"# Pad sequences\n",
"context_padded, token_padded, ner_padded, srl_padded, question_padded = (\n",
" pad_all_sequences(context_seqs, token_seqs, ner_seqs, srl_seqs, question_seqs)\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 44,
"id": "37ffc0e5",
"metadata": {},
"outputs": [],
"source": [
"# Split data menjadi train dan test sets\n",
"indices = list(range(len(context_padded)))\n",
"train_indices, test_indices = train_test_split(indices, test_size=0.2, random_state=42)\n",
"\n",
"\n",
"def get_subset(data, indices):\n",
" return np.array([data[i] for i in indices])\n",
"\n",
"\n",
"# Train data\n",
"train_context = get_subset(context_padded, train_indices)\n",
"train_token = get_subset(token_padded, train_indices)\n",
"train_ner = get_subset(ner_padded, train_indices)\n",
"train_srl = get_subset(srl_padded, train_indices)\n",
"train_q_type = get_subset(q_type_categorical, train_indices)\n",
"train_question = get_subset(question_padded, train_indices)\n",
"\n",
"# Test data\n",
"test_context = get_subset(context_padded, test_indices)\n",
"test_token = get_subset(token_padded, test_indices)\n",
"test_ner = get_subset(ner_padded, test_indices)\n",
"test_srl = get_subset(srl_padded, test_indices)\n",
"test_q_type = get_subset(q_type_categorical, test_indices)\n",
"test_question = get_subset(question_padded, test_indices)"
]
},
{
"cell_type": "code",
"execution_count": 45,
"id": "df580682",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Model: \"functional_2\"</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1mModel: \"functional_2\"\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓\n",
"┃<span style=\"font-weight: bold\"> Layer (type) </span>┃<span style=\"font-weight: bold\"> Output Shape </span>┃<span style=\"font-weight: bold\"> Param # </span>┃<span style=\"font-weight: bold\"> Connected to </span>┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩\n",
"│ context_input │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">54</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ - │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">InputLayer</span>) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ token_input │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">54</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ - │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">InputLayer</span>) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ ner_input │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">54</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ - │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">InputLayer</span>) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ srl_input │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">54</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ - │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">InputLayer</span>) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ text_embedding │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">54</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">100</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">180,100</span> │ context_input[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>]… │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Embedding</span>) │ │ │ token_input[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>] │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ ner_embedding │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">54</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">50</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">1,700</span> │ ner_input[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>] │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Embedding</span>) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ srl_embedding │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">54</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">50</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">1,400</span> │ srl_input[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>] │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Embedding</span>) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ bidirectional_4 │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">54</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">234,496</span> │ text_embedding[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>… │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Bidirectional</span>) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ token_features │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">54</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">200</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ text_embedding[<span style=\"color: #00af00; text-decoration-color: #00af00\">1</span>… │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Concatenate</span>) │ │ │ ner_embedding[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>]… │\n",
"│ │ │ │ srl_embedding[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>]… │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ context_attention │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">54</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ bidirectional_4[<span style=\"color: #00af00; text-decoration-color: #00af00\">…</span> │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Attention</span>) │ │ │ bidirectional_4[<span style=\"color: #00af00; text-decoration-color: #00af00\">…</span> │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ bidirectional_5 │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">54</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">336,896</span> │ token_features[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>… │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Bidirectional</span>) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ context_att_pool │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ context_attentio… │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">GlobalMaxPooling1…</span> │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ token_pool │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ bidirectional_5[<span style=\"color: #00af00; text-decoration-color: #00af00\">…</span> │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">GlobalMaxPooling1…</span> │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ q_type_input │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">5</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ - │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">InputLayer</span>) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ all_features │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">517</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ context_att_pool… │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Concatenate</span>) │ │ │ token_pool[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>], │\n",
"│ │ │ │ q_type_input[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">…</span> │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ dense_1 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">512</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">265,216</span> │ all_features[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">…</span> │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ dropout_4 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dropout</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">512</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ dense_1[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>] │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ dense_2 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">131,328</span> │ dropout_4[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>] │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ dropout_5 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dropout</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ dense_2[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>] │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ decoder_input │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">65,792</span> │ dropout_5[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>] │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ repeat_vector_2 │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">14</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ decoder_input[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>]… │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">RepeatVector</span>) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ decoder_lstm (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">LSTM</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">14</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">525,312</span> │ repeat_vector_2[<span style=\"color: #00af00; text-decoration-color: #00af00\">…</span> │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ time_distributed_2 │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">14</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">1801</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">462,857</span> │ decoder_lstm[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">…</span> │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">TimeDistributed</span>) │ │ │ │\n",
"└─────────────────────┴───────────────────┴────────────┴───────────────────┘\n",
"</pre>\n"
],
"text/plain": [
"┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓\n",
"┃\u001b[1m \u001b[0m\u001b[1mLayer (type) \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Param #\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mConnected to \u001b[0m\u001b[1m \u001b[0m┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩\n",
"│ context_input │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m54\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ - │\n",
"│ (\u001b[38;5;33mInputLayer\u001b[0m) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ token_input │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m54\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ - │\n",
"│ (\u001b[38;5;33mInputLayer\u001b[0m) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ ner_input │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m54\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ - │\n",
"│ (\u001b[38;5;33mInputLayer\u001b[0m) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ srl_input │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m54\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ - │\n",
"│ (\u001b[38;5;33mInputLayer\u001b[0m) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ text_embedding │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m54\u001b[0m, \u001b[38;5;34m100\u001b[0m) │ \u001b[38;5;34m180,100\u001b[0m │ context_input[\u001b[38;5;34m0\u001b[0m]… │\n",
"│ (\u001b[38;5;33mEmbedding\u001b[0m) │ │ │ token_input[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m] │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ ner_embedding │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m54\u001b[0m, \u001b[38;5;34m50\u001b[0m) │ \u001b[38;5;34m1,700\u001b[0m │ ner_input[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m] │\n",
"│ (\u001b[38;5;33mEmbedding\u001b[0m) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ srl_embedding │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m54\u001b[0m, \u001b[38;5;34m50\u001b[0m) │ \u001b[38;5;34m1,400\u001b[0m │ srl_input[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m] │\n",
"│ (\u001b[38;5;33mEmbedding\u001b[0m) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ bidirectional_4 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m54\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m234,496\u001b[0m │ text_embedding[\u001b[38;5;34m0\u001b[0m… │\n",
"│ (\u001b[38;5;33mBidirectional\u001b[0m) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ token_features │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m54\u001b[0m, \u001b[38;5;34m200\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ text_embedding[\u001b[38;5;34m1\u001b[0m… │\n",
"│ (\u001b[38;5;33mConcatenate\u001b[0m) │ │ │ ner_embedding[\u001b[38;5;34m0\u001b[0m]… │\n",
"│ │ │ │ srl_embedding[\u001b[38;5;34m0\u001b[0m]… │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ context_attention │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m54\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ bidirectional_4[\u001b[38;5;34m…\u001b[0m │\n",
"│ (\u001b[38;5;33mAttention\u001b[0m) │ │ │ bidirectional_4[\u001b[38;5;34m…\u001b[0m │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ bidirectional_5 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m54\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m336,896\u001b[0m │ token_features[\u001b[38;5;34m0\u001b[0m… │\n",
"│ (\u001b[38;5;33mBidirectional\u001b[0m) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ context_att_pool │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ context_attentio… │\n",
"│ (\u001b[38;5;33mGlobalMaxPooling1…\u001b[0m │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ token_pool │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ bidirectional_5[\u001b[38;5;34m…\u001b[0m │\n",
"│ (\u001b[38;5;33mGlobalMaxPooling1…\u001b[0m │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ q_type_input │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m5\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ - │\n",
"│ (\u001b[38;5;33mInputLayer\u001b[0m) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ all_features │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m517\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ context_att_pool… │\n",
"│ (\u001b[38;5;33mConcatenate\u001b[0m) │ │ │ token_pool[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m], │\n",
"│ │ │ │ q_type_input[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m…\u001b[0m │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ dense_1 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m512\u001b[0m) │ \u001b[38;5;34m265,216\u001b[0m │ all_features[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m…\u001b[0m │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ dropout_4 (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m512\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ dense_1[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m] │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ dense_2 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m131,328\u001b[0m │ dropout_4[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m] │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ dropout_5 (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ dense_2[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m] │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ decoder_input │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m65,792\u001b[0m │ dropout_5[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m] │\n",
"│ (\u001b[38;5;33mDense\u001b[0m) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ repeat_vector_2 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m14\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ decoder_input[\u001b[38;5;34m0\u001b[0m]… │\n",
"│ (\u001b[38;5;33mRepeatVector\u001b[0m) │ │ │ │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ decoder_lstm (\u001b[38;5;33mLSTM\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m14\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m525,312\u001b[0m │ repeat_vector_2[\u001b[38;5;34m…\u001b[0m │\n",
"├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n",
"│ time_distributed_2 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m14\u001b[0m, \u001b[38;5;34m1801\u001b[0m) │ \u001b[38;5;34m462,857\u001b[0m │ decoder_lstm[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m…\u001b[0m │\n",
"│ (\u001b[38;5;33mTimeDistributed\u001b[0m) │ │ │ │\n",
"└─────────────────────┴───────────────────┴────────────┴───────────────────┘\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Total params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">2,205,097</span> (8.41 MB)\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1m Total params: \u001b[0m\u001b[38;5;34m2,205,097\u001b[0m (8.41 MB)\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">2,205,097</span> (8.41 MB)\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m2,205,097\u001b[0m (8.41 MB)\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Non-trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> (0.00 B)\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"embedding_dim = 100\n",
"lstm_units = 128\n",
"ner_embedding_dim = 50\n",
"srl_embedding_dim = 50\n",
"dropout_rate = 0.3\n",
"\n",
"\n",
"# Function untuk membuat model prediksi pertanyaan\n",
"def create_question_prediction_model():\n",
" # Input layers\n",
" context_input = Input(shape=(max_context_len,), name=\"context_input\")\n",
" token_input = Input(shape=(max_token_len,), name=\"token_input\")\n",
" ner_input = Input(shape=(max_token_len,), name=\"ner_input\")\n",
" srl_input = Input(shape=(max_token_len,), name=\"srl_input\")\n",
" q_type_input = Input(shape=(q_type_vocab_size,), name=\"q_type_input\")\n",
"\n",
" # Shared embedding layer for text\n",
" text_embedding = Embedding(vocab_size, embedding_dim, name=\"text_embedding\")\n",
"\n",
" # Embedding untuk NER dan SRL\n",
" ner_embedding = Embedding(ner_vocab_size, ner_embedding_dim, name=\"ner_embedding\")(\n",
" ner_input\n",
" )\n",
" srl_embedding = Embedding(srl_vocab_size, srl_embedding_dim, name=\"srl_embedding\")(\n",
" srl_input\n",
" )\n",
"\n",
" # Apply embeddings\n",
" context_embed = text_embedding(context_input)\n",
" token_embed = text_embedding(token_input)\n",
"\n",
" # Bi-directional LSTM untuk context dan token-level features\n",
" context_lstm = Bidirectional(\n",
" LSTM(lstm_units, return_sequences=True, name=\"context_lstm\")\n",
" )(context_embed)\n",
"\n",
" # Concat token features (tokens, NER, SRL)\n",
" token_features = Concatenate(name=\"token_features\")(\n",
" [token_embed, ner_embedding, srl_embedding]\n",
" )\n",
" token_lstm = Bidirectional(\n",
" LSTM(lstm_units, return_sequences=True, name=\"token_lstm\")\n",
" )(token_features)\n",
"\n",
" # Apply attention to context LSTM\n",
" context_attention = tf.keras.layers.Attention(name=\"context_attention\")(\n",
" [context_lstm, context_lstm]\n",
" )\n",
"\n",
" # Pool attention outputs\n",
" context_att_pool = tf.keras.layers.GlobalMaxPooling1D(name=\"context_att_pool\")(\n",
" context_attention\n",
" )\n",
" token_pool = tf.keras.layers.GlobalMaxPooling1D(name=\"token_pool\")(token_lstm)\n",
"\n",
" # Concat all features (tidak ada answer feature)\n",
" all_features = Concatenate(name=\"all_features\")(\n",
" [context_att_pool, token_pool, q_type_input]\n",
" )\n",
"\n",
" # Dense layers with expanded capacity for sequence generation\n",
" x = Dense(512, activation=\"relu\", name=\"dense_1\")(all_features)\n",
" x = Dropout(dropout_rate)(x)\n",
" x = Dense(256, activation=\"relu\", name=\"dense_2\")(x)\n",
" x = Dropout(dropout_rate)(x)\n",
"\n",
" # Reshape untuk sequence decoder\n",
" decoder_dense = Dense(vocab_size, activation=\"softmax\", name=\"decoder_dense\")\n",
"\n",
" # Many-to-many architecture for sequence generation\n",
" # Decoder LSTM\n",
" decoder_lstm = LSTM(lstm_units * 2, return_sequences=True, name=\"decoder_lstm\")\n",
"\n",
" # Reshape untuk input ke decoder\n",
" decoder_input = Dense(lstm_units * 2, activation=\"relu\", name=\"decoder_input\")(x)\n",
"\n",
" # Decoder sequence with teacher forcing\n",
" # Expand dimensionality to match expected sequence length\n",
" repeated_vector = tf.keras.layers.RepeatVector(max_question_len)(decoder_input)\n",
"\n",
" # Process through decoder LSTM\n",
" decoder_outputs = decoder_lstm(repeated_vector)\n",
"\n",
" # Apply dense layer to each timestep\n",
" question_output_seq = tf.keras.layers.TimeDistributed(decoder_dense)(\n",
" decoder_outputs\n",
" )\n",
"\n",
" # Create model\n",
" model = Model(\n",
" inputs=[\n",
" context_input,\n",
" token_input,\n",
" ner_input,\n",
" srl_input,\n",
" q_type_input,\n",
" ],\n",
" outputs=question_output_seq,\n",
" )\n",
"\n",
" # Compile model with categorical crossentropy for sequence prediction\n",
" model.compile(\n",
" optimizer=\"adam\", loss=\"sparse_categorical_crossentropy\", metrics=[\"accuracy\"]\n",
" )\n",
"\n",
" return model\n",
"\n",
"\n",
"# Buat model\n",
"model = create_question_prediction_model()\n",
"model.summary()"
]
},
{
"cell_type": "code",
"execution_count": 46,
"id": "6ba404db",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 35ms/step - accuracy: 0.5274 - loss: 4.3786 - val_accuracy: 0.5680 - val_loss: 3.4016\n",
"Epoch 2/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 33ms/step - accuracy: 0.5615 - loss: 3.3640 - val_accuracy: 0.5680 - val_loss: 3.3180\n",
"Epoch 3/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 35ms/step - accuracy: 0.5558 - loss: 3.1577 - val_accuracy: 0.5770 - val_loss: 2.9719\n",
"Epoch 4/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 31ms/step - accuracy: 0.5658 - loss: 2.9229 - val_accuracy: 0.5833 - val_loss: 2.8770\n",
"Epoch 5/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 32ms/step - accuracy: 0.5684 - loss: 2.7838 - val_accuracy: 0.5883 - val_loss: 2.8030\n",
"Epoch 6/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 32ms/step - accuracy: 0.5678 - loss: 2.7217 - val_accuracy: 0.5889 - val_loss: 2.7586\n",
"Epoch 7/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 32ms/step - accuracy: 0.5832 - loss: 2.5477 - val_accuracy: 0.5920 - val_loss: 2.7165\n",
"Epoch 8/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 32ms/step - accuracy: 0.5817 - loss: 2.5231 - val_accuracy: 0.5979 - val_loss: 2.6560\n",
"Epoch 9/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 34ms/step - accuracy: 0.5866 - loss: 2.4224 - val_accuracy: 0.5886 - val_loss: 2.6570\n",
"Epoch 10/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 34ms/step - accuracy: 0.5896 - loss: 2.3792 - val_accuracy: 0.5998 - val_loss: 2.5975\n",
"Epoch 11/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 33ms/step - accuracy: 0.5894 - loss: 2.3246 - val_accuracy: 0.5998 - val_loss: 2.5801\n",
"Epoch 12/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 33ms/step - accuracy: 0.5967 - loss: 2.2601 - val_accuracy: 0.6039 - val_loss: 2.5552\n",
"Epoch 13/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 35ms/step - accuracy: 0.5894 - loss: 2.2631 - val_accuracy: 0.6042 - val_loss: 2.5384\n",
"Epoch 14/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 35ms/step - accuracy: 0.6062 - loss: 2.1692 - val_accuracy: 0.6104 - val_loss: 2.5017\n",
"Epoch 15/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 35ms/step - accuracy: 0.6087 - loss: 2.1076 - val_accuracy: 0.6135 - val_loss: 2.4925\n",
"Epoch 16/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 36ms/step - accuracy: 0.6048 - loss: 2.0866 - val_accuracy: 0.6098 - val_loss: 2.4662\n",
"Epoch 17/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 36ms/step - accuracy: 0.6097 - loss: 2.0495 - val_accuracy: 0.6123 - val_loss: 2.4682\n",
"Epoch 18/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 37ms/step - accuracy: 0.6120 - loss: 1.9992 - val_accuracy: 0.6126 - val_loss: 2.4572\n",
"Epoch 19/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 39ms/step - accuracy: 0.6111 - loss: 1.9984 - val_accuracy: 0.6188 - val_loss: 2.4301\n",
"Epoch 20/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 49ms/step - accuracy: 0.6121 - loss: 1.9544 - val_accuracy: 0.6138 - val_loss: 2.4277\n",
"Epoch 21/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 56ms/step - accuracy: 0.6210 - loss: 1.8891 - val_accuracy: 0.6138 - val_loss: 2.4257\n",
"Epoch 22/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 45ms/step - accuracy: 0.6174 - loss: 1.8878 - val_accuracy: 0.6120 - val_loss: 2.4424\n",
"Epoch 23/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 42ms/step - accuracy: 0.6179 - loss: 1.8573 - val_accuracy: 0.6216 - val_loss: 2.4079\n",
"Epoch 24/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 41ms/step - accuracy: 0.6195 - loss: 1.8307 - val_accuracy: 0.6176 - val_loss: 2.4069\n",
"Epoch 25/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 43ms/step - accuracy: 0.6215 - loss: 1.8256 - val_accuracy: 0.6185 - val_loss: 2.4048\n",
"Epoch 26/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 47ms/step - accuracy: 0.6215 - loss: 1.7727 - val_accuracy: 0.6198 - val_loss: 2.4082\n",
"Epoch 27/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 51ms/step - accuracy: 0.6348 - loss: 1.7045 - val_accuracy: 0.6176 - val_loss: 2.4146\n",
"Epoch 28/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 40ms/step - accuracy: 0.6256 - loss: 1.7402 - val_accuracy: 0.6232 - val_loss: 2.4063\n",
"Epoch 29/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 38ms/step - accuracy: 0.6301 - loss: 1.6912 - val_accuracy: 0.6201 - val_loss: 2.3900\n",
"Epoch 30/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 38ms/step - accuracy: 0.6426 - loss: 1.5917 - val_accuracy: 0.6210 - val_loss: 2.3955\n",
"Epoch 31/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 42ms/step - accuracy: 0.6291 - loss: 1.6419 - val_accuracy: 0.6229 - val_loss: 2.3927\n",
"Epoch 32/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 48ms/step - accuracy: 0.6394 - loss: 1.6025 - val_accuracy: 0.6235 - val_loss: 2.3868\n",
"Epoch 33/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 44ms/step - accuracy: 0.6279 - loss: 1.6680 - val_accuracy: 0.6198 - val_loss: 2.3958\n",
"Epoch 34/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 35ms/step - accuracy: 0.6429 - loss: 1.5414 - val_accuracy: 0.6188 - val_loss: 2.3630\n",
"Epoch 35/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 36ms/step - accuracy: 0.6388 - loss: 1.5534 - val_accuracy: 0.6229 - val_loss: 2.3805\n",
"Epoch 36/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 38ms/step - accuracy: 0.6534 - loss: 1.4814 - val_accuracy: 0.6279 - val_loss: 2.3940\n",
"Epoch 37/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 40ms/step - accuracy: 0.6500 - loss: 1.4601 - val_accuracy: 0.6241 - val_loss: 2.3974\n",
"Epoch 38/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 47ms/step - accuracy: 0.6500 - loss: 1.4935 - val_accuracy: 0.6304 - val_loss: 2.3958\n",
"Epoch 39/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 52ms/step - accuracy: 0.6485 - loss: 1.4417 - val_accuracy: 0.6269 - val_loss: 2.4015\n",
"Epoch 40/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 41ms/step - accuracy: 0.6451 - loss: 1.4721 - val_accuracy: 0.6251 - val_loss: 2.3890\n",
"Epoch 41/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 39ms/step - accuracy: 0.6618 - loss: 1.3730 - val_accuracy: 0.6220 - val_loss: 2.4143\n",
"Epoch 42/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 39ms/step - accuracy: 0.6575 - loss: 1.3942 - val_accuracy: 0.6298 - val_loss: 2.3959\n",
"Epoch 43/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 39ms/step - accuracy: 0.6506 - loss: 1.4094 - val_accuracy: 0.6269 - val_loss: 2.4056\n",
"Epoch 44/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 41ms/step - accuracy: 0.6509 - loss: 1.3967 - val_accuracy: 0.6216 - val_loss: 2.4178\n",
"Epoch 45/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 46ms/step - accuracy: 0.6629 - loss: 1.3460 - val_accuracy: 0.6344 - val_loss: 2.3807\n",
"Epoch 46/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 36ms/step - accuracy: 0.6677 - loss: 1.3198 - val_accuracy: 0.6269 - val_loss: 2.3913\n",
"Epoch 47/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 35ms/step - accuracy: 0.6653 - loss: 1.3295 - val_accuracy: 0.6298 - val_loss: 2.3925\n",
"Epoch 48/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 38ms/step - accuracy: 0.6637 - loss: 1.3107 - val_accuracy: 0.6298 - val_loss: 2.3655\n",
"Epoch 49/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 36ms/step - accuracy: 0.6593 - loss: 1.3313 - val_accuracy: 0.6369 - val_loss: 2.3792\n",
"Epoch 50/50\n",
"\u001b[1m115/115\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 43ms/step - accuracy: 0.6654 - loss: 1.3019 - val_accuracy: 0.6248 - val_loss: 2.4192\n"
]
}
],
"source": [
"checkpoint = ModelCheckpoint(\n",
" \"question_prediction_model.h5\",\n",
" monitor=\"val_accuracy\",\n",
" save_best_only=True,\n",
" verbose=1,\n",
")\n",
"\n",
"early_stop = EarlyStopping(monitor=\"val_accuracy\", patience=10, verbose=1)\n",
"\n",
"# Reshaping question data for sequence-to-sequence training\n",
"# We need to reshape to (samples, max_question_len, 1) for sparse categorical crossentropy\n",
"train_question_target = np.expand_dims(train_question, -1)\n",
"test_question_target = np.expand_dims(test_question, -1)\n",
"\n",
"# Training parameters\n",
"batch_size = 8\n",
"epochs = 50\n",
"\n",
"# Train model\n",
"history = model.fit(\n",
" [train_context, train_token, train_ner, train_srl, train_q_type],\n",
" train_question_target,\n",
" batch_size=batch_size,\n",
" epochs=epochs,\n",
" validation_data=(\n",
" [test_context, test_token, test_ner, test_srl, test_q_type],\n",
" test_question_target,\n",
" ),\n",
" callbacks=[\n",
" # checkpoint,\n",
" early_stop,\n",
" ],\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 47,
"id": "184209bc",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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xERefvnlPMckhBBCiMJRkvpeeVGxYsUcsZDLfQDY2dkxYMAABgwYQGpqKr179+ajjz5i8uTJWFtbA+Dl5cWoUaMYNWoU4eHhNGrUiI8++kiSUkKYmXz1LYQoEHt7e77//numTZtGt27dHtquS5cuGAwG5syZk23/l19+iUajyewI3Ht8cAWZ2bNnZ3ut0+no06cPq1atyjXJEhERke97Wbx4MS1btmTAgAH07ds32/bOO+8AsHTpUgD69OlDZGRkjvsho+bCvTaKomR+O5dbG0dHR9zc3Ni5c2e297/77rs8x30vgfbg8s4PfmZarZaePXvy119/cfjw4YfGBGBhYcHAgQP5/fffWbRoEfXq1TPrt59CCCGEUJWkvldedOnShYMHD7Jv377MfQkJCcybNw9fX19q164NwJ07d7Idp9frqV27NoqikJaWhsFgyCxpcI+HhwflypUjJSWlUGIXQuSdjJQSQhTYw4Zw369bt260adOGDz74gGvXrlG/fn3+/fdf1q5dy5tvvplZx6BBgwYMHDiQ7777jpiYGJo3b86WLVsICgrKcc6PP/6Ybdu2ERgYyPDhw6lduzZRUVEcPXqUzZs3ExUVled7OHDgAEFBQYwZMybX9729vWnUqBGLFy9m0qRJDB48mF9++YWJEydy8OBBWrZsSUJCAps3b2bUqFH06NGDNm3a8PLLL/P1119z6dKlzKl0u3btok2bNpnXeu211/j444957bXXaNy4MTt37uTixYt5jt3R0ZFWrVrx6aefkpaWhre3N//++y9Xr17N0XbGjBn8+++/tG7dmhEjRlCrVi1CQkJYsWIFu3fvzjYFYPDgwXz99dds27aNTz75JM/xCCGEEKJwlYS+1/1WrVqVOfLpwft87733WLp0KZ07d2bcuHG4urry888/c/XqVVatWpVZWqBDhw54enrSokULypYty7lz55gzZw5du3bFwcGB6OhoypcvT9++falfvz729vZs3ryZQ4cO8fnnnxcobiGECZl7+T8hxNPh/mWJH+XBZYmVjOV7J0yYoJQrV06xtLRUqlWrpsyaNUsxGo3Z2iUlJSnjxo1TypQpo9jZ2SndunVTgoODcyxLrCiKEhYWpowePVrx8fFRLC0tFU9PT+W5555T5s2bl9kmL8sSjx07VgGUy5cvP7TNtGnTFEA5ceKEoiiKkpiYqHzwwQdKpUqVMq/dt2/fbOdIT09XZs2apdSsWVPR6/WKu7u70rlzZ+XIkSOZbRITE5Vhw4YpTk5OioODg9K/f38lPDw8x/1OnTpVAZSIiIgcsd28eVPp1auX4uzsrDg5OSn9+vVTbt++netndv36dWXw4MGKu7u7YmVlpVSuXFkZPXq0kpKSkuO8derUUbRarXLz5s2Hfi5CCCGEKDwlte+lKIqybds2BXjotmvXLkVRFOXy5ctK3759FWdnZ8Xa2loJCAhQ/v7772zn+uGHH5RWrVopZcqUUaysrJQqVaoo77zzjhITE6MoiqKkpKQo77zzjlK/fn3FwcFBsbOzU+rXr6989913j4xRCFE0NMqD8z6EEEKUeg0bNsTV1ZUtW7aYOxQhhBBCCCFECSU1pYQQQmRz+PBhjh8/zuDBg80dihBCCCGEEKIEk5FSQgghADh9+jRHjhzh888/JzIykitXrmSuWCOEEEIIIYQQpiYjpYQQQgCwcuVKhg4dSlpaGkuXLpWElBBCCCGEEKJQyUgpIYQQQgghhBBCCFHkZKSUEEIIIYQQQgghhChykpQSQgghhBBCCCGEEEXOwtwBFEdGo5Hbt2/j4OCARqMxdzhCCCGEKEYURSEuLo5y5cqh1Zbe7/ekvySEEEKIh8lrf0mSUrm4ffs2Pj4+5g5DCCGEEMVYcHAw5cuXN3cYZiP9JSGEEEI8zuP6S5KUyoWDgwNkfHiOjo7mDkcIIYQQxUhsbCw+Pj6Z/YXSSvpLQgghhHiYvPaXJCmVi3tD0B0dHaWTJYQQQohclfYpa9JfEkIIIcTjPK6/VHoLIQghhBBCCCGEEEIIs5GklBBCCCGEEEIIIYQocpKUEkIIIYQQQgghhBBFTmpKPQGDwUBaWpq5wxAmYGlpiU6nM3cYQgghRIkj/aWSQ/pLQgghTE2SUgWgKAqhoaFER0ebOxRhQs7Oznh6epb6wrVCCCGEKUh/qWSS/pIQQghTkqRUAdzrYHl4eGBrays/lJ9yiqKQmJhIeHg4AF5eXuYOSQghhHjqSX+pZJH+khBCiMIgSal8MhgMmR2sMmXKmDscYSI2NjYAhIeH4+HhIUPThRBCiCcg/aWSSfpLQgghTE0KnefTvZoItra25g5FmNi9P1OpeyGEEEI8GekvlVzSXxJCCGFKkpQqIBmCXvLIn6kQQghhWvKzteSRP1MhhBCmJEkpIYQQQpQo6QYjd+JTzB2GMAFFUcwdghBCCCEKkSSlxBPx9fVl9uzZ5g5DCCGEgIwkxvS/ztJ9zh4uhsWZOxxRQMlpBi6FxXEpLN7coZiE9JeEEEKI3ElSqpTQaDSP3KZNm1ag8x46dIgRI0aYPF4hhBCiIBbsucav+69zOyaJq5EJ5g5HFJCFVkNSmoHkdAPpBmORXVf6S0IIIUTRktX3SomQkJDM58uXL2fKlClcuHAhc5+9vX3mc0VRMBgMWFg8/q+Hu7t7IUQrhBBC5N+/Z0L58J+zALzfuRYd63iaOyRRQBY6LdaWOpLTDCSkGnCyKZrvUaW/JIQQQhQtGSlVSnh6emZuTk5OaDSazNfnz5/HwcGB9evX4+/vj5WVFbt37+by5cv06NGDsmXLYm9vT5MmTdi8eXO28z44HF2j0fDjjz/Sq1cvbG1tqVatGn/++acZ7lgIIURpcvJmNOOXHUdR4MXACrzWspK5QxJPyFavAyAxJb3Irin9JSGEEKJoSVLKBBRFITE1vcg3Uxf/fO+99/j44485d+4cfn5+xMfH06VLF7Zs2cKxY8fo1KkT3bp148aNG488z/Tp0+nfvz8nT56kS5cuvPjii0RFRZk0ViGEEOKeW9FJDPv5MElpBlpXd2d69zqyQlgxlN/+klajITnNQGRCqvSXhBBCiBJKpu+ZQFKagdpTNhb5dc/+ryO2etP9Ef7vf/+jffv2ma9dXV2pX79+5uv/+7//Y82aNfz555+MGTPmoed55ZVXGDhwIAAzZszg66+/5uDBg3Tq1MlksQohhBAAcclpvLrwEBFxKdT0dGDOoIZY6OQ7t+JI+kvZSX9JCCGEkJFS4j6NGzfO9jo+Pp63336bWrVq4ezsjL29PefOnXvsN39+fn6Zz+3s7HB0dCQ8PLzQ4hZCCFE6pRuMjF5yjAthcXg4WLHglSY4WFuaOyxRwkl/SQghhDAdGSllAjaWOs7+r6NZrmtKdnZ22V6//fbbbNq0ic8++4yqVatiY2ND3759SU1NfeR5LC2z/0Kg0WgwGotu5RwhhBAln6IoTPnzDDsvRmBjqeOnIU0o52xj7rDEIxSkvxR8J5GY5DQ8HKzxcLQq8HVNSfpLQgghhOlIUsoENBqNSYeFFxd79uzhlVdeoVevXpDxTeC1a9fMHZYQQgjBj7uusuTADTQa+OqFBtQr72TukMRjFKS/VMbBihSDEQWKbV9L+ktCCCFEwcn0PfFQ1apVY/Xq1Rw/fpwTJ04waNAg+QZPCCGE2W04HcKM9ecA+E/X2nSo42nukEQhsbtvBT5TFyw3FekvCSGEEAUnSSnxUF988QUuLi40b96cbt260bFjRxo1amTusIQQQpRix4OjeXP5cRQFBjeryKstfM0dkihE1pY6dBoNBkUhOc1g7nByJf0lIYQQouA0SnH92smMYmNjcXJyIiYmBkdHx2zvJScnc/XqVSpVqoS1tbXZYhSmJ3+2QghRvF2LTKDv3H1ExqfQpoY78wc3NstKe4/qJ5QmRdVfuhIRT3xKOuWcbXCzL1hdKWE60l8SQgiRF3ntL8lIKSGEEEIUe7svRdLj2z1ExqdQy8uRbwY1MktCShQ9Oyu1llRiSrq5QxFCCCGEiRXPipFCCCGEEBmr7P20+yoz1p3DqEB9H2fmv+yPvZV0YUqLe3WlElINKIqCRqMxd0hCCCGEMBHp0QkhhBCiWEpOMzB59SnWHLsFQF//8nzYsy7WljpzhyaKkI3eAg0a0gxG0gxG9Bby5y+EEEKUFJKUEkIIIUSxcys6idd/PczpW7HotBr+07UWrzT3lVEypZBOq8FGryMxNZ2EVIMkpYQQQogSxOzFGL799lt8fX2xtrYmMDCQgwcPPrJ9dHQ0o0ePxsvLCysrK6pXr866deuytbl16xYvvfQSZcqUwcbGhnr16nH48OFCvhMhhBCi9FAUhZt3EzlzO4Yj1++yJyiSzWfD+PvkbVYcDubX/deZv/MKX2+5xI+7rnD2dix5XVvl4NUoun+zm9O3YnGxteTXYQEMbVFJElKlmG3GFD6pKyWEEEKULGYdKbV8+XImTpzI3LlzCQwMZPbs2XTs2JELFy7g4eGRo31qairt27fHw8ODlStX4u3tzfXr13F2ds5sc/fuXVq0aEGbNm1Yv3497u7uXLp0CRcXlyK+OyGEEKJkuhIRz9Q/z7DrUmS+jvNwsKJ1dXda13DnmapuONvqs72vKAq/HbjB9D/PkG5UqO3lyA8v++PjamviOxBPGzsrCyLjU0hINZg7FCGEEEKYkFmTUl988QXDhw9n6NChAMydO5d//vmHBQsW8N577+Vov2DBAqKioti7dy+WlpYA+Pr6ZmvzySef4OPjw8KFCzP3VapUqdDvRQghhCjpElPT+XZbEPN2XiHNoGCh1eBqp8dGr8PaQoe1Xoe1hRYbvQ4bSx3WGVtoTBL7r0QRHpfCiiM3WXHkJloNNPBxpnV1D1rXcKempwPT/zrD0oPBADzv58WsvvWx0ctULZE1Uio5zUC6wSgrLwohhBAlhNmSUqmpqRw5coTJkydn7tNqtbRr1459+/blesyff/5Js2bNGD16NGvXrsXd3Z1BgwYxadIkdDpdZpuOHTvSr18/duzYgbe3N6NGjWL48OEPjSUlJYWUlJTM17GxsSa9VyGEEOJppigKG8+E8r+/znI7JhmAZ2u4M61bHXzd7PJ0juQ0A4ev3WXHxXB2XIzgYlg8R29Ec/RGNF9uvohepyXVYESjgXc71uSN1pVlup7IZKnTYmWhIyXdQGKqAUcbSUoJIYQQJYHZklKRkZEYDAbKli2bbX/ZsmU5f/58rsdcuXKFrVu38uKLL7Ju3TqCgoIYNWoUaWlpTJ06NbPN999/z8SJE3n//fc5dOgQ48aNQ6/XM2TIkFzPO3PmTKZPn14IdymEEEI83a5GJjD1zzPsvBgBgLezDVO71aZ97bL5ShpZW+p4ppobz1Rz44OuaiHznRcj2HEhgj1BkcSlpONgbcE3AxvybI2cU/iFsNOrSamE1HQcbSzNHY4QQgghTOCp+prJaDTi4eHBvHnz8Pf3Z8CAAXzwwQfMnTs3W5tGjRoxY8YMGjZsyIgRIxg+fHi2Ng+aPHkyMTExmVtwcHAR3dHT5dlnn+XNN9/MfO3r68vs2bMfeYxGo+GPP/544mub6jxCCCHyJinVwGcbL9Dxy53svBiBXqdlbNuqbJ7Ymg51PJ94FJO3sw0DAyow92V/jk5pz+pRzdk8sbUkpMRD2Vqp36UmphTvulLSXxJCCCHyzmwjpdzc3NDpdISFhWXbHxYWhqenZ67HeHl5YWlpmTlVD6BWrVqEhoaSmpqKXq/Hy8uL2rVrZzuuVq1arFq16qGxWFlZYWVl9cT3VJx169aNtLQ0NmzYkOO9Xbt20apVK06cOIGfn1+ez3no0CHs7PI2bSOvpk2bxh9//MHx48ez7Q8JCZFi9UIIUUQ2nQ1j2p9nuBWdBEDr6u5M616HSnmcqpdfljotjSrI//Hi0ezurcCXZsBoVNBqTT+9U/pLQgghRNEy20gpvV6Pv78/W7ZsydxnNBrZsmULzZo1y/WYFi1aEBQUhNFozNx38eJFvLy80Ov1mW0uXLiQ7biLFy9SsWLFQruXp8GwYcPYtGkTN2/ezPHewoULady4cb46WADu7u7Y2hbNikienp4lPnEohBDFwZpjNxn+y2FuRSfh7WzDDy/7s2hok0JLSAmRV3oLLRZaLYqikJRWOKOlpL8khBBCFC2zTt+bOHEi8+fP5+eff+bcuXOMHDmShISEzNX4Bg8enK0Q+siRI4mKimL8+PFcvHiRf/75hxkzZjB69OjMNhMmTGD//v3MmDGDoKAglixZwrx587K1KY2ef/553N3dWbRoUbb98fHxrFixgp49ezJw4EC8vb2xtbWlXr16LF269JHnfHA4+qVLl2jVqhXW1tbUrl2bTZs25Thm0qRJVK9eHVtbWypXrsx///tf0tLSAFi0aBHTp0/nxIkTaDQaNBpNZrwPDkc/deoUbdu2xcbGhjJlyjBixAji4+Mz33/llVfo2bMnn332GV5eXpQpU4bRo0dnXksIIUROx4OjmbTqFAAvBlZg88TWdDTBVD0hTEGj0WBnpY6WSkhNL5RrSH9J+ktCCCGKltmm7wEMGDCAiIgIpkyZQmhoKA0aNGDDhg2Zxc9v3LiBVpuVN/Px8WHjxo1MmDABPz8/vL29GT9+PJMmTcps06RJE9asWcPkyZP53//+R6VKlZg9ezYvvvhi4d2IokBaYuGd/2EsbSGPvyhYWFgwePBgFi1axAcffJD5C8aKFSswGAy89NJLrFixgkmTJuHo6Mg///zDyy+/TJUqVQgICHjs+Y1GI71796Zs2bIcOHCAmJiYbPUU7nFwcGDRokWUK1eOU6dOMXz4cBwcHHj33XcZMGAAp0+fZsOGDWzevBkAJyenHOdISEigY8eONGvWjEOHDhEeHs5rr73GmDFjsnUit23bhpeXF9u2bSMoKIgBAwbQoEGDR67EKIQQpVVYbDKv/3qY1HQj7WuX5f961C2U6VGiFDNBf8lWk0JsWjJJ8WlglcfRUtJfkv6SEEKIYsusSSmAMWPGMGbMmFzf2759e459zZo1Y//+/Y885/PPP8/zzz9vshgfKy0RZpQruuvd8/5t0Od9OsWrr77KrFmz2LFjB88++yxkDEXv06cPFStW5O23385sO3bsWDZu3Mjvv/+ep07W5s2bOX/+PBs3bqRcOfWzmDFjBp07d87W7j//+U/mc19fX95++22WLVvGu+++i42NDfb29lhYWDy0rhjAkiVLSE5O5pdffsms0TBnzhy6devGJ598kpnUdHFxYc6cOeh0OmrWrEnXrl3ZsmWLdLKEEOIByWkGRvx6hLDYFKqXtefLAQ0kISVMzwT9JfeMLV+kvyT9JSGEEMXWU7X6nngyNWvWpHnz5ixYsACAoKAgdu3axbBhwzAYDPzf//0f9erVw9XVFXt7ezZu3MiNGzfydO5z587h4+OT2cEiI4H4oOXLl9OiRQs8PT2xt7fnP//5T56vcf+16tevn61oaIsWLTAajdnqidWpUydbUXwvLy/Cw8PzdS0hhCjpFEXh/dWnOBEcjbOtJfMHN8beyuzfWQlhNtJfkv6SEEKIoiO9TlOwtFW/hTPHdfNp2LBhjB07lm+//ZaFCxdSpUoVWrduzSeffMJXX33F7NmzqVevHnZ2drz55pukpqaaLNx9+/bx4osvMn36dDp27IiTkxPLli3j888/N9k17mdpaZnttUajyVYkXwghBMzfdYXVx26h02r4blAjKpaRguZPo++//57vv/+ea9euQUaiYcqUKTlG4NyzaNGizBqe91hZWZGcnFx4QZqov3Q1MoH4lHTKOVlTxj4PRb2lv/RI0l8SQghhTpKUMgWNJl/Dws2pf//+jB8/niVLlvDLL78wcuRINBoNe/bsoUePHrz00kuQUfPg4sWL1K5dO0/nrVWrFsHBwYSEhODl5QWQY5rl3r17qVixIh988EHmvuvXr2dro9frMRgeXSOiVq1aLFq0iISEhMxv//bs2YNWq6VGjRp5/CSEEEJsuxDOx+vPAzDl+do0r+pm7pBEAZUvX56PP/6YatWqoSgKP//8Mz169ODYsWPUqVMn12McHR2zjZgp9IL2Juov2djpiDMmk4ieMvrCWdVO+ktCCCFE0ZDpe6WMvb09AwYMYPLkyYSEhPDKK68AUK1aNTZt2sTevXs5d+4cr7/+OmFhYXk+b7t27ahevTpDhgzhxIkT7Nq1K1tn6t41bty4wbJly7h8+TJff/01a9asydbG19eXq1evcvz4cSIjI0lJSclxrRdffBFra2uGDBnC6dOn2bZtG2PHjuXll1/OrI8ghBDi0YLC4xm35BhGBQYG+DC4WUVzhySeQLdu3ejSpQvVqlWjevXqfPTRR9jb2z+yDqdGo8HT0zNze1p+hmauwJdSOCvwIf0lIYQQoshIUqoUGjZsGHfv3qVjx46ZNQ3+85//0KhRIzp27Mizzz6Lp6cnPXv2zPM5tVota9asISkpiYCAAF577TU++uijbG26d+/OhAkTGDNmDA0aNGDv3r3897//zdamT58+dOrUiTZt2uDu7p7rMsu2trZs3LiRqKgomjRpQt++fXnuueeYM2dOgT8TIYQoTWKS0hjxy2HiUtJp4uvC9O51C3+UjCgyBoOBZcuWkZCQkGu9onvi4+OpWLEiPj4+9OjRgzNnzhRpnAVlq9ehAVINRlLTC2+amfSXhBBCiMKnURRFMXcQxU1sbCxOTk7ExMTg6OiY7b3k5GSuXr1KpUqVsLa2NluMwvTkz1YIURoYjApDFx1i58UIvJ1tWDumBW55qcsjMj2qn2BOp06dolmzZiQnJ2Nvb8+SJUvo0qVLrm337dvHpUuX8PPzIyYmhs8++4ydO3dy5swZypcvn+sxKSkp2UbkxMbG4uPjY5b+0qWwOJLSDFRwtcXZVm/y84uHk/6SEEKIvMhrf0lGSgkhhBClyMfrz7HzYgQ2ljrmDfaXhFQJUqNGDY4fP86BAwcYOXIkQ4YM4ezZs7m2bdasGYMHD6ZBgwa0bt2a1atX4+7uzg8//PDQ88+cORMnJ6fMzcfHpxDv5tHsMlaITEh9dF0lIYQQQhRvkpQSQgghSoHkNAM/7rrC/F1XAfisX33qlHMyd1jChPR6PVWrVsXf35+ZM2dSv359vvrqqzwda2lpScOGDQkKCnpom8mTJxMTE5O5BQcHmzD6/LHVq3WlEguxrpQQQgghCp+svieEEEKUUIqicCw4mpVHbvLXidvEJau/wI9rW5Wufl7mDk8UMqPRmGsB7NwYDAZOnTr10Ol+AFZWVlhZFY+RdXZ6tQubnGbAYDSi08r3rEIIIcTTSJJSQgghRAkTGpPMmmO3WHkkmMsRCZn7vZ1teLFpBd5oVcWs8QnTmzx5Mp07d6ZChQrExcWxZMkStm/fzsaNGwEYPHgw3t7ezJw5E4D//e9/NG3alKpVqxIdHc2sWbO4fv06r732mpnvJG8sLbToLbSkphtJTDXgYC1JKSGEEOJpJEkpIYQQogRITjOw6WwYK4/cZNelCIwZy5hYW2rpUteLvv7laVq5DFqtrLJXEoWHhzN48GBCQkJwcnLCz8+PjRs30r59ewBu3LiB9r7RRHfv3mX48OGEhobi4uKCv78/e/fupXbt2ma8i/yx01uQmp5KQooBB2tLc4cjhBBCiAKQpFQBGY2FtwSxMA/5MxVCPE2S0wycvBnD0Rt3OXL9Lvuv3MmcngfQxNeFfv4+dK7nKb+wlwI//fTTI9/fvn17ttdffvklX375ZSFHVbg/W231Ou4mQmKq1JUqStJfEkIIYUqSlMonvV6PVqvl9u3buLu7o9fr0WjkW+enmaIopKamEhERgVarRa+XpaWFEMVPSEwSR66rCaijN6I5cyuG9HvDoTKUc7Kmj395+jQqj6+bndliFaIo+ksWigElPZV4QxqJSTq00h8rVNJfEkIIURgkKZVPWq2WSpUqERISwu3bt80djjAhW1tbKlSokG16gxBCmIPRqHApPJ6DV+9w4GoUR6/f5XZMco527g5W+Fdwwb+iC40qutDQx1mm54lioSj6S4oCd2KSMCigxFqht5Cf30VB+ktCCCFMSZJSBaDX66lQoQLp6ekYDAZzhyNMQKfTYWFhIaPehBBmYTAqnAuJ5cDVKA5cucOha1HcTUzL1kan1VDLywH/CmoCqlEFF8q72Mj/W6LYKor+0oI1p9h35Q5vtK5Cv8Y+hXINkUX6S0IIIUxNklIFpNFosLS0xNJS6nQIIYTIv6uRCWw4HcrBq3c4fO0ucSnZ6+LYWOrwr+hCQCVXGvu60MDHGVu9/NgWT5cn6i9d3gYOXuBR86FNqpZzZeWJcLYFRfPyM9WeLFghhBBCFDnp3QohhBBFKN1g5IedV/hq8yVSDVkFgx2sLGjs60JApTIEVnalbjknmY4kSq/gg7B0IOht4eU/wMsv12atq7vz8frz7AmKJCnVgI1eV+ShCiGEEKLgJCklhBBCFJHLEfG89fsJjgdHA9C0sivtapWlaeUy1PJyRCf1oIRQlakK7jUg5Dj8/Dy8tAbK++doVtPTAW9nG25FJ7E7KJL2tcuaJVwhhBBCFIx8BSuEEEIUMqNR4cddV+jy1S6OB0fjYG3BZ/3qs3R4U15rWZm63k6SkBLifrauMORP8AmE5Bj4pQdc35ejmUajyUxEbT4bZoZAhRBCCPEkJCklhBBCFKLrdxJ4Yd5+PvznHCnpRlpWc+PfCa3o619eigUL8SjWTvDSavBtCalx8FtvuLIjR7N2tdSk1JbzYRiNihkCFUIIIURBSVJKCCGEKARGo8Kv+67RafYuDl6Lwk6vY0avevzyagBeTjbmDk+Ip4OVPQz6Hao8B2mJsKQ/XNqUrUlAJVccrCyIjE/l+M1os4UqhBBCiPyTpJQQQghhYreik3h5wQH+u/YMSWkGmlZ2ZcObrRgUWEFGRwmRX3pbGLgUanSB9GS1APq5v7PettDSuoY7yBQ+IYQQ4qkjSSkhhBClntGooChPPu3HaFT4bf91On65kz1Bd7C21DKtW22WvNYUH1dbk8QqRKlkYQX9f4HaPcGYBr8PhtOrMt/OrCt1TpJSQgghxNNEVt8TQghRqsUmp/Hi/AOExSYztm1VXgiogKUu/9/ZnL0dywd/nOLYDXX6UKMKznzevwGV3OwKIWohSiGdJfT5CSys4eQyWPUapKdAg0E8W90DnVbDxbB4rt9JoGIZ+XcnhBBCPA1kpJQQQohSK91gZMySY5y6FUN4XAr/XXuGDl/uZP2pkDyPnEpISeejf87Sbc5ujt2Ixt7KgqndarPijeaSkBLC1HQW0PN7aDQEFCP8MRIO/YSTrSUBvq4AbD4Xbu4ohRBCCJFHkpQSQghRan207hw7L0ZgY6njzXbVKGOn52pkAiMXH6X393s5eDXqkcdvOhtG+y92MH/XVQxGhS71PNk8sTVDW1RCp5XaUUIUCq0Wun0FgW+or/+ZCCd/p929KXxSV0oIIYR4akhSSgghRKm09OANFu65BsCXA+rzZrvq7Hi3DeOeq4aNpY5jN6Lp/8M+Xvv5MEHhcdmOvR2dxPBfDjP8l8PcjkmmvIsNC19pwncv+uPpZG2mOxKiFNFooNPHWYmpg/NpV8tDfXotipjENPPGJ4QQQog8kaSUEEKIUmff5Tv894/TALzdoTqd6noBYG9lwcT21dnxzrMMCqyATqth87kwOny5k8mrT3I7Ookfd12h3Rc72HQ2DAuthpHPVmHThNa0qelh5rsSopTRaKDpKPX57aNUtFeo5mGPwaiw/aJM4RNCCCGeBlLoXAghRKly/U4CIxcfId2o0L1+OUa3qZqjjYejNTN61ePVFpX4dMN5/j0bxtKDwSw9GJzZpnFFFz7qVY8ang5FfAdCiEwuFcGpAsTcgOADtKvtzaXweDafC6dHA29zRyeEEEKIx5CRUkIIIUqN2OQ0hv18mOjENOqXd+LTvn5oNA+v/VTVw555gxuz8o1mNKrgDICzrSWf9KnH7683k4SUEMWB7zPq47XdtKul1pXafiGc1HSjeeMSQgghxGPJSCkhhBClgsGoMG7pMYLC4/F0tGb+4MZYW+rydGxjX1dWjWzO8eBoKrnZ4WyrL/R4hRB55PsMnFgC13bToO0U3Oz1RMancuhaFC2qupk7OiGEEEI8goyUEkIIUSrMWHeO7RcisLbU8uOQxng45q8guUajoWEFF0lICVHc3BspdfsourQE2mbUd9skq/AJIYQQxZ4kpYQQQpR4yw/d4KfdVwH4on8D6no7mTskIYSp3KsrZUyH4P2ZU/g2nwtDURRzRyeEEEKIR5CklBBCiBLtwJU7/Cdjpb0J7arTpZ6XuUMSQphapZbq47XdPFPNDSsLLTfvJnEhLM7ckQkhhBDiESQpJYQQosS6EBrHG78dIc2g8LyfF+Oey7nSnhCiBLiv2Lmt3oJnMmpJbZYpfEIIIUSxViySUt9++y2+vr5YW1sTGBjIwYMHH9k+Ojqa0aNH4+XlhZWVFdWrV2fdunW5tv3444/RaDS8+eabhRS9EEKI4kRRFHZcjGDowoN0nL2Tu4lp+JV34rN+9R+50p4Q4ilWsYX6eOsopMTTrrY6hW/TuXDzxiWEEEKIRzL76nvLly9n4sSJzJ07l8DAQGbPnk3Hjh25cOECHh4eOdqnpqbSvn17PDw8WLlyJd7e3ly/fh1nZ+ccbQ8dOsQPP/yAn59fEd2NEEIIc0lISWf10Zss2nuNyxEJAGg08FxND2b0qpfnlfaEEE8hl4rgXAGib0Dwfp6rqY6cOhEcTXhscr4XNhBCCCFE0TB7UuqLL75g+PDhDB06FIC5c+fyzz//sGDBAt57770c7RcsWEBUVBR79+7F0tISAF9f3xzt4uPjefHFF5k/fz4ffvhhEdyJEEIIcwiOSuTnvddYfjiYuOR0AOytLOjXuDxDmvni62Zn7hCFEEXBtyUcXwzXduNRtR31fZw5ERzNlvPhDAyoYO7ohBBCCJELs07fS01N5ciRI7Rr1y4rIK2Wdu3asW/fvlyP+fPPP2nWrBmjR4+mbNmy1K1blxkzZmAwGLK1Gz16NF27ds12biGEECWDoijsDYpk+C+HaTVrGz/uvkpccjq+ZWyZ1q02+ya3ZWq3OpKQEqI0ua+uFEC7muqI+y3npK6UEEIIUVyZdaRUZGQkBoOBsmXLZttftmxZzp8/n+sxV65cYevWrbz44ousW7eOoKAgRo0aRVpaGlOnTgVg2bJlHD16lEOHDuUpjpSUFFJSUjJfx8bGPtF9CSGEKBw37yay6sgtVh29yY2oxMz9Lau5MbSFL89W90CrlbpRQpRKudSV+nzTRXZdiiQp1YCNXqbwCiGEEMWN2afv5ZfRaMTDw4N58+ah0+nw9/fn1q1bzJo1i6lTpxIcHMz48ePZtGkT1tZ5qx8wc+ZMpk+fXuixCyGEyL/E1HQ2nA5l5ZGb7L18J3O/nV5Hz4bevNLcl2plHcwaoxCiGHigrlTNKs/h7WzDregkdgdF0r522TycRAghhBBFyaxJKTc3N3Q6HWFh2YdVh4WF4enpmesxXl5eWFpaotNlfdtVq1YtQkNDM6cDhoeH06hRo8z3DQYDO3fuZM6cOaSkpGQ7FmDy5MlMnDgx83VsbCw+Pj4mvFMhhBD5oSgKh67dZeWRYP45GUJCatYU7eZVytCvcXk61vHEVv/UfbcihChMvq3g+G9wdReaqu1oX7ssi/ZeY/PZMElKCSGEEMWQWXvzer0ef39/tmzZQs+ePSFjJNSWLVsYM2ZMrse0aNGCJUuWYDQa0WrVklgXL17Ey8sLvV7Pc889x6lTp7IdM3ToUGrWrMmkSZNyJKQArKyssLKyKpR7FEIIkZ2iKCSlGYhKSCU6MY27iancTUzjbkIqdxNTiUpIZcfFCK7fyZqeV8HVlr7+5endyJvyLrZmjV8IUYz5PqMmpe7VlaqlJqW2nA/DaFRkeq8QQghRzJj9K+aJEycyZMgQGjduTEBAALNnzyYhISFzNb7Bgwfj7e3NzJkzARg5ciRz5sxh/PjxjB07lkuXLjFjxgzGjRsHgIODA3Xr1s12DTs7O8qUKZNjvxBCiKJxLTKBH3ZeYfuFcO4kpJKabnzsMbZ6HV3redGvsQ9NfF3QaOSXSSHEY/hm1JW6fQxS4gio5IqDlQWR8akcvxlNowou5o5QCCGEEPcxe1JqwIABREREMGXKFEJDQ2nQoAEbNmzILH5+48aNzBFRAD4+PmzcuJEJEybg5+eHt7c348ePZ9KkSWa8CyGEELk5fSuG73dcZv2pEIxK9vf0Oi3Otpa42ulxtrXExVaPs60eVztLqnrY06G2J3ZWZv8xJYR4mjhXAOeKEH0dbhxAX60drWu48/fJEDafDZOklBBCCFHMaBRFUfLQrlSJjY3FycmJmJgYHB0dzR2OEEI8VRRFYd+VO3y//TK7LkVm7m9b04OhLXyp5GaHi60eW71ORj+J/IsPBzt3MOPfHeknqIrt5/DHaHUKX4s3of101h6/xfhlx6le1p5/J7Q2d3RCCCFEqZDXfoJ8BS2EEMIkjEaFTefC+H77ZY4HRwOg1UC3+uV4o3UVankVo19axdPpwDxY/w50+Aia5157UogH60o9W90DnVbDxbB4rt9JoGIZO3NHKIQQQogMkpQSQgjxRCLiUth6Pox5O69wOSIBAL2FlgGNfRjesjIVykhhcmECcWGwZbr6/PBP0Gy0WUdLiWLsgbpSTrYOBFZyZe/lO6w9fptxz1Uzd4RCCCGEyCBJKSGEEPkSEpPEwatR7L8SxcGrdzITUQAOVha83KwiQ1tUwt1BVjUVJrTlf5Aarz6PugIhJ6BcA3NHJYqjB+pKUa0d/RqXZ+/lOyw7eIPRbaqik1X4hBBCiGJBklJCCCEeSlEUbt5NYv+VOxy4GsXBq1HciErM0a6mpwM9GnjzYtMKOFpbmiVWUYLdOqJOxwLwqAPhZ+D0KklKiYer1BKOXYdru6BaOzrX9WLan2e5HZPMzosRtKnpYe4IhRBCCCFJKSGEEA8TFpvM8F8Oc/JmTLb9Wg3UKedEYCVXAjI2Z1u92eIUJZyiwPqMFXb9XoCaXeH3l+HMGmj/P5nCJ3Ln2xKO/aYmpQBrSx19GpVnwZ6rLD5wQ5JSQgghRDEhSSkhhBA53LybyIs/HuD6nUQsdRr8yjsTUMmVwEqu+Fd0wUFGQ5VswQfBqTw4ljN3JHDyd7h5CCztoN00sHEGvT3EBKv7fQLMHaEojireqyt1HJJjwdqRQYE+LNhzla3nwwiNScbTydrcUQohhBClntbcAQghhCherkYm0H/uPq7fSaSCqy1b33qWVSObM6lTTZ6t4SEJqZLu1lH4qQMs6AhpSeaNJSUeNk9Vn7d6Cxy9wNJGHS0F6hQ+IXLj7AMuvqAYIPgAAFU9HAio5IpRgeWHgs0doRBCCCEkKSWEEOJ+F8Pi6P/DPm7HJFPF3Y7fX2+Gj6usnleqnF4FKBB9A/Z/b95Ydn8BcSFqcqHp6Kz9dXqrj2f+AKPBbOGJYs73GfUxYwofwKCACgAsP3QDg1ExV2RCCCGEyCBJKSGEEACcvhXDgB/2ERGXQi0vR5a/3kymt5Q2igJn/8x6vesLSIg0TyxRV2HvHPV5h4/A8r6/i1XagrUTxIfC9b3miU8Uf74t1cdruzN3darribOtJbdjktlxMdx8sQkhhBACJCklhBAC4Mj1uwycv5+7iWnUL+/E0uGBuNlbmTssUdRCjkPMDbV+U9l6kBoH2z82Tyz//gcMKVCpddZ0vXss9FCru/pcpvCJh3mwrtR9Bc8Blhy4Yc7ohBBCCCFJKSGEEHsvR/LyTweIS04nwNeV314LlNX0Squza9XHau2h0wz1+eEFEHGxaOO4sh3O/w0aHXT6OPcV9upmTOE79ycY0oo2PvF0yKWuFMDAjCl8W8+HExJj5rppQgghRCknSSkhhCjFtl8IZ+jCQySmGmhZzY1FrzaRQual1f1T92p3h0qtoHpn9Rf6e8XGi4IhHTZMVp83GQZla+fezrcV2LpB4h24uqPo4iumvv/+e/z8/HB0dMTR0ZFmzZqxfv36Rx6zYsUKatasibW1NfXq1WPdunVFFm+RyZzCl1VXqqqHPYFS8FwIIYQoFiQpJYQQpdSG06EM/+UwKelG2tXyYP7gxtjqLcwdljCX8LMQdRksrKFaB3Vf+/+po5UurIOrux53BtM4slCNxcYFnp388HY6C6jdQ31+ek3RxFaMlS9fno8//pgjR45w+PBh2rZtS48ePThz5kyu7ffu3cvAgQMZNmwYx44do2fPnvTs2ZPTp08XeeyFKpe6UgCDAu8VPA8m3WA0R2RCCCGEkKSUEEKULoqicD40ls82XmD0kqOkGRS6+nnx/Uv+WFvqzB2eMKd7U/eqPAdWDupz9+rQeKj6/N8PwFjIv7wnRsHWD9XnbT4AW9dHt6/bR3089xekpxRubMVct27d6NKlC9WqVaN69ep89NFH2Nvbs3///lzbf/XVV3Tq1Il33nmHWrVq8X//9380atSIOXPmFHnshco3Z10pMgqeu9haEhKTzI6LEeaLTwghhCjlJCklhBAlnNGocPTGXWauO8ezn22n0+xdzNkWhMGo0KdReb5+oSGWOvlxUOrdP3Xvfq3fA70DhJyAUysKN4ZtMyA5GjzqgP/Qx7ev0AwcvCAlBoK2FG5sTxGDwcCyZctISEigWbNmubbZt28f7dq1y7avY8eO7Nu3r4iiLCJO5cGlkjoN9UZWgs7KQkdffyl4LoQQQpibzNMQQogSKM1g5ODVKDacDuXfs6GExWaNItFbaGlVzZ1u9b3o5lcOrTaXItKliSEdVg+HhAjo/g24VjJ3REUv4iJEnAOtJVTvlP09e3doORG2TIct/1OTVpY2po8h7Awc/kl93mmmOj3vcbRaqNML9n8HZ1ZDzS6mj+spcurUKZo1a0ZycjL29vasWbOG2rVzr8kVGhpK2bJls+0rW7YsoaGhDz1/SkoKKSlZ/5fExsY+tG2x4vsM3L2q1pWq3iFz9wsBFZi/6yrbLoRzOzqJcs6F8PdaCCGEEI8kSSkhhChBwuOS+WzjBf49G0Z0YtaKZPZWFrSt6UGnup60ru6OnZX8959p79dqQgNgfhvo/4ta5Ls4UBQ4swZcK0O5BoV3nXMZU/cqPws2zjnfbzoSDv0EsTfVBFDLt/J+7uCDcGUHoDy63fl/QDFCrW5QuXXez1+ntxrT+XWQmgh627wfW8LUqFGD48ePExMTw8qVKxkyZAg7dux4aGIqv2bOnMn06dNNcq4i5dsSjv2ao65UFXd7mlZ2Zf+VKJYfCmZC++pmC1EIIYQoreS3EiGEKCGCoxJ56acDXL+TCICrnZ4OtcvSsa4nzauUwcpCakblEH4Ots9Unzv5QEww/NoLOn8CTV4zd3RwfDGsHQ1ooPkYaPMfsLQ2/XUeNnXvHksbeG4KrBkBu76EhoPVEVSPkpoAm6bCofl5j0NnBR0+zEfgQPnG4FQBYm7ApX+hTs/8HV+C6PV6qlatCoC/vz+HDh3iq6++4ocffsjR1tPTk7CwsGz7wsLC8PT0fOj5J0+ezMSJEzNfx8bG4uPjY9J7KBT36kqFZNSVsnbMfGtQYMXMpNTYtlWxkKnMQgghRJGSpJQQQpQAQeFxvPTjQUJjk/FxteGTPn4E+LrKL1iPYkiHP0aBIRWqdYT+P8OfY9W6Sf+8pSasOn0MOkvzxJeWrNZYAnWU0d5v4OK/0Ot78PY33XWirkLoSXWVvRpdH96uXj91RFLIcdjxMXT9/OFtr++DP0aqU6YAaj4Pdo9JYoE6ddDFN3/xazRQtzfsmQ2nV5XqpNSDjEZjtul292vWrBlbtmzhzTffzNy3adOmh9agArCyssLKyqpQYi1U9+pK3b0KRxZBi3GZb3WsUxZXOz2hsclsvxBBu9plH3kqIYQQQpiWJKWEEOIpd/pWDIMXHCQqIZVqHvb89logZR0LYTRNSbP3a7h9FKycoNtsdTRQ7/ngUVutnXToR4i4oE7ne9wqcIXh0HyIvQWO5aHjR7DuHYi8AD+2h2cmQOt3wcIECYJzGaOkfJ8BuzIPb6fVqqOYfn4eDi+EgNfV1fnul5akrp6371s1keZYHnp8A1XaPnmcj3IvKXXpX0iJy1o9sBSZPHkynTt3pkKFCsTFxbFkyRK2b9/Oxo0bARg8eDDe3t7MnKmODBw/fjytW7fm888/p2vXrixbtozDhw8zb948M99JIQkYDhvfh01TwLEc1OsL9xU8n7fzCksO3pCklBBCCFHE5Ct0IYR4ih28GsXAefuJSkjFr7wTy19vVnoSUqkJBT/2/ml7nWaqv6SSMeqm5UR4YQno7dXCyPPbQPh508ScV8kxsCtjJFKbyeron9EHoG5fdRWxXZ/BvDYQcvLJr/W4qXv3q9QSanRRY9g0Jft7Nw/D3Jawb46akGr4EozaW/gJKQBPPyhTFdKT4cL6wr9eMRQeHs7gwYOpUaMGzz33HIcOHWLjxo20b98egBs3bhASEpLZvnnz5ixZsoR58+ZRv359Vq5cyR9//EHdunXNeBeFqOkoaDJc/bu55o1sqzW+0ESdgrj9Qji3opPMGKQQQghR+mgURXlM5dHSJzY2FicnJ2JiYnB0dMzDEUIIUfS2Xwjnjd+OkJxmJLCSKz8OaYyDtZmmmhW1M3/A6hFQsbk67c7aKe/HGtLhp3Zw+5g6bW/QcjUZ9aCws7B0AETfAL0D9PkRanTK7Yymt+X/1MSTWw0YuTf7SnRn18LfEyDxDmgtoNW7aiKtINMMY27Cl3XUmlVvXQCHPIwSibwE3waqiakhf4FPoJrg2/OVWqjc3hO6fw3VO+Y/niex9SPY+ak6BXDQ8kK9lPQTVE/d52A0wqph6sIGlnbq39/y6lTYgfP2s+/KHcY9V42JUvBcCCGEeGJ57SfISCkhhHgK/XMyhOG/HCY5zUjbmh78/GpA6UlI3TqqjnQwpMCVbbCwK8Q9fBn7HPZ+pSak7k3byy0hBVC2NgzfDhWfgdQ4WPoC7J6trohXmOJC1dpNoBYX1z0w0752Dxh1AGp1B2M6bJ8BPz6nJtHy69xf6mOFZnlLSAG4VYPGr6rP170L856F3V+qCal6/WHUvqJPSAHU7aM+Bm2BpLtFf31R/Gm10OsHqNwG0hJgcV+IuAjAoMAKACw/dIN0g9HMgQohhBClhySlhBCiEIXEJHErOomohFQSU9MxGp88ofH7oWDGLj1KmkHheT8v5r7kj7VlKVlZL/Y2LBsE6UlQsQXYeUDYKfipPUQGPf748HOw/WP1eeePs6btPYxdGXh5DfgPVaf9bJ4Kv/aEy9sKLzm1cxakJUL5JlDzIYXH7d3VWld9fgJrZwg5AfNaw7m/83et/Ezdu9+z74GVI0Scg/CzYOsGA36DPvPNU38LwKOmWg/MmJb/z0GUHhZ6GPArlGsESVHqapsxt+iQUfA8LDaFbRcizB2lEEIIUWpIoXMhhCgki/ZcZdpfOUev6C202FjqsLHUYW2pxdpSh6O1JeVdbPBxtaWCq23mo4eDFVpt1kieH3dd4cN/zgEwMKACH/asi077kJE+JU1qopqQigsB95owcCkkRsFvvSHqCizoAIN+h/KNcz/ekK6uCHdvtb36A/N2XQs9PP8llK0DG96DK9vVrWxdaDZGHaFjoTfNPd65rK4OBtBu2sNHcZFR/6peX7VA+Z/j4NJGWPM6uG0F9xqPv1ZcGNzYpz6v1S1/cdq5qfH985Y6cqvr5+o+c6vbG7aeVadnNXrZ3NGI4srKAV5cAQs6wZ1L8GsvrF7dQD//8vyw8wpLDlynvRQ8F0IIIYqE1JTKxVNXI0EIUeycvBlNn+/3kmZQ0Ou0pBZwOojeQkt5FxsquNpibaFjwxl1mtrrrSrzXueaaB6VtChJFAVWDoUza8DGFYZvBddK6nvxEbCkv7qSnqUt9PsZqnfIeY5dn6ur6lk5wej9jx8llZuoK7D/ezj2mzqaCcDBCwJGQOOhYOPyZPe5chicXglV28FLq/J+nCFdHcF1bRe4VVc/n8etQHfoJ/hnIng3huFbHt32YdKS1FULi4s7l+GbRqDRqTWy7N0L5TLST1A99Z9D9A34qSPE3YbyTbjedSmtvzoIwKqRzfCvaKZRf0IIIUQJkNd+giSlcvHUd7KEEGYVm5zG81/v5kZUIp3revLdi40wKpCSbiAp1UBSmoHkNCPJafeeG7ibmEZwVCI37yZyI0rdbkcnY8hlut87HWsw6tkqpSchBeqUu+0z1cLeg9eqo4PulxIPvw+Gy1vUhET3b6Dhi1nvh51Vp7cZUqHn99Bg0JPFkxgFRxbCgXkQn1HPytJOHZ3TdCS4+Ob/nCEn4IdW6vPXd4GXX/6Oj49Qj4+7rdab6v/Lo0da/dwdru6A9v+DFuPzH29x9UNrCDmujt5q8lqhXEL6CaoS8TmEn1NHTCVHQ9V2vGf1PsuOhFLT04G/xj6DpU4qXQghhBAFkdd+gkzfE0IIE1IUhcmrT3EjKpHyLjZ83McPjUaDTgO2egts9Xn/bzfdYCQkJpkbUYkZCaskGlZw5rlapWxayenVakIK1Gl0DyakAKzs1RXX1o6Bk8tg7SiID4NnJoDRoL7O77S9R7F1hZZvQbOx6simvXMg/AwcmAsH56lJoQ7/B84V8n7OzdPVx3r98p+Q4r46Uws7w7k/Ye/XD082JUbBtd3q81r5rCdV3NXtoyalTq8ptKSUKEE8aqlT+X7pAUGbmV7LmX9t+nE+NI6Fe64yolUVc0cohBBClGjy9Y8QQpjQ0oPB/HMyBAuthm8GNsTJpuAr4lnotPi42tKiqhsvBFTg7Y41Sl9C6tYRtQ4UQNPR0Gjww9vqLKHX3KxEzJbpsH4S7PlSXW3P2gm6ffXo0UP5ZaFXR12N3KMWRK/ynLoK3dk/YG5LOL8ub+e5ulMd5aW1gDbvFzwenybQ+RP1+eZpcGVH7u3O/wOKATz9sqZBlhR1eqmP1/dAbIi5oxFPA58ANaGrtcDq3EqWV1yLBiNfbrrEregkc0cnhBBClGiSlBJCCBM5HxrL9L/OAPBupxo0rPCE9YVKu9jbsHQQpCdDtQ7qyKPH0WjU6WgdM0ZWHfwBtn6oPu/0CTh6FU6sGg1UaQsvr4aRe8HbX50OtGwgbPwA0lMffqyiqAkkUFf5c638ZLE0fhUavKgmx1YOhZibOducXas+5nfVvaeBsw/4BKqrJV4uYK0sUfpUa69O7QWqXVvCYud5GNOSmPbnGXNHJoQQQpRokpQSQggTSExNZ/Tio6SkG3m2hjuvPfOEiYXSLjURlg5U6zW514Q+P4FWl/fjm43KOCZjpFq1jlD/hUILN5uydWDoBnVlPoB9c9QpddE3cm9/7i91RJilLbR658mvr9Go9ZS86kPiHbXWVnpK1vtJ0erqgQC1ejz59YqjDh/CyH3Q8CVzRyKeJn79oedc0FrSPHkny/UfcuzsRf7NWGBCCCGEEKYnSSkhhDCBqWvPcDkigbKOVnzerz5abT6miKUlw91rhRle3mIIOwtn/4RdX8Afo+CnDvBpFfilJ8SFFV0sRqM6ZS/kuLrS3sBlYF2AIsr1+sIrf6vT+Xp+b9ppe49joYeOH8ELS9Rpg7cOw9xnck7nM6TD1owRYM1Gg4OJpmda2kD/X9XVAG8dgfXvZr13cSMY09Rkn3t101yvuPEJgLK1zR2FeBo1GKhOxbV2poE2iDX6Kfz8x3oSUtLNHZkQQghRIkmhcyGEeEJrjt1kxZGbaDXw1QsNKWNvlfeD05JhYSe15lHA6+oUNYt8HF8QigKXt6rJiTtBcOcSRAer051yc2Ub/NRe/UWtTBEU/d3xsVqTSWsJA357sppHFZqqm7nU7KqupLdyqJocWjZQHUH13FQ1cXViCUReVJNvzcea9touFaHPj/BbXziyCLwbq6sDZk7dK6GjpIR4UpVawmtbMC7uh8/dK3yfOpm1qzUMGviKuSMTQgghShwZKSWEEBmr5kXEpXDgyh32Xo4kNd2Yp+OuRMTzwZrTAIx7rhpNK5fJ34X//Y+akCKj/tFPHSDqar7jz5P0FDi2GL5vAb/1Vq93eUvGtDIFrByhXCPwGwBtPoC+C2Hwn+BSCaKvq4mpW0cKJ7Z7dn0BOzIKdT//Bfi2KNzrFQWXirlP54u4CNs/Vve1fEsdUWVqVdupf5YA/7ylrrh3r85SSVt1TwhTcquK9rXNRLs3xlGTRP/zEwjZ8r25oxJCCCFKHI2iKA/5arz0io2NxcnJiZiYGBwdCzBlRAhRbCWmpnM1MoGrkQlcibj3GM+VyATikrOmZzhaW9CxjifP1y9H8yplsNTlzOEnpxno/d1ezobE0rSyK4tfa4ouP9P2zv4Jv7+sPm/1LhyaD0l31eRQjzmmG8mSGAWHF8DBeRCfMQ3P0k6tn1KuIbhVgzJVwc499ylu8eGwuJ86nc7STl2lqlo708R2j6LAjk9h+wz19bOT4dn3THuN4uD8P+rUxOQY0OjUFfAcy8PYI2BpXTjXNBph2SC4uB50VmBIUYupjz1atFMaSxDpJ6hKxeeQnsKBrwYRGLcZAKXpGDQd/pe/GndCCCFEKZTXfoIkpXJRKjpZQpQURiPs+RLKVHvoSmKKorDsUDDfbgvi5t2HL++t0UB5FxuSUo1ExmcVhnaxtaRTXU+e9ytHYCVXLDISVFPXnubnfdcpY6dn3fiWlHXMR1Lh7jWY2wpSYtSaR+3/p66StvJVCD6gtgkYoRZsLuh0vqgrsO87OL4Y0hLVfQ5eEPg6+L+i1hvKq5Q4WP6yOpVPawE9vjVd4XBFUesq7fpcff3cFHXkUEl193rWdD5QP8vCLsidFA3z26h/JwCemQDtphXuNUsw6SeoSsvnEBKdyMovxjNW+7u6o+bz0Hse6O3MHZoQQghRbD1VSalvv/2WWbNmERoaSv369fnmm28ICAh4aPvo6Gg++OADVq9eTVRUFBUrVmT27Nl06dIFgJkzZ7J69WrOnz+PjY0NzZs355NPPqFGjRp5iqe0dLKEKBHO/AErhqjPO8+CwBHZ3o6IS+G9VSfZcj48c5+LrSWV3e2p5GZHZXc7KrvZUdndngqutlhb6jAYFQ5di+Lvk7dZfyqUOwmpmce62evpVNeT8i62fLz+PACLhjbh2RoeeY85PVWtI3XrCJRvAkPXgy5jlThDGmz9EPbMVl97NYB+C9WRLXlhNEDwQdj/LZz7O6tOVNm6as2iOr3VWkYFkZ4Ka0fDqYxfzNpNVxNqTzLaRlFg039h7zfq6w4fQfMxBT/f0yI9FfZ+Danx0Pa/RTPqIuws/PicmqB8fae6Op8oEOknqErT57Bg91WOr/uRz/Rz0ZOu/vsZsBicfcwdmhBCCFEsFVpSytfXl1dffZVXXnmFChUqPHGgy5cvZ/DgwcydO5fAwEBmz57NihUruHDhAh4eOX/JS01NpUWLFnh4ePD+++/j7e3N9evXcXZ2pn59tYPdqVMnXnjhBZo0aUJ6ejrvv/8+p0+f5uzZs9jZPf5brdLUyRLiqbegM9zYm/X6vqTGxjOhTF59iqiEVPQ6LW93rE4/fx9c7PKelEk3GDlwNYq/T4aw4XQIdxPTsr3/euvKTO5cK38x//sfNQlj7QRv7AbnXP4vvfgvrBmRNZ2v+zdQp2fOdknR6spuwYfUEVa3jkBKbNb7VduptYwqP2uaqVpGo5pE2jdHfR04EjrOAG0BShQqCmx4Dw7MVV/nklQUJhZyEuJCoHpHc0fyVJN+gqo0fQ7pBiM9vt2Ddcghfradjb0hRp0O2/hVdeShqVbOFEIIIUqIQktKzZ49m0WLFnH69GnatGnDsGHD6NWrF1ZWBZteEhgYSJMmTZgzR/0Fx2g04uPjw9ixY3nvvZz1RObOncusWbM4f/48lpaWebpGREQEHh4e7Nixg1atWj22fWnqZAnxVAs5AT+0UqeT+b8Ch34EIKX1f/hPZAdWHLkJQC0vR74cUJ+ank/27znNYGTf5Tv8ffI2m86GUdfbiQWvNMm13tRDXfwXlvRTnw/4DWp1e3jbB6fzNRkOTV5TE0/BB9QRURHnc66ap7eH2j3V5JxHPhNmebX3GzW5Buroq15z8zfN0GiEfybCkYXq6+dnQ+OhhROrECYm/QRVafscjgdH0+u7PZQnjL99luIUflB9w8IGAoZDizfBLp+LXQghhBAlVKFP3zt69CiLFi1i6dKlGAwGBg0axKuvvkqjRo3yfI7U1FRsbW1ZuXIlPXtmjQAYMmQI0dHRrF27NscxXbp0wdXVFVtbW9auXYu7uzuDBg1i0qRJ6HS5T38ICgqiWrVqnDp1irp16+Z4PyUlhZSUrPoxsbGx+Pj4lJpOlhBPrT9Gw/HfoG4f6LtALZS97SMAvkzrw9fG3rzeqioT2lfDysKE06OMRoi8ALZuYO+e9+NibsHcZyApCgJehy6fPv6YB6fz5cbFF3wCwScAygeAR23QWeQ9roI6uUIt2m1MA9+WamLKqfzjjzMa4M9x6p8dGrWoe2HXVBLChEpbMuZhSuPn8N8/TvPr/utULmPLhh4G9DtmqqNVyfhCoOlIdXSqjbO5QxVCCCHMqshqSqWlpfHdd98xadIk0tLSqFevHuPGjWPo0KFoHjNV5Pbt23h7e7N3716aNWuWuf/dd99lx44dHDhwIMcxNWvW5Nq1a7z44ouMGjWKoKAgRo0axbhx45g6dWqO9kajke7duxMdHc3u3btzjWPatGlMnz49x/7S1MkS4qmTEAlf1FZXEhu2iVSvxny5+SLK7i95z2IZALfrjaJc7xmmmbaWmghXd8CF9XBxI8SHgk6vjlx6ZuLjk1OGdPilO1zfo9YiGbYpfyOLLv4Lf45Rp+t5N8pKQPkEgH0+6lmZ2uWtagH01Hj1tZOPWifrXpLMs15WvSwyPoe1o+DkctBoodcP6iqAQjxFSmMyJjel8XOISUrjuc93EBmfok7f7lQTLv2rfnkQelJtZOWk1vBr+gZYOZg7ZCGEEMIsCj0plZaWxpo1a1i4cCGbNm2iadOmDBs2jJs3b/Ltt9/Stm1blixZ8shzFCQpVb16dZKTk7l69WrmyKgvvviCWbNmERISkqP9yJEjWb9+Pbt376Z8+dy/wZeRUkLkgaKoI1yKYgROXuycpf4SUK4h57utZcLvJzkXotZS+sZ3L91CM2oeNRujrmBXkMRU7G24uAEubFATUunJWe/p9GDIKICut4emo9TpctZOuZ9r2wzY8QnoHeD1HVCmSv7jURQwpmdP8hQHt4+rU/FuHwPFmP09Cxs1iXYvUXVqBZxZDRod9PkR6vY2V9RCFFhpTMbkprR+Dn+duM3YpccAmNy5Jq+3rqL+/3zuL/X/+ohzakMbV3UxiCavgZW9eYMWQgghilhe+wn5/u3y6NGjLFy4kKVLl6LVahk8eDBffvklNWvWzGzTq1cvmjRp8thzubm5odPpCAsLy7Y/LCwMT0/PXI/x8vLC0tIy21S9WrVqERoaSmpqKnp9VgHjMWPG8Pfff7Nz586HJqQArKysClwTS4hSIT0VFveFO5fh5dXgnreVLAtLakoK7JuPHvg0ui3ffaWOgnS10zOzdz061ukKB31h3dtqQW5DGnT+5PGJqbQkNcFyZZs6Iuret973OPlA9U5Qo5M6Xe3abtjyPwg5Djs/hYPz1IK3ASNAb5t13JUd6tRCgG6zC5aQAjX+4paQAijXAIZvhZQ4uHVUrXUVfABuHoLkaHV02PU9We21ltBvEdR63pxRCyFEgXSrX47rdxL47N+LzFx/HisLLa+0qAS1u0PNrnBmDWyfCXeCYPNU2PMVNBul/mx42BcXQgghRCmV76RUkyZNaN++Pd9//z09e/bMtdh4pUqVeOGFFx57Lr1ej7+/P1u2bMmsKWU0GtmyZQtjxuS+JHiLFi1YsmQJRqMRbcZqTxcvXsTLyyszIaUoCmPHjmXNmjVs376dSpUq5fc2hRD32/W5OlIIYEl/GL4NbF2LNITgqER2XIxgx8UIHIP+5HNtGBGKEz9G+aHRQIfaZfmwZz3cHTISzAHD1QTOX2/CwR/UaX5dv8y+SlzMrazkSfABdWUy4/2r62mgfOOMRFRntVbT/Ymtqs9BlbZw7k911FbkRfUXkP3fQ+t3oOFgNSmzerhajLzRYKjXt+g+tKJm5QCVW6sbGbW37lzKnqRKiICe38vqb0KIp9qYttVITjMyZ1sQ0/46i5WljoEBFUCrU/+fr90TTv2ufiFx92pGbcBvIPB1te5UEf8MFUIIIYqrfE/fu379OhUrVjRZAMuXL2fIkCH88MMPBAQEMHv2bH7//XfOnz9P2bJlGTx4MN7e3sycOROA4OBg6tSpw5AhQxg7diyXLl3i1VdfZdy4cXzwwQcAjBo1iiVLlrB27Vpq1Mga0eHk5ISNjc1jYyqtw9GFyFXISZjfRp02Zu2sJlkqPgMvrwELfR5OUDAJKekcvBrFzktqIupKRELmeyv102isvchGt1dIfuZdnqnqRhn7h4x2PLYY1o5Wk0J+L6ijeu6tXBd7K2d7Ow+o0FRNmlTrmPdC5kaDWidp20yIuaHuc64ItmXg9lFwr6WOJrp/BJUQ4qkk/QRVaf8cFEXho3/O8ePuq2g08EX/+vRq+MDIfEO6OmV552fqAhkAlnbQZJhad8qcNQGFEEKIQlRoNaUOHTqE0WgkMDAw2/4DBw6g0+lo3LhxvoOdM2cOs2bNIjQ0lAYNGvD1119nnv/ZZ5/F19eXRYsWZbbft28fEyZM4Pjx43h7ezNs2LBsq+89rMD6woULeeWVVx4bT2nvZAmRKT1VTUiFnYZa3eDZ9+GnDpAaB42GQLevTFNEHEhNN3I8OJo9QZHsvRzJsRvRpBuz/nvSaTX4V3Chb7kI+h99GUVriWbCaXDIfapvNidXwJrXQTFk36/RQdk6WUW5fQLURNKT3FN6Chz5Wa15lRCu7rOwgRHbwaPm444WQjwFpJ+gks9BTUxNWXuGX/dfR6uBbwY2oqufV86GRiOc/0v92RB6St1nYQ3+r0DzceDkXeSxCyGEEIWp0JJSAQEBvPvuu/Ttm30KyurVq/nkk09yLU7+tJFOlhAZts2EHR+rxVpHH1C/0b24EZYMUEcedfpYnYZQAEajwvnQOPZejmR3UCQHr0aRmJo9aVTexYZnqrrRuro7zau64WRjCWvegBNLoV5/6DM/7xc8+yds/T9wqZSVgCrXqPCKz6YmwIG5cHo1tHoH6vQsnOsIIYqc9BNU8jmojEaF91af5PfDN7HQavj+JX/a1y6be2NFUX+O7vwUbh1R9+n0anLqualSEF0IIUSJUWhJKXt7e06ePEnlypWz7b969Sp+fn7ExcUVPOpiQjpZQjwwba/vAqjbJ+u9vXPg3w9Ao4VBv0O19nk+rdGo8Mu+a8zZFkRkfGq291zt9DSrUoZnqrrRooobFco8MNUtPhy+rKOuevfaVijv/8S3KYQQ+SX9BJV8DlkMRoWJvx9n7fHb6HVa5g9pTOvqj5j+rSjqoho7P8taCMLFF3rPV780EUIIIZ5yhbb6npWVFWFhYTmSUiEhIVhYFJOl4oUQTyY9Ff4YqSakanWDOr2zv99stLrk9bHfYOWrMGxTnqamhcYk887KE+y6FAmArV5HQCVXnqnqRvMqbtT0dECrfcTUucML1YRU+SaSkBJCCFFs6LQaPu9Xn5Q0IxvOhDLil8MsGhpAsyplcj9Ao1EXyqjSFi5vhbVj4e41WNARWr4FrScVz9VWhRBCCBPT5qFNNh06dGDy5MnExMRk7ouOjub999+nffu8j5YQQhRjuz5T60jZuELXL3LWWNJo1JXsKjSHlFhYOgAS7jzylH+duE2HL3ew61Ik1pZapnevw/EpHVg0NIDXWlamdjnHRyek0lPh8E/q88A3THGXQgghhMlY6LR8PbAhbWt6kJJuZNjPhzhyPerxB1ZpCyP3gN8AUIxq3akf20HEhaIIWwghhDCrfCelPvvsM4KDg6lYsSJt2rShTZs2VKpUidDQUD7//PPCiVIIUXRCTsCujH/LXT97+MpAFnoY8KtaGPzuNfh9sJo4ekBMYhrjlx1j7NJjxCan41feib/HtmRIc1/0Fvn4L+jsWogPA3tPqNW9oHcnhBBCFBq9hZbvXmzEM1XdSEw18MqCQ5y+FfP4A22cofc86LtQXek25Dj80AoOzFOn+gkhhBAlVL6TUt7e3pw8eZJPP/2U2rVr4+/vz1dffcWpU6fw8fEpnCiFEEUjPRX+GJUxba97zml7D7Jzg0HLQe8A13fDureydZ53X4qk4+ydrD1+G51Ww7jnqrFqZHOqehSgkOuBuepjk2FqQkwIIYQohqwtdcwb7E+ArytxKem8svAg1yIT8nZw3d4wah9UbgPpybD+HfitN8SGFHbYQgghhFnku9B5aSCFO0WptW0G7PgkY7W9g2D/iCKt97v4rzqFTzFCx5kkN36dTzacZ+GeawBUcrPji/71aVjBpWBx3TwMPz6nrlA04czDR28JIUQRkH6CSj6HR4tNTmPAD/s5FxJLBVdbVo5shoeDdd4ONhrh0HzYNEVNTlk7Q7fZUKeX+r6iqD9zjQZQDFmPihF0VqC3fdwVhBBCiEJVaKvv3XP27Flu3LhBamr26Trduz/902qkkyVKpZATML9t7qvt5UXGinyKRstyy14EJ+gAaODjROsa7uh1DwzM1FlBrefBtXLu57vfqtfg1AqoPxB6zc1fXEIIYWLST1DJ5/B44XHJ9Pl+L8FRSdT2cmTZ601xtM5HAfOIC7B6uPozGkBrmZV8ehitBTQfC89OBgurJ78JIYQQogAKLSl15coVevXqxalTp9BoNNw7XJNRCNlgMDxp7GYnnSxhNmfWwJk/oNU74Fm36K6bngrz26jFzWt1h/6/5Cxu/ggxiWmsO3Wbstvfpm3Sv/m4sEZNTDUbCxUCc28SGwKz66rJshHboVzDfJxfCCFMT/oJKvkc8uZaZAJ95+4lMj6VppVdWTQ0AGtLXd5PkJ4KOz+FXV+oCam8KlsXev1QtP0JIYQQIkOhJaW6deuGTqfjxx9/pFKlShw8eJA7d+7w1ltv8dlnn9GyZUtTxG9W0skSRS4tCTa8B0cWqa+tHOGFxVCpVdFc/960PdsyMOpAnqbtJacZ2HY+nDXHbrH9QgSpBiOWpPOqxXpaucbi7+uC9aMKmUffgCvbs16XbwLNxkCtbqC9r7N+LzafpjBs45PeqRBCPDFT9hOCg4PRaDSUL18egIMHD7JkyRJq167NiBEjTBRx4ZD+Ut6dvhXDC/P2E5+STue6nswZ1Ajdo1aczU1yDKTEgUan/pzU6ECrfeC1Di5ugL/GQ+IddWRV2w+g+bjsP1uFEEKIQlZoSSk3Nze2bt2Kn58fTk5OHDx4kBo1arB161beeustjh07Zor4zUo6WaJIRQbBiiHqKCU0UKYK3AlS6yf1+kEtevqkFEXtzCZFQeJdtaOaFAWJUZAQDnu/yZi2t/CR1zMaFfZfvcPaY7dZdzqEuOT0zPdqejrQs6E33euXo5yzTd7iCj8H++bAyd/BkDEV2LkiNBsNDV4EnSV8WQcSIh4bmxBCFBVT9hNatmzJiBEjePnllwkNDaVGjRrUqVOHS5cuMXbsWKZMmWKyuE1N+kv5szcoklcWHiLVYOTFwAp82LNu5kwDk4sPVxNTF9apr32aQq/v8zZlXgghhDCBvPYTLPJ7YoPBgIODA2QkqG7fvk2NGjWoWLEiFy5ceLKohShtTq1UO42p8WDrpi4HXbGFWj/i3J+w8lU1IRP4er5PnXDmX6LWTcc5+Sa2hjh0PHrI/03P9myLa0TyziskpRlITjNkPBrV56kGjgdHExqbnHlMOSdrujfwpmfDctT0LMAvJB61oMe30HYKHJwHh3+C6Ouw/l3Y9hFUaKbev0M5dQSVEEKUMKdPnyYgIACA33//nbp167Jnzx7+/fdf3njjjWKdlBL507yqG18OaMCYpUdZfOAGbvZWTGhfvXAuZu8BLyyB44th/XsQvB++fwY6fgj+Q/M1RV8IIYQoTPlOStWtW5cTJ05QqVIlAgMD+fTTT9Hr9cybN4/KleXbFyHy5MHpehWfgT4/gqOX+rrfIjUxc+hH9TEuFJ6bkrdOZHQwaesnY3fhL+weeCtBseIuDkQr9txV7InGnijFgWDFg8XXniPp2pnHnt7R2oKufl70aOBNgK8r2vxOP8iNQ1l47r/QciIcXwL7v4OoK+oUBIAmw9RRU0IIUcKkpaVhZaUWo968eXPmgjE1a9YkJCTEzNEJU+vq50VUQh3+u/YMX225hJuDFS83rVg4F9NooOFL4NsS/hgF13fD3xPg/D/QfU5Wn0MIIYQwo3xP39u4cSMJCQn07t2boKAgnn/+eS5evEiZMmVYvnw5bdu2Lbxoi4gMRxeF6sHpeq3ehtbvge6BHLGiwK7PYOuH6uv6g6D71w9PzqSnwL45KDs/Q5OWSLqiZbmmE7aBQ0iwcCJacSDeYEFyxiioeyOhktKMpKYbsLbUYW2hw0avU59barGx1GFjmfFar6OckzXPVHPDyqKQ61IYDXBhPRyYqybwXlwBtq6Fe00hhMgjU/YTAgMDadOmDV27dqVDhw7s37+f+vXrs3//fvr27cvNmzdNFrepSX+p4L7YdJGvt1xCo4FvBzWiS71CThAZjerP1M3TwJAC1s7ql0G+raBMVbU2lRBCCGFChVZTKjdRUVG4uLgU3rz4IiadLFFoHpyu12c+VHlMIvfor+oxigGqtof+P4P+gTFQQZth3bsQdRmAg8YafKJ9jenDB1DX26kQb0gIIUofU/YTtm/fTq9evYiNjWXIkCEsWLAAgPfff5/z58+zevVqE0VtetJfKjhFUfjgj9MsOXADvU7LoqFNaF7VrfAvHH4e1rwOIcez9untwdMPyjVQV7j1aiCJKiGEEE+sUJJSaWlp2NjYcPz4cerWLbnLy0onS5icIQ3WvZ01Xc+3JfSen/eh8xc2wIpXID0JvP1h0AqwKwPRwbBxMpz7C4BorQvTkgey2bI1vw4LpGEFl0K8KSGEKJ1M3U8wGAzExsbi4pL1f/a1a9ewtbXFw8Pjic9fWKS/9GQMRoXRi4+y4UwodnodC4cGEFCpCEYFG9Jg37dqEfTQU5CWmLPN/Ymqii2gcmuwcij82IQQQpQYhTZSqnLlyqxZs4b69eubIs5iSTpZwuS2fgQ7P1Wn67V+F1pPyv/SzMGHYEk/SLqrfoNZtw/s+RrSk1A0OjY79GBieBfSLR34ZVgATXxlupsQQhQGU/YTkpKSUBQFW1tbAK5fv86aNWuoVasWHTt2NFHEhUP6S08uOc3AsJ8PsSfoDjaWOn56pTHNqxTBiKl7DOkQeVEdOXX7uPoYclL9Eux+Wkuo2AyqdVBHbbvXkGLpQgghHqnQklI//fQTq1ev5tdff8XVtWT+0iudLGFSt4/D/Lbq9Lve88Gvf8HPFXERfusNMcGZu5QKzfiIYfx40RYrCy0LXymiKQBCCFFKmbKf0KFDB3r37s0bb7xBdHQ0NWvWxNLSksjISL744gtGjhxpsrhNTfpLppGUamDEr4fZdSkSKwst8wc3plV1d/MFdH+i6tYRtUTA3WvZ2zhVgGrt1a1Sq5xlBYQQQpR6hZaUatiwIUFBQaSlpVGxYkXs7LL/EDp69GjBoy4mpJMlTCY9FeY9C+FnoHZPtR7Uk4oNgWWDID4MY9spTDhXnbUnQtDrtMwb7M+zNYrvVA8hhCgJTNlPcHNzY8eOHdSpU4cff/yRb775hmPHjrFq1SqmTJnCuXPnTBa3qUl/yXSS0wyMWnyUrefD0Vto+eElf9rULCY/zxUF7lyGoE1w6V+4tkctln6PTg8Vm4N3Y/DyA6/64FxRRlIJIUQpl9d+gsVD33mInj17PmlsQpQeO2epCSlbN+j6uWnO6egFw7diNCq8t+YUa0/cxEKrYc6ghpKQEkKIp0xiYiIODmqtnn///ZfevXuj1Wpp2rQp169fN3d4oohYW+qY+5I/Y5ceZeOZMEb8ephvBzWiQx1Pc4emJpfcqqpb05GQmgBXd2UlqaJvwJXt6naPtZNak8qrvlo43csvo3h6Ia/eK4QQ4qljktX3Shr55k+YxP3T9vr9DHVMl9BVFIX/rj3Nb/tvoNXANwMb0dWvkJeTFkIIASbuJ/j5+fHaa6/Rq1cv6taty4YNG2jWrBlHjhyha9euhIaGmixuU5P+kumlGYy8ufw4/5wMwUKr4asXGhbvn++KApGX4OoOCD0JIScg7CwY03K2tbQFnwDwHwo1nwddvr8bF0II8RTJaz9B1noVojCkp8Ifo9SEVO2eJk9I/d/f5/ht/w00Gvi8f/3i3WEVQgjxUFOmTOHtt9/G19eXgIAAmjVrBhmjpho2bJjn88ycOZMmTZrg4OCAh4cHPXv25MKFC488ZtGiRWg0mmybtbX1E9+TKDhLnZavBjSgZ4NypBsVxi49ytrjt8wd1sNpNOBeHQKGQ/dv4PWd8P5teH0XdJ8DASPAJ1BNSKUlqqOpVgyBr/zU0eTxEea+AyGEEGaW768otFotmkfMETcYDE8akxBPv8KYtgekG4y8v+YUvx++CcDHvevRq2F5k51fCCFE0erbty/PPPMMISEh2VY2fu655+jVq1eez7Njxw5Gjx5NkyZNSE9P5/3336dDhw6cPXs2R/3P+zk6OmZLXj2qjyeKhoVOy+f9G2Ch07LyyE3eXH6cNINCX/+n5Oe9hT6jtpRf1j6jQR1RdWoFHFkEsbdg64ew41Oo0xsCR4C3vzmjFkIIYSb5TkqtWbMm2+u0tDSOHTvGzz//zPTp000ZmxBPp9vHYVdGIqrr52BnmpXwktMMjFt6jH/PhqHVwMd9/Ojf2Mck5xZCCGE+np6eeHp6cvOm+oVD+fLlCQgIyNc5NmzYkO31okWL8PDw4MiRI7Rq1eqhx2k0Gjw9i0HdIpGNTqvh0z5+WOq0LD14g3dWniDNYGRgQAVzh1YwWh141ITn/gut34Uza+DgPHV1v5PL1M27sTqyqk5PsLAyd8RCCCGKSL6TUj169Mixr2/fvtSpU4fly5czbNgwU8UmxNPn/ml7dXqZbNpebHIaw38+zIGrUegttHwzsCEdi0PxUyGEEE/EaDTy4Ycf8vnnnxMfHw+Ag4MDb731Fh988AFabcEqLcTExADg6ur6yHbx8fFUrFgRo9FIo0aNmDFjBnXq1CnQNYVpabUaZvSqi16n4ed915m8+hQJKekMe6bS0z2izcIK6r+gbjePqMmpM6vh1mFYcxj+/QB8nwGHcuriLg5e4FhOfXTwAkuZYiqEECWJyQqdX7lyBT8/v8wO1dNMCneKAtv6oTp1z9YNRh8wySipyPgUhiw4yJnbsdhbWTB/cGOaVSljknCFEELknyn7CZMnT+ann35i+vTptGjRAoDdu3czbdo0hg8fzkcffZTvcxqNRrp37050dDS7d+9+aLt9+/Zx6dIl/Pz8iImJ4bPPPmPnzp2cOXOG8uVzThVLSUkhJSUl83VsbCw+Pj7SXypkiqLw0T/n+HH3VQD6NCrPR73qYm1Zglayi4+Ao4vg0AKIu/3otjauapLKqTxUag01OoFr5aKKVAghRB7ltb9kkqRUUlISkydPZv369Y8tqvk0kKSUKJBCWG0vOCqRwQsOcjUygTJ2en5+NYC63k4mCVcIIUTBmLKfUK5cOebOnUv37t2z7V+7di2jRo3i1q38F7keOXIk69evZ/fu3bkmlx4mLS2NWrVqMXDgQP7v//4vx/vTpk3LtVSD9JcKn6Io/LT7KjPXn8dgVKhf3om5L/vj5WRj7tBMy5AOl7fCnSA1ORUbAnEhag2q2BAwpOR+nHtNqNEZanRRa1NpS1DCTgghnlKFlpRycXHJNmRYURTi4uKwtbXlt99+y9GpehpJUkrkW3oqzHtWLW5epxf0W/TEp7wYFsfLPx0gLDYFb2cbfnstkEpuDy9WK4QQomiYsp9gbW3NyZMnqV69erb9Fy5coEGDBiQlJeXrfGPGjGHt2rXs3LmTSpUq5Tuefv36YWFhwdKlS3O8JyOlzG9PUCSjlxwlOjENN3sr5r7UiMa+j56iWWIoCiTdhdjbaqIq4gJc3ADX96pfCN5j6wbVO6lJqiptQC99JyGEMIdCS0rdWz74Hq1Wi7u7O4GBgbi4uDxZ1MWEJKVEvpl42t6R63d5ddEhYpLSqF7Wnl9eDcTTSWooCCFEcWDKfkJgYCCBgYF8/fXX2faPHTuWgwcPcuDAgTydR1EUxo4dy5o1a9i+fTvVqlXLdywGg4E6derQpUsXvvjii8e2l/6SeQRHJTL8l8OcD43DUqdhWvc6vBhY0dxhmU/SXQjaAhfWwaXNkBKT9Z7OCsrWBsUIhrSMLTWXx1SwcQHnCuBSUX10rqhuLhXByUdqWQkhRD4V6fS9kkY6WSJf8jBtL91gZPGBGySlGXCxtcTZVo+rnT7zubONJRY6tZjtjosRvPHrEZLSDDSs4MzCV5rgbKs3w40JIYTIjSn7CTt27KBr165UqFCBZs2aQUatp+DgYNatW0fLli3zdJ5Ro0axZMkS1q5dS40aNTL3Ozk5YWOjTvEaPHgw3t7ezJw5E4D//e9/NG3alKpVqxIdHc2sWbP4448/OHLkCLVr137sNaW/ZD6Jqem8s+Ik/5wKAWBgQAWmd6+D3qJghfFLDEOaOnLqwno1SRV93XTntvcEF1+o/CzU7Aqe9eBpLjgvhBCFrNCSUgsXLsTe3p5+/fpl279ixQoSExMZMmRIwaMuJqSTJeC+jk1CBCTegcQoSIrK/pgYBfFhao2DR0zb+2XfNaasPfPIyzlaW+Bip+fW3STSjQqtq7vz/UuNsNXne5FMIYQQhcjU/YTbt2/z7bffcv78eQBq1arFiBEj+PDDD5k3b16ezvGw1dgWLlzIK6+8AsCzzz6Lr68vixapP6smTJjA6tWrCQ0NxcXFBX9/fz788EMaNmyYp2tKf8m8FEXh+x2XmbXxAooCjSu68N1LjfBwkBE9kDHdL+I8RF0BnR50lhmPuTzXWqh9vbvXIfqGmsyKvpHx+jqk5rKQk1MFNTlVsytUaAY6M/bX7o0C09uaLwYhhHhAoSWlqlevzg8//ECbNm2y7d+xYwcjRoyQQueiZEi6C7/1gVtH8ta+TFV4dWOu0/bSDUae/Ww7N+8m0axyGawttdxNTCM6MZW7iWnEJKXlOKZ7/XJ81q++fOMphBDFUFH0E06cOEGjRo0wGAx5aG0e0l8qHradD2fcsmPEJafj6WjNDy/7U9/H2dxhlRz3allFX4ewM+oorKAtkH5fvTcbF6jeWU1QVWlbuMmhtCQ1jpAT6hZ6EsLOqiP2a3QG/1egclvQSh9SCGFehZaUsra25vz58/j6+mbbf+3aNWrVqpXvgpzFkXSySrnEKPilh/pD3soJvPzA1lVdgti2zH3P73t08gGL3KfY/XniNuOWHsPVTs+eSW2x0WdfESbdYCQmKS0zUWWh0+Ln7YRWK0PChRCiOJKklEr6S8XHlYh4Rvx6hKDwePQ6Lf0al2doC1+qejiYO7SSKTURrmyH83+rSaqkqKz3LGygfGOwtAULK3XTWan9RAtrdXSWhVX2x0eN4jIa1BFfIScg5CREXlBrZD2KUwVoNBgavgSOXoX+cQghRG7y2k/I9zhTDw8PTp48mSMpdeLECcqUKVOwaIUoLuIj1IRU+Bmwc4fBa6FsnQKfTlEU5m6/DMArzX1zJKQALHRaythbUcbe6olCF0IIIUTpVNndnjWjmjPx9xNsOhvG4gM3WHzgBi2rufFKc1/a1PCQL7tMSW8LNbuomyEdgvfD+X/UJFX0Dbi2q3Cvb+cOnn7gVV/98tTTD9JT4OgvcGIpxNyAbR/C9plQvaM6eqpqO9Dm7IcWG4oiNbqE+RnSISZYnfar0YBvK/NOzS1MigJXd8DhBdBzrlmn/+b7Ex44cCDjxo3DwcGBVq1aQcbUvfHjx/PCCy8URoxCFI24UDUhFXEe7MvCkL/AvUYeDny43UGRnA2JxcZSx8tNS/HKOEIIIYQoVA7Wlsx72Z/9V6JYtPcqm86GsetSJLsuRVKxjC1DmvnSt3F5HK0tzR1qyaKzAN9n1K3jDAg7DeHnID1ZTRQZUtXH9BS1Bml6asZjsvoL8L3V/3JbEdCQpo6KKlNFTUDdS0Q5eOaewOn8MbSbCmf/hKM/w/U9asH3C+vAsbw6csq3BWh0aoJKo1On+WV7nfH4sNFbuU0LNBrV+0lLgrRE9TE9Ket1csx9NVnv3leb9U7W85RYsHJU783eQy0s71BW7ZPbZ+xz8AQHL7CWkZklniEdgg/ApY1waZNa49erPng3Bm9/dbMr4ICY9FQ1eRx1JecWfR2M6VltHctDk2HQaEjBr1fcGNLh3FrY85U6AhPAtyUEDDdbSPmevpeamsrLL7/MihUrsLBQc1pGo5HBgwczd+5c9Pqnf5UwGY5eCsXehp+7wZ0gcCinJqTcqj7xaV/8cT97gu4wtIUvU7sVfMSVEEKI4sMU/YTevXs/8v3o6Gh27Ngh0/dEgQVHJfLr/ussO3iD2GT1lyw7vY6+/uUZ0tyXyu725g5RFLaIi2py6viS7FMMn4TWIitRhSYj+ZZsmnPnlXMFNUHnWS9j8wOn8jLSqqDuJRXTk9WkpDaj+L/O8uGfqdGoJhKToyEpOpfHGLXWmmtlNanqUgksH7MIQ0KkmoC6tBGCtkJKzKPbu/hmJKgyElVefmrs8aHq73YxN9XH2FvqFnNLfR0f+ugpsDorcK2UtdgVqFNv6/WFgNfV6zyNUhPh+GLY+03WyqQWNupU32ajwcX0AygKrabUPZcuXeL48ePY2NhQr149KlYs+E18++23zJo1i9DQUOrXr88333xDQEDAQ9tHR0fzwQcfsHr1aqKioqhYsSKzZ8+mS5cuBT7n/aSTVcpE31ATUnevqbWhhvyl/kf0hE7djKHbnN3otBp2vPMs5V1kRRQhhCgJTNFPGDp0aJ7aLVy4sEDnLwrSX3o6JKams/roLRbtvUZQeNYqcu1rl2V69zqUc7Yxa3yiCKSnwLm/1ORU7C21TpViyHg0PvDaoCYcjGnqcUo+E+M6K7C0UWtqWdqom5VDRh1WF7U+64O1WW1c1dFPybFqwiA+XJ3BEB+WtcVlPCZH535da+esBJWXn3rO5Bi1fXJGkuResuTe/pQ4dVSYhXVG/a+MR0ubB17bgrWTmmSxdlYfbZyzXls7qSPmFEVN1MSGQNx9W+br0IwRP37Q4EWo2r5wpoYlx0BkENy5BJEX1S/dk2Oyj2TLNqrtEUlFjS4rQaW1UDdjunqfj6ttlv1EauLwXpLKtYr6aO0MV3eqiahbR4H7UhM2rlCtPVTrAM4VIeQ43DysLkR151LusaLkLS4Lm4xYKquP928O5dQRgWnJcGY1HJibNaIIoEJzCBwBNbs9+s8vNVGdChgdDHG31X9Pmf/G0jM2o/p4b5/eXp1q61XfdEnWxCg4OB8O/pCVZLMtoybYmrxWqCPACj0pZSrLly/PHGUVGBjI7NmzWbFiBRcuXMDDwyNH+9TUVFq0aIGHhwfvv/8+3t7eXL9+HWdnZ+rXr1+gcz5IOlmlSNRV+Lm7OvfexVdNSDlXMMmpRy85yj8nQ+jV0JsvBzQwyTmFEEKYn/QTVPI5PF0URWFP0B0W7rnK1gvhKAo4WFkwtXsd+jTyRiOjTERujIZcphamZE0ttLRRf8G/l4Aq7LpVSdHqFMmQkxB6St0izmWfcmUOVo7qZ5WWkPdj7Dyg/gBo8BJ41Mz/NWND1Dq4kZcytovqY3xo/s9VUBY2aoLO2jn7o5UjJEbCncvqtLiU2Lydz9NPrYNWrYM6+ulhf5+SouH2MTVBdeuImqxKCFff01qoiSXHcuDkrT46lr/vtbc6LTSv/+cpCgQfVJNT5/7M+rvm6A2NXwWPWmriKSZYHexwLxGVGJm38+fGsby6mmfNrlCxecbIxHy6ex32fQvHflUTkKAm95qPVZOiRVBDqtCSUn369CEgIIBJkyZl2//pp59y6NAhVqxYka9AAwMDadKkCXPmzIGMqYA+Pj6MHTuW9957L0f7uXPnMmvWLM6fP4+lZe5/OPk954Okk1VK3LmsjpCKvQVlqsLgP9X/qEzg+p0E2ny2HaMC68e3pJaX/D0SQoiSQvoJKvkcnl6XwuJ4Z+VJjgero07a1fJgRu96eDg8ZnqNEMVReopaE/Zekir0FKTGZ41issl4tHbK2Jfx2spBHVmTlpRR9yv5vsfkrNepCVnT0pLu3vc8GlLjcsZj7aTWvrq3Od733MoBLm6Ek8uzJy28/dVEQd0+arwPigtTRwrdPpa1xYc9/DOxLwtu1cGtGpSpBnZuWYnDzFFsDzzqrLJG7BjSskbzGNLUkXP3EpRaXVbyySIPCzUpijo1L+pyRpLqclayKj5cXa2yekd15FhBV4tUFHU0mkarLgRQWMnR2NtqYfDDC/OWdLJyVGfiOHmrI+/ujTbT3l/H7b590Tfg8tasJBIZf5+qd1ITVFWeA6v7pl4rivr3IOJCRlLyYlZyMvZWVjuv+tBiPNTqUaSF2wstKeXu7s7WrVupV69etv2nTp2iXbt2hIU94h/HA1JTU7G1tWXlypX07Nkzc/+QIUOIjo5m7dq1OY7p0qULrq6u2NrasnbtWtzd3Rk0aBCTJk1Cp9MV6JwPkk5WKRBxQR0hFR8KbjVgyJ9q8UQT+c8fp/ht/w2ereHOoqF5mzYqhBDi6SD9BJV8Dk+3dIORebuu8OWmi6QZFJxtLfmwZ12e9ytn7tCEeHoY0jKmBt5VEyIOnqC3y9txl/6FY4vVqWv3Rt/orKDW81C9s1pa5F4CKu52znNotGrCyb26+uhWPWOrqiYyROFJS4Yza9RRSKkJ6kwb5wpqAsrZJ+OxQu4JxseeOwmubFdX87ywPmvKHRl/P6q0Uac23ks+Par2VuU28MybUKm1WWqu5bWfkO80WXx8fK7FzC0tLYmNzeOwvAyRkZEYDAbKli2bbX/ZsmU5f/58rsdcuXKFrVu38uKLL7Ju3TqCgoIYNWoUaWlpTJ06tUDnTElJISUlJfN1fu9DFBOKAv9MhBv7H9825qY6jNSjDgxeC/buJgsjMj6FFYdvAvB6qyomO68QQgghhKlY6LSMerYqbWp48NbvJzgbEsuYJcdYfzqU/+tRF1e7p3/xIiEKnc5SHYVk55b/4+5Nz4qPUEdOHV8M4Wfh9Cp1y0ajrgpermHWVrZukUzBErmwtIYGA9XN5Oe2gRqd1c1oUKcOnv9b3e5eg4sbsrfXaNVC8m7V1QRlZnKymlr37CmQ76RUvXr1WL58OVOmTMm2f9myZdSuXduUseXKaDTi4eHBvHnz0Ol0+Pv7c+vWLWbNmsXUqVMLdM6ZM2cyffp0k8cqitjNQ+pwyrzy9FMTUrauJg3j573XSEk3Ut/HmaaVTXtuIYQQQghTquXlyB+jWzBnWxDfbgvin5MhHLgSxcze9Whfu2weziCEeCL27tB8jLoC2u1jakH6m4fUxMK9BJRnvezTtkTpoNVBxWbq1uFDCD+nJqWMhqwElGvlvE2jLMbynZT673//S+/evbl8+TJt27YFYMuWLSxZsoSVK1fm61xubm7odLocU/7CwsLw9Mx9KpWXlxeWlpbodFnzRGvVqkVoaCipqakFOufkyZOZOHFi5uvY2Fh8fHzydS+iGDi+RH2s0QUC33h0W50llG9SsKJxj5CQks4v+9QlNt9oVVmKhgohhBCi2NNbaJnYvjrtaqmjpi6FxzP8l8P0aVSeKd1q42Rj2v6SECIXGg14N1I3IR6k0UDZ2upWwmjze0C3bt34448/MqfNvfXWW9y6dYutW7dStWrVfJ1Lr9fj7+/Pli1bMvcZjUa2bNlCs2bNcj2mRYsWBAUFYTRmLfV48eJFvLy80Ov1BTqnlZUVjo6O2TbxlLm3ZCeoCanKrR+9FXQVg8dYdiiYmKQ0KrnZ0aGO6WpUCSGEEEIUNr/yzvw19hleb1UZjQZWHb1Juy928NeJ25h5wW4hhBAlVL6TUgBdu3Zlz549JCQkcOXKFfr378/bb79N/fr1832uiRMnMn/+fH7++WfOnTvHyJEjSUhIYOjQoQAMHjyYyZMnZ7YfOXIkUVFRjB8/nosXL/LPP/8wY8YMRo8enedzimIkPVUt8Bf3hEuXXlinFhl08gHflqaKLl/SDEZ+2nUFgOEtK6PTyigpIYQQQjxdrC11TO5SixWvN6Oymx0RcSmMXXqMIQsPcf1OPpa7F0IIIfKgwOsB7ty5k59++olVq1ZRrlw5evfuzbfffpvv8wwYMICIiAimTJlCaGgoDRo0YMOGDZmFym/cuIFWm5U78/HxYePGjUyYMAE/Pz+8vb0ZP348kyZNyvM5RTGyYZJaB6pSKxjyV8HPc2Kp+ug3ALQFyrU+sb9O3OZ2TDJu9lb0buRtlhiEEEIIIUyhsa8r68a35IcdV/h2exA7L0bQ4cudjGlTlRGtK2NlUUhLrgshhChVNEo+xuKGhoayaNEifvrpJ2JjY+nfvz9z587lxIkTRVLkvKjIEsdF5MIGWDog6/Xru8DLL//niQuDL2qBYoAxh9WVBoqYoih0mr2LC2FxvNOxBqPb5G8qqxBCiKeH9BNU8jmUHlcjE/jPH6fYE6QuTV7F3Y6PetWjaeUy5g5NCCFEMZXXfkKeh5R069aNGjVqcPLkSWbPns3t27f55ptvTBWvKG3iw2FtxpRLq4y/oPu/K9i5Tq1QE1Llm5glIQWw/UIEF8LisNPreKlpRbPEIIQQQghRGCq52fHbsEC+eqEBbvZ6Lkck8MK8/bz1+wnuxKeYOzwhhBBPsTwnpdavX8+wYcOYPn06Xbt2zbb6nRD5oijw51hIjASPOjBoubr/1EqIDcn/+e5N3as/0LRx5sP3Oy4DMCiwgqxQI4QQQogSR6PR0KOBN1smPsuLgRUyC6E/98UOlh28QZrBmIezCCGEENnlOSm1e/du4uLi8Pf3JzAwkDlz5hAZGVm40YmS6cgiuLgBdHroM19dCa9CMzCmwaH5+TtXyEkIOw06K6jb22QhphmMfLnpIh2+3MHAefuZtPIk324L4s8Ttzl24y534lMyV6E5euMuB69GYanT8OozlUwWgxBCCCFEceNka8lHveqxamRzank5Ep2YxnurT9F0xhamrD3Nket3ZaU+IYQQeZbnQudNmzaladOmzJ49m+XLl7NgwQImTpyI0Whk06ZN+Pj44ODgULjRiqdfZBBsfF99/txUKFtHfd5sNNzYpxY9b/kW6O3ydr57o6RqdAYbF5OEGBQex5vLj3P6VmzGnnj2XbmTo52dXoePqy0JqekA9GjgjZeTjUliEEIIIYQozhpVcOGvMS1Y9P/t3Xd4VGX6//H3THqvpJFCIBB6AgFCAEUUBfTrghWVVeyrgquyq6vb1PW34q6udVnUdZW1AaKC2JBqUHoLNYROAul1Ukid8/tjMJoFFYXMSfm8rmuumTlz5sw952zcm3ue537WHmH2lwcpqa7nzXVHeXPdUWKDvZmYHMXE5K4khPmaHaqIiLRhP6nR+f/KysriP//5D2+99Rbl5eVcfPHFLF68+NxGaAI17mwlTQ3wn0sgd6tjtb0bP/p2pTx7E7w0GMqOwGX/gKG3n9nx/tHbMQ3whveg17izCs9uN/jvuiM89fle6hrtBHi58fCE3ni4WskurSGn9AQ5pTVkl9aQb6tt8V6LBZbefz49w1WYFRHp6JQnOOg8yDcam+x8faCYjzJy+WJ3PjX1Tc2v9e/qz6TkrlyeFEW4v6epcYqIiPOcaZ5wVkWpbzQ1NfHxxx/z+uuvqygl32/lX2H138EzAO5eBwFdW76+4RX4/CEI7uFYRc/6I7NLsz6HudeBTxeYkQkuP7+XU17FCR5csIOvDzimpJ7XM5Rnrkn63uSptqGJ4+UnyC6t4VhpDXEhPpzfq8vP/nwREWk/lCc46DzI6dTUN7JsTwEfZeSyel8RjXbHPzUsFriodxhPXjmAMD8Vp0REOjqnFqU6GiVZrSBnI7w+Dgw7XP3G6fs/1VXBs32hrgKunw+J43/4mPNvhMzFMHwajH/yZ4e2eHsuf1y4E1ttI55uVn5/aR9uHB6HxWL52ccUEZGOS3mCg86D/JjS6no+3ZHLooxcthwtAyDMz4PZvxxMSlyw2eGJiEgrOtM84YwbnYv8bHWV8OEdjoLUwMnf35DcwxdSpjoer/vnDx+zptTRLB0g+eetuldR08Cv527j13O3YattJCk6gE9/fR43pXVTQUpERETkLAX7uHNjWjc+uHsESx84n17hvhRW1jH5lfX8d+0RNUQXEREVpcQJljzs6BUVEAOXPv3D+6b+CiwucOQryNv+/fvt+gCa6iF8AEQM+Mkhfb2/mHHPr2bx9lxcrBbuu6gn7989gh5d1IxTRERE5FzrFe7HwntGctnASBrtBo8u3s1v3tvOie/0nxIRkc5HRSlpXXsWw7a3AQtc8Yqjn9QPCYiGflc4Hq/71/fvt32e4/4njpIyDINZqw7wy/9sIN9WS3yoD+/flcYDF/fCzUV/DiIiIiKtxcfDlX9eP4g/XtYHF6uFD7cd58rZa8kuqTE7NBERMYn+FS6tpzIfPr7P8XjU/dBt5Jm9L22a437X+2DLPfX14v1wfLNjRNWAa844nIYmOw9/sJOnv8gC4PphsXz661EMig0642OIiIiIyM9nsVi4/bzuvH1bKqG+7mTm2bj8n1+zKqvQ7NBERMQEKkpJ66ivgYW/ghOlEDEQLvj9mb+362CIHQH2Rtj471Nfz3jXcZ8wFnzDzuiQttoGbnljE/M352C1wF8m9mPmlQPwdnc987hERERE5JxI6xHCx/eOIjkmkIoTDdw6ZxMvrtiP3a4+UyIinYmKUnLuFe2D1y6CQ1+Cqydc+W9wdf9px0i7x3G/5Q2or/52u70Jdsx3PD7DqXvHymq4evZavj5QjJebC/++aQg3pXX7afGIiIiIyDkVGeDF/F8NZ0pqLIYBzy7bx51vbabiRIPZoYmIiJOoKCXn1o734NULoHAP+ITBlAUQ1vunHyfxUgjqBifKYPvcb7cfXg22447eVL0m/Ohhdh6r4Ip/rWVfQRVhfh4suCuNi/qE//R4REREROSc83B14a9XDODpqwfi7mpleWYho59exQvL91NeU292eCIi0spUlJJzo74GPpoOH94BDdUQfz7c9bXj/uewusDwk6Ol1v0L7HbH428KVP2vAjfPHzzEsj0FXPvKOooq6+gd4ceiaSPp3/VHGq2LiIiIiNNdMySGD+8eQfcuPpTXNPDc8n2MfGolMz/LpNBWa3Z4IiLSSlSUkrP3zXS9bW85Vtm74BG4cRH4neWIpOQp4BEApQdh/xdQVwmZHzteS7rhB9/6xprD3PnWZk40NHFez1AW3JVGVKDX2cUjIiIiIq2mf9cAlj0wmpeuH0TvCD+q65t4ZfUhRv19FX9ctJOcUq3SJyLS0ajLs5yd7fPhkwcco6N8wuCqf0P3C87NsT18YcjNsOYFWDcLakqgoQaCe0D0kNO+pclu8MQne5iz9ggA1w2N4YlJ/XFzUf1VREREpK1zsVq4PCmK/xsYyaqsQmatOsiWo2W8vT6buRtz+EVSFHdf0INe4X5mhyoiIueAilLy89TXwOcPnRwdhWOa3pWvnf3oqP817FeOgtSRr6A827Et+XqwWE7Z1VbbwIz5GSzPdCwp/ND4RO4e3QPLafYVERERkbbLYrFwYe9wxiSGsfFwKbO+PMjqfUUs3HachduOc3HfcKaPSSApJtDsUEVE5CyoKCVnruEElB6C4n2Q/ndHM3MscMHDcP6Djj5Q51pAV+h3BexcAOVHHZ838LpTdtuTa+Oed7ZwpKQGd1cr/7gmicuTos59PCIiIiLiNBaLhdTuIaR2D2HnsQr+9eUBluzOZ9meApbtKeC8nqFMH5NAavcQs0MVEZGfQUUpacneBBXHoGQ/lByEkgNQfPJxRQ5gfLuvTxhc9Rp0H926MQ2/x1GUAog/DwJjWry8YHMOf1y0i7pGO10DvZg1ZTDJ+tVMREREpEMZEB3A7F+mcKCwin99eYCPMnL5an8xX+0vZmi3IKaNSWB0ry4aJS8i0o6oKCXf2rfUsXpebfn37+MZACE9IXIgjH743E/XO52ug6HbeY4pfIOnNm+ubWjiscW7mbcpB4DRvbrw/ORkgnzcWz8mERERETFFQpgvz16bzANje/Fy+kEWbD7GpiNl3PzGJgZ0DWDamAQu6RuO1arilIhIW2cxDMM4g/06FZvNRkBAABUVFfj7+5sdjnPk74L/XOJoWO7iDsHdISQBQno4ilAhCRDaE7xDTtvPqdXVlELedkcTdYuF7JIa7n5nC7tzbVgs8MDYXkwfk6DkQ0REWl2nzBNOQ+dB2ooCWy2vrj7EuxuyOdHQBECvcF+mjUngsgGRuGrBGxERpzvTPEFFqdPodElWVSH8+0LH9Lz482HKB+DadkcbLd9TwIz3MrDVNhLs484L1yVzXs8uZoclIiKdRKfLE76HzoO0NSVVdbyx5gj/XXuEyrpGAOJDffjjZX24sHeYpvWJiDjRmeYJ+tmgs2usg/m/dBSkgrvDNf9tswWpxiY7f1+yl9vf3IyttpFBsYF8cu8oFaREREREhBBfD347LpGvH76Q317SiyBvNw4XV3Pbfzdzy5xNHCyqMjtEERH5HypKdWaGAR/fBzkbwCMAbngPvIPNjuoUDU12dh2v4Mb/bORfXx4E4OYR3Zh/ZxpRgV5mhyciIiIibUiAlxvTL+zJV7+7kLtG98DNxcKXWUWMf341T36WSWVtg9khiojISWp03pmteQG2zwWLC1w7x9EzymR2u8Gh4iq251Sw41g5249VsCfPRn2jHQAfdxeeumoglydFmR2qiIiIiLRhvh6uPDyhN5OHxvDEJ3tYubeQV1cf4sOtx3l4Qm+uHNRV/UhFREymolRntfczWP6Y4/GEv0GPC00JwzAMVmUVsuFQKduPlbPruI2qkz0Avsvf05Uh3YL5/aV9SAjzNSVWEREREWl/4kN9eP3moazcW8ATn2RyuLia3y7Yztvrj/L4L/qRFBNodogiIp2WilKdUf4u+OB2wIAht8GwO0wL5aWVB3h22b4W2zzdrPSPCmBgdCBJMY77uGBv/ZIlIiIiIj/bhb3DGZkQyhtrjvDSiv1k5JQzcdYarh0SzW8uSSTc39PsEEVEOh0VpTqbqkKYex00VEP8aMcoKZNsyy7jhRX7AbhyUFdSuwczMDqQnmG+WrpXRERERM45D1cX7hrdgysHdeWpJXv5cOtx3tt8jPe3HGNUzy5cNbgrl/SNwMvdxexQRUQ6BRWlOpPvrrQXkgDX/hdc3EwJpbqukQfmZ9BkN/hFUhTPTk42JQ4RERER6XzC/D159tpkpqTG8dTnmWw6UsbqfUWs3leEj7sL4/tHctXgrgzvHqLR+iIirUjDUTqL76605xkA188HryDTwvl/n2ZypKSGyABPnpjY37Q4REREOoKZM2cydOhQ/Pz8CAsLY9KkSWRlZf3o+xYsWEDv3r3x9PRkwIABfPbZZ06JV6StSIkLYsFdI1j12wv49UU9iQn2orq+iQ+2HuOG1zYw8m8reerzvewrqDQ7VBGRDklFqc5izfPfrrR3zX8hNMG0UJbvKWDuxmwA/nFNEgHe5ozWEhER6SjS09OZNm0a69evZ9myZTQ0NHDJJZdQXV39ve9Zu3Yt119/Pbfddhvbtm1j0qRJTJo0iV27djk1dpG2ID7UhxkX92L1g2N4/640bkiNxd/TlbyKWl5OP8glz63mshe/4pkvslhzoJjahiazQxYR6RAshmEYZgfR1thsNgICAqioqMDf39/scM7e0XXwxgRHY/NLnzG1sXlRZR3jn19NSXU9t4+K54//19e0WERERH6O9pAnFBUVERYWRnp6Oueff/5p95k8eTLV1dV88sknzduGDx9OcnIyL7/88o9+Rns4DyJno7ahiVV7C/lw23FW7S2k0f7tP5vcXawkxwQyvEcIad1DGBQbiKeb+lCJiHzjTPME9ZTq6Opr4KN7HAWp5CmmFqQMw+DhD3ZQUl1P7wg/fjsu0bRYREREOrKKigoAgoODv3efdevWMWPGjBbbxo0bx6JFi067f11dHXV1dc3PbTbbOYtXpC3ydHNhwoBIJgyIpLS6nuV7Clh3qIR1B0vIt9Wy8UgpG4+U8uKK/bi7WkmJDWJ49xDO7xVKckwgFot6UYmI/BgVpTq6lU9A6SHw7wrjZ5oaytyNOazYW4i7i5Xnr0vWr0kiIiKtwG63c//99zNy5Ej69//+vo35+fmEh4e32BYeHk5+fv5p9585cyaPP/74OY9XpD0I9nHn2qExXDs0BsMwOFJSw7qDJc1FquKqOsfjQyU8t3wfA6MDuG1UPJcOiMRNq0qLiHwvFaU6sqNrYf1sx+PLX3Q0ODfJoaIqnvhkDwAPjkukd4SG+YuIiLSGadOmsWvXLr7++utzetxHHnmkxcgqm81GTEzMOf0MkfbAYrEQH+pDfKgPN6TGYhgGB4uqTxaoilmRWciOYxXcNy+Dv32+l5tHdmPy0FgCvNRHVUTkf7WJsv2sWbPo1q0bnp6epKamsnHjxu/dd86cOVgslhY3T0/PFvtUVVUxffp0oqOj8fLyom/fvmfUG6FDqa+Bj6Y5pu0N+iX0HGtaKA1Ndh54bzsnGppI6x7CbaPiTYtFRESkI5s+fTqffPIJq1atIjo6+gf3jYiIoKCgoMW2goICIiIiTru/h4cH/v7+LW4i4ihSJYT5cuPwOP41JYW1D1/IA2N7EerrTm5FLU9+tpcRM1fw+Me7ySmtMTtcEZE2xfSi1Pz585kxYwaPPvooW7duJSkpiXHjxlFYWPi97/H39ycvL6/5dvTo0Ravz5gxgyVLlvD222+TmZnJ/fffz/Tp01m8eLETvlEbseIv307bG/ekqaH8c+UBtueU4+/pyj+uTcJq1fx6ERGRc8kwDKZPn87ChQtZuXIl8fE//gNQWloaK1asaLFt2bJlpKWltWKkIh1fiK8H943tyde/u5C/XTWAnmG+VNc38caaI4x+ehX3vLOFLUfLzA5TRKRNML0o9eyzz3LHHXdwyy23NI9o8vb25vXXX//e91gsFiIiIppv/9sPYe3atUydOpULLriAbt26ceedd5KUlPSDI7A6lKNrYcPJkWEmT9vbml3GP1cdAOCJSf2JCvQyLRYREZGOatq0abz99tu8++67+Pn5kZ+fT35+PidOnGje56abbuKRRx5pfn7fffexZMkS/vGPf7B3714ee+wxNm/ezPTp0036FiIdi6ebC5OHxrL0gfOZc8tQzusZit2Az3bmc9XstUx44SueW7aP3bkVaEF0EemsTC1K1dfXs2XLFsaO/XZqmdVqZezYsaxbt+5731dVVUVcXBwxMTFMnDiR3bt3t3h9xIgRLF68mOPHj2MYBqtWrWLfvn1ccsklpz1eXV0dNputxa3dakPT9qrrGnlgfgZNdoNfJEUxMbmrabGIiIh0ZLNnz6aiooILLriAyMjI5tv8+fOb98nOziYvL6/5+YgRI3j33Xd59dVXSUpK4v3332fRokU/2BxdRH46i8XCBYlhvHVbKkvuP4+rU6Jxc7GQmWfjhRX7uezFrxn1t1U8tng3aw8W09hkNztkERGnsRgmluVzc3Pp2rUra9eubTFU/KGHHiI9PZ0NGzac8p5169axf/9+Bg4cSEVFBc888wyrV69m9+7dzb0T6urquPPOO3nzzTdxdXXFarXy73//m5tuuum0cTz22GOnXU2moqKi/fVL+Pxh2DDbMW3vnnWmjZIyDIPffbCD9zYfIyrAk8/vO58AbzV3FBGR9s9msxEQENA+84RzSOdB5Ocrra5nRWYBS/cU8NX+Imobvi1EBXq7cWFiGJf0C+f8Xl3wdtfaVCLS/pxpntDu/guXlpbWooA1YsQI+vTpwyuvvMITTzwBwEsvvcT69etZvHgxcXFxrF69mmnTphEVFdViVNY3OsxqMt+dtvcL86btVdQ08Nv3t7NsTwEWCzxzbZIKUiIiIiIiJwX7uHPNkBiuGRLDifomvtpfxNI9BazILKCspoEPtx3nw23H8XC1MqF/BL8cHkdKXBAWi3qzikjHYmpRKjQ0FBcXl5+08sv/cnNzY9CgQRw44OhbdOLECX7/+9+zcOFCLrvsMgAGDhxIRkYGzzzzzGmLUh4eHnh4eJyT72Sa+hpYdM/JaXs3QoI50/YycsqZ9s5WjpefwN3FyuMT+zGiR6gpsYiIiIiItHVe7i5c0i+CS/pF0NhkZ8vRMpbuKWDpnnxySk+wKCOXRRm5JIb7MWV4LFcM6oqfp37wFZGOwdSeUu7u7qSkpLRY+cVut7NixYozXvmlqamJnTt3EhkZCUBDQwMNDQ1YrS2/mouLC3Z7B56fveIvUHb45Gp7f3X6xxuGwX++Psw1L6/lePkJYoO9+eDuEVw/LNbpsYiIiIiItEeuLlZSu4fwp//ry+oHx7Bo2kiuHRKNp5uVrIJK/vzRblKfXMEjH+5g1/EKs8MVETlrpk/fmzFjBlOnTmXIkCEMGzaM559/nurqam655RY4uVJM165dmTlzJgB/+ctfGD58OAkJCZSXl/P0009z9OhRbr/9dgD8/f0ZPXo0Dz74IF5eXsTFxZGens6bb77Js88+a+p3bTUmT9urqGngwfe3s3SPY8TbhP4R/O3qgfjrFxwRERERkZ/FYrGQHBNIckwgf7isLx9uPcY7G7I5UFjF3I05zN2YQ1JMIFNSY7l8YBRe7i5mhywi8pOZXpSaPHkyRUVF/PnPfyY/P5/k5GSWLFlCeHg4nFwp5rujnsrKyrjjjjvIz88nKCiIlJQU1q5dS9++fZv3mTdvHo888ghTpkyhtLSUuLg4/vrXv3LXXXeZ8h1bVX21qdP2tueUM+3drRwrc0zX+8NlfbgpLU7z3UVEREREzpEALzduGRnPzSO6sfFwKe9syObzXXlszylne045jy3eTXJMIClxQQyOC2JwTJB6uopIu2Dq6nttVbtaTWbJ72H9LKevtmcYBnPWHuHJzzJpaDKICfZi1g2DGRgd6JTPFxERMUu7yhNakc6DiLmKq+pYsPkY7248Sk7piVNe7xnm21ykSokLonuoj344FhGn6bCr78l3VBbAptccj//veacVpCpONPC793ewZHc+AOP7OabrBXjp1xgREREREWcI9fXg7gt68Kvzu7O/sIotR8vYcrSMrdllHC6uZn9hFfsLq5i3KQeAQG83zu/ZheuGxZDWPUQFKhFpE1SUas82vgJNdRA9DHpe7JSPrG+0M/X1jWTklOPmYuEPl/Zh6ohu+j81ERERERETWK0WEiP8SIzw44ZUxyJDJVV1bM0udxSpjpax/Vg55TUNLN6ey+LtuXQL8ea6YbFcnRJNqG87X4VcRNo1FaXaq7rKb0dJjbwPnFQUeurzvWTklOPv6cpbt6WSFKPpeiIiIiIibUmIrwcX9w3n4r6OPr31jXZ2Hi/nw63H+SgjlyMlNTz1+V6e+SKLS/qFc/2wWEb2CMVq1Q/NIuJcKkq1V1vfhNoKCEmAxEud8pFf7M7n9TWHAfjHtckqSImIiIiItAPurlZS4oJJiQvm95f24ZMduczdmENGTjmf7czns535xAR7cd3QWK5JiSbM39PskEWkk1BRqj1qaoB1/3I8HnEvfGd1wtaSU1rDgwu2A3D7qPjmX11ERERERKT98PFwZfLQWCYPjSUzz8a8jdl8uO04OaUnePqLLJ5dto+eYb70ifSnT6TfyXt/TfMTkVaholR7tOtDsB0DnzAYeF2rf1x9o53p727FVttIckwgD43v3eqfKSIiIiIiratPpD+PT+zPwxP68NnOPOZuzGbz0TL25leyN7+Shdu+3beLn8e3haoIf/p3DaBHF63oJyJnR0Wp9sYwYM0LjsfD7wK31h9a+9Tne9l+rAJ/T1f+ecMg3F1bf2SWiIiIiIg4h5e7C1elRHNVSjS55SfYk2sjM89GZr6NzLxKjpRUU1RZR1FlEav3FTW/r1uIN+P6RzCuXwTJ0YHqSSUiP5mKUu3NgRVQuBvcfGDIra3+cf/bRyo6yLvVP1NERERERMwRFehFVKAXY7/TrqOmvpGs/Eoy8yodxao8GzuOV3CkpIZX0g/xSvohwv09GNfPUaAaFh+Mm4t+yBaRH6eiVHuz5nnHfcrN4BXUqh+lPlIiIiIiIuLt7sqg2CAGxX7774+qukbSs4pYsjufVXsLKbDV8ea6o7y57iiB3m5c1Duc8f0jOK9nKJ5uLqbGLyJtl4pS7cnxrXDkK7C6wvC7W/WjvttHalBsIL+boD5SIiIiIiLi4OvhymUDI7lsYCR1jU2sPVDCkl35LMssoLS6ng+2HuODrcfwdnfhgsQujOsXwZjeYfh7upkduoi0ISpKtSdrX3Tc978aAmNa9aO+6SMV4OXGS9cP0vBbERERERE5LQ9XF8b0DmNM7zD+2mRn89Eyvtidzxe78smtqOWznfl8tjMfNxcLI3qEMq5fBBf3DaeLn1b0E+nsLIZhGGYH0dbYbDYCAgKoqKjA39/f7HAcSg/BSylg2OHutRDer9U+6ovd+fzqrS0AvHbTkBbzyUVERDq7NpknmEDnQUR+jGEY7Dxe4ShQ7S7gQGFV82sWCwyJC2ruQxUTrN61Ih3JmeYJGinVXqyb5ShIJYxt1YLUd/tI3XFevApSIiIiIiLys1gsFgZGBzIwOpAHx/XmQGEVX+zOZ+nufLYfq2DTkTI2HSnj/32aSfcuPozsEcrIhBCGdw8h0Nvd7PBFxAlUlGoPqoth29uOxyPva7WP+d8+Ug+NVx8pERERERE5NxLCfEkIS2DamARyy0+wdHc+S3bns/FwKYeKqjlUVM1b649isUD/qABGJIQwskcoQ7sF4+WuZukiHZGKUu3Bxn9DYy1EDYJu57XKR+wrqGTGexnsOm5THykREREREWlVUYFe3DwynptHxlNR08C6QyWsO1jMmoMlHCisYufxCnYer+CV9EO4u1gZFBvIyIRQUuODSYoJ1Ip+Ih2EilJtXX01bHzV8XjkfY7J1+dQk93g1dWHeG7ZPuqb7AR4uTHrhsFEB2lOt4iIiIiItL4AbzfG949gfP8IAApstaw9WMyaAyWsPVBMbkUtGw6XsuFwKQDurlYGxQSS2j2E4fHBDIoN0kgqkXZKRam2bts7cKIUgrpBn1+c00MfKqriNwu2sy27HIALe4cx88oBhPt7ntPPEREREREROVPh/p5cMSiaKwZFYxgGR0pqWHOgmHWHSthwqJTiqrrmItWLgJuLhaToQFK7B5MaH8KQbkF4u+ufuiLtgf5S27KmRlj3kuNx2nSwnpvqv91u8MbaI/x9yV7qGu34ebjyp8v7ck1KNJZzPBJLRERERETk57JYLMSH+hAf6sMvh8dhGAaHiqvZcKiUDYcdRap8Wy2bj5ax+WgZs1YdxNfDlSsHd+XG4XH0DPcz+yuIyA9QUaoty/wIyrPBOwSSp5yTQ2aX1PDb97ez8eTQ1/N6hvK3qwYSFeh1To4vIiIiIiLSWiwWCz26+NKjiy83pMZiGAbZpTVsOFTK+sMlrD9YQm5FLW+uO8qb644yvHswN6V14+K+4eqZK9IGqSjVVhkGrHnB8XjYr8D97Ho8GYbBOxuyefKzTGrqm/B2d+H3l/ZhSmqsRkeJiIiIiEi7ZLFYiAvxIS7Eh2uHxmAYBmsOlPDmuiMszyxg/aFS1h8qJdzfgxuGxXH9sBjC1K5EpM1QUcrZSg7Cgqk/vp+9CQr3gJs3DLvjrD6yscnOXW9vYXlmIQCp8cE8fXUSsSFqZi4iIiIiIh2HxWJhVM9QRvUMJbf8BO9uyGbepmwKbHU8t3wfL63cz/j+EdyU1o0hcUFYrfqBXsRMKko5W2Md5O888/2H3ArewWf1kSv3FrI8sxAPVyu/G9+bm0d00398RURERESkQ4sK9OK34xK596IEluzK5811R9lytIxPduTxyY48vN1d6BnmS89wP3qFf3PvR1SAp2aTiDiJilLOFhgDv/zgzPZ18YCY1LP+yLkbswG4eWQ3bh0Vf9bHExERERERaS88XF2YmNyVicld2Z1bwVvrjvJRRi419U1sP1bB9mMVLfb39XAlIcyXXuG+9I305/KkKEJ8PUyLX6QjsxiGYZgdRFtjs9kICAigoqICf39/s8M5K8fLT3De31ZiN2DVby8gPtTH7JBERETatY6UJ5wNnQcRac8amuwcLalmX0EV+woq2X/y/nBxNY32lv9E9nC1cuXgrtw6Ml6r+YmcoTPNEzRSqoN7b1MOdgPSuoeoICUiIiIiIgK4uVhJCPMjIcyPSwdENm+vb7RzpKS6uUi1KquQHccqmLsxh7kbczi/VxduGxXP+T1DNcVP5BxQUaoDa2yy897mHACuT401OxwREREREZE2zd3VSq+TvaUuI5L7x/Zk89Ey/vPVYZbuyWf1viJW7yuiZ5gvt42KZ9Kgrni6uZgdtki7paJUB5a+r4i8ilqCvN0Y1y/c7HBERERERETaFYvFwtBuwQztFkx2SQ1vrD3Me5ty2F9YxcMf7uTvX2Txy9RYLhsYhZ+nKz7urni5u+DuajU7dJF2QUWpDmzuRscoqatTovFwVfVeRERERETk54oN8ebRy/vxwMW9eG9TDm+sOcLx8hO8uPIAL6480GJfV6sFb3cXvN1dHfceLvi4uzIqIZSb0roR4O1m1tcQaVNUlOqg8itqWbm3AIDJQzV1T0RERERE5Fzw93Tj9vO6c/OIbizdU8CcNUfYm2/jREMTDU2OJumNdgNbbSO22sYW791wuJSX0w8yZXgct42KJ9zf06RvIdI2qCjVQb232dHgfFh8MAlhvmaHIyIiIiIi0qG4uli5dEDkKY3ST9Q3UdPQSE19Eyfqm6iua6SmoYn8ilr+u/YIe/MreXX1IeasOcJVKV351fk96KZFqaSTUlGqA2qyG8zf5Ji6d8MwjZISERERERFxBndXK+6uVgI4/fS864bG8GVWEf/68gCbjpQxd2MO8zflMGFAJHeP7kH/rgFOj1nETCpKdUBf7S/iePkJArzcGN8/wuxwRERERERE5GTj9DG9wxjTO4xNR0qZ/eVBVu4t5NMdeXy6I4/ze3XhrtHdSY0PwcVqMTtckVanolQHNHdjNgBXDtbypCIiIiIiIm3R0G7BDL05mMw8Gy+nH+Tj7bms3lfE6n1F+Hu6Miw+hOHdgxnePYQ+kf4qUkmHpKJUB1Noq2V5ZiEA12vqnoiIiIiISJvWJ9KfF64bxG8uTuTVrw6yaFsuttpGlmcWsDzTsXjVd4tUaT1C6BPhj1VFKukAVJTqYBZsOUaT3WBIXBC9wv3MDkdERERERETOQGyIN/9v0gAeu7wfu3NtrD9UwvpDJWw6UnZKkSrAy42h3YJIjgkkOSaIgTEB+Huevo+VSFvWJopSs2bN4umnnyY/P5+kpCReeuklhg0bdtp958yZwy233NJim4eHB7W1tS22ZWZm8rvf/Y709HQaGxvp27cvH3zwAbGxHXf0kN1uMG+TY+redRolJSIiIiIi0u64ulhJigkkKSaQX43uQWOT/ZQiVcWJBpZnFjbPkrFYIKGLr6NIFRvIoJggeoX74upiNfvriPwg04tS8+fPZ8aMGbz88sukpqby/PPPM27cOLKysggLCzvte/z9/cnKymp+brG0HLZ48OBBRo0axW233cbjjz+Ov78/u3fvxtPTs9W/j5nWHCwmp/QEfp6uXPadZUlFRERERESkfTpdkWpXro0tR8vIyCknI6eMnNIT7C+sYn9hFQu2HAPAy82FAdEBjOwRyrj+4SSG+53yb2cRs1kMwzDMDCA1NZWhQ4fyz3/+EwC73U5MTAz33nsvDz/88Cn7z5kzh/vvv5/y8vLvPeZ1112Hm5sbb7311s+KyWazERAQQEVFBf7+/j/rGGa4550tfLYzn6lpcTw+sb/Z4YiIiHRI7TVPONd0HkRE2o7iqjoyssvJyClnW04ZO3IqqKxrbLFPbLA34/qFc0m/CAbHBqlxurSqM80TTB0pVV9fz5YtW3jkkUeat1mtVsaOHcu6deu+931VVVXExcVht9sZPHgwTz75JP369YOTRa1PP/2Uhx56iHHjxrFt2zbi4+N55JFHmDRpklO+lxmKKutYutsxv1hT90RERERERDqPUF8PxvYNZ2zfcDjZ2uVgURWbj5axIrOA1fuLyS6t4d9fHebfXx0m1NedsX3CuaRfOCN6hGrVdjGNqRNMi4uLaWpqIjw8vMX28PBw8vPzT/uexMREXn/9dT766CPefvtt7HY7I0aM4NgxxxDFwsJCqqqqeOqppxg/fjxLly7liiuu4MorryQ9Pf20x6yrq8Nms7W4tTcfbD1Go90gOSaQPpH6tVJERKQzWb16NZdffjlRUVFYLBYWLVr0g/t/+eWXWCyWU27fl3+JiEj7YrVa6Bnux/XDYnlt6lC2/eliZk8ZzBWDuuLv6UpxVT3zNuVw65zNpDyxjGnvbGXB5hwKbLVncHSRc8f0nlI/VVpaGmlpac3PR4wYQZ8+fXjllVd44oknsNvtAEycOJEHHngAgOTkZNauXcvLL7/M6NGjTznmzJkzefzxx534Lc4tu91g3kZHg/MbNEpKRESk06muriYpKYlbb72VK6+88ozfl5WV1WJI/ff18xQRkfbNx8OVCQMimTAgkoYmOxsOlbJ0Tz5LdxeQb6vl0515fLozD4DeEX6MTuzC6F5dGBIXjLurmqVL6zG1KBUaGoqLiwsFBQUtthcUFBAREXFGx3Bzc2PQoEEcOHCg+Ziurq707du3xX59+vTh66+/Pu0xHnnkEWbMmNH83GazERMT8zO+kTnWHyrhSEkNvh6u/F+SGpyLiIh0NhMmTGDChAk/+X1hYWEEBga2SkwiItI2ublYGdUzlFE9Q3n8F/3YcayCFZkFpO8vZsexcvbmV7I3v5JX0g/h7e7CiB4hjO7VhfN7dSEuxMfs8KWDMbUo5e7uTkpKCitWrGju92S321mxYgXTp08/o2M0NTWxc+dOLr300uZjDh06tMXqfAD79u0jLi7utMfw8PDAw8PjrL+PWd49OUpqYnIU3u7tbvCbiIiImCQ5OZm6ujr69+/PY489xsiRI79337q6Ourq6pqft8d2ByIi0pLFYmle2W/GJYmUVtfz1f4i0vcVsXpfMcVVdSzPLGR5ZiGc7F0V6utOkLc7wT7uBPm4EeztTmDzc3eCvd3pFuqNn6eb2V9P2gHTKxgzZsxg6tSpDBkyhGHDhvH8889TXV3NLbfcAsBNN91E165dmTlzJgB/+ctfGD58OAkJCZSXl/P0009z9OhRbr/99uZjPvjgg0yePJnzzz+fMWPGsGTJEj7++GO+/PJL075naymp+rbB+fWauiciIiJnIDIykpdffpkhQ4ZQV1fHa6+9xgUXXMCGDRsYPHjwad/T3tsdiIjIjwv2cWdiclcmJnfFbjfIzLeRvq+I9Kwithwto7iqjuKquh89jsUCPbr4knyy4JUcHUjvSD/cXDQVUFoyvSg1efJkioqK+POf/0x+fj7JycksWbKkufl5dnY2Vuu3/8MtKyvjjjvuID8/n6CgIFJSUli7dm2L6XpXXHEFL7/8MjNnzuTXv/41iYmJfPDBB4waNcqU79iaPth6jPomOwOjA+jfNcDscERERKQdSExMJDExsfn5iBEjOHjwIM899xxvvfXWad/T3tsdiIjIT2O1WugXFUC/qADuuSCBytoGjhTXUFZT77hV11Na03Dy/uTz6nqKq+oprqrjQGEVBwqreH+LY1Eyd1cr/aP8HUWqmEAGxQQRG+Jt9tcUk1kMwzDMDqKtsdlsBAQEUFFR0aL5Z1vSZDd47atD/GPpPuqb7Dx5xQBuSNVIKRERkdbW1vMEi8XCwoULm1sjnKkHH3yQr7/+mnXr1p3R/m39PIiIiHmKKuvYcayc7TnlbMtx3NtqG0/Zr3eEH5cnRfGLpChiglWg6kjONE8wfaSU/HQ5pTX8ZsF2Nh4uBeDivuFcldLV7LBERESkHcvIyCAyUgumiIjI2evi58FFfcK5qI9jBpRhGBwpqWF7TjkZJ2+7cytONlXP4ukvshgcG8jE5K5cOiCSLn7tt+ez/DQqSrUjhmHw4dbjPLp4N1V1jXi7u/Do5X25dkgMFovF7PBERETEJFVVVc0rEQMcPnyYjIwMgoODiY2N5ZFHHuH48eO8+eabADz//PPEx8fTr18/amtree2111i5ciVLly418VuIiEhHZbFYiA/1IT7Uh0mDHAMqKmoaWLI7j8Xbc1l7sISt2eVszS7n8Y93MzIhlInJXRnXL1wN0zs4FaXaidLqev6wcCef78oHICUuiGevTdKSnCIiIsLmzZsZM2ZM8/Nvej9NnTqVOXPmkJeXR3Z2dvPr9fX1/OY3v+H48eN4e3szcOBAli9f3uIYIiIirSnA243JQ2OZPDSWAlstn+xwFKi255Tz1f5ivtpfzO8XWjkvIZT+XQPoE+lP30h/YoK9NCijA1FPqdNoaz0SVmUV8tD7OyiqrMPVauGBi3tx1+geuFj1hygiIuJsbS1PMIvOg4iItIYjxdUs3p7LRxnHOVhUfcrrfh6u9I70o0+kf3OhKjHCD083F1PildM70zxBRanTaCtJVk19I3/9NJN3Njh+2ewZ5stzk5O1yp6IiIiJ2kqeYDadBxERaU2GYbAnz8b6Q6Vk5tnIzLOxv6CK+ib7KftaLY4+VkHe7gT7uBPk406Ij3uL58He7oT4uhMf6qMClhOo0Xk7d7Coitv/u5nDxY7K8K0j43lofKL+eERERERERKTDs1gs9IsKoF/Ut4MyGprsHCyqOlmkqmRPrqNYVVJdT4GtjgJb3Y8e12qB+FCfFiOt+kT6E+7voWmBJlBRqg2qqmvkzjcdBanIAE+euSaJkQmhZoclIiIiIiIiYho3Fyu9I/zpHeHPFYMc2wzDoKiqjkJbHaXV9c23spr/ua9uoKCylvKaBg4WVXOwqJpPduQ1HzvI261FoSopJpDuoT5Y1TanVako1cYYhsHvPtjBwaJqIvw9WTx9lJbDFBERERERETkNi8VCmJ8nYX6eP7qvYRgUVdax5+RIq2+mBR4qrqaspoG1B0tYe7CkeX8/D1cGxgSQFB1IUkwgyTGBhPv/+OfImVNRqo15Y80RPt2Rh6vVwqwpg1WQEhERERERETkHLBYLYf6ehPl7ckFiWPP22oYm9hc4pgXuybOxO7eCnccrqKxrZM2BEtYc+LZQFe7v0VykGhYfzKCYQFxdrCZ9o/ZPRak2ZMvRUp78LBOAP1zWh5S4ILNDEhEREREREenQPN1cGBAdwIDob/tXNTbZ2VdQxfZj5WzPKScjp5x9BZUU2OpYuqeApXsKAPD3dOW8Xl0YkxjG6F5dNLDkJ1JRqo0orqrjnne20mg3+L+Bkdw8opvZIYmIiIiIiIh0Sq4uVvpG+dM3yp/rh8UCUFPfyK7jNrbnlLMtp4w1B0qoONHApzvy+PRkf6oBXQO4ILELFySGkRwTiIt6Uv0gFaXagCa7wa/nbqPAVkePLj787aqB6vovIiIiIiIi0oZ4u7syLD6YYfHBcPLf8hk55XyZVciXWUXsPF7RfHtp5QECvd0YmRBKhL8nnm5WvNxc8PzOzfHcsT3Q252e4b64dbKpgCpKtQHPLsti7cESvN1dePmXKfh46LKIiIiIiIiItGUuVgspcUGkxAXxm0sSKaysZfW+YlZlFbJ6XxHlNQ3NI6jOhKeblYFdAxkUF8jg2CAGxQaeUQP39kzVD5OtyCxg1qqDADx11UB6hvuZHZKIiIiIiIiI/ERhfp5cnRLN1SnRNDbZ2ZZTzsbDpVTWNlLb0ERtQxMnmu/t1DY0UXdyW15FLZW1jWw8UsrGI6XNx4wO8mouUA2ODaJPpD/urh1nNJWKUibKLqnhgfkZANw8ohu/SIoyOyQREREREREROUuuLlaGdgtmaLfgM9rfbjc4VFzF1uxytmWXsS27nKyCSo6VneBY2QkWb88FwN3VyoCuAQyKCWTQyWJVZIBnu20BpKKUSWobmrj7nS3YahsZFBvI7y/tY3ZIIiIiIiIiImICq9VCQpgfCWF+XDskBoDK2ga251SwLbuMrdllbMspp7ymgS1Hy9hytAw4DEC4vweDYoJIjg1kUEwgA6ID8HZvH+We9hFlB/TY4t3szrUR7OPOv6YM7lDD70RERERERETk7Ph5ujGqZyijeoYCYBgGR0pqmkdSbcspIzOvkgJbHUt257Nkdz6c7HWV0MXXsXpgpH/zfZCPu8nf6FQqSpngvc05zNuUg8UCL143iMgAL7NDEhEREREREZE2zGKxEB/qQ3yoD1cOjgbgRH0TO49XNBeqtmaXUVhZR1ZBJVkFlSzcdrz5/ZEBni2KVH2j/IkJ8sZqNW/qn4pSTrY7t4I/LdoFwIyxvZorniIiIiIiIiIiP4WXuwvD4oMZFu/oXWUYBvm2Wvbk2hy3PMftaEkNeRW15FXUsmJvYfP7n5jUnxuHx5kWv4pSTuZitRAR4En3UB+mjUkwOxwRERERERER6SAsFguRAV5EBnhxUZ/w5u2VtQ3sza9sUazKyq+kb6SfqfGqKOVkvSP8WTx9FBiYOkRORERERERERDoHP0+3U1YDbGiyYzV51T4VpUwQ4OVmdggiIiIiIiIi0om5uZi/4Jr5EYiIiIiIiIiISKejopSIiIiIiIiIiDidilIiIiIiIiIiIuJ0KkqJiIiIiIiIiIjTqSglIiIiIiIiIiJOp6KUiIiIiIiIiIg4nYpSIiIiIiIiIiLidCpKiYiIiIiIiIiI06koJSIiIiIiIiIiTqeilIiIiIiIiIiIOJ2r2QG0RYZhAGCz2cwORURERNqYb/KDb/KFzkr5koiIiHyfM82XVJQ6jcrKSgBiYmLMDkVERETaqMrKSgICAswOwzTKl0REROTH/Fi+ZDE6+898p2G328nNzcXPzw+LxXLOj2+z2YiJiSEnJwd/f/9zfnz5cboG5tL5N5+ugfl0Dcz3c6+BYRhUVlYSFRWF1dp5OyEoX+r4dA3Mp2tgLp1/8+kamK+18yWNlDoNq9VKdHR0q3+Ov7+//rBMpmtgLp1/8+kamE/XwHw/5xp05hFS31C+1HnoGphP18BcOv/m0zUwX2vlS5335z0RERERERERETGNilIiIiIiIiIiIuJ0KkqZwMPDg0cffRQPDw+zQ+m0dA3MpfNvPl0D8+kamE/XoG3T9TGfroH5dA3MpfNvPl0D87X2NVCjcxERERERERERcTqNlBIREREREREREadTUUpERERERERERJxORSkREREREREREXE6FaWcbNasWXTr1g1PT09SU1PZuHGj2SF1WKtXr+byyy8nKioKi8XCokWLWrxuGAZ//vOfiYyMxMvLi7Fjx7J//37T4u2IZs6cydChQ/Hz8yMsLIxJkyaRlZXVYp/a2lqmTZtGSEgIvr6+XHXVVRQUFJgWc0cze/ZsBg4ciL+/P/7+/qSlpfH55583v67z71xPPfUUFouF+++/v3mbrkHreuyxx7BYLC1uvXv3bn5d579tUr7kPMqXzKd8yXzKl9oW5UvOZ2a+pKKUE82fP58ZM2bw6KOPsnXrVpKSkhg3bhyFhYVmh9YhVVdXk5SUxKxZs077+t///ndefPFFXn75ZTZs2ICPjw/jxo2jtrbW6bF2VOnp6UybNo3169ezbNkyGhoauOSSS6iurm7e54EHHuDjjz9mwYIFpKenk5uby5VXXmlq3B1JdHQ0Tz31FFu2bGHz5s1ceOGFTJw4kd27d4POv1Nt2rSJV155hYEDB7bYrmvQ+vr160deXl7z7euvv25+Tee/7VG+5FzKl8ynfMl8ypfaDuVL5jEtXzLEaYYNG2ZMmzat+XlTU5MRFRVlzJw509S4OgPAWLhwYfNzu91uREREGE8//XTztvLycsPDw8OYO3euSVF2fIWFhQZgpKenG8bJc+7m5mYsWLCgeZ/MzEwDMNatW2dipB1bUFCQ8dprr+n8O1FlZaXRs2dPY9myZcbo0aON++67zzD0N+AUjz76qJGUlHTa13T+2yblS+ZRvtQ2KF9qG5QvOZ/yJfOYmS9ppJST1NfXs2XLFsaOHdu8zWq1MnbsWNatW2dqbJ3R4cOHyc/Pb3E9AgICSE1N1fVoRRUVFQAEBwcDsGXLFhoaGlpch969exMbG6vr0AqampqYN28e1dXVpKWl6fw70bRp07jssstanGv0N+A0+/fvJyoqiu7duzNlyhSys7NB579NUr7UtihfMofyJXMpXzKP8iVzmZUvuZ71EeSMFBcX09TURHh4eIvt4eHh7N2717S4Oqv8/Hw4ef6/Kzw8vPk1Obfsdjv3338/I0eOpH///nDyOri7uxMYGNhiX12Hc2vnzp2kpaVRW1uLr68vCxcupG/fvmRkZOj8O8G8efPYunUrmzZtOuU1/Q20vtTUVObMmUNiYiJ5eXk8/vjjnHfeeezatUvnvw1SvtS2KF9yPuVL5lG+ZC7lS+YyM19SUUpEnGLatGns2rWrxdxkcY7ExEQyMjKoqKjg/fffZ+rUqaSnp5sdVqeQk5PDfffdx7Jly/D09DQ7nE5pwoQJzY8HDhxIamoqcXFxvPfee3h5eZkam4jI/1K+ZB7lS+ZRvmQ+M/MlTd9zktDQUFxcXE7pUF9QUEBERIRpcXVW35xzXQ/nmD59Op988gmrVq0iOjq6eXtERAT19fWUl5e32F/X4dxyd3cnISGBlJQUZs6cSVJSEi+88ILOvxNs2bKFwsJCBg8ejKurK66urqSnp/Piiy/i6upKeHi4roGTBQYG0qtXLw4cOKC/gTZI+VLbonzJuZQvmUv5knmUL7U9zsyXVJRyEnd3d1JSUlixYkXzNrvdzooVK0hLSzM1ts4oPj6eiIiIFtfDZrOxYcMGXY9zyDAMpk+fzsKFC1m5ciXx8fEtXk9JScHNza3FdcjKyiI7O1vXoRXZ7Xbq6up0/p3goosuYufOnWRkZDTfhgwZwpQpU5of6xo4V1VVFQcPHiQyMlJ/A22Q8qW2RfmScyhfapuULzmP8qW2x6n50lm3SpczNm/ePMPDw8OYM2eOsWfPHuPOO+80AgMDjfz8fLND65AqKyuNbdu2Gdu2bTMA49lnnzW2bdtmHD161DAMw3jqqaeMwMBA46OPPjJ27NhhTJw40YiPjzdOnDhhdugdxt13320EBAQYX375pZGXl9d8q6mpad7nrrvuMmJjY42VK1camzdvNtLS0oy0tDRT4+5IHn74YSM9Pd04fPiwsWPHDuPhhx82LBaLsXTpUsPQ+TfFd1eTMXQNWt1vfvMb48svvzQOHz5srFmzxhg7dqwRGhpqFBYWGobOf5ukfMm5lC+ZT/mS+ZQvtT3Kl5zLzHxJRSkne+mll4zY2FjD3d3dGDZsmLF+/XqzQ+qwVq1aZQCn3KZOnWoYJ5c5/tOf/mSEh4cbHh4exkUXXWRkZWWZHXaHcrrzDxhvvPFG8z4nTpww7rnnHiMoKMjw9vY2rrjiCiMvL8/UuDuSW2+91YiLizPc3d2NLl26GBdddFFzgmXo/Jvif5MsXYPWNXnyZCMyMtJwd3c3unbtakyePNk4cOBA8+s6/22T8iXnUb5kPuVL5lO+1PYoX3IuM/Mli+H4D6GIiIiIiIiIiIjTqKeUiIiIiIiIiIg4nYpSIiIiIiIiIiLidCpKiYiIiIiIiIiI06koJSIiIiIiIiIiTqeilIiIiIiIiIiIOJ2KUiIiIiIiIiIi4nQqSomIiIiIiIiIiNOpKCUiIiIiIiIiIk6nopSISCuxWCwsWrTI7DBERERE2izlSyKdm4pSItIh3XzzzVgsllNu48ePNzs0ERERkTZB+ZKImM3V7ABERFrL+PHjeeONN1ps8/DwMC0eERERkbZG+ZKImEkjpUSkw/Lw8CAiIqLFLSgoCE4OFZ89ezYTJkzAy8uL7t278/7777d4/86dO7nwwgvx8vIiJCSEO++8k6qqqhb7vP766/Tr1w8PDw8iIyOZPn16i9eLi4u54oor8Pb2pmfPnixevNgJ31xERETkzChfEhEzqSglIp3Wn/70J6666iq2b9/OlClTuO6668jMzASgurqacePGERQUxKZNm1iwYAHLly9vkUTNnj2badOmceedd7Jz504WL15MQkJCi894/PHHufbaa9mxYweXXnopU6ZMobS01OnfVUREROTnUL4kIq3KEBHpgKZOnWq4uLgYPj4+LW5//etfDcMwDMC46667WrwnNTXVuPvuuw3DMIxXX33VCAoKMqqqqppf//TTTw2r1Wrk5+cbhmEYUVFRxh/+8IfvjQEw/vjHPzY/r6qqMgDj888/P+ffV0REROSnUr4kImZTTykR6bDGjBnD7NmzW2wLDg5ufpyWltbitbS0NDIyMgDIzMwkKSkJHx+f5tdHjhyJ3W4nKysLi8VCbm4uF1100Q/GMHDgwObHPj4++Pv7U1hYeNbfTURERORcUL4kImZSUUpEOiwfH59ThoefK15eXme0n5ubW4vnFosFu93eKjGJiIiI/FTKl0TETOopJSKd1vr160953qdPHwD69OnD9u3bqa6ubn59zZo1WK1WEhMT8fPzo1u3bqxYscLpcYuIiIg4i/IlEWlNGiklIh1WXV0d+fn5Lba5uroSGhoKwIIFCxgyZAijRo3inXfeYePGjfznP/8BYMqUKTz66KNMnTqVxx57jKKiIu69915uvPFGwsPDAXjssce46667CAsLY8KECVRWVrJmzRruvfdeE76tiIiIyE+nfElEzKSilIh0WEuWLCEyMrLFtsTERPbu3QsnV3qZN28e99xzD5GRkcydO5e+ffsC4O3tzRdffMF9993H0KFD8fb25qqrruLZZ59tPtbUqVOpra3lueee47e//S2hoaFcffXVTv6WIiIiIj+f8iURMZPFcKx4ICLSqVgsFhYuXMikSZPMDkVERESkTVK+JCKtTT2lRERERERERETE6VSUEhERERERERERp9P0PRERERERERERcTqNlBIREREREREREadTUUpERERERERERJxORSkREREREREREXE6FaVERERERERERMTpVJQSERERERERERGnU1FKREREREREREScTkUpERERERERERFxOhWlRERERERERETE6VSUEhERERERERERp/v/DbMi+LVI8QgAAAAASUVORK5CYII=",
"text/plain": [
"<Figure size 1200x400 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"WARNING:absl:You are saving your model as an HDF5 file via `model.save()` or `keras.saving.save_model(model)`. This file format is considered legacy. We recommend using instead the native Keras format, e.g. `model.save('my_model.keras')` or `keras.saving.save_model(model, 'my_model.keras')`. \n"
]
}
],
"source": [
"# Plot training history\n",
"plt.figure(figsize=(12, 4))\n",
"plt.subplot(1, 2, 1)\n",
"plt.plot(history.history[\"accuracy\"])\n",
"plt.plot(history.history[\"val_accuracy\"])\n",
"plt.title(\"Model Accuracy\")\n",
"plt.ylabel(\"Accuracy\")\n",
"plt.xlabel(\"Epoch\")\n",
"plt.legend([\"Train\", \"Validation\"], loc=\"upper left\")\n",
"\n",
"plt.subplot(1, 2, 2)\n",
"plt.plot(history.history[\"loss\"])\n",
"plt.plot(history.history[\"val_loss\"])\n",
"plt.title(\"Model Loss\")\n",
"plt.ylabel(\"Loss\")\n",
"plt.xlabel(\"Epoch\")\n",
"plt.legend([\"Train\", \"Validation\"], loc=\"upper left\")\n",
"plt.tight_layout()\n",
"plt.savefig(\"question_prediction_training_history.png\")\n",
"plt.show()\n",
"\n",
"# Simpan model dan tokenizer\n",
"model.save(\"question_prediction_model_final.h5\")\n",
"\n",
"# Simpan tokenizer\n",
"tokenizer_data = {\n",
" \"word_tokenizer\": tokenizer.to_json(),\n",
" \"ner_tokenizer\": ner_tokenizer.to_json(),\n",
" \"srl_tokenizer\": srl_tokenizer.to_json(),\n",
" \"q_type_tokenizer\": q_type_tokenizer.to_json(),\n",
" \"max_context_len\": max_context_len,\n",
" \"max_question_len\": max_question_len,\n",
" \"max_token_len\": max_token_len,\n",
"}\n",
"\n",
"with open(\"question_prediction_tokenizers.json\", \"w\") as f:\n",
" json.dump(tokenizer_data, f)"
]
},
{
"cell_type": "code",
"execution_count": 58,
"id": "71ec455a",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"WARNING:absl:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hasil disimpan di: bleu_calculation.xlsx\n",
"\n",
"Model Performance Metrics:\n",
"Average BLEU Score: 2.04%\n",
"Average ROUGE-1 Score: 26.22%\n",
"Average ROUGE-2 Score: 9.07%\n",
"Average ROUGE-L Score: 25.70%\n"
]
}
],
"source": [
"from collections import Counter\n",
"import pandas as pd\n",
"# Fungsi untuk memprediksi pertanyaan\n",
"def predict_question(context, tokens, ner, srl, q_type):\n",
" context = preprocess_text(context)\n",
"\n",
" context_seq = tokenizer.texts_to_sequences([context])[0]\n",
" token_seq = tokenizer.texts_to_sequences([\" \".join(tokens)])[0]\n",
" ner_seq = ner_tokenizer.texts_to_sequences([\" \".join(ner)])[0]\n",
" srl_seq = srl_tokenizer.texts_to_sequences([\" \".join(srl)])[0]\n",
"\n",
" context_padded = pad_sequences(\n",
" [context_seq], maxlen=max_context_len, padding=\"post\"\n",
" )\n",
" token_padded = pad_sequences([token_seq], maxlen=max_token_len, padding=\"post\")\n",
" ner_padded = pad_sequences([ner_seq], maxlen=max_token_len, padding=\"post\")\n",
" srl_padded = pad_sequences([srl_seq], maxlen=max_token_len, padding=\"post\")\n",
"\n",
" # Q-type one-hot encoding\n",
" q_type_idx = q_type_tokenizer.word_index.get(q_type, 0)\n",
" q_type_one_hot = tf.keras.utils.to_categorical(\n",
" [q_type_idx], num_classes=q_type_vocab_size\n",
" )\n",
"\n",
" # Predict\n",
" pred = model.predict(\n",
" [context_padded, token_padded, ner_padded, srl_padded, q_type_one_hot],\n",
" verbose=0,\n",
" )\n",
"\n",
" # Convert prediction to words\n",
" pred_seq = np.argmax(pred[0], axis=1)\n",
"\n",
" # Convert indices to words\n",
" reverse_word_map = {v: k for k, v in tokenizer.word_index.items()}\n",
" pred_words = [reverse_word_map.get(i, \"\") for i in pred_seq if i != 0]\n",
"\n",
" return \" \".join(pred_words)\n",
"\n",
"\n",
"\n",
"\n",
"def evaluate_model_performance(test_data):\n",
" output_path = \"bleu_calculation.xlsx\"\n",
" scorer = rouge_scorer.RougeScorer([\"rouge1\", \"rouge2\", \"rougeL\"], use_stemmer=True)\n",
"\n",
" bleu_scores = []\n",
" rouge1_scores = []\n",
" rouge2_scores = []\n",
" rougel_scores = []\n",
"\n",
" rows = []\n",
"\n",
" for i in range(len(test_data)):\n",
" sample_context = contexts[test_data[i]]\n",
" sample_tokens = tokens_list[test_data[i]]\n",
" sample_ner = ner_list[test_data[i]]\n",
" sample_srl = srl_list[test_data[i]]\n",
" sample_q_type = q_types[test_data[i]]\n",
" actual_question = questions[test_data[i]]\n",
"\n",
" pred_question = predict_question(\n",
" sample_context, sample_tokens, sample_ner, sample_srl, sample_q_type\n",
" )\n",
"\n",
" actual_tokens = actual_question.split()\n",
" pred_tokens = pred_question.split()\n",
"\n",
" max_n = 4\n",
" weights = [1 / max_n] * max_n\n",
" clipped_counts = []\n",
" total_counts = []\n",
" precisions = []\n",
"\n",
" log_text = f\"Sample {i+1}:\\n\"\n",
" log_text += f\"Actual Tokens: {actual_tokens}\\n\"\n",
" log_text += f\"Predicted Tokens: {pred_tokens}\\n\"\n",
"\n",
" for n in range(1, max_n + 1):\n",
" ref_ngrams = Counter(tuple(actual_tokens[j:j + n]) for j in range(len(actual_tokens) - n + 1))\n",
" cand_ngrams = Counter(tuple(pred_tokens[j:j + n]) for j in range(len(pred_tokens) - n + 1))\n",
"\n",
" clip_sum = sum(min(cnt, ref_ngrams.get(ng, 0)) for ng, cnt in cand_ngrams.items())\n",
" total = sum(cand_ngrams.values())\n",
" p_n = clip_sum / total if total > 0 else 0\n",
"\n",
" clipped_counts.append(clip_sum)\n",
" total_counts.append(total)\n",
" precisions.append(p_n)\n",
"\n",
" log_text += f\"{n}-gram: clipped count = {clip_sum}, total candidate = {total}, precision = {p_n:.4f}\\n\"\n",
"\n",
" c = len(pred_tokens)\n",
" r = len(actual_tokens)\n",
" bp = 1 if c > r else np.exp(1 - r / c)\n",
" log_text += f\"Brevity Penalty: BP = {bp:.4f} (c={c}, r={r})\\n\"\n",
"\n",
" if all(p > 0 for p in precisions):\n",
" bleu = bp * np.exp(sum(w * np.log(p) for w, p in zip(weights, precisions)))\n",
" else:\n",
" bleu = 0.0\n",
"\n",
" log_text += f\"BLEU score = {bleu:.4f}\\n\"\n",
"\n",
" bleu_scores.append(bleu)\n",
" rows.append({\"Result\": log_text})\n",
"\n",
" try:\n",
" rouge_scores = scorer.score(actual_question, pred_question)\n",
" rouge1_scores.append(rouge_scores[\"rouge1\"].fmeasure)\n",
" rouge2_scores.append(rouge_scores[\"rouge2\"].fmeasure)\n",
" rougel_scores.append(rouge_scores[\"rougeL\"].fmeasure)\n",
" except Exception as e:\n",
" print(f\"Error calculating ROUGE score: {e}\")\n",
"\n",
" df = pd.DataFrame(rows)\n",
" df.to_excel(output_path, index=False)\n",
" print(f\"Hasil disimpan di: {output_path}\")\n",
"\n",
" results = {\n",
" \"avg_bleu_score\": np.mean(bleu_scores),\n",
" \"avg_rouge1\": np.mean(rouge1_scores),\n",
" \"avg_rouge2\": np.mean(rouge2_scores),\n",
" \"avg_rougel\": np.mean(rougel_scores),\n",
" }\n",
"\n",
" return results\n",
"\n",
"\n",
"loaded_model = load_model(\"question_prediction_model_final.h5\")\n",
"\n",
"with open(\"question_prediction_tokenizers.json\", \"r\") as f:\n",
" tokenizer_data = json.load(f)\n",
"\n",
"# Ambil beberapa sampel dari data test\n",
"# sample_idx = random.randint(0, len(test_indices) - 1)\n",
"# sample_context = contexts[test_indices[sample_idx]]\n",
"# sample_tokens = tokens_list[test_indices[sample_idx]]\n",
"# sample_ner = ner_list[test_indices[sample_idx]]\n",
"# sample_srl = srl_list[test_indices[sample_idx]]\n",
"# sample_q_type = q_types[test_indices[sample_idx]]\n",
"\n",
"performance_metrics = evaluate_model_performance(test_indices)\n",
"\n",
"print(\"\\nModel Performance Metrics:\")\n",
"print(f\"Average BLEU Score: {performance_metrics['avg_bleu_score'] * 100:.2f}%\")\n",
"print(f\"Average ROUGE-1 Score: {performance_metrics['avg_rouge1'] * 100:.2f}%\")\n",
"print(f\"Average ROUGE-2 Score: {performance_metrics['avg_rouge2'] * 100:.2f}%\")\n",
"print(f\"Average ROUGE-L Score: {performance_metrics['avg_rougel'] * 100:.2f}%\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "myenv",
"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.10.16"
}
},
"nbformat": 4,
"nbformat_minor": 5
}