From e55ca8a1d1eb94bf3bc40cd6c598ce5e17f60e3f Mon Sep 17 00:00:00 2001 From: lxr-tech <1838593642@qq.com> Date: Tue, 31 May 2022 23:25:01 +0800 Subject: [PATCH] update example-12 lxr 220531 --- tutorials/fastnlp_tutorial_2.ipynb | 2 +- tutorials/fastnlp_tutorial_3.ipynb | 16 +- tutorials/fastnlp_tutorial_4.ipynb | 10 +- tutorials/fastnlp_tutorial_5.ipynb | 59 ++ tutorials/fastnlp_tutorial_6.ipynb | 59 ++ tutorials/fastnlp_tutorial_7.ipynb | 59 ++ tutorials/fastnlp_tutorial_8.ipynb | 59 ++ tutorials/fastnlp_tutorial_e1.ipynb | 14 +- tutorials/fastnlp_tutorial_e2.ipynb | 734 ++++++++++++++++++++++--- tutorials/figures/E2-fig-pet-model.png | Bin 0 -> 57162 bytes 10 files changed, 916 insertions(+), 96 deletions(-) create mode 100644 tutorials/fastnlp_tutorial_5.ipynb create mode 100644 tutorials/fastnlp_tutorial_6.ipynb create mode 100644 tutorials/fastnlp_tutorial_7.ipynb create mode 100644 tutorials/fastnlp_tutorial_8.ipynb create mode 100644 tutorials/figures/E2-fig-pet-model.png diff --git a/tutorials/fastnlp_tutorial_2.ipynb b/tutorials/fastnlp_tutorial_2.ipynb index 3aa27c86..4ee9579f 100644 --- a/tutorials/fastnlp_tutorial_2.ipynb +++ b/tutorials/fastnlp_tutorial_2.ipynb @@ -867,7 +867,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.4" + "version": "3.7.13" }, "pycharm": { "stem_cell": { diff --git a/tutorials/fastnlp_tutorial_3.ipynb b/tutorials/fastnlp_tutorial_3.ipynb index 353e4645..172e1232 100644 --- a/tutorials/fastnlp_tutorial_3.ipynb +++ b/tutorials/fastnlp_tutorial_3.ipynb @@ -29,13 +29,7 @@ "\n", "### 1.1 dataloader 的职责描述\n", "\n", - "在`fastNLP 0.8`中,在数据加载模块`DataLoader`之前,还存在其他的一些模块,负责例如对文本数据\n", - "\n", - " 进行补零对齐,即 **核对器`collator`模块**,进行分词标注,即 **分词器`tokenizer`模块**\n", - "\n", - " 本节将对`fastNLP`中的核对器`collator`等展开介绍,分词器`tokenizer`将在下一节中详细介绍\n", - "\n", - "在`fastNLP 0.8`中,**核对器`collator`模块负责文本序列的补零对齐**,通过" + "在`fastNLP 0.8`中,在数据加载模块`DataLoader`之前" ] }, { @@ -45,13 +39,7 @@ "source": [ "### 1.2 dataloader 的基本使用\n", "\n", - "在`fastNLP 0.8`中,在数据加载模块`DataLoader`之前,还存在其他的一些模块,负责例如对文本数据\n", - "\n", - " 进行补零对齐,即 **核对器`collator`模块**,进行分词标注,即 **分词器`tokenizer`模块**\n", - "\n", - " 本节将对`fastNLP`中的核对器`collator`等展开介绍,分词器`tokenizer`将在下一节中详细介绍\n", - "\n", - "在`fastNLP 0.8`中,**核对器`collator`模块负责文本序列的补零对齐**,通过" + "在`fastNLP 0.8`中,在数据加载模块`DataLoader`之前," ] }, { diff --git a/tutorials/fastnlp_tutorial_4.ipynb b/tutorials/fastnlp_tutorial_4.ipynb index 532118b0..3e148bf3 100644 --- a/tutorials/fastnlp_tutorial_4.ipynb +++ b/tutorials/fastnlp_tutorial_4.ipynb @@ -5,21 +5,21 @@ "id": "fdd7ff16", "metadata": {}, "source": [ - "# T4. model 的搭建与 driver 的概念\n", + "# T4. trainer 和 evaluator 的深入介绍(一)\n", "\n", - " 1 fastNLP 中预训练模型的使用\n", + " 1 fastNLP 结合 pytorch 搭建模型\n", " \n", " 1.1 \n", "\n", " 1.2 \n", "\n", - " 2 fastNLP 中使用 Pytorch 搭建模型\n", + " 2 fastNLP 中的 driver 与 device\n", "\n", " 2.1 \n", "\n", " 2.2 \n", "\n", - " 3 fastNLP 中的 driver\n", + " 3 fastNLP 中 trainer 的补充介绍\n", "\n", " 3.1 \n", "\n", @@ -51,7 +51,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.4" + "version": "3.7.13" } }, "nbformat": 4, diff --git a/tutorials/fastnlp_tutorial_5.ipynb b/tutorials/fastnlp_tutorial_5.ipynb new file mode 100644 index 00000000..1e41a36e --- /dev/null +++ b/tutorials/fastnlp_tutorial_5.ipynb @@ -0,0 +1,59 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fdd7ff16", + "metadata": {}, + "source": [ + "# T5. fastNLP 与 paddle 或 jittor 的结合\n", + "\n", + " 1 fastNLP 结合 paddle 训练模型\n", + " \n", + " 1.1 \n", + "\n", + " 1.2 \n", + "\n", + " 2 fastNLP 结合 jittor 训练模型\n", + "\n", + " 2.1 \n", + "\n", + " 2.2 \n", + "\n", + " 3 fastNLP 实现 paddle 与 pytorch 互转\n", + "\n", + " 3.1 \n", + "\n", + " 3.2 " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "08752c5a", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tutorials/fastnlp_tutorial_6.ipynb b/tutorials/fastnlp_tutorial_6.ipynb new file mode 100644 index 00000000..bd4b37ed --- /dev/null +++ b/tutorials/fastnlp_tutorial_6.ipynb @@ -0,0 +1,59 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fdd7ff16", + "metadata": {}, + "source": [ + "# T6. trainer 和 evaluator 的深入介绍(二)\n", + "\n", + " 1 fastNLP 中预定义模型 models\n", + " \n", + " 1.1 \n", + "\n", + " 1.2 \n", + "\n", + " 2 fastNLP 中预定义模型 modules\n", + " \n", + " 2.1 \n", + "\n", + " 2.2 \n", + "\n", + " 3 fastNLP 中的更多 metric 类型\n", + "\n", + " 3.1 \n", + "\n", + " 3.2 " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "08752c5a", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tutorials/fastnlp_tutorial_7.ipynb b/tutorials/fastnlp_tutorial_7.ipynb new file mode 100644 index 00000000..0a7d6922 --- /dev/null +++ b/tutorials/fastnlp_tutorial_7.ipynb @@ -0,0 +1,59 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fdd7ff16", + "metadata": {}, + "source": [ + "# T7. callback 自定义训练过程\n", + "\n", + " 1 \n", + " \n", + " 1.1 \n", + "\n", + " 1.2 \n", + "\n", + " 2 \n", + "\n", + " 2.1 \n", + "\n", + " 2.2 \n", + "\n", + " 3 \n", + "\n", + " 3.1 \n", + "\n", + " 3.2 " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "08752c5a", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tutorials/fastnlp_tutorial_8.ipynb b/tutorials/fastnlp_tutorial_8.ipynb new file mode 100644 index 00000000..0664bc41 --- /dev/null +++ b/tutorials/fastnlp_tutorial_8.ipynb @@ -0,0 +1,59 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fdd7ff16", + "metadata": {}, + "source": [ + "# T8. fastNLP 中的文件读取模块\n", + "\n", + " 1 fastNLP 中的 EmbedLoader 模块\n", + " \n", + " 1.1 \n", + "\n", + " 1.2 \n", + "\n", + " 2 fastNLP 中的 Loader 模块\n", + "\n", + " 2.1 \n", + "\n", + " 2.2 \n", + "\n", + " 3 fastNLP 中的 Pipe 模块\n", + "\n", + " 3.1 \n", + "\n", + " 3.2 " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "08752c5a", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tutorials/fastnlp_tutorial_e1.ipynb b/tutorials/fastnlp_tutorial_e1.ipynb index 6ec04cb4..8897c800 100644 --- a/tutorials/fastnlp_tutorial_e1.ipynb +++ b/tutorials/fastnlp_tutorial_e1.ipynb @@ -6,7 +6,7 @@ "source": [ " 从这篇开始,我们将开启**`fastNLP v0.8 tutorial`的`example`系列**,在接下来的\n", "\n", - " 每篇`tutorial`里,我们将会介绍`fastNLP v0.8`在一些自然语言处理任务上的应用" + " 每篇`tutorial`里,我们将会介绍`fastNLP v0.8`在自然语言处理任务上的应用实例" ] }, { @@ -82,9 +82,9 @@ "\n", " 包含9个数据集,各语料的语言均为英语,涉及多个自然语言理解`NLU`任务,包括\n", "\n", - " **`CoLA`**,文本分类任务,预测单句语法正误分类;**`SST2`**,文本分类任务,预测单句情感二分类\n", + " **`CoLA`**,文本分类任务,预测单句语法正误分类;**`SST-2`**,文本分类任务,预测单句情感二分类\n", "\n", - " **`MRPC`**,句对分类任务,预测句对语义一致性;**`STSB`**,相似度打分任务,预测句对语义相似度回归\n", + " **`MRPC`**,句对分类任务,预测句对语义一致性;**`STS-B`**,相似度打分任务,预测句对语义相似度回归\n", "\n", " **`QQP`**,句对分类任务,预测问题对语义一致性;**`MNLI`**,文本推理任务,预测句对蕴含/矛盾/中立预测\n", "\n", @@ -216,15 +216,15 @@ "\n", " 即使用较小的、不区分大小写的数据集,**对`bert-base`进行知识蒸馏后的版本**,结构上\n", "\n", - " 模型包含1个编码层、6个自注意力层,详解见本篇末尾,更多细节请参考[DistilBert论文](https://arxiv.org/pdf/1910.01108.pdf)\n", + " 包含**1个编码层**、**6个自注意力层**,**参数量`66M`**,详解见本篇末尾,更多请参考[DistilBert论文](https://arxiv.org/pdf/1910.01108.pdf)\n", "\n", - "首先,通过从`transformers`库中导入`AutoTokenizer`模块,使用`from_pretrained`函数初始化\n", + "首先,通过从`transformers`库中导入**`AutoTokenizer`模块**,**使用`from_pretrained`函数初始化**\n", "\n", " 此处的`use_fast`表示是否使用`tokenizer`的快速版本;尝试序列化示例数据,检查加载结果\n", "\n", - " 需要注意的是,处理后返回的两个键值,`'input_ids'`表示原始文本对应的词素编号序列\n", + " 需要注意的是,处理后返回的两个键值,**`'input_ids'`**表示原始文本对应的词素编号序列\n", "\n", - " `'attention_mask'`表示自注意力运算时的掩模(标上`0`的部分对应`padding`的内容" + " **`'attention_mask'`**表示自注意力运算时的掩模(标上`0`的部分对应`padding`的内容" ] }, { diff --git a/tutorials/fastnlp_tutorial_e2.ipynb b/tutorials/fastnlp_tutorial_e2.ipynb index 93143090..c8f4b7dc 100644 --- a/tutorials/fastnlp_tutorial_e2.ipynb +++ b/tutorials/fastnlp_tutorial_e2.ipynb @@ -25,31 +25,53 @@ "\n", " 将首先简单介绍提示学习模型的研究,以及与`fastNLP v0.8`结合的优势\n", "\n", - "**`prompt`**,**提示词、提词器**,最早出自**`PET`**,\n", + "**`prompt`**,**提示词**,最早出自论文[Exploiting Cloze Questions for Few Shot TC and NLI](https://arxiv.org/pdf/2001.07676.pdf)中的**`PET`模型**\n", "\n", - " \n", + " 全称 **`Pattern-Exploiting Training`**,虽然文中并没有提到**`prompt`的说法,但仍视为其开山之作\n", "\n", - "**`prompt-based tuning`**,**基于提示的微调**,描述\n", + " 其大致思路包括,对于文本分类任务,假定输入文本为,后来被称`prompt`,后来被称`verbalizer`,\n", "\n", - " **`prompt-based model`**,**基于提示的模型**\n", + " 其主要贡献在于,\n", "\n", - "**`prompt-based model`**,**基于提示的模型**,举例\n", + "\n", "\n", - " 案例一:**`P-Tuning v1`**\n", + "**`prompt-based tuning`**,**基于提示的微调**,\n", "\n", - " 案例二:**`PromptTuning`**\n", + " xxxx,更多参考[prompt综述](https://arxiv.org/pdf/2107.13586.pdf)\n", "\n", - " 案例三:**`PrefixTuning`**\n", + " 以下列举些经典的`prompt-based tuning`案例,简单地介绍下`prompt-based tuning`的脉络\n", "\n", - " 案例四:**`SoftPrompt`**\n", + " 案例一:**`P-Tuning v1`**,详细内容参考[P-Tuning-v1论文](https://arxiv.org/pdf/2103.10385.pdf)\n", "\n", - "使用`fastNLP v0.8`实现`prompt-based model`的优势\n", + " 其主要贡献在于,\n", "\n", - " \n", + " 其方法大致包括,\n", "\n", - " 本示例仍使用了`tutorial-E1`的`SST2`数据集,将`bert-base-uncased`作为基础模型\n", + " 案例二:**`PromptTuning`**,详细内容参考[PromptTuning论文](https://arxiv.org/pdf/2104.08691.pdf)\n", "\n", - " 在后续实现中,意图通过将连续的`prompt`与`model`拼接,解决`SST2`二分类任务" + " 其主要贡献在于,\n", + "\n", + " 其方法大致包括,\n", + "\n", + " 案例三:**`PrefixTuning`**,详细内容参考[PrefixTuning论文](https://arxiv.org/pdf/2101.00190.pdf)\n", + "\n", + " 其主要贡献在于,\n", + "\n", + " 其方法大致包括,\n", + "\n", + "通过上述介绍可以发现`prompt-based tuning`只是模型微调方式,独立于预训练模型基础`backbone`\n", + "\n", + " 目前,加载预训练模型的主流方法是使用`transformers`模块,而实现微调的框架则\n", + "\n", + " 可以是`pytorch`、`paddle`、`jittor`等,而不同框架间又存在不兼容的问题\n", + "\n", + " 因此,**使用`fastNLP v0.8`实现`prompt-based tuning`**,可以**很好地解决`paddle`等框架**\n", + "\n", + " **和`transformers`模块之间的桥接**(`transformers`模块基于`pytorch`实现)\n", + "\n", + "本示例仍使用了`tutorial-E1`的`SST2`数据集、`distilbert-base-uncased`模型(便于比较\n", + "\n", + " 使用`pytorch`框架,通过将连续的`prompt`与`model`拼接,解决`SST2`二分类任务" ] }, { @@ -98,7 +120,7 @@ "print(transformers.__version__)\n", "\n", "task = 'sst2'\n", - "model_checkpoint = 'bert-base-uncased'" + "model_checkpoint = 'distilbert-base-uncased' # 'bert-base-uncased'" ] }, { @@ -111,20 +133,32 @@ "\n", " 以下首先简述`P-Tuning v2`的论文原理,并由此引出`fastNLP v0.8`的代码实践\n", "\n", - "`P-Tuning v2`出自论文 [Prompt Tuning Can Be Comparable to Fine-tuning Universally Across Scales and Tasks](https://arxiv.org/pdf/2110.07602.pdf)\n", + "**`P-Tuning v2`**出自论文[Prompt Tuning Can Be Comparable to Fine-tuning Universally Across Scales and Tasks](https://arxiv.org/pdf/2110.07602.pdf)\n", + "\n", + " 其主要贡献在于,**在`PrefixTuning`等深度提示学习基础上**,**提升了其在分类标注等`NLU`任务的表现**\n", + "\n", + " 并使之在中等规模模型,主要是**参数量在`100M-1B`区间的模型上**,**获得与全参数微调相同的效果**\n", + "\n", + " 其结构如图所示,通过**在输入序列的分类符`[CLS]`之前**,**加入前缀序列**(**序号对应嵌入是待训练的连续值向量**\n", + "\n", + " **刺激模型在新任务下**,从`[CLS]`对应位置,**输出符合微调任务的输出**,从而达到适应微调任务的目的\n", + "\n", + "\n", "\n", - " 其主要贡献在于,在`PrefixTuning`等深度提示学习基础上,提升了其在分类标注等`NLU`任务的表现\n", + "本示例使用`bert-base-uncased`模型,作为`P-Tuning v2`的基础`backbone`,设置`requires_grad=False`\n", "\n", - " 并使之在中等规模模型,主要是参数量在`100M-1B`区间的模型上,获得与全参数微调相同的效果\n", + " 固定其参数不参与训练,**设置`pre_seq_len`长的`prefix_tokens`作为输入的提示前缀序列**\n", "\n", - " 其结构如图所示,\n", + " **使用基于`nn.Embedding`的`prefix_encoder`为提示前缀嵌入**,通过`get_prompt`函数获取,再将之\n", "\n", - "" + " 拼接至批量内每笔数据前得到`inputs_embeds`,同时更新自注意力掩模`attention_mask`\n", + "\n", + " 将`inputs_embeds`、`attention_mask`和`labels`输入`backbone`,**得到输出包括`loss`和`logits`**" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -178,24 +212,24 @@ "source": [ "接着,通过确定分类数量初始化模型实例,同时调用`torch.optim.AdamW`模块初始化优化器\n", "\n", - " 根据`P-Tuning v2`论文:*Generally, simple classification tasks prefer shorter prompts (less than 20)*\n", + " 根据`P-Tuning v2`论文:*`Generally, simple classification tasks prefer shorter prompts (less than 20)`*\n", "\n", " 此处`pre_seq_len`参数设定为`20`,学习率相应做出调整,其他内容和`tutorial-E1`中的内容一致" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "Some weights of the model checkpoint at bert-base-uncased were not used when initializing BertForSequenceClassification: ['cls.predictions.transform.dense.bias', 'cls.predictions.decoder.weight', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.LayerNorm.bias', 'cls.seq_relationship.weight', 'cls.predictions.transform.dense.weight', 'cls.predictions.bias', 'cls.seq_relationship.bias']\n", - "- This IS expected if you are initializing BertForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n", - "- This IS NOT expected if you are initializing BertForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n", - "Some weights of BertForSequenceClassification were not initialized from the model checkpoint at bert-base-uncased and are newly initialized: ['classifier.bias', 'classifier.weight']\n", + "Some weights of the model checkpoint at distilbert-base-uncased were not used when initializing DistilBertForSequenceClassification: ['vocab_layer_norm.bias', 'vocab_layer_norm.weight', 'vocab_projector.weight', 'vocab_transform.bias', 'vocab_transform.weight', 'vocab_projector.bias']\n", + "- This IS expected if you are initializing DistilBertForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n", + "- This IS NOT expected if you are initializing DistilBertForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n", + "Some weights of DistilBertForSequenceClassification were not initialized from the model checkpoint at distilbert-base-uncased and are newly initialized: ['pre_classifier.weight', 'classifier.weight', 'pre_classifier.bias', 'classifier.bias']\n", "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n" ] } @@ -225,7 +259,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": { "scrolled": false }, @@ -240,7 +274,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "b72eeebd34354a88a99b2e07ec9a86df", + "model_id": "21cbd92c3397497d84dc10f017ec96f4", "version_major": 2, "version_minor": 0 }, @@ -262,30 +296,17 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "Loading cached processed dataset at /remote-home/xrliu/.cache/huggingface/datasets/glue/sst2/1.0.0/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad/cache-18ec0e709f05e61e.arrow\n", - "Loading cached processed dataset at /remote-home/xrliu/.cache/huggingface/datasets/glue/sst2/1.0.0/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad/cache-e2f02ee7442ad73e.arrow\n" + "Loading cached processed dataset at /remote-home/xrliu/.cache/huggingface/datasets/glue/sst2/1.0.0/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad/cache-294e481a713c5754.arrow\n", + "Loading cached processed dataset at /remote-home/xrliu/.cache/huggingface/datasets/glue/sst2/1.0.0/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad/cache-ed9d9258aaf0fb54.arrow\n", + "Loading cached processed dataset at /remote-home/xrliu/.cache/huggingface/datasets/glue/sst2/1.0.0/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad/cache-f44c5576b89f9e6b.arrow\n" ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d15505d825b34f649b719f1ff0d56114", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/2 [00:00, ?ba/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" } ], "source": [ @@ -308,7 +329,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -353,7 +374,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -369,31 +390,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - " " + "最后,使用之前完成的`dataloader_train`和`dataloader_valid`,定义训练模块`trainer`" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...\n", - "To disable this warning, you can either:\n", - "\t- Avoid using `tokenizers` before the fork if possible\n", - "\t- Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)\n" - ] - } - ], + "outputs": [], "source": [ "trainer = Trainer(\n", " model=model,\n", " driver='torch',\n", - " device=[0, 1],\n", - " n_epochs=20,\n", + " device=1, # [0, 1],\n", + " n_epochs=10,\n", " optimizers=optimizers,\n", " train_dataloader=dataloader_train,\n", " evaluate_dataloaders=dataloader_valid,\n", @@ -405,14 +415,559 @@ "cell_type": "markdown", "metadata": {}, "source": [ - " " + " 使用`trainer.run`方法训练模型,同样每次只对验证集中的`10`个`batch`进行评估" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
[22:53:00] INFO Running evaluator sanity check for 2 batches. trainer.py:592\n", + "\n" + ], + "text/plain": [ + "\u001b[2;36m[22:53:00]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Running evaluator sanity check for \u001b[1;36m2\u001b[0m batches. \u001b]8;id=406635;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=951504;file://../fastNLP/core/controllers/trainer.py#592\u001b\\\u001b[2m592\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n" + ], + "text/plain": [] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:1, Batch:0 -----------------------------\n", + "\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m1\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n", + " \"acc#acc\": 0.540625,\n", + " \"total#acc\": 320.0,\n", + " \"correct#acc\": 173.0\n", + "}\n", + "\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.540625\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m173.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:2, Batch:0 -----------------------------\n", + "\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m2\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n", + " \"acc#acc\": 0.5,\n", + " \"total#acc\": 320.0,\n", + " \"correct#acc\": 160.0\n", + "}\n", + "\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.5\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m160.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:3, Batch:0 -----------------------------\n", + "\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m3\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n", + " \"acc#acc\": 0.509375,\n", + " \"total#acc\": 320.0,\n", + " \"correct#acc\": 163.0\n", + "}\n", + "\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.509375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m163.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:4, Batch:0 -----------------------------\n", + "\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m4\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n", + " \"acc#acc\": 0.634375,\n", + " \"total#acc\": 320.0,\n", + " \"correct#acc\": 203.0\n", + "}\n", + "\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.634375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m203.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:5, Batch:0 -----------------------------\n", + "\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m5\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n", + " \"acc#acc\": 0.6125,\n", + " \"total#acc\": 320.0,\n", + " \"correct#acc\": 196.0\n", + "}\n", + "\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.6125\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m196.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:6, Batch:0 -----------------------------\n", + "\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m6\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n", + " \"acc#acc\": 0.675,\n", + " \"total#acc\": 320.0,\n", + " \"correct#acc\": 216.0\n", + "}\n", + "\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.675\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m216.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:7, Batch:0 -----------------------------\n", + "\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m7\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n", + " \"acc#acc\": 0.64375,\n", + " \"total#acc\": 320.0,\n", + " \"correct#acc\": 206.0\n", + "}\n", + "\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.64375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m206.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:8, Batch:0 -----------------------------\n", + "\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m8\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n", + " \"acc#acc\": 0.665625,\n", + " \"total#acc\": 320.0,\n", + " \"correct#acc\": 213.0\n", + "}\n", + "\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.665625\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m213.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:9, Batch:0 -----------------------------\n", + "\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m9\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n", + " \"acc#acc\": 0.659375,\n", + " \"total#acc\": 320.0,\n", + " \"correct#acc\": 211.0\n", + "}\n", + "\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.659375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m211.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
---------------------------- Eval. results on Epoch:10, Batch:0 -----------------------------\n", + "\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m10\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n", + " \"acc#acc\": 0.696875,\n", + " \"total#acc\": 320.0,\n", + " \"correct#acc\": 223.0\n", + "}\n", + "\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.696875\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m223.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n" + ], + "text/plain": [] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "trainer.run(num_eval_batch_per_dl=10)" ] @@ -421,14 +976,55 @@ "cell_type": "markdown", "metadata": {}, "source": [ - " " + "可以发现,其效果远远逊色于`fine-tuning`,这是因为`P-Tuning v2`虽然能够适应参数量\n", + "\n", + " 在`100M-1B`区间的模型,但是,**`distilbert-base`的参数量仅为`66M`**,无法触及其下限\n", + "\n", + "另一方面,**`fastNLP v0.8`不支持`jupyter`多卡**,所以无法在笔者的电脑/服务器上,完成\n", + "\n", + " 合适规模模型的学习,例如`110M`的`bert-base`模型,以及`340M`的`bert-large`模型" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n" + ], + "text/plain": [] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "{'acc#acc': 0.737385, 'total#acc': 872.0, 'correct#acc': 643.0}" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "trainer.evaluator.run()" ] diff --git a/tutorials/figures/E2-fig-pet-model.png b/tutorials/figures/E2-fig-pet-model.png new file mode 100644 index 0000000000000000000000000000000000000000..c3c377c08a0ba3199cca4fb3610aa0ad08ce41fb GIT binary patch literal 57162 zcmbrl1yEc~_cs_LcyKa!aF+oB1bwgpf&~r1VQ_bsBsdK25(uurHCV8j;1+`G1a}>r zy?NiieOq6BTf1Au6m`4$p6=7fPycSjI~6%xEOM+zj~?MF$jhiddh`SW{4g<|10(-T zo=gG%9=oc`Nj<6@q1*-@o>@vNOFnv36N`Oof(ATeI>~=
V;(cc zKfT!RRYAN=@s8F{O!01lH^8jW-t3XtVfj652;H{sRmf{Wn~F_F0d~l*kDxMMY~GM^ zW*jmfdHxs4zsHbDzo-D11P-|hJz1ot^{|!-i}lT>+sO= z`mlbo{8~eL8+`d|E&Fy^m$z>f@l&bTZDeqi)6vMfwTRR|`a~C$ n(2bVJz$f$wS=}RNh^D &4Kz&o<}U!&%BIX{4uj;$)N7v+aYK74V3b#Kl`VxZk4=2 zq+-jVwIoyLBQq%v(X~3HTTyS83;?W&d!JQ2E=&;mSkEbmGkB1&?k_lJW^;6iZBVYj zk8V-w{|Gz^*6r= 3X=X>&gNrI8;&Vc~1l4-dx(nk#6N!y+3%N?BPpkqLlEIK-5cu+Y9u z69#}#4X>aK{s0b2-E8cuq~Cmx56ngyxK0M~S>Ocjt@TBPV3_Ox=%` Fsn2?{2ewgWFibkK>Ip{QxD!G z(i4hHME5#B25ee=0iy~$`J+H9mB#x&m(MFGcs44AqFg>$`0lP4{u}lkZgq39e|s$E zdqGV1zY=8}`67a7dgIu39Ex8` rBPs?qm{=G8QR};X}P&ofh92hy#&FtT=tF8oY5vhA|@q#x-zww zz @1$yXuAv;CR*8TY z60G|dhbHxs@{LQdqwSJE%78Xc*!?xct~?$=6POkFt+==tpAi7Y{MSsk!=*2dwigGB z>@u3gmGJQ6LGI3@sxPA6wE)Hco;QDaeSNY&1dSC7U0BekEfYQmL%O=U{JK%}v7(=c zl;*5v|9hwPxbtK=4SaPL!-RA@YBbPZ ;|KMdCneIl@l;`*=|CMw&e(-8s zVqy>}r|!`{EGH)iUn};SJfF{U ?A zX%(1_iwlw|V1MZ U?)&4UCDW zm%{?&^*?87E-WryU91CCH>Sa5>=`@|Fc@52UHwl!BswljX?`<}@PFu9=)mPM^6J8T zwL3(rz`?2;1inTcj^ Pf?csPEZyR-)U z=g3Hm#3*pku!s8_Ko{UI{!`rmxzN^{^gQpd-(GBO!Y>uc;Drp~fHitY+}8(4Xy1ZF z{&N=&a?8EjUy0=V6$$8` QCOSn-MJLlq{!JuE9L>+-ZlmS%P>HrV+;EcltERl@pU z>Z$#}N>@;b{M~px*wk%rCSGE5d$JgC3>E(tEdaF4_`FV3(?<8Zs9Ka>ITsh&JJL7O zFObFvqxdfdG^)w0D#T3qCio)+U}_c?Ow`_g2-4EiX@!JzfJ6LmgJQit+wN&%-kq*` zNtYo>0S^azpP1dZxo(b-&;^4{3E?I61v_V>`X64H<+8S&Ot^$ty=f_3U%w*rma5On zO4`d9OdK4 rv&)aF z5&`n|o!R+qmu%ZO_ge2 Vk XWPoShfL7dNzu%4m{<)#2R;55Li-A3e(5M&s!I& zYN=$w>-^B5_uJ%3OV&HdH4UG0bAu+8c)iAx9(e5{%8q0m)3630R(@(nysm(U1V&RW zbF`C+pQk#0Wf6pMi{H29>F;d>I;^S5zTvY@e#5sBmnWLam!ACQja_G6+p9X8r*3v* zhO#YbHFftMsd;U+HKvfah8ByS#rT|IWRl)j N$SgBxQlw`X;B!Vx ztE=K6Rg|}|5k@bi={Ytq9ZdV T1kk-DAK%j9zJGn)uT!qJ5i4omVv~(vZa*+J9kass2DN-p8KM9Qk_Zh zKyyWFF3V^**WpGAMSiMYX90_4k56*TUDKC5{h`YReIEriE&*cehj}#FmYH{JQ%0k# z1AU< T!9xfBn5VWN*?L01|5+dUN4ton>7ANGXZ6kn+R)GbK}U`j2H*&L z>Q7Ge0<{(cx4X}XZc!=c9z~%^nd-`t@bED~z+WQg ^Fz52>>eyaB zij)(G3iL9sqZ*^tjE!Ff-fs+N(zCNG0*3ziPc%X1V&93(Omy&2`~^URqSxZY8Vhg~ z;_0t#NtZ*1(!kQ;R@C+s^pMePu`AR}hkq-uGFm@He(PI>F^;N`F;OGGV>I1HyZ+sA zIhu8frvk&;)X)j-RH0n&Ea(?w3ZECXev8~B|D*}Dw6u8b)gUefdZ(Lq3P_Z5v7v52 z`f)F|MLT{O*9JZj+5eW-MSMs?FN3M<0=Vgp$0aKJa}Cmxl2gyDrCh7i-A(JzF{R$_ zEw-jQ@_qL_ zz`++S9{U;H7_8;?^NlR5Mq`LN_P<9!MSbo0d-w8$9-PX{F?;0BH>H5HSeKxQO{(zGGpmN7H+i_$}oN^B~FM z` vujkXFyWnTN8zfx4!MyJLUYp>>1?eKsBY;c2gEiHPM=w z!`(`8wXE065BJPT00v)kv`9G @+dLjS<6knm_=;~059OMa)y9mCZ%rQiEv1jY)%rWHChp94ETJw?YNkQ(?K zlT3kp)9 YULPv|kz`l!SM zG2NWpG(0>v)`xKJQ$iJHg9*hywIOpDiz|)W0xGehKiNm}@9QRjsQX>YNR0IwC}Xq1 zy4^B=lZ#<9V`2DAdb)S*y(X!ND+CzJ7PG)gq8)ZDDyI41bjj3J!M|3j>>O38zMm zz4#m7o!#9FtxJW2fy`R=?2VqH5nNvU=AgW)gOD!xZw80|T*XA?F%T2Itxc!>0U>gY zZC;CC^FqkT$b=25BF0`M2ta^%Cyy!rM=MS?GmS8q4cLm?CqLOOAc4muSj^=H@?s%p zx`(CjI;)xgn$K^L^Xk{8N}I?Y9T&Y=&V>PeeUKks4U=-lmN_2SpPb&{08`Eiofq zqP(fOfEZ1d@h5Zq4(o*&8wZyp@I6CPtZW+PiNPiUMn*5=79}1{fNV!CA(xl`S^&Pf z)CBzJ?njZzTfda|d5&%PT6iAF0ZtZ(j|y!>0g3qr=?NqPhtLFzn1m!3*kl{n$=R78 z@4M_WJe*G02^>Zy6fWDWaC9Dl~@K1=|(KelJjpPyKK^*-JB zIWRz&_Z@)`BhY)6YS5D(D;~MGXGi;1{&6CJwJR*l6J#e;NF5kpC+vuC(9nMe>t2vD zEOZA&(qkBaEk`JqaFj9yl*6~srFkGYjsAqKF<(SH0rkcL)U!~oKW>W%QT~e0DEzmQ zia4WgB964InF|Iz9XB`LH{FJ{=pR635nK|$LktD-HSoRglJ_PRVAhWnDCpgbcT?|C zIa|1q0H3v|T8FPE7+#DwIWcV!17D^DV@UqW0cw|1rmuQU4pK6Kphz$q2S@Lus>HBS zRAy!-J|oWG&Ok^XKMcalu?@wN04%~PsM4VI |i+VKp<6r04O#8@SpxfZ~7A;Q^z2 5{{fx|C((AfxO{@N4;G>zj=1N>v~RGo+`dd;N)*yQEqV3JMA-2>|m$&1`K4 zjYe&&+9B*KijR09uh|H0o=c$d9bntv-^ygYWeMh>$L$gysWucNGstQD=V?^&(Q&se z#vq|@doDXozzt+IS=)ZxbzQ6=oLag}q4tOSWwXgsejZ=Ko> *FWb!f z7l}CyyMD3nEE8+J=Q?n>r^;;mbr}E3`op-$SUCZTipMbwvvCKnxYQIjGbhU^%h<+$ zT(9t#TgUcu(!d@G*A3XeR|O5Ga&J~yAFXr&^^_)qJq$?H!%xH4l5?_|Wy*`W;6J^` zMS#25Gnh!)^mxKetzI7TbF1#Ib41HA#rJwYyiV^pFt1Smh>4r6D}OccygWJbE~DsJ zsVyv1Z8}~pj!On3&jBbIPXup(a{g;`vrhO9jWj<56BE;Frka+6laqkPs7ZMgbMcim zwBW$af0!cwMrW*L2;{EoX0!k*WbB?_XH%II?%@+|wRuzgD;QtMu%Smb^-*yDNjw9) z1lQ_4HICmWU%bJQG+UZaKdP-{7&hN~`D+#SOy510nmIDmCC=iWUkU#5^0RqzEKw5a z)0eSFC;FvBZoy%)&WDVZUv+Xlm8Ot?2HpleP@!juITIo(7v$c#PiuUuB{)8MVK-_B zch7moz}iPopO?HOLT(b#BK3iKEpOd?JX|Tcvq(t+{K=`=jas1Tjv!mRrb6ih#?g@^ z59-5!DfLSCwxSbGVos(;kzhbz>dg)RZWtBjK$V6v5MrL?vO;1g`zhiI6;rVYdVb(X z6F`5)(cZe>olhG95|Q}{nkvcozvHWwV{shNH%$IHJOumf@WZyQ*r;p#o)|Fc^=LRh z9fA9oD{S4*;^~<9QzI@oBs*iijr;tR?5#Pe_nqP2)^qb2pu`=bmP2r(=RW)}(Q)Ha z*!CYFK^?IPa8t&P3fD{JZ!&dVUs#;^mSR3goAEkMp%J}!j`f_2N__ePdK|p8b*V|u ze{Ug37jjx4eu-{C<4tOCje`guhk_HV|4e)B6L@5YZXHc>imT~OA$7Pkde5h}9y~11 zJ~UH=#Zvu9__RNsXJAy}^j1SZP&x9r8m=02o%b-aoyLFS+IAbxNd2&^sdMF& 6jC)GCbUjdX1RO;SN1tWcYbGUDSg-Q}>&K6RP?N(=bzG6)}xtYfA*iIzEp<{9(-> zM<&Y|U-h=8dHu){)c-%?t38Wu=gej%AJlZ(c&Hj}D8zt3?53ci0s-0)#wI48($YY* zHXu+L_`CNhQ=q}$Y*RrY0`RQ3fPc<`qMV`qjE4P>Bc$qmcAx-+gFMRKqsgi7o{1}4 zB7##9zP4D*F Y~;aYr{tDHk9J%@6H9uLBbgmpeQ0!IU^t zAn@Pri_!em=_XKSTD?1Qk7g5uSPUD%eZ|Ck5Q|IFi1+g=Y9oF+;>RzpM;9Yc@z`<6 z7!BaTFEjF|Q>=2Q^OOi$Z*t#waz#yVuKMWGs#CsP!5w7sdWgMQ-=LdBXD2 KAzyO=c}@UnRTT)4-~ecbDXcf z@H=I&Bq#5Pv3{9I;;a>`82cvjFsJsPI@CH-XyP7kfR*iwsP`7D30wFn`qtIyXLK2X zE$z2_CXqE#IU8BybzV;;7P(rVe>hU{yGtV*%BI9A-#US6P?E0PIW~5ydihuE6N@h2 z+S=i0P$ww$UN~mD;-;Vp-|p!PD5cs(-^aQfj@L75qiYKKrN^#Bw~v)Q c-K9MvJHg%KFgxpH9B2h(F(}n2bt3ydri>-OC#VTGm?PS#!S1fHNE3n{o zzDwf)m4$G^ma8&**o*vSdR*iC1+y7V^0^3c{-i_m8b3#}1B`YGh4&UKA#dR&pLv67 z8o2dpztYaBHW5jLmZl)pp-_CL&TJS+h%zl2rI*cJ7r`VU6+D1C40@!&mFphuqc^ z%UL8*8%o8}ZSPFHh*Fg#CUy04rjf^SjMB&si{zd qIvXWmd2(H9!!Khx{no1a>>?AWrNF4PM%}t zb?CRagmkv>xtfLVo&cu>glXx?BIT>8>Yko$Nd!JER5Ra3p<^Tx{+}>UcaEq{daIt7 zR#r>Tq4qYJ9beFCb|bukM*CNnklT1*lS~S_Bwq->6-@o`F5=;Xz{fsYS7)uQ!qQpL zdXMG%K+(RTU$%VCD&qXw2&8)cf$`ztB-mre)J~}GY0rFG4~!4OY{NrUTRnVPk^3f_ z%CVf^?0tKJ!$ahBi?D#tgJUz_X{yun{8p7NYwtrcl%O8UTl(Pe_2Xh2UNa>&^8A9` zQ?Q5fyO1SGtwQzKafx4084#)6C9L6tozO5o*bKN+kO&YB^v5RUz^4nQm4uf-rcD0> z2ibD+9E(0F7M=ZjzDW@L(oX~SR&Y?hsXc9?9hbc3l;0}yedu9W@ohW6pV?#Et3C|Q zH wOVp8WBf&+nBxjMki*3MjY-OC@Wg=}oT51ft)ke}E zWKaawB KRb-(|LVWK_kpqAY-;O^#-WKMZA?2m^no_Qpj#sff?Y S#agIv@a1VR9I}E&iO)ci531s@83!>w>igrb~_B4Cm=@NV3`F*!z`F3ul zgDox3`+&PO4&zfK-9NhPSc%-F=o2>Gj KDa8n-OX2V zz!xvy`_0AiL8!o^vetK5JDT4BQ1+(8;&`)(+z?4ZaylV5HhgQ>fMiJa$EVx{cc*g) z0KRvNpQ}Gxt=IfW`?jdAj4~BFwa=h=bnHphP=~>iYoZTfPc~1`>?G8=Vq#8;B#8tz zC6?)o8;+Ju;evt3c8i pB;Gm7IJ5 z@@J9hUtw51OS)*wwHd3%{T^)qOU`V9o+nse?tJ3{IrF4Rq?`jE z-R(_Ui%=da3`3Y+D;k rQ!PHHJSLz)yWTZPx>L4>X>bcFa93 zq4#=cp5Z4@`EbI-F`WJ5 GEw;_~_+QvIR0rqt|1G!;XaN`W z0#_4P%gR6#G$h=F4#2$r$L-Yg)zPXnPysyw8Xy71?Ov|Ey`fV!((cftup8$0tEmdh zD `@R*dx45x7 zt`d}sn!bkKN7SM{n+3DRbgl+@RDDHm5*^PM1y#?T3qsDfK8?>GXr*0Kxn8|=Gt-!S z10CD>7C*D0wS?4={S1I 9Zi_7Pj+#!r}H_G2BsEK7GXrmk`e5~P0;>NF>V+*L6y zBd5Oh+g^HfL9#9sdi#$@Pc6nOrYJ7!N1L{W%ej5dy=baL9WVzyQ@h0YwEB?EsL0kB zw8iYtXudR28&;_8|BJA*42Y_0+qNyGbayv0q#~h|ba#y~ba#hJ!ywWr+;lh6p~TSL z2-4EhUEdn-=Xu}v-}gsFahTbA?X|9ToyU1DxgAH$AGd}j7gM@|H^jbG;bl66ftB`M zmL$UF^HS$*uVN m@FqRqDwV>Yny=6_|oaShpHp=fk+% >J90cJ|GSjuhtE3)9mWmY2| z!`Ds7o?p}=H;s+t4~GGY(pG4ZGI8j>t5e&_YwD0 ?)Qj)3+M z_V!yE44}v%a!I1gq=Oid#bn}ZHx57Cbfn-4(aSc16U{fet(Uogo{?z4Fh7WSknaiJ zC+C*5VO(M(ru7FEK)1z-3mJKNuqNCq0ILM42)gtP4RwJg*5JZ-At9l_{3RNCnDc5k z_N~qg8*dvY70lQ;I?%Qw?-}VoKVT2bStYNDqL-v7d!~eYFc- Na8AM14tYebfXv*vCk3O}`1}<2cvV#vo>d4zz`RR3ma_{i}!(IOFB{}9B zTvqJnuFm!dX@VkR;n=X->x=7?+x>P-@DUlo<20LIsz_s@2|kHf*Uz6RtroSG6KEbD z9-`yrQOOWAbo3S6pEDGeo12@WvBQMMa49;WFgUj1hTK Kd%1W((HV9Wu9T?%y{NiQJOn4;w5PXM^yv4% z1*z-%_y1t=dS{!%k#GR?2)q_(68OCBnWBrP0ON4<*xBckQrzy(+9UpL(7DwMk$T8X zk`*0|Q*AZ%x%E#9za5&gDCHMOp(LsU*q(n5Oh^=6#!6M8x)i{XCI?dsMiL+{4*0h~ z3lR<5f=UAD(KXh@e)D3%&w(&03^ }aorvaOi1Tl><5Zo}GD331;mYT7^rGr9 zFG+?>RS8!=#wg1#U=*w^q`ZU}Q ! zH6GhJBBVGT7KW2K`nDI*{p(j+>nWju`~94p20KcWP*U1m#i=q7wLsf3L6CK^#K$E` zcOn7Qeeuas{l10N)~i3SscG1=t>L# #^>7QJ?V4&BgwzWQ&o=E&`?G6=*$QbJz7_Yl&*_ZE;*nddK zrl;gvO0BEEM3fXUz5izCS2-&5)|DXdQ&pW49@X3mN$zzM39XyQcL?Vb+tTNWSFB#U zmKeVl;jatYt{fzHCLyfHUt1odbDXyi@Zaky!8F1;yY+Fqq$%h 3Lu`%$;rwlr+O*6>xs^$(o0_$ngl zpEx4RwMcVc%4%=-)H!y&bxXOL(3PPi68ncMuW*k$KZV!D{rC*)4ca~sB6@@9rpo^J zvE-5zm&YJ``Gp@J5Kve&qheb?^Ed4$YI)vzbDDxh?fe*w`<%zH4(8bdyp|LV*Fgin zxexCcz>a8f`K>o|(-dJVG?0{=+v2U(O(c71uh+*>?}}B%r9|k9#V2;|XjtACUzWc$ z*9tA#dd^+xiRcid)ZDKc3Zl`QmeU~E3*RMd`@*J&DeXrC_AEGuo68X-yrL@6&SvZ+ z{t!nOm$mKve(oVD+xkZZVxVHP=pxGLdr rZ%)8> z4O*q0JR!@ac&@xP-}7-w{x#b#M}m~p<-UG-NrBYJIOzJ6Zj(DK)_ID+|ItH)XW}J? z(8mb=Hf#hbB$`?ZAGZ2eJrek<9&raeFutuzv45%^_-$yFPA**J?mDKG7?V;MOkub% zPD$j1cXaa7_qq;Ts{6=GMGvYTbj{B485xY(m0 0 zt;}A5((_LgbM2?ilZof+_xo?XVvL9sY~iEaD-O=>h(nh|_mU1bKPV!HslqARncasD ziW@*=EgM#2^Yf5@8OUhp$`(d!z^C$=+*?TaYKNOzbmIY7W$La*ydUtXx*FwTl~A-p zBm{^(`v%@Qh zvVg=Qc)5|~t$%%U6UdZd16t3=EuWQz;MlTl!cC?TZTU=&VO(t$OKulC)x3!|ng^+s z?v&Tm{RUUwe~9(u3>_dawGY$x{9d96i4~wKzx29h3hJqSnPeD2dw?^y$IeRbMy6kW zR*5MXlhX<%C#G#vI^QZPJ15--dS*a~Glbw@stlSiQ)PyZE&3BVhh6Nev=a?9CH5yJ z>YdM_2b38RXt}Vw=_rZW=v%)RH$(@k8e46*PQP=;F~g0uyPdPziCkn|@@&y^eynhP zrPega1?%V^eS2*$D9YT^aL-V|Y+uN0DCwO8moh~{*x{1LBpMX`WTy(De%Ne)T!yK5 zc<@Y3P0c5ZiMhDA0`i?9zyP-R<6#R2yKarRt!*h5eRXJdgz`SV-`vdaZdSmufO-IA z_uy)}CanJ{pV61q>m}4SR$Z{Ez0=h|6zui(y|h1NGu=HE&1d1?i4E4`i}c#vp?yi9 zYWpGDXNS}A5)EVe1goOA%PFkMfvg#SstVOf!DI2!Sz63`N$0xgbss*z{Qy4!#roMw zU;6VOEal#QwZ VL^|Nepg3bJ%2l-M}+T=z5dd+Neu z=3aWuOG<60Ll KqwKou&lIK_x!f`*2+zZ#=>$Zvp&iAl|310NtF z7jO 5c THmbX`Z(TrTh`=9 zj|Luv$3p0H6Nnq!wRzVpOx92 v45U^q#~M}oV=Dl z19C1d&1ly&9GkmLQSjgqG!ImrKuy;LI$YE-lRA9l>#joi#S%){`PB%J=Y}6d25?dO zT|@lZd2#TpP{NF8NKSXli)xLh(RNA%=^@PXIdN&yR)R!=EDpA~R6_R=2--9GOy!nm+`s z^>2CGgvgAwco`X&^ld;8y(cGSs}RcBY2BerWGw2)mZ9Rh z5kDi2G-YqEs*QZ+T&%URc+LTf$^kDgAave09Sy#|el|(O&%~<%>o^CM|9OM7PZspA z%t^dsO6M9w1J>_J{{pms^+bC&w{^QxMUfkxurRpYh!TuXvZA8mzkFkCEFE|gMvjR5 z@;bF+1__!?72;Gia>=o32%0?RN4H8s$1q0#Vp;+@_A~!;z~ZBf5Z}68q0i+pHVq=U zf|S-3(`zkG^IX87#alZBCmAUJOuer#guDJ6^}?kIGYjAT4#~!hVx~DpwK_BK+U30s z@?2_rOl|2+)Ce#S?W&-%6}JT+MsXB*>c6_)O>ep6r}=y?r%pQ~y6D{4uh8s-PBK){ zB=Cce_{Y}M{eI;KznA+#l#`wPkHZSWo5t1I`KA_)rWaxXqYEa^&RkaUy)WhZ5cWz6 zz~FH)P&hycVwIlX%U~QGV?E8rq!3Kx#{haJAq^sw8K64(%30^0x1d%P&4%~-xrqva zu}EVZ{2kDF2E-#4pq7V+?{vs@i>kWg|Hea6{*+J7XN|B;Q&3O{iHr>XPeC8>Xho-x znu`l37?V;%s>KB{T>)e5h#253Z)Ghq+ny{@*3v@J)zuYt>rXuDa{egI0M_2v;bZ5U z%xD_CSiFCZMYejlT!pXq#cmNj$DlgdzcW#7j)>^*mlHhbzzu5%D*(Xc^~Q&agUju* zqZ6;g9!7kZo26jN0F_J*@KmBa3?^`=+v)|B2_C;}{j}N*vuf`5zCPKPy)U(DZS~_C zShfMr(-wvJF_6L!G496loeAu9(FeN-dpu=Apfy|mXeb6xc|;Po82}T0&eb}$BZ)eC z!4UjRmtc6*Ca1%42MfQviF_jG+m|YrtLy74_3LT4C1!vD4$R8NB;~r=sTvaBW}X6N zX<$}p0|@U_LZ_spybYczP-O(X0uT;z{RLlX%I(|_e)g6aS2msvyJUML>s=r%+#fLP zod#}3T&Js^HnbP3R(oP@?#hSXZ2tw?lb%0(`n=e2%s3e^Wim2wJNc3?U%s%o*o Wu0ro-`mJPxg0F2MZB&Ho(0;NTP<5(&{-;^v< znHW>KiJfS;NHw-6iZlZ+xo&{8-i9r%|Gy}5xAO+_-H|fLBKS_5ztz|+7-S3r`W{CH z9s`P#rn6sO_*;TDvpgBG`RHJWtE^xx`^Bqid>$ttpVS!cjCp0tc*VHS(%nn=?={>9 zBaPKIp3SiKpYP{WKcah#%>k?gT?ad?A53{0nhdXAX;)03 geM=vEL1f|+yEU1h>1)(^O1ik=$ zJ}LxaQ35viM`d3eG?p_mFrZ m_JzC%9e*2vR$gJDRNr|I*Uf0X**K z`_$ >*;NGNfcnfu9+2MyNH2VVaF5e&z{R#90fCOW&j_OY#OBkeuHz7F* 4lqll2)?QM#`;jRIY|B}lYq+o$KH*m;pn=5RmDISPPAY3N|pysqA z!{K3cn-QQ-1H?iyo2u)!Sf-b1KjE+4#cjFvzHX$r@T%G_#wdzxN}Z_U+By1?5I#>j zz0Ul?EZxZjtrG2DdN%)0xBP%|liw$|i5qOE=qmiRP+^DvV#cHGg&v{W2gG5As~-wO zFRVkcJUnE+Y@P_p0JQ8y^#ZY-!49UpIf&V8U=$J!dQ_%ma6x>sFiTa-M5rC8&BV;x z!VXBY#?1=$h>r5Fj(P`+j5TXf1DKOxj;^%D{hP{9@z*>m3uU=ei7FM94HETTe6q40 zo-*~alCqi#%7ks5-7vE=OPmi-1x#O{M>$TPbT6dno0$ME41X=}9R*(InlYm(bMMgS zT0piM+w=Q+TwE}B0ZiAzkU8uyoLdo~#2vyfTnvBjEJ-UW!`k~3uW#&b9i&6zao5Ol zncTE|)xjTqxwVx4H2rSCVrM+I{E#{4A~x}u)1O0FEp}n%HxuAg5hIBit5!%a#wG=* zYw{jboM1K{7~F2cm-krEOOi2R-GJdL?8A`WHxZ%Eq$o~U->GZAu2+2i6PnZ2Hykk% zL7!l6c!@gli%fn0l_zG`)7`ZpyVhZika*;OC0 K>;s~l?FC(8zXqYnaNpX~hhJ(+T (OW2_JU6)Ul*jM=|vVzI U3yM;JZRN0fz}wlnVA_9PeKCdc5nmV z3lj-AGcY>5OdjSz)^r c0I}AY8j^6LA1N8h&H!6pG8Y{K%R0u_ z??=LQTxV>h?1GU}c}mol0_D`=jZo`zdR{Hzq=FxwZPTN;)+6r<26@y#p{>lCk&ywA zsf>JTqf4+F2hgJ0e4q3%+|J<)-L(=Y5~0tz%c#p%+h$oZHs|Ma6{62so+`4a7@8S= ze?r)(VUs_8Z@UZ=lmjdfpG#-pAYI+kaWT>UM75=;?7)mn!cJ4o=Qdd-plK}^-+L0; z?Dtj~m8*UmyHUX=)aO?qP0H35iN;-1n~`ydUKU^6S7=8HohouxkC>{Qp^!83dWM}$ zOGWi&9IqMpZQ4L!w>gd}T8FJ(gUWL^|M7%ZMtdo`N^G9`4LIDvm!Bq}Q$cl=VRF-C z(z8S(&OY;Pa!Mw!YLh;K3;+*9v<}%*GKc7D_Tq?kLiKk{bF3;T!Y`wD(!Wp4$7xm< zS?)Twq{(OK6?c`k1T3IwjHlZu6ruIUhUrI^niPszfiW33)8ygwSheHuvx-W7o`R(@ zfiV^Di^mc<2wt06CBx>KL)Wd*$h-jafz{RR+FEfAK6sW)8MZD*pbhR1HID`Un$)nS zTkC{Rv+wu1f{r>$-%a&uI9S|2<&U3gr7Bu(v9tDn?{PCDZ1wHOVQNRI1f|LZ5u;#; z`Z&~@oV5THzOjq=eTx3Zz0zDQ5>*(_Oh3iOlwX}}1G0LSj-DzCiXK?N!Mbj0FBwvz zPdBysPt5g$NK934yo#3!mn3`;*KuCSojoeon9&5aOarW)sJ_ z!u`hbyWLNjpZm#}vPvObvA?)-`}HQ^)Vk?12JdR7v&R2U>WReBq*-Hmis;IsDdTPp zzD5c(b^(^rKC9};vAAls`s1#czidC{TiKb3IYKH 2Hem)U5@SChsBJB?e)emmT z?v?xY_irT)?)np*LHD^hL2^gnn0nGF4-H)Fn4lzT(=ZV671$;^;mad_Gu$B{IYqN0 z{tP=NZpb!!O;fKVahS3=SagRW=LLRYxxe>x1eM-;|NR)2-(?Iy4G=tQWZi-;guZ!V z0)JW1RwD8Od}(=)`*I5%S%@SO8|9kMR$BnYfe*N8miC9#4Vd3bi>e8Y9-3t4hV)Qh z#@pi=qDYMpS>P~}(8|+Dz>KZIgEnsZ{lop2UX$mi*AQ2ZV0|oJNoJ4OH+E9s-(YmE z @J&%1i^qPw3k( >_ns=tOriw z=9H8E-%nkPRZN(Ars2w-*>cK$r<}T^;GIvmuAK~p^ RN{>?g(hRkvg zzW^27CR2>H6SG|}pD&pZM?D95Wj~#+5T#I~8d>K6j0(5DE<@>{j7NJ~#!jXaU%EOU z4qbis*mW@|_;Hf%(^GRV!;q(4B8(Mkg#(jq(IE8al4L3MwgGp2lq+y9f%T6;^@e zS4xMA-buV_1cS6-x3o-p`pSf)_s``;1OJm8JyJSX_Ddz-jN{GNWB0?&Q!p&?Qy~yhhi|DJgHzIk|_&i@a+3kb`FNc z*2AU@BADqY(pReUNqz*s@gN!lYR&KbX&7%yVJboOA2X-#wu6PI1OO*LCw7w~R>tS2 z({O7L_HVZ1=o`SR=g<#L;#N15wd~%8*57~;B MN4^o=e;geGyJb_xtTAq_NmgS4+CU=h88@P%69gtXoB@wi) zRrJ#Dil-DQIaOnm6KE`7X4BQ2NEwD&lztS&LV9kqA1^n9GD@Eqg3sSJ{up5two2m! zT%LGQU~CEbQt~GlEO$=+1Hl8|1O =&ckgD9FUV0xBKk3w#4g zHmeb$jVQL4SXeb^H?rH50pdYkM=LJ>G# OGBr>bjB_(4HBd2A4 zJ9ZMPLkno1>r;M;L P%v(WWzHfJ>v!9EjSW!UA%*fIsgC>uiZ_xRwlYO-6mw zZCtH5 qaO4m6c1=~%&E$x!j0*+2bGAgqQ9^!&NFs;fR8IJ1 zg5~=$E&28`Z+)%en@d8xl~$GZqE;XTX9EwhG}IW*!^$P;l10^cui!^d=7O?Ks7*+6 zOzObGmy>6@AB8s!KW(^J%37~~`qb~egm(N?)@U$nXcf1yvs9JT=%T^Guz;zTdzYRM zbeJf#yuSNpu$LLPKB6x4``=gJYB%NIbmF$;8 o-XK|3%0fSFAyL2a!#AE1(i46T|uj_ly zzY2ZIT7SMWEX}$jREg_V)<~ g`Oy@Xc3e$<>23_t zW7|?<)X+Mm4s0og3K<6SQF?3+4J{q>;Tq#29fQEFf+4Fy&`6;#i!1c*mJbu}MA0)} zr<6RUhsjl_L9O^*^^fNzmZSsVPz;{A8OT#^zQ# 6QDsnf1oO`o>gAA26*H;w<1Xv!a!HD74KZSWl?gfUzP zKJ22P3iBHfo4)14Z*Oqv=nI1_baXAqeg8C3i>-Ze?fA-|Ef;l#bJ5QZW$y^*mcN(e zqfwW}uoxN1?dN6QvZj;AlJNNtMG8h;TLvl+No<4Qa?2B=>*HP7a_ixHrtAxd@6g|{ zp2F7h%VOF#af2+(&3U5GZ;FpUmZu$ZP}K5>J^WJz jESMs@!=utJ*xvf!T4DNbKm5N^Lr?24> ze_}QTWnr)Zy3%<1TDvs)08!THBfaYjEAQ4HxM5}D(kv9I+JVyPt)Jcv^pU0&B0`iu zZB%g|%x7nzsKRogp4k|vm_{CJX2SxKMrgAyAK3KQ5B<8f@NV6@-$v%W=y1*BIzSP4 zmR>IY5X2gpbw97GM=7hXdH9gh% *aDQe+ zCGC@|#cSg_>uiJ_wtQ;%rsxQ&)PAClxlo)NgDtVb>Jm_Aggjdc`CBzc7=UuagwZ(6 zAXqqdBWrdqK6hJ_nsiWBL^MIVMoQ!IHulliuFnro_fgL}W``&PlZH1!fS>e!Q~X&+ zu*gp_28VVFDFoBuv1pUk51&(l7e>p2i)bd)PyG !M!rjk z|BdEke7o~VFTebQ!~9Q1*DN!kS-BnRQoiYari#7n7U1%&cq$GDHFM)g-}ca9yrn<; zBr7O4aZ*auNqLEB;{{)o`Ps_sddL!wY-UbnU{+9wsZ+t!LgA!N`;*)YMvB%hB@)zg z>#aZB0FVcNS^2^cbo&hZHy=sOkP=5j!UP(L^ot;pkkV4E)7GHtg`5K~zqn4l9mw4P z7wmX;+9^ayxP{@B4$S$d!g iMABqyKBk}mm}MU<4;VrUE86A z5$!}3B`=zy1s%HWTCobgdIEuXcVns-<5{wASRD1-NjQ0y*=8S6XpLfy@-!q{gzua+ zG9r$~Qj@aUc;Vfo2Ja;XX%@>jQ31>JX#q~71!*7YI67n3)GO1c27jIG^WCz2C63Q7 z@lqI|q<|U1J1N@}i))D)jO#pXS6lk?oKfP&f~jQssbBK~o?^ty(5+Uq&i(TeT9QHl zAmgs>j}@7Z-@cn0UI_T$NlOe{rT8$A&bxNU5pVZ`EqtPns5$&1C1EiucgJoXk8;of zt4AKKtGN@JdE(`_IGH;l34 )<63N#=KcAZ-{pE04Z%?_u` zvfJz=QlAozGo|7yw2bC8_8Q5vm?>}7uDX4xMc*vSzZ-)W5ycRd2^pnR;gLj0Hp7)m z=hX!5MlhP)7$^20<$Q)L4|@2LrB#@R?iDZ7|Foh5@6`LTh}(OHZZexE6dd6bV?^wN zOMyZ@X&+ym)z+Bv-_IjwAz$}?*4i>b@K96mO*erBDQyj{uaXWGN1(n^BDG0@%ne-m zWhuMSg#>}S!zHu7bWJH6z `!46%8N?Jfwv?7X)w_^>&VHf3aCR9}CaHF!$3F}YrpyP3 zajOU@VKWuwmF_+fBR!nrWarp+_hs5(@$Av_gIX%rI;kr|XnL@;@g<#%EfuuT4>%QHYQ*^;(cX-8gXR^L0P z7iYR9k0%O1S#x{_4i%7EJC**22m9R Ylgv7Krs%|i~4S0Q-1OG6hxgrlCbTrN*`B;;) zpai7Xlfz;7rh#gKaOGWKZHZj^YR6!-JbaM&(vjqM|265)8vWo%@8lM}WKPMs)`$F` z*|>#%+dwR{C@I4QD^Mt_i38?OP0FH-B9$fIKB1uVT9F%OR&LK?Ti437?2N8n1M&5N z21McO0JA>yvs@)KIsfk3hq-Yw^7MS?=UXCP7dFY~yMc-=JE3kZiT-^{uG1%7_na-S zFmzf+$o+kZB1Ui}VdHhw=ci*+2g{m%-`@`CF?=PZjr*C$WvrQ-;nSYG!Fj7Spn5oA zp1%6;K9z}{6Z`(UkGs0T)w}u4OYqE$lrDu`uB#<` dWQEH!cts()lUHc%dUs0=5IQcV%{b%Y(2W z0?Lx_ v*Ri6iR7O`6f$v8$0`DkZKtD?}(&e zD+?J2ezp@V+wrPHAbikpxrlwlBj{PCrS67i#HsXWpgYQ!!ssMm**z|B(9 5~N$xsjOk z;bm16{1Tv|&LFcy*$)@mCB-R7Fk~2}FW;^eXrFeKZ1nM6A3x!u!n0>GGsT!rf{ 6IU zGx{R|H@oZti(NkW3nI?#_P!cq+>(9PVDasd9w_n&guVhfQW-TccbLV+AHg}ifeTc` zH~jQ}=BJ7lf24fnPP{IB46>pzNcr?M*4*h)5#5 *iE&99zGhse7rtnCe0hEH<~R|}@g-b&sJsNbf8 w+HSkF9w-WWJ|`u0!k5}nt*N_M+Jx5YozM-N`lOfyHM |`Xe2IJE2@1CDA7k{^D;gEs!@<+0ExA(7aBP_shx045;p;w|{3co{ z=~(voA)?5)^Ux03UQ*spkvw)*eM`unI=T>{du-a{{<@-?6 zNFjf-bl-SYt7_Yc2l7chIK98pjDtf+*DIESqc$$Qoo;>DbX?j#MENalcwBtZ;k54Z z3B$JX2B9e)mY4()Bmrk>MnbAPdZy+Fhnhqp4(O#Le=d1hPaecaoIgl+^?Nw9pK|J$ zK3}ANFrz6n5;JC&?$+M;)! 911c<|4$BWre(xGcA zO;dY)kStA!$Zt3;7 T_me6 ^F`XSx0O|4#^Ga^n!0UcLI51;eTG=}b;m9cC%IT@&%t3EpcNL9e4=el# z$ClRRQUCz#E!*#=GbWOjY0B+A_0%2$Z1V^Sr}*~xXK^`cZ5;_okU}1Pk@lx~z88 O;;2 zd>A(EbuWZkzWPa*Oqns79!5M@HT)cZRWtDc _My%IAoX@>%C=0XO%7PJ(c(SDfU9_5O72tGYmk$_l`Yld6Ri|Kd-%=Tc>mU zvz09Z>lju98)uMq_ro-xLJ+fJFTVzF8+#z-fx0}l7}yu~82)CW75JJ?Oz--27RRc! z3YRrGWp)_ZRZM&p9hgJ)TOk(Nc>xXXD3C~?7ic-`d}GNhz8cuNKla3o*USp9{chjx ze8v49U4ykUKC<0{u!i^IKNk`4(sOVLFngeBHv;3Ky&<6ux}9a@D+;xF{3DhmbGh(K z98*8X;?(z^xHWU-`fIE-fgmXbdC;F0?A{*237-fg&c23wmrSL9O{e#*T6J?N=pm}m zHU;a%kfy%YAvi8^XOGr(J{d>0(#* _yrQ(;%otTJT`?p=LJ}|Wd53-)8U z|8ZI|3FA%@Eq%hYHRRYU_Y43q_$PT8JfeVy8%^MdQ1*3b$xq^BpkLRR6A7n6K^{r^ zZ)*y);11a(;M&BG8?FRVfmY|A9f7UuJLlT#V1SxR{BJK2d=tiG7L6$rTq2MjXMQ1= z3MB@h8GyEksixN_rG-%_aGx0R)VNK?r4JoCYWt~%BtKW?FbuoANC)ULL><$o;l0 _SMGIqsvY(e$IW74>UIF%O?f0N%jk{Q;D~VO^ji( 5*)t9+B{ZhBFtDC5^m#7_Qbd)Bt;w@uKZqM7PaCykA@2aM zJ1C^xmc$E`VnB$~8PE>4>4<5K;UPMPvYX-a*3zTcx(-@UPN&$k^q}ctBIS0&4Vhl~ zRi|8(v5%B8Ri}%cw+rJajo8`wey*aO89b^VcAqkqi9E}}&MeOm`r9k!3dqnl{Zfg> zjg3nfn7=9|o+m-gz@5x57nGw#_nVH29cp@bAwC;W(%s*JJFBLz;WLSEG*u*h)77H{ zIcaS!Mc%yW$}J;)-Dn=;FvX?-Llr%p4q}D*Q;OVG22#05O77VL59Z9Nf@c*&NyOKg zI5#3hkgT?#EN#r<>2H=|4l@ -nEJMFOxaW`F^Fxh+jW? ziIrdCL_Y^rRF_lrA6YRq?WDP9D(S|ArlAH2rLmgDw=Jg0pOR>_4GK40Hbos~9GI5n z>I-NrV8;1lC&Z7nABWV_`mTTzk8mhDloPlzl(}G|4i3Mi4S>RrK9X$6Pw$gVQ$PKr z>x6z3qNaQo%qSFSK2V;9gPbLKDmV+KKE4jS>?%0FH{^)XS^6%)=y%AoiX<9vTrSGb zlEnTf=MFh#=_m_l>M@z|hAhxOo7qnS4gIOGb=%K{f=v4<-GAKH)je=$8sw(TURfDU zWm)C?&Oy^u Di6(CBeUr?*1N T5A%UTDuRY}=`=s0T_8oUkR(^I zmLnzA5ir#hCnz8{o;A)PEI`x~wV9s9=LuZk#P{Myv%u!^|HItS+|* g8R@izaiv`T_*XOq!#-@l;VcuF*G6-u%?3|d zWl-frHS~h$f(AkCBeE|uz4xK#Hztt)$cu4Q PI^4yl@EOM{&Y9PCgY8H&=aGaTiHY)Zy9gU}1q|LrQ!y#)b=ZJSX~Ju0YiK2cdB zcn7r&;ip%BB;KNysM(nRUv1TBW9%d%s-r`kO{@GKDZecUiB)^guV>Zjj|S_&qdFp# zLACi&gCZcZM)V?h?Hgk=X$r)MyJGd^?3F9@?{+%tO2annvZ{yT8vsIp@<=n@*46d& z841suJcX|TDAf2`3Q?8JMh#e=1|R?}uwm>Z#~iK|+1$lJXb|T{{ja8~47TH8mzrrF z`G0qvv_n4NHB}G4r7`z2FHWHvam58*96tk4UVC(@{?x*1r){Onn&;{_7I5TB)$p WXz2kgd6L3kLGDD;eR?B(cfXueh{jzuz8y} zoy_;m&>9gU^u2d`h+wVc86c=VD)l68W}dA4&!+*Ay?;gmAdX=!SiBN)S3V`@%>^j! zZ-88ClT2 ~TB4SKw|<7P0@Gx)`2 ApLCY7?0yOxKlX`%xtA0+Sr5J0MN zT3VK8W?kAx4HsP|)H>WA67`w `vu}|F)o6X5OGQdt zX@{q*R!a;EXjTVY5j-`BBZR2^E2KuJc?|$5k_Gd{)6_HNaS_^F-)$m@mVqh|mcaBW zGZR?2&dqfMmI`|4cGB`SjV}vR4CES;4e*}%6}zK*3Pn2}Ig?HZ%oWpd7vUuVHX-1% zpUp-VKZo*K4~nNFWK)cC->9p0{H<@MukzOV>b64*9DQc-yxzaZB^d9i|0}U3zLM#Y zCuo+m2_xom!Tn>=AZ$4Lm-kF8E$iRiNNIwgNuz@pH9lr`jwLf(t_oh8@xb|iv>!OT z8uH!YmC09-8tF$zSaC^8cu0g@5*in@@>BLX^sbf4?s)PRS^LhQxnN|ZCc~BAnzm%# z?id;%qqK(<-<=G-7}V^;>IJ>HL>_>+M&?FD!TN1}5k2mGfJ_^Utln1(FnG4;6%3*z z1M@e(_bY{b6?rgpMa5Wu>mjW|d#%Cw>BZHEfMkFLa6O#SUD5CB@5|Mn=m~!QG0A3x zV4|8(3;~&fSdK_289d6Db%^?X#D-xQ2<$`oM70XWMTPM=?TzcvUjZ12lhXOjt<1Z_ zR%5Q;05cyAFC8(pro0nM%vz~ <_=+TVcp`mF z*L>0ZhJ--i^6LJL_YIf_@G?gkg;WrCHW6S({G0n6(%@h+NG##C=Cb%1D~`|lQmAMM zke(MN^o9QH1&+v&)td;zya#;kJ6nRJEy9GRsl^ovV6w({G2^atRCQ^*OXceh>-)Yr z5_~Q&ujLrUFO2{g0k+rHdqoyGmn0*pd_dpLuei;k*WOjGbh<(qvr)ITU(T65CDYX7 z4x@ NjUSD_T2TV1^O#Hn{tX= zV_MI0LqEGyH#0xKQz1@<|J*xpjk#>KBF{RL7?CWFc%z0q>U-3m0L}4$z|@ms|Dlt3 zMOs-PSLyc&WVLohHA@zJQiu`-SworOI1| zRvCAb>06`2ZCE>hoMC!Wli+KJYDj#$<3FowMphUVX%rsy(^#741Mh)Q-!%n=U;dsB zn0>l@sAy*I)`$zr0zk)F`%qn+gtBAx;54kQ8PywDH{t+bli5t{pToo6@+hL#v0wYb z&V(&pd+2~NUHE!)^WVEWDzt;>BJs;@C{C3l; sg1$8I%sj69ATUDSr9dFjYDq-hNmV=4k53;&c=# z8|GLcn4YYWW7>Tbkk|oVTbs$lU$Z{3ly8Fv3o?I|?mw@%W(S{c@2=yEPuOAGP9bYJ zE2djmiOfKd+uB;3A;{}R9EQsM-E0_}nzF2JZS|67)&BA<5(Q$?R?PFaSl`+m6<7Hw zD+I|wKgMVeN;w^&Bdi jQdKnW;QKVSS$6#aDmSQlZv0nHfa1xq3;*F$ndy zqX;RFkhjI?$-@{R%YAh~Nq)B0F5RBzE!Ng|TVd;$K__IPB?s+?{C{>G);fdYSYj5* zi %*H2VFzYngrn2Yr;_0Y|qrnj=_MFQjM&@l9{i-~z~XgJb$QJq>& z`ZjD^HZotpy1j-bDj~dC_&lr?8R#4IOroc+GiZ5Q36DF~T8i}@dLLUk^WBbJM-Xdg zP_OsrU#fbPx~Caj{pY=Xop8)XS8%nINVpNmyP8pnY^`MQ@MU+OHgiADwn27Z6@Vj$ zkXOvH`Qmp96SK14inOSRxUu+R{+(f6M`6p@D{A@5stB`Yx=+LSVD9MEFCK?w>p#ID zqOuH29842pC6kc4U-O+-_u>*+15v}HWD_`+K%Q$yz0-O?$flBxPMCU;#!>>*7n>%x z6PVU3Ob1BBC1w1YnS9>7k_?cktFI4D&OF`yiT)02wrzdd$M-%j17CZ7OF0FtDSU^v z3`C?85sUaXExQT0Y^kmOPF7g<1xdUlyq1r+xw-Y4Ej<^GkUns~Gh9Xm-~%T|BAo4V zUz#%FfOY;B2UJfPz(!!rie(BfmDIzg38<(95G9YrXuw@b%kAa%{vp@rPJH!`CyC{r zwH9MfxRMU!nae^0(FqS-?tn`z5G4Z{SsG`^AY~hpI6bB%{>bK6kqxLh0dEUVcz<=B z2|jodFu*K> l;=4+o~-zv5%psb1Xn-uSXv+`h8B+%{EjHB~Aap!5`=GJGdW6`DFi8V2-g!AaEh zkl8A;NGxzL1we}I;MQU`z(>Ub!kZos2_9kGUHL4BGRo0FQiy3Zpr&8s=!sv^(+8G0 z^~JLzKmC7J4NmS3UwbyYkL){AQjt4t)^#1P+WB)%Z@!|e&@wZl`dpo^`E|+Ven}Jp zCYzR0N}prwu<)YN6Bu0Z_I$ &!xm5+-ty052prQf}A|R!uCGY)7LSa2$Y=k#}}Z z&Ju7?tZz4%kI+zC&Uv3N1$+B^O*L=kasiBxqmD^r){WZ{jxKim@N?jx ~0dPiaaA{bWgN`bit1RE489r9-I`Q2VHwzcsz znqesmS@+yoflNu9pM9ZJTViV+){|r3CjlfB{{lKVRRI!OB}F=pLAt=c%U2P<7A$HY zJYi?>SqJ-wx|w@62)_;a;i @ 4#%Lj)awqGWM))DTEZ|a8hn+dsU6X(qSDd_nInuJ^@6Rpfij1TOhlh^ z731AQ%#!kj1k)m{Z!i!H%E($pY7KHMDnQI^hWIQ v7^RhS^}MG95=1J0ILIg6v|a1RN#M zHZ!9gLh_W2A3k9NGW@|4^;o8*^r3N>oNfc(JA DWoh&GSP9Q(4_@;|XqV4>%&_BEozoBEd$(bMgEA3~|r$i59Puto8^%+ksHSF?xd@rU(!^4xDlRLQI!#l?VzrgL=s6(I8Xn#lyXM@ctZQYHn zx%Fd9(msJ^Mjc3zPse|;eR3p}MN$NamNh9P4~EXZ=C^}6Q!*LFyGTTQK(9Q#N^r}w zPXJ;}Jfhx+cn@GQO{yNs7WNJ Hx?T6%6voA!35*Z606>N^Yn{G#85}b=YyPp@+h(~M?>Q2Os=5I9 z JtX4)F2)m@UL88NLK`s7_zG_%=$%FQ6ruwVE7gW5KFU0EE1F>gzdP`;4n! zWYHQ++1mUX@0&Ej;CEQ`n&YZRfrHBm{1|9;gJ*2{na3xSu*Z}NNJHfz1Hv1Rbd`sp zW4{3wd4LTbsW4R8(GlD=&DVAfKsN~l1g4*|05a{^>Y+5SX)vNHF<>U`GVHc4OM==r zkEKvlkK&UuXuO E&XSJkUMdz0wdJ!c2@ z6R80)vsVnY&RlT#KCo0cv_^L;#%~=k0L<^UiU8PK-}&X)cVN{_5ui&%6PJ((QR~|| z{?qn~-uE9@8=En<;r!{`nZl+Y8G%E;2{^r;S0_Ln4p5z|0Ylx1l;;ogZ=CGgXqKHi zzh_|j%bx-v31=jzrj#X%67Cs*H{O>Lg#B#+;q*0f_F@UuJ^K2iLWqo{=Ix9Y#t@aZ za`Y7$zz%{qYy5-X{b*@GdC!v1x^Zv 2^GOs3#!fm$w>iK9)mT^kjaDsUpCBQRd26$~rPF@i z(zjv82M43A)F1j4v(Q6RO8T%rw*20-N`e*!Xp-vCdIEo06Y;PrDOMnOt!$xKZIren zJM(a%#QgcbAYujaCJy|?1M#rz4MuwG4LYP7w_6YGgn0xAFz#&3Thvn7^fygkxra?5 zCBNc^$Hw{r1b799Sn_O%Dz%@fkvIup)*qol0Ql{kX=46)V%H4HZ!XjgmmzoSH{kxS z8qO3KuZ6%_%RfvE;d)D~Fgw@b#Wk&_jy#lHH2OoKhk3|DMfXDT6ZmWsEtomgd}Swk zs@qrVGzrM0;ra3o@8HP#rqTQvf;bHH^z?qUI9m>&WmLA{kXAlLaJ!nHZ4NxT)@4@# zR-UQqA%wsHGlqj?0h5Bu@!UpZPTSCzmP9K271(^RcfSO57M!BghFo1K-QGM}KYDu# zUaxf^H+@m|7~s64V4!|y@NDTYxK%GsAnt>eyoUiuS}nL33tz7|OVn&;_MBb{#&l@U z8CM>`AG)-l#^UbWu&8S!5VN%%56(rE*WRxXLF(3Gxt_BTHAUE-L?944Q$#MQc5r%N z@ A(EgbH1ZjuB~#dN^#ZrYjU@PUI1=d4nm`o&_i`vtTWG>Z#Dagy@4o>3fS21nx;v| z0bIQ5U?>+!kb8CC9VWrT;^Y8g3(`jPFzR6>VvzkWtcn#L*>GpN%}2(}hHt?==UZAa zeV;`qFo*RVFZ*Fp4Fuky*ck-r4ii?ag5Rv!>qp|mZ}fW0^iEn*TU3*W|16H(lukn- zX?HW8D)L)tfj7y#65&Upqv6~H&5>mVOfm1AaJ}P-eT*rjpWA{cq75?45D!&^nY?lD zBtO#ckKMpSUY I0&8!y`lQ^)D z48vh-nr4**b)o*9n^o__!sL1^q1!3NajkRVT7RhR)7{0Rk+YmEB {hyg zM5U@ZB9@3}#7HaW8OS1-K&a-mG?u&_Yrl-VJ2gACEW{)Bf$9X$uXOOp>DOeuwhgX6 z@Vl2``};lgg*u7w>U6krh8CoVuNhA+J `x`QsoHo|y+w(PM_o%5{?DVO2chst2mwG8YCgc#A(Z^$1dlryE$94cKor4{!u z9NDLfEld*}3B0fC?$P_Hn%=}a(L Rz$S7%=6t7EI=N=h#*yf$5xE6y7V_t^ zFVN6Te)R!|U@x{lhg_faY#x5k6BY=6RttCe7^o67_AScjctNFk?T)~o%rKPo<~U{N zs^DQ`F8TZdL&UH3c~BM)Sk{_fruE$e$^}ERcDTtR`TI1^eYNT{;DblPg|$!7 `+|x(0!e1VuIP{V=FBfH!RVc=cHhBu^Y1QiU<97%+xEdY4;& z!eP|MnW+qP>@0%N1g-Kp*v!iowz!P8^eP&c11s_B(S`!wB^%%%pM2d~aC9T{Tj3$@ zIwlNx+k4<@0o93_Dy<{Q{lH;7PKJb=7U24C0E&z@t-@B)oChT=;@oy9DP>nZv-c zkE(S-G?vvy9!k1`fsu<)*_luVK9_ACC8n;XQKl5f3`NmRm1&vZ@_%_C2e?D%lJ*f& zUivNEe^$$}rJO>-hj0Ay$IWbB{pAqoy0kR?8+X9J<( z_RbDqieNH2C#xoZ%|~&<0&%L7dR;tL@?bf`B;p)c-gSsEgD|b`MY*D-2K|8DuDfyB zavjsqbD@OSRHG4SZpm$bDHGsV8Lt30240 3&wkK;#}E$jaC_Ksg)H}VtZY4o5PjpdXSdA>FE@SZvKv;}I!gflKr z!~fKEI-k5zSFYLZX5VMEyP4u9nndjokA`mCSO1IM)3#%(w8e$Th*erR+Cng#Hw?+7 z-pMXJU$o&N&d+iDx^qyl)}v`iDO&peXZr@e6NXrW?QZ-=z|#YQad&8!W370#3Qar7 z?&d>se$9%46(YwU0(bG_UPG%d&>ijQ?R}x$6q&*e{+?60ilK0d@G?Mv&=k h?#pc(JCk8eJQpcS73n}N@hFEk_2>}RM3+4=8^Rw(F0E3_vto|r%9qI8 zG-qRSx18*#9kO0*7?Y99o}Z=_enA`$(r7bRa3Sz^y_d5R;I%!2I{|fjlbMMCkn>^l zv>RDZvr`PKYPVKPqjtLp-PL>EBT#t2^8C7Wf?BLrD{;j&+Mq+k4hTp}gaOW*G;XT| z6XhB}P3j_}(8AmtN#-9}3W;4f@pheSG{Bh@?2k1IIKS=M8Nyfc8u`;myu2lejKP18 zrN+qAR7?{KV;zpfl%I?pnmaHP=SRGQbQU=jMO)E}dzr5S&F;76j@Fn-1##6sl6_T= zGy dSg*6JK5dSryY~Ic?|e1kjmuLiHlb$t; eq|i8>>ZcbK F#&UKU=mH z m_iEJKr|lRtn38Qk4?rZ%&(R =E#5MDUmnENl WsbGyCffD~Yv*_qNU`K2ofYypy z&C1126GlcxaYR$-}Ds >y)Sd>$ROPH9PUUQX z!tCo^eKYp~Znb0%KV_NlFesi$0Z1y0BiZetE1P;iNi>ZOl7ZFuR~4vjF@vbgp8(pU z-l>MZYbsnDcG+~Gb3OF+N&l@56pT!VfSr~-P>Q8V)`6A``S3Z6#sC&B>EkmyAmm0& zDR??=JBcKsE}~UPL6p(LP-w)rVU|r-hiI|LzcAy8I0CxhvS{_@&^)zvN4^!bV`NXN z56eI2I1N|IPqXcsiJ9we^9}GKYG~M3qRzx*vqWPZU &ME80@R;I1bL1y-= zpg$4r1XQqMuyAmUZa=F(HrQe^kETX6;?aypvhw8t#3`i#b5Paao{$Ez>V+{); vChBts#k4nQ2 h2fhKmYbBM&o zi>S`NMESkZR%%+`aebWuy3~NlJW)M3vL$MI-dgvx314COm0C4@@l%c*!C(nT6XqSE zXS;l4eTIuHW|6$LHIpdx8sMqQvz*L+6pyp-yrTnz{ur%efIA2FsYUDBPvAUTIJqD4 z;|j0q0Pu<=5hli%y}%m4eVR5HVqn_9^qU1}JDYNhb%4x_z%mA7=xf7;Ba6Wu7h+iA zA6!&D9xUQ_;z^sycu4lCA!(l1dLgTYr)kbQ9i|l8lYSr@XTn@O19f*fp1X7kpepin zabsh{!Od;3RJ|Ceyud?=c#r`SPUmF($Dg1*=~7QuL&LJyA{`XCRVU2nl#)6g$edj> z{uS^9=(}4otoW1CRUC$G3@KBqFdB#v-Z-9aBkRdlea81V!GLb>3ph-oH`_3T0mQRn zX}kjic-m&XAi&5V@Y(C~(^x+nVAEa%x&QXPEt>mrBg_R7i;Nzf#UaeM=CCvE_bu%} zH=f^V(D8RApMZa$sv9|=!ou`J8nUzNxxZkpU2=nQd!IcRoo3yL{u8xZe@&g=!Ikv6 zLGUZHYELVdG~>-W=05`kHBTC!%)grtcuyRw*F?R{sr00MR1@52w>Qd}1b@_H)I<45 z0)?a!hx7B?OnGkzG3u9syn*YTz+dm~0U9g0s+x|5cNdN5gI_ggYJ?S?OJTruZT$Y` zA{IKVJzj0Dx29{jWA8gr=9w;!%fF9(SUFn>5Ot3pw6F5p9QsYgDLuRHx{iM6SG$q? zkC %_kHD@$sUh8Axgij#q z>o^EXxpSA%=2D%Hyg@p*G+{QsCj_^1trmTLNBEr3zz1?V;o6*D5GjD%BfLhv;QFk6 z{C<%Ky 9xru7sqjCD>fiD+l|P0b=w3$+`{+%)0@QOl}vt~P4tx0(dq{r~dou0g{r zUn%I6Eo5n8pO0j;qmL fA+SJ4vjGN$tBSQ|2FEc!rP^u008+WLlKpGdP2woL6l^IG= z)qd>HRJ)S6Hp0m7xN~k{-Pan6eVl~U5&1bJ`6>&GP__)G39H*$_0!!= $)puQ#z zEPUWi;&s2u3Rph6)t!s!?5k?=CDXS3{8rYJW<{SSjs{qj*Jxpph++?JkAZ~|7qG8i z-YF61Q`|^_#u_GJ-0j0MkQv{Y3vZd*whltE=6Q9Gh=;RIEJ>i1zqyk9NDrE>`@Z`7 z4}FSX`REw3v2+Ip7^U6Gfg+nL3}`EU0$ebn#s*gbSe2;SRHiR;3|(|I*v^0^<$|%tt=bHXGJb zR9{iB=8_gWMQx2}Yd{T>8X)ZzI?jaQt?s#EnqQCIl39SR8Q+fnNPnDTqB1q({x<}2 z9Q?bAjfyp<@WPYHoXXgt^*1Erc)51-7pmeKABN~i*dN@%5|-Rg#udEPgFFKS%fBoN zLy-TJKb>9J#>4Krcvmd<&f4$LK+w^vb+m#4ANh<|dn%j1>0QKju>o6&iIGKG)c~t{ z8he~2=mg}P!6zM1_XhCy!E|vk;K+WMdAP^nz8i11@T61)5pl4?iJgbWUIQ|YG|#>1 zk|uq;oVW>qEaaJ{Hj_P#+!?^{n&I{0lD -~!e}Y= zi@KjsareP!X(f9@o7uba6TnOLbrnMqqD{Gk`LZ4YV;fb)qI8BW(cvRIbzHZmtlDAz zFC~6jpJ_v6NC(zrc)QuefJQ_)AX@|^5IszBGx2F80h gugZf8b8O8>
2+# zS_LV&QoWsPyyqz%)*-GCXv8N-5>aT$Qw!owumOr-F3k7v_E7QZz!2aPIQ_fdU^th! zn5E;`9Y;kL##!Bao(TJV1W0CV 0> `T2=UaU#A`%Pjh7q%-DwIKc&`UJ(2Fo%gZPmVVyMvuzqz}7Q&vDyVhPnyrSS=I zfr^F2b{iH94WA)%**|gYA4=_mr}=>1@@~KQ|B)vMyI4TAK6Zz`p={y5g6BO||NUUx z-{b4B+oty9aQ@F|W2h&a#&5uFK7YY?Uk0jLVGMrbT%{i L zklc4)39=-BX&OTsmfHIZc59>syn>NXsbp5|;j1z23i%_5o9{k85ZKqH^*c8Q?0oU% z@tCcS w?X*tR 8e08eG*pteV;u;1{he_@ctku z;Q<)gW`sU<-X9$150Z*Yya51L%$l<;{k(KFQRtaC1Y29geA46)qpDRn;cs-jTFlh5 zul!N9o^i9CU`*TKbDGmYt~GLS2|z4|_L)!mpxCJ8f@eXHeMs5ce~9j(Qm4V68@`Gt zfPC_EA7kO;?XU0pX>FY=zkRx_$QnJpyYB{Br1GwBbW^+EOD-shJdr^rCc9-f5V(wX zK0sHSu!gE8HnL&iO>T=KZXI8IScKhS*_fcF<%Np&B%-|uWe6KX2Ry8&4BGtdLVW9~ zM>A)|PmY-v{J~0LMMf#(Sp3?u-_ZwYDfjFHk7nz1LW$8y%;*%qfF!w%w$_?UE ~ zGCOV~iO1@xwv_xwW)TT6t4Z1q)AV6;$ 3J9}alAnjF4f{3b+Ytcu5_KB= !Q9s>f8)GLU($!+N4I98L#MgPl$py!q6F&^pFORM%7QB1_$^F)$OXp zeYH$TEGOXYbi)p)s0kp(Ke>h$PnUt>W?Az oj2il{v(w6rl5Q$?RiJd}@ZO(zI%Xm>q~ z$4OnI= m5RoK9n1lwcOA(ixn)pvHzrU1AP)Q9U6{EhWue *Mqarx~pO+WjK}kVcI=u|l z*y~8VY1?%w=5QvoFd{h~d-R{Y5J7rzZXSb eh`NF@y8 zp1R8-Y>wZHJzaK8{eg*{@5a#pn&p{|c!p7};A+tn;I5bYr(~)g^)DjD#K73SY_GSy zf7nOD ?-h|Wb$;h7s3oj?FScsHBdu+wTZk}JT+TZ5EN=vC>7u8eo#4- zQ~+1k$St%|fH{?9p){}$ bYgsa8Oab?Vkts>mnP6pd$_HF9Gt(lgzpec0cJE= zIewoBwr-cEliKH%&n#=ga9qOf>w&9n`^6MAmjpgd_DGq&^QM2MTGIY 9)+z%vlN}L4YQkAF*<^>&^e!Y+hmPd0@0`)X+Z#qHghYPkHYDDx z!{4=crI8^-JbS^Xp7(*_`?d-G=|FvNsi?z4a`6-tS9&FU6xJUehwA9)ShFEgU WJ>wM_KGD^?8YQGMx1EpNu$iJ^>SA)k z45fXQ2~4?_?~K_beyvTwyRozPFLJv<-)(C(KKY&frV`}A?p&pJ iA1dh`EPm4Mkf?8}h@JP9*6zOf5%H)<8w%iQPegpUrax$+%tzXa`sT4ei`l95 zE2{`SuSLdo3yx4?`(!o9MYe)ReNQO(A32G=&F(QC;(@gY=pVk+({)B7i>dOdlQ0)g z=HP=eN-wH*>TuoDuKb)mGWZl}v!mC+iSZo9YxFnFe{+}S&si
9goi z-`-aYA-%4lZUXXN35h@PqYZ1wi!n$!?U4vx3*Fbxsi*OMMhh6aq4|I^sy+Q(kB;!R zX8ZY_IDe% I>12y>A6!24s6G%( z(s~mMj?JB?-r8_2Z_rBcM3f*uew&f4Y*O<>a3v;m-OB~j=MUX_wXncm>j{sKkS84a z?cw13iyv0C;(KWQ$om3M lxZdwY1u|pL0a?fpeq_HM7#?uubkXNeV1UVn#eM0x4# ?4K6$JuZ{T=uT2JRnOx4j(G}fHud`?E z)%K6AB mw7F5`>HQFf*^P ^SncxU?l&ZpS##E0P(;E$!@$E|sc3&+d4m$QHPss(BX+*^ zN7b *nhA2}U0P-Ab%0l}6 zsoBjBc|Ppn69T#wDK(cd+8`Lbbn2YZS``OsfQg9z-#{u&H1wmIVQ|h?^m!j2=8t3T zO?&6!c%9u*J54lvh_+r a=QosQZudjWl@@-9<6fUFYb z5iB|ad4Dbi>Bf>UH5+BC k-O;V%NqbQf7v$2thUTsI_nzNUqYJTv*~b@s^AkjgB-%-C`bwB z6pn6)E~&2AnwkF1q9KT&n=9PF4JV)}0Qg?KKg`mV@gax3NjERSf@vHJmpzGnHx%-> z27S9A$JlXaB7^o~`s0@&&RYwO+}k2i{LTl f(Bd1bVi(OWna*$s}e}EGN zWBTsDIdr _7jAx!lR;$!%1OudiS`>!3Mk>1%j6*|YGgOCN)X0*)z_yg^MO_f?m z&J$i-yfrD{9r`k9CmA&cZgp{D5gqz6^2y(bk-UJ)n=pbT8$IXLwE^7@f2MW3+ zdq{YA&eg#tVm}w&1db)m>#lC8@7HFO7T9pgT@r|F#=xPI9#W4*!t2%e$1aT*e*Gs% zpMc9zK?!>AQ?DtYnqElbOa0svp*l%#xmkZtlH)7k*u_dO4dcc@`<=lEsq+#1nGwZD zbaKk0IgE7m^S5q){e*V>6Rs)j4kv1SULl};ayR=#hu0+>D+9LkyhE^MGP(2ii@MkH z-3PoWopWjS1z{eT&O@z-b0Zc|M_py}4oOdVn0E PdmGAvTNsHuRaS*eBHZ*wo^j zKwz2uYy6p?*NYq&;-bE8<>!_F2%Rm3jrAp7egc&Bwk8%0a`MDJN3TU`wn$v_!xuB> z#3V6x_CDp_^e>lN&EA=ePt9+H`KqwKhj{_e`CZ$;wM3kvE@*ePc0&9>#G5weqe9D~ zjpn7J{U)~YLG_NDAretzHkDlZ(C1ZrUiW8GQRyT~!D$@9kLKlm*%rtGiyk%felH_N ziuyGqqgitRa>m`{!A_Z^1v?g%=M(d&dmsIZbKRaGV%z!bzPJ;Nf3Nq=qSHHWq_7{j z+R^)QhXU~aExS@aJBe%eD~qI-?4nU}^t#nfXN(<@)j7w}yPaqd{chD9ky+YPk_XGn z`r5v&nTgW-Jwkn*Jdn9_b?N9w?}h3+bc1voykrF92lT3=)R5C(-Zq$&fbiA%zc2j! z{t@QJOHF47$Pw{mF0RLLx#Tp`e`NGO*`~VRTV6z^f%H4}=z(k^_XaP28q?=x!uK(F zOSEG*{O0)_arK)oNyNUh+wE`4am%-W=nIm!^3vs_umMpAOaRt|NAXF{>At0Ut;d09 ze+mcqGqg+ip2pzOfePQ=DQr0=`Sv^rgTvZ}#wlrtIpE|l^)})cZ^!Y_MV~%aE*oEZ zschi#t+pdMz47CuJ&x|BuN!XTfEM-Hp~cwaA>qov{7Jvz5kZfqAqOXSb}Wm7;9%zi z1DVGr3~EjT?2jS;Q1?~xfaG1fvfwyDu}ObGYTEy74fODYf4I_yGAjLoa}w()_Pr)0 z!N9jH%FzK=7jXvti9QS8`d)_M53BSiMq-XnwcYs_W)Qhi+@tw)?tTkcs k^x@A?%_cDEDZR5L9T$|fKYZA`9nXezFJDmudjEv)1DkfIq#!jVfYeh z!P8= ;nj>{D&7$|;MI!}$2t;slD z6d%dr!AcTsze0^g^baA&RHnwgT2RmJxPOpG)M$x*a-%wN;>#r8^tbnB#Zp@%$u@|J z3@S>ET1D_JA%`uqn- $IV@F1&T#J-y&2|!q0m8mNGTVM}yYB#ekt@fVd1Zec cJLOseOOqB_yVFMNTRPMjW$zv%{;@YUeIaDY0X zHi#M6gHtU(=hc)bKTdcN`jgcgdLL0r)w!E&-{w~`Yw7B^OtG41kOgt20!$~)yo1%M zvZ^*Db02$qsmp6vIrX+4%)-$=^(&W=P4~QujWjcVFxpy;NIPyI4XY;a3*frou$`Yg zl~u6gLQTQH;Oa8U->SB85NpBxin`Ylz)#vtrr-u0a*2&Tl~>^Ya;qpzBmLfp*?{~O zg1|2Qc7ov7^a@oyW)lpMo2z7g4o~wn?$sXbJNavF0G*as4?#9&Vv&a;ubkceY5ez4 z?Yh}#i??{H{~jGhnZTy$(+8KSKN41 C5O@X*eRqZm(U z=>AqAO6~RVc;v>*dERmry6MO9xNpEXJv(JgYdYo^caClvsmIO#Z{eaOQSXyqx@e0B z`clZ>!AAGW+HwW@VvlnH;jM5L&8dFhaK@#{i8K5%rUj<{$m@#>WkgN923nqxYlSG^ zkg~|KKzZ|r