From ae817627d3b883725802a3b9146ab552c06f1981 Mon Sep 17 00:00:00 2001
From: Shan Yi
Date: Thu, 30 Aug 2018 15:03:19 +0800
Subject: [PATCH] fix_fit_a_line
---
.../quick_start/fit_a_line/README.cn.md | 615 ++++++++----------
.../fit_a_line/image/predictions_en.png | Bin 0 -> 140104 bytes
.../quick_start/fit_a_line/image/ranges.png | Bin 6668 -> 6737 bytes
.../fit_a_line/image/ranges_en.png | Bin 0 -> 30337 bytes
4 files changed, 286 insertions(+), 329 deletions(-)
create mode 100644 doc/fluid/new_docs/beginners_guide/quick_start/fit_a_line/image/predictions_en.png
create mode 100644 doc/fluid/new_docs/beginners_guide/quick_start/fit_a_line/image/ranges_en.png
diff --git a/doc/fluid/new_docs/beginners_guide/quick_start/fit_a_line/README.cn.md b/doc/fluid/new_docs/beginners_guide/quick_start/fit_a_line/README.cn.md
index 8886a8307c3..c421ab6e05f 100644
--- a/doc/fluid/new_docs/beginners_guide/quick_start/fit_a_line/README.cn.md
+++ b/doc/fluid/new_docs/beginners_guide/quick_start/fit_a_line/README.cn.md
@@ -1,329 +1,286 @@
-```eval_rst
-.. _quick_start_fit_a_line:
-```
-# 线性回归
-让我们从经典的线性回归(Linear Regression \[[1](#参考文献)\])模型开始这份教程。在这一章里,你将使用真实的数据集建立起一个房价预测模型,并且了解到机器学习中的若干重要概念。
-
-本教程源代码目录在[book/fit_a_line](https://github.com/PaddlePaddle/book/tree/develop/01.fit_a_line), 初次使用请参考PaddlePaddle[安装教程](https://github.com/PaddlePaddle/book/blob/develop/README.cn.md#运行这本书)。
-
-## 背景介绍
-给定一个大小为$n$的数据集 ${\{y_{i}, x_{i1}, ..., x_{id}\}}_{i=1}^{n}$,其中$x_{i1}, \ldots, x_{id}$是第$i$个样本$d$个属性上的取值,$y_i$是该样本待预测的目标。线性回归模型假设目标$y_i$可以被属性间的线性组合描述,即
-
-$$y_i = \omega_1x_{i1} + \omega_2x_{i2} + \ldots + \omega_dx_{id} + b, i=1,\ldots,n$$
-
-例如,在我们将要建模的房价预测问题里,$x_{ij}$是描述房子$i$的各种属性(比如房间的个数、周围学校和医院的个数、交通状况等),而 $y_i$是房屋的价格。
-
-初看起来,这个假设实在过于简单了,变量间的真实关系很难是线性的。但由于线性回归模型有形式简单和易于建模分析的优点,它在实际问题中得到了大量的应用。很多经典的统计学习、机器学习书籍\[[2,3,4](#参考文献)\]也选择对线性模型独立成章重点讲解。
-
-## 效果展示
-我们使用从[UCI Housing Data Set](https://archive.ics.uci.edu/ml/datasets/Housing)获得的波士顿房价数据集进行模型的训练和预测。下面的散点图展示了使用模型对部分房屋价格进行的预测。其中,每个点的横坐标表示同一类房屋真实价格的中位数,纵坐标表示线性回归模型根据特征预测的结果,当二者值完全相等的时候就会落在虚线上。所以模型预测得越准确,则点离虚线越近。
-
-![BostonHousePricePredictions](./image/predictions.png)
-图1. 预测值 V.S. 真实值
-
-## 模型概览
-
-### 模型定义
-
-在波士顿房价数据集中,和房屋相关的值共有14个:前13个用来描述房屋相关的各种信息,即模型中的 $x_i$;最后一个值为我们要预测的该类房屋价格的中位数,即模型中的 $y_i$。因此,我们的模型就可以表示成:
-
-$$\hat{Y} = \omega_1X_{1} + \omega_2X_{2} + \ldots + \omega_{13}X_{13} + b$$
-
-$\hat{Y}$ 表示模型的预测结果,用来和真实值$Y$区分。模型要学习的参数即:$\omega_1, \ldots, \omega_{13}, b$。
-
-建立模型后,我们需要给模型一个优化目标,使得学到的参数能够让预测值$\hat{Y}$尽可能地接近真实值$Y$。这里我们引入损失函数([Loss Function](https://en.wikipedia.org/wiki/Loss_function),或Cost Function)这个概念。 输入任意一个数据样本的目标值$y_{i}$和模型给出的预测值$\hat{y_{i}}$,损失函数输出一个非负的实值。这个实值通常用来反映模型误差的大小。
-
-对于线性回归模型来讲,最常见的损失函数就是均方误差(Mean Squared Error, [MSE](https://en.wikipedia.org/wiki/Mean_squared_error))了,它的形式是:
-
-$$MSE=\frac{1}{n}\sum_{i=1}^{n}{(\hat{Y_i}-Y_i)}^2$$
-
-即对于一个大小为$n$的测试集,$MSE$是$n$个数据预测结果误差平方的均值。
-
-### 训练过程
-
-定义好模型结构之后,我们要通过以下几个步骤进行模型训练
-1. 初始化参数,其中包括权重$\omega_i$和偏置$b$,对其进行初始化(如0均值,1方差)。
-2. 网络正向传播计算网络输出和损失函数。
-3. 根据损失函数进行反向误差传播 ([backpropagation](https://en.wikipedia.org/wiki/Backpropagation)),将网络误差从输出层依次向前传递, 并更新网络中的参数。
-4. 重复2~3步骤,直至网络训练误差达到规定的程度或训练轮次达到设定值。
-
-## 数据集
-
-### 数据集介绍
-这份数据集共506行,每行包含了波士顿郊区的一类房屋的相关信息及该类房屋价格的中位数。其各维属性的意义如下:
-
-
-
-
-
- 属性名 |
- 解释 |
- 类型 |
-
-
-
-
- CRIM |
- 该镇的人均犯罪率 |
- 连续值 |
-
-
- ZN |
- 占地面积超过25,000平方呎的住宅用地比例 |
- 连续值 |
-
-
- INDUS |
- 非零售商业用地比例 |
- 连续值 |
-
-
- CHAS |
- 是否邻近 Charles River |
- 离散值,1=邻近;0=不邻近 |
-
-
- NOX |
- 一氧化氮浓度 |
- 连续值 |
-
-
- RM |
- 每栋房屋的平均客房数 |
- 连续值 |
-
-
- AGE |
- 1940年之前建成的自用单位比例 |
- 连续值 |
-
-
- DIS |
- 到波士顿5个就业中心的加权距离 |
- 连续值 |
-
-
- RAD |
- 到径向公路的可达性指数 |
- 连续值 |
-
-
- TAX |
- 全值财产税率 |
- 连续值 |
-
-
- PTRATIO |
- 学生与教师的比例 |
- 连续值 |
-
-
- B |
- 1000(BK - 0.63)^2,其中BK为黑人占比 |
- 连续值 |
-
-
- LSTAT |
- 低收入人群占比 |
- 连续值 |
-
-
- MEDV |
- 同类房屋价格的中位数 |
- 连续值 |
-
-
-
-
-
-### 数据预处理
-#### 连续值与离散值
-观察一下数据,我们的第一个发现是:所有的13维属性中,有12维的连续值和1维的离散值(CHAS)。离散值虽然也常使用类似0、1、2这样的数字表示,但是其含义与连续值是不同的,因为这里的差值没有实际意义。例如,我们用0、1、2来分别表示红色、绿色和蓝色的话,我们并不能因此说“蓝色和红色”比“绿色和红色”的距离更远。所以通常对一个有$d$个可能取值的离散属性,我们会将它们转为$d$个取值为0或1的二值属性或者将每个可能取值映射为一个多维向量。不过就这里而言,因为CHAS本身就是一个二值属性,就省去了这个麻烦。
-
-#### 属性的归一化
-另外一个稍加观察即可发现的事实是,各维属性的取值范围差别很大(如图2所示)。例如,属性B的取值范围是[0.32, 396.90],而属性NOX的取值范围是[0.3850, 0.8170]。这里就要用到一个常见的操作-归一化(normalization)了。归一化的目标是把各位属性的取值范围放缩到差不多的区间,例如[-0.5,0.5]。这里我们使用一种很常见的操作方法:减掉均值,然后除以原取值范围。
-
-做归一化(或 [Feature scaling](https://en.wikipedia.org/wiki/Feature_scaling))至少有以下3个理由:
-- 过大或过小的数值范围会导致计算时的浮点上溢或下溢。
-- 不同的数值范围会导致不同属性对模型的重要性不同(至少在训练的初始阶段如此),而这个隐含的假设常常是不合理的。这会对优化的过程造成困难,使训练时间大大的加长。
-- 很多的机器学习技巧/模型(例如L1,L2正则项,向量空间模型-Vector Space Model)都基于这样的假设:所有的属性取值都差不多是以0为均值且取值范围相近的。
-
-![featureScale](./image/ranges.png)
-图2. 各维属性的取值范围
-
-#### 整理训练集与测试集
-我们将数据集分割为两份:一份用于调整模型的参数,即进行模型的训练,模型在这份数据集上的误差被称为**训练误差**;另外一份被用来测试,模型在这份数据集上的误差被称为**测试误差**。我们训练模型的目的是为了通过从训练数据中找到规律来预测未知的新数据,所以测试误差是更能反映模型表现的指标。分割数据的比例要考虑到两个因素:更多的训练数据会降低参数估计的方差,从而得到更可信的模型;而更多的测试数据会降低测试误差的方差,从而得到更可信的测试误差。我们这个例子中设置的分割比例为$8:2$
-
-
-在更复杂的模型训练过程中,我们往往还会多使用一种数据集:验证集。因为复杂的模型中常常还有一些超参数([Hyperparameter](https://en.wikipedia.org/wiki/Hyperparameter_optimization))需要调节,所以我们会尝试多种超参数的组合来分别训练多个模型,然后对比它们在验证集上的表现选择相对最好的一组超参数,最后才使用这组参数下训练的模型在测试集上评估测试误差。由于本章训练的模型比较简单,我们暂且忽略掉这个过程。
-
-## 训练
-
-`fit_a_line/trainer.py`演示了训练的整体过程。
-
-### 配置数据提供器(Datafeeder)
-首先我们引入必要的库:
-```python
-import paddle
-import paddle.fluid as fluid
-import numpy
-```
-
-我们通过uci_housing模块引入了数据集合[UCI Housing Data Set](https://archive.ics.uci.edu/ml/datasets/Housing)
-
-其中,在uci_housing模块中封装了:
-
-1. 数据下载的过程。下载数据保存在~/.cache/paddle/dataset/uci_housing/housing.data。
-2. [数据预处理](#数据预处理)的过程。
-
-接下来我们定义了用于训练和测试的数据提供器。提供器每次读入一个大小为`BATCH_SIZE`的数据批次。如果用户希望加一些随机性,她可以同时定义一个批次大小和一个缓存大小。这样的话,每次数据提供器会从缓存中随机读取批次大小那么多的数据。
-
-```python
-BATCH_SIZE = 20
-
-train_reader = paddle.batch(
-paddle.reader.shuffle(
-paddle.dataset.uci_housing.train(), buf_size=500),
-batch_size=BATCH_SIZE)
-
-test_reader = paddle.batch(
-paddle.reader.shuffle(
-paddle.dataset.uci_housing.test(), buf_size=500),
-batch_size=BATCH_SIZE)
-```
-
-### 配置训练程序
-训练程序的目的是定义一个训练模型的网络结构。对于线性回归来讲,它就是一个从输入到输出的简单的全连接层。更加复杂的结果,比如卷积神经网络,递归神经网络等会在随后的章节中介绍。训练程序必须返回`平均损失`作为第一个返回值,因为它会被后面反向传播算法所用到。
-
-```python
-def train_program():
-y = fluid.layers.data(name='y', shape=[1], dtype='float32')
-
-# feature vector of length 13
-x = fluid.layers.data(name='x', shape=[13], dtype='float32')
-y_predict = fluid.layers.fc(input=x, size=1, act=None)
-
-loss = fluid.layers.square_error_cost(input=y_predict, label=y)
-avg_loss = fluid.layers.mean(loss)
-
-return avg_loss
-```
-
-### 定义运算场所
-我们可以定义运算是发生在CPU还是GPU
-
-```python
-use_cuda = False
-place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
-```
-
-### 创建训练器
-训练器会读入一个训练程序和一些必要的其他参数:
-
-```python
-trainer = fluid.Trainer(
-train_func=train_program,
-place=place,
-optimizer_func=fluid.optimizer.SGD(learning_rate=0.001))
-```
-
-### 开始提供数据
-PaddlePaddle提供了读取数据者发生器机制来读取训练数据。读取数据者会一次提供多列数据,因此我们需要一个Python的list来定义读取顺序。
-
-```python
-feed_order=['x', 'y']
-```
-
-除此之外,可以定义一个事件相应器来处理类似`打印训练进程`的事件:
-
-```python
-# Specify the directory path to save the parameters
-params_dirname = "fit_a_line.inference.model"
-
-# Plot data
-from paddle.v2.plot import Ploter
-train_title = "Train cost"
-test_title = "Test cost"
-plot_cost = Ploter(train_title, test_title)
-
-step = 0
-
-# event_handler to print training and testing info
-def event_handler_plot(event):
-global step
-if isinstance(event, fluid.EndStepEvent):
-if event.step % 10 == 0: # every 10 batches, record a test cost
-test_metrics = trainer.test(
-reader=test_reader, feed_order=feed_order)
-
-plot_cost.append(test_title, step, test_metrics[0])
-plot_cost.plot()
-
-if test_metrics[0] < 10.0:
-# If the accuracy is good enough, we can stop the training.
-print('loss is less than 10.0, stop')
-trainer.stop()
-
-# We can save the trained parameters for the inferences later
-if params_dirname is not None:
-trainer.save_params(params_dirname)
-
-step += 1
-```
-
-### 开始训练
-我们现在可以通过调用`trainer.train()`来开始训练
-
-```python
-%matplotlib inline
-
-# The training could take up to a few minutes.
-trainer.train(
-reader=train_reader,
-num_epochs=100,
-event_handler=event_handler_plot,
-feed_order=feed_order)
-```
-
-![trainTestCost](./image/train_and_test.png)
-
-## 预测
-提供一个`inference_program`和一个`params_dirname`来初始化预测器。`params_dirname`用来存储我们的参数。
-
-### 设定预测程序
-类似于`trainer.train`,预测器需要一个预测程序来做预测。我们可以稍加修改我们的训练程序来把预测值包含进来。
-
-
-```python
-def inference_program():
-x = fluid.layers.data(name='x', shape=[13], dtype='float32')
-y_predict = fluid.layers.fc(input=x, size=1, act=None)
-return y_predict
-```
-
-### 预测
-预测器会从`params_dirname`中读取已经训练好的模型,来对从未遇见过的数据进行预测。
-
-```python
-inferencer = fluid.Inferencer(
-infer_func=inference_program, param_path=params_dirname, place=place)
-
-batch_size = 10
-tensor_x = numpy.random.uniform(0, 10, [batch_size, 13]).astype("float32")
-
-results = inferencer.infer({'x': tensor_x})
-print("infer results: ", results[0])
-```
-
-## 总结
-在这章里,我们借助波士顿房价这一数据集,介绍了线性回归模型的基本概念,以及如何使用PaddlePaddle实现训练和测试的过程。很多的模型和技巧都是从简单的线性回归模型演化而来,因此弄清楚线性模型的原理和局限非常重要。
-
-
-## 参考文献
-1. https://en.wikipedia.org/wiki/Linear_regression
-2. Friedman J, Hastie T, Tibshirani R. The elements of statistical learning[M]. Springer, Berlin: Springer series in statistics, 2001.
-3. Murphy K P. Machine learning: a probabilistic perspective[M]. MIT press, 2012.
-4. Bishop C M. Pattern recognition[J]. Machine Learning, 2006, 128.
-
-
-
本教程 由 PaddlePaddle 创作,采用 知识共享 署名-相同方式共享 4.0 国际 许可协议进行许可。
+# 线性回归
+让我们从经典的线性回归(Linear Regression \[[1](#参考文献)\])模型开始这份教程。在这一章里,你将使用真实的数据集建立起一个房价预测模型,并且了解到机器学习中的若干重要概念。
+
+本教程源代码目录在[book/fit_a_line](https://github.com/PaddlePaddle/book/tree/develop/01.fit_a_line), 初次使用请参考PaddlePaddle[安装教程](https://github.com/PaddlePaddle/book/blob/develop/README.cn.md#运行这本书),更多内容请参考本教程的[视频课堂](http://bit.baidu.com/course/detail/id/137.html)。
+
+## 背景介绍
+给定一个大小为$n$的数据集 ${\{y_{i}, x_{i1}, ..., x_{id}\}}_{i=1}^{n}$,其中$x_{i1}, \ldots, x_{id}$是第$i$个样本$d$个属性上的取值,$y_i$是该样本待预测的目标。线性回归模型假设目标$y_i$可以被属性间的线性组合描述,即
+
+$$y_i = \omega_1x_{i1} + \omega_2x_{i2} + \ldots + \omega_dx_{id} + b, i=1,\ldots,n$$
+
+例如,在我们将要建模的房价预测问题里,$x_{ij}$是描述房子$i$的各种属性(比如房间的个数、周围学校和医院的个数、交通状况等),而 $y_i$是房屋的价格。
+
+初看起来,这个假设实在过于简单了,变量间的真实关系很难是线性的。但由于线性回归模型有形式简单和易于建模分析的优点,它在实际问题中得到了大量的应用。很多经典的统计学习、机器学习书籍\[[2,3,4](#参考文献)\]也选择对线性模型独立成章重点讲解。
+
+## 效果展示
+我们使用从[UCI Housing Data Set](https://archive.ics.uci.edu/ml/datasets/Housing)获得的波士顿房价数据集进行模型的训练和预测。下面的散点图展示了使用模型对部分房屋价格进行的预测。其中,每个点的横坐标表示同一类房屋真实价格的中位数,纵坐标表示线性回归模型根据特征预测的结果,当二者值完全相等的时候就会落在虚线上。所以模型预测得越准确,则点离虚线越近。
+
+
+ 图1. 预测值 V.S. 真实值
+
+
+## 模型概览
+
+### 模型定义
+
+在波士顿房价数据集中,和房屋相关的值共有14个:前13个用来描述房屋相关的各种信息,即模型中的 $x_i$;最后一个值为我们要预测的该类房屋价格的中位数,即模型中的 $y_i$。因此,我们的模型就可以表示成:
+
+$$\hat{Y} = \omega_1X_{1} + \omega_2X_{2} + \ldots + \omega_{13}X_{13} + b$$
+
+$\hat{Y}$ 表示模型的预测结果,用来和真实值$Y$区分。模型要学习的参数即:$\omega_1, \ldots, \omega_{13}, b$。
+
+建立模型后,我们需要给模型一个优化目标,使得学到的参数能够让预测值$\hat{Y}$尽可能地接近真实值$Y$。这里我们引入损失函数([Loss Function](https://en.wikipedia.org/wiki/Loss_function),或Cost Function)这个概念。 输入任意一个数据样本的目标值$y_{i}$和模型给出的预测值$\hat{y_{i}}$,损失函数输出一个非负的实值。这个实值通常用来反映模型误差的大小。
+
+对于线性回归模型来讲,最常见的损失函数就是均方误差(Mean Squared Error, [MSE](https://en.wikipedia.org/wiki/Mean_squared_error))了,它的形式是:
+
+$$MSE=\frac{1}{n}\sum_{i=1}^{n}{(\hat{Y_i}-Y_i)}^2$$
+
+即对于一个大小为$n$的测试集,$MSE$是$n$个数据预测结果误差平方的均值。
+
+### 训练过程
+
+定义好模型结构之后,我们要通过以下几个步骤进行模型训练
+
+ 1. 初始化参数,其中包括权重$\omega_i$和偏置$b$,对其进行初始化(如0均值,1方差)。
+
+ 2. 网络正向传播计算网络输出和损失函数。
+
+ 3. 根据损失函数进行反向误差传播 ([backpropagation](https://en.wikipedia.org/wiki/Backpropagation)),将网络误差从输出层依次向前传递, 并更新网络中的参数。
+
+ 4. 重复2~3步骤,直至网络训练误差达到规定的程度或训练轮次达到设定值。
+
+## 数据集
+
+### 数据集介绍
+这份数据集共506行,每行包含了波士顿郊区的一类房屋的相关信息及该类房屋价格的中位数。其各维属性的意义如下:
+
+| 属性名 | 解释 | 类型 |
+| ------| ------ | ------ |
+| CRIM | 该镇的人均犯罪率 | 连续值 |
+| ZN | 占地面积超过25,000平方呎的住宅用地比例 | 连续值 |
+| INDUS | 非零售商业用地比例 | 连续值 |
+| CHAS | 是否邻近 Charles River | 离散值,1=邻近;0=不邻近 |
+| NOX | 一氧化氮浓度 | 连续值 |
+| RM | 每栋房屋的平均客房数 | 连续值 |
+| AGE | 1940年之前建成的自用单位比例 | 连续值 |
+| DIS | 到波士顿5个就业中心的加权距离 | 连续值 |
+| RAD | 到径向公路的可达性指数 | 连续值 |
+| TAX | 全值财产税率 | 连续值 |
+| PTRATIO | 学生与教师的比例 | 连续值 |
+| B | 1000(BK - 0.63)^2,其中BK为黑人占比 | 连续值 |
+| LSTAT | 低收入人群占比 | 连续值 |
+| MEDV | 同类房屋价格的中位数 | 连续值 |
+
+### 数据预处理
+#### 连续值与离散值
+观察一下数据,我们的第一个发现是:所有的13维属性中,有12维的连续值和1维的离散值(CHAS)。离散值虽然也常使用类似0、1、2这样的数字表示,但是其含义与连续值是不同的,因为这里的差值没有实际意义。例如,我们用0、1、2来分别表示红色、绿色和蓝色的话,我们并不能因此说“蓝色和红色”比“绿色和红色”的距离更远。所以通常对一个有$d$个可能取值的离散属性,我们会将它们转为$d$个取值为0或1的二值属性或者将每个可能取值映射为一个多维向量。不过就这里而言,因为CHAS本身就是一个二值属性,就省去了这个麻烦。
+
+#### 属性的归一化
+另外一个稍加观察即可发现的事实是,各维属性的取值范围差别很大(如图2所示)。例如,属性B的取值范围是[0.32, 396.90],而属性NOX的取值范围是[0.3850, 0.8170]。这里就要用到一个常见的操作-归一化(normalization)了。归一化的目标是把各位属性的取值范围放缩到差不多的区间,例如[-0.5,0.5]。这里我们使用一种很常见的操作方法:减掉均值,然后除以原取值范围。
+
+做归一化(或 [Feature scaling](https://en.wikipedia.org/wiki/Feature_scaling))至少有以下3个理由:
+- 过大或过小的数值范围会导致计算时的浮点上溢或下溢。
+- 不同的数值范围会导致不同属性对模型的重要性不同(至少在训练的初始阶段如此),而这个隐含的假设常常是不合理的。这会对优化的过程造成困难,使训练时间大大的加长。
+- 很多的机器学习技巧/模型(例如L1,L2正则项,向量空间模型-Vector Space Model)都基于这样的假设:所有的属性取值都差不多是以0为均值且取值范围相近的。
+
+
+
+ 图2. 各维属性的取值范围
+
+
+#### 整理训练集与测试集
+我们将数据集分割为两份:一份用于调整模型的参数,即进行模型的训练,模型在这份数据集上的误差被称为**训练误差**;另外一份被用来测试,模型在这份数据集上的误差被称为**测试误差**。我们训练模型的目的是为了通过从训练数据中找到规律来预测未知的新数据,所以测试误差是更能反映模型表现的指标。分割数据的比例要考虑到两个因素:更多的训练数据会降低参数估计的方差,从而得到更可信的模型;而更多的测试数据会降低测试误差的方差,从而得到更可信的测试误差。我们这个例子中设置的分割比例为$8:2$
+
+
+在更复杂的模型训练过程中,我们往往还会多使用一种数据集:验证集。因为复杂的模型中常常还有一些超参数([Hyperparameter](https://en.wikipedia.org/wiki/Hyperparameter_optimization))需要调节,所以我们会尝试多种超参数的组合来分别训练多个模型,然后对比它们在验证集上的表现选择相对最好的一组超参数,最后才使用这组参数下训练的模型在测试集上评估测试误差。由于本章训练的模型比较简单,我们暂且忽略掉这个过程。
+
+## 训练
+
+`fit_a_line/trainer.py`演示了训练的整体过程。
+
+### 配置数据提供器(Datafeeder)
+首先我们引入必要的库:
+```python
+import paddle
+import paddle.fluid as fluid
+import numpy
+from __future__ import print_function
+```
+
+我们通过uci_housing模块引入了数据集合[UCI Housing Data Set](https://archive.ics.uci.edu/ml/datasets/Housing)
+
+其中,在uci_housing模块中封装了:
+
+1. 数据下载的过程。下载数据保存在~/.cache/paddle/dataset/uci_housing/housing.data。
+2. [数据预处理](#数据预处理)的过程。
+
+接下来我们定义了用于训练和测试的数据提供器。提供器每次读入一个大小为`BATCH_SIZE`的数据批次。如果用户希望加一些随机性,她可以同时定义一个批次大小和一个缓存大小。这样的话,每次数据提供器会从缓存中随机读取批次大小那么多的数据。
+
+```python
+BATCH_SIZE = 20
+
+train_reader = paddle.batch(
+ paddle.reader.shuffle(
+ paddle.dataset.uci_housing.train(), buf_size=500),
+ batch_size=BATCH_SIZE)
+
+test_reader = paddle.batch(
+ paddle.reader.shuffle(
+ paddle.dataset.uci_housing.test(), buf_size=500),
+ batch_size=BATCH_SIZE)
+```
+
+### 配置训练程序
+训练程序的目的是定义一个训练模型的网络结构。对于线性回归来讲,它就是一个从输入到输出的简单的全连接层。更加复杂的结果,比如卷积神经网络,递归神经网络等会在随后的章节中介绍。训练程序必须返回`平均损失`作为第一个返回值,因为它会被后面反向传播算法所用到。
+
+```python
+def train_program():
+ y = fluid.layers.data(name='y', shape=[1], dtype='float32')
+
+ # feature vector of length 13
+ x = fluid.layers.data(name='x', shape=[13], dtype='float32')
+ y_predict = fluid.layers.fc(input=x, size=1, act=None)
+
+ loss = fluid.layers.square_error_cost(input=y_predict, label=y)
+ avg_loss = fluid.layers.mean(loss)
+
+ return avg_loss
+```
+
+### Optimizer Function 配置
+
+在下面的 `SGD optimizer`,`learning_rate` 是训练的速度,与网络的训练收敛速度有关系。
+
+```python
+def optimizer_program():
+ return fluid.optimizer.SGD(learning_rate=0.001)
+```
+
+### 定义运算场所
+我们可以定义运算是发生在CPU还是GPU
+
+```python
+use_cuda = False
+place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
+```
+
+### 创建训练器
+训练器会读入一个训练程序和一些必要的其他参数:
+
+```python
+trainer = fluid.Trainer(
+ train_func=train_program,
+ place=place,
+ optimizer_func=optimizer_program)
+```
+
+### 开始提供数据
+PaddlePaddle提供了读取数据者发生器机制来读取训练数据。读取数据者会一次提供多列数据,因此我们需要一个Python的list来定义读取顺序。
+
+```python
+feed_order=['x', 'y']
+```
+
+除此之外,可以定义一个事件相应器来处理类似`打印训练进程`的事件:
+
+```python
+# Specify the directory to save the parameters
+params_dirname = "fit_a_line.inference.model"
+
+# Plot data
+from paddle.v2.plot import Ploter
+train_title = "Train cost"
+test_title = "Test cost"
+plot_cost = Ploter(train_title, test_title)
+
+step = 0
+
+# event_handler prints training and testing info
+def event_handler_plot(event):
+ global step
+ if isinstance(event, fluid.EndStepEvent):
+ if event.step % 10 == 0: # record the test cost every 10 seconds
+ test_metrics = trainer.test(
+ reader=test_reader, feed_order=feed_order)
+
+ plot_cost.append(test_title, step, test_metrics[0])
+ plot_cost.plot()
+
+ if test_metrics[0] < 10.0:
+ # If the accuracy is good enough, we can stop the training.
+ print('loss is less than 10.0, stop')
+ trainer.stop()
+
+ # We can save the trained parameters for the inferences later
+ if params_dirname is not None:
+ trainer.save_params(params_dirname)
+
+ step += 1
+```
+
+### 开始训练
+我们现在可以通过调用`trainer.train()`来开始训练
+
+```python
+%matplotlib inline
+
+# The training could take up to a few minutes.
+trainer.train(
+ reader=train_reader,
+ num_epochs=100,
+ event_handler=event_handler_plot,
+ feed_order=feed_order)
+```
+
+![png](./image/train_and_test.png)
+
+## 预测
+提供一个`inference_program`和一个`params_dirname`来初始化预测器。`params_dirname`用来存储我们的参数。
+
+### 设定预测程序
+类似于`trainer.train`,预测器需要一个预测程序来做预测。我们可以稍加修改我们的训练程序来把预测值包含进来。
+
+
+```python
+def inference_program():
+ x = fluid.layers.data(name='x', shape=[13], dtype='float32')
+ y_predict = fluid.layers.fc(input=x, size=1, act=None)
+ return y_predict
+```
+
+### 预测
+预测器会从`params_dirname`中读取已经训练好的模型,来对从未遇见过的数据进行预测。
+
+```python
+inferencer = fluid.Inferencer(
+ infer_func=inference_program, param_path=params_dirname, place=place)
+
+batch_size = 10
+test_reader = paddle.batch(paddle.dataset.uci_housing.test(),batch_size=batch_size)
+test_data = test_reader().next()
+test_feat = numpy.array([data[0] for data in test_data]).astype("float32")
+test_label = numpy.array([data[1] for data in test_data]).astype("float32")
+
+results = inferencer.infer({'x': test_feat})
+
+print("infer results: (House Price)")
+for k in range(0, batch_size-1):
+ print("%d. %f" % (k, results[0][k]))
+
+print("\nground truth:")
+for k in range(0, batch_size-1):
+ print("%d. %f" % (k, test_label[k]))
+```
+
+## 总结
+在这章里,我们借助波士顿房价这一数据集,介绍了线性回归模型的基本概念,以及如何使用PaddlePaddle实现训练和测试的过程。很多的模型和技巧都是从简单的线性回归模型演化而来,因此弄清楚线性模型的原理和局限非常重要。
+
+
+## 参考文献
+1. https://en.wikipedia.org/wiki/Linear_regression
+2. Friedman J, Hastie T, Tibshirani R. The elements of statistical learning[M]. Springer, Berlin: Springer series in statistics, 2001.
+3. Murphy K P. Machine learning: a probabilistic perspective[M]. MIT press, 2012.
+4. Bishop C M. Pattern recognition[J]. Machine Learning, 2006, 128.
+
+
+
本教程 由 PaddlePaddle 创作,采用 知识共享 署名-相同方式共享 4.0 国际 许可协议进行许可。
diff --git a/doc/fluid/new_docs/beginners_guide/quick_start/fit_a_line/image/predictions_en.png b/doc/fluid/new_docs/beginners_guide/quick_start/fit_a_line/image/predictions_en.png
new file mode 100644
index 0000000000000000000000000000000000000000..f111c7cd766b7e9981513cc8c65be87dbbf3a79e
GIT binary patch
literal 140104
zcmeEuWmJ`GyY56#Oi)1(DMh3^CoKX3(w%}d(%ogz!UCkEq#FdJQ)v*8lJ1u7hI3E+
zzJ2yMXOBJ3pYw0OV~w>YbH4GsPu%x)UHA1YKUrzfTh||4M<5Wl#KnZ=5s1rQ5C{z9
z)l2Y=mDkE;_z!`dh^n1}rJ
zs+1(Ro~1d14(c2RCvz*f8iC*yaI(_TGc~Y#sB2*K+JcX4y|R|<;cI<9G8J|yCMhc+
z1LN0XE;a@VF4Bs6E~a{1`eXw94|$!q;Rfagb~+E8%*`xpxt;jPF7C?>pHW{kl0CdQ
z#m~Et~rDPupS=typWM^Qd*JEO4e#pVWz|6+Z!NE-TkcEkvg^>yV;h<+`<7VgJ
zX5oDJuY(MpW}|P&Eie51U(bTS_{fay?5wyM866!R85~&|ENzS!nYp;QQ1@VAp@%c*
zZJjObbe!ldY#;yo4#EbudN!}E>|R@1JVf15N7vHcj*kpl`u7#gt)!&>X$k<6-#t-xovQ{r3+-
zod~Vrma%yagQ8<5Y^i5&ZeU?2F3d*;zcA>(*5_v9(Boo3>g&@Z4Y`=;*>u@h=($+*
z4d@LxSPeN04GazSSPlMtpa1H5=4V3Bgr2i*wX5ukPvFr
zIUiC<>FB+-Kz&J#8mPbTEo@-(+QC5oxs9dy!;7Bge*Isxf}Mkvl@rOz!6d@M#DQdH
zMzXL73JYwcVoD9*jP9?kb3&`%t$tNdS+%$
z9eN#oW<7cxBnK;}jv*@>o1Q)yBQ%c@HF5saMEdtvFgsBn|6^IeAOEqi3@l(Z*}$@S
z8|mnWxJ0TcE-a|%G`uqAE{m&Db8tR?DA$N7OZJ@UogA8)Zkeyd+dGcR9IedX2FIQ`p*+8=B5o?zb}DJ
z=}a^(i+jyc(qzd`=q=)iCli
za&i>4KKlm*wBjJ@*y^uhA=dmDlob@h&USI&xO;bcW+uVq4|Rd$6%)Vl4_gMNrlv1m
zw0&Cf8!~fv`TVRXyEnMs#C~Zf*`;ad>!`BrLr2&m)CK
z-GY_jVu@pq?x@jG%>uf!gr8RL7EjXC((v%{1KeYz)n2NpQ8Ng}a9WbAU&V*{O9ws7
z_tJ>loi+ZgHbBs@LOXV+ClL`2NZ>Cc()pCM-FN$g`H#fP1z>r21R*dHGG*28UdGQW{}4?Zyc=FLBl$c629;l5XGR
zwVCzZGSJi{syr%_lN!~Km7Ux*{?X1@yK;mT`Qyj4*Jd96{{GkdR|%(oo^I4*&)q}R
zp%V}gv|0XhaNx9s;gydX7aW*T&U#oRycwU3zreeelqjDpS$C46?-DLeO9xTM4zn^d
z7kv9>_d7?e(s5n6rq*(T{{?BCFoP+t{f#gseK<0y{^?5$)$9B2sQ13PnR^o+Tohnxh!$
zZ*~IzINA%4qSN6gtZ%)DCe)&y-cp=|t_f_xi4ANPPt
zRI5OxQu%6b{U^r8nF<$~YfAIM`-GzBBCc75KeTGJa#Z$&wvR-#c5kia?o?~xWu3yO*_wV0*
zeTqs-TqmdHDJkRv0s=fduA1f#y2-h%r{50}D19z3FRwjlWW0X;dQ<;rY6b@7)zA^G
z_bu10g%doEG7q$mRSM8!ILwE?>b$ETyG@{*Fu24p_q?A}tuo+`n
z)4i74l83MDw)p{HtEH{YCdSvMw3vtDMM`0zJUe?D+a5Bsblk=CcyG04QNUN;*w`3p
zJ0Do$;Ac{9J=4T)`Wu;jEonVvRKwb?t+wX;?09!~x6M&g#YTH^dD)h5%c`3-hg3mM
zE|CUHj*AaDBmCC$Y&$_Fjyu)8C18ttl1^>zNosZVOQn3p;$d@T*SST-dryxRVs>Xu
zXQ0AzVdk(_T_kKVXn_bxwq6CWx2^=EFzpdkKqT3H%YcX7E&EXKI4
z3m3V_jI?jzl-nUkl?rOItdvyfvHk0IMKsRVenn&BoTytL#AVoG#u}uxlwu2XkJcSAk^fa;jkRfSs-i}FnClm56_#=NuAovyA(x5h$u^Tr&@7R
zFg7<=O0}A8xr0yo=)5>PTf*Klpm6Ee#6)PV%YsNwT)tQ_C9Mt1A3BjESuu9CfI(NPbNv!Pji{-uhy9u&eQ;X$T0oe92Y4!P6
zf`b($6iMQ=2|DxgaH=$0D$^H)ZQG}o^3$zel1A45#9giw`>mC8bmPa_t-OWh`bIwi
zE`vl$mGIa8yRXGBg?S?|y;`qY`KBE@p%W#Y&L)jfKhVcn!ll+A$s^23dYM#I{lvE^
zdH|hh#>8_(!y{|HZx#b7Tq)}rBO`OhV@6bY)%A6y{c-Va^daQL5>2|2L>2*^cHex
zOavCAWr;47k000XQg|NJlWIy@9kkKrQ)#Q`{$3p^&9N{vI4GbJ_i~Y4K#w1fqCN5CbmcG=Gy35~
z6sum-%@8w4wtpP%ANo&?agPoR>}PAAzF6p&=VyqE)U^)mv{<+^?zSz3z4!ZFZ-@EZ
zrihv<9o}kvQ8@iAL085YF@;#;aXx1>q(~rU9eLp7ue0|_4=!gNU7f>D*VWh@cq|&^
z%Q=_8-FR-{>1)ezpjMU1M`TociR;8*E=J{~l>&MMcG@nSx@`Kbu#vj06k5
z9WFd92pS~tsbvj_sBotgITAe+tlSFmOgq|q(Us?q-4kRRg1H*7J2!Tlhfdz%pfaH-
zVfS0@*^uXQ#JW|%dSDBtkzR~FmLAE#;4OnYzR5V1Q)ZGiER_w?G}~&$r8ZAg9<1M@
zAPJtljhRG`Un&sJv!dub{Dei5zw)J`G=6DR=5O4DX)CGKFXVIUO*Zm-v5LfTs=emQ
z$J2}7F6-C+$dJa{tQ8xbYMtJrT(!uR9stCRhF`i&C4sUr0ud*vt<*Tbz#kN$_47Y#Eau^CW)=d4qi)@V$9H9EE0NqSa(
zg?obNic4&q>~MT~0L`kE4AK18U|923fdQY2(KL-xznqfUy6e5&!wdD(%qPOj3y>(N
z--s=t$ztiPsUL3jZjk6t73#`d*r>9y4jCvP;in0(9&1kLbFX3|JVT0|D9=559?lX)@mow`KvmyzFAEwP7H{7Qxa+
zj4kHW87w+v#LvtnhF9JDhVgQXUVSIWKsHI}$07Ckq^!(6yLKBeu$m8ySrwEVENDYn
zq^$S2+Uqy3Al>Zjux_-h#$pYdCO5m2`%r#beihM)^TIXGk??VEQ#uh|De6sS9NkT5
zv1LgVGZuQXjIM?|&<3{;=&U|ieetFlx|ioE=@60DjE1%P&r7~8*W*=Y;i?v9g?b_L>G;*)&ah5%Ox1;Jsnrv0MV5G_we_yFb%`C<`9xN@uO_uo
zo$4_w61uqIhjt1w=jE#m(@YK7s~QRV+U*3p*b>VtDwB|gf55cHk;52wkH<%pUW)#J
z;e|;PM+*l7gESmcQuavfXjRcJHpAMJImX=;aUr31S=MQ`cNq&l)4cEQ>Cx3LQP0h~
z*5$A=IOR|(@_EL6rqMO-ammnDDnx%*%d%h$L8|JeDo
z9zn06c+1r1ox9==`Pq*fj2Ytvs&phoky$3K$14uB1+K39Yf3c=Dk?@CF{kG#|)APb%5k0
z97`i2CeC$9udEz-SH7&&bqRM&CC>cl79mH*_-hlB&p#=LC56YL+>iIdBO`fSF#>7!
z($7;yD(tga7O72wG6dRUso|idRapDEw>mQ6alG2P^5|e~@!PjxJu9cQjPY{k?X*%X
zhq<!edF
z)Sq@vt>&7JHj3Zu((T_f-`N*oWn~R#6v^&hW%LOnppa!ZFXkgN5|&V5cRTv=;f8`d
zw}sF1_F%6&r`-L<6o-O-ZL06$I8sv2Q+gfJ8DCb+9yQ>n{`2{Bh5hpHwze1Dmezb<
z^rqch?6C6v6Jr%D$mvAb()ODw@x=#7HU{hf>;D52sVJ(m~48?)gHe
z>zonM>LX)M;a!~S>gufd%rkR*I@K>O&AYMz*2M~x(n`glVPU(Lm1aXMbL%}Gt^xiT
z{nUEbZ`>dxBy2oyOU9Gh`}tE+Nmkyq%S~QBw0Z1x|0|5{)tt=C)~>DrZ?2V13c2Rr
zxf=UFS-VnFQ=RwcakWX~WO)4JUq)AlO3TOuZyC6_RGgUu3I4>W^mxF{1Qte8N%nNq
zH1Y9Q7V9DWaP!?i{nNgq-pWcUKlb(T|JA))fn5Bsy55U#)gH3rHtz`ihVNe*s(X_yScfYw1w01Ep9KH;Te0<
zcXRMG_4m+#_Iv;M7uQCE<4H+e3eg_R_k}H=wlB5ff1YRl0~)f>p*BdyC!4Nz0YMt$m2qH`A&IXk2z-
z`8rK~z>ghU`BHJWt<*&-g+zKjT=w2S_nN1t=cyAs2>*~$rJrlGE*r=J=QjCa>3OVS
z)T$giuzB>-b?&huQi0vxM_)&jW)q=E(5y-NS{1f#1JL_+0wbs6ZuZ(q}n6+pkTCJv2Zt
zVPYcgd*!E-AoPa`e+>ecYb4CO(cvnzMjn?i;0*na;0MwyJY(ptd&XXeEU{z0ZegW`GW?(XhK
zoGN26Osz#elJEDLZTr{5hRem8?kUTT-FVahu?qvJZTRr=*S*FE-EZ^SQ~ZTS(I}go(GML%kAkgh+5brykhOQU=Abl9^m0D
zefR^yN@h{QO!Clr@fboN(dBMO8HrVfyQ-w3;-_;(dL{hf)v(K-6!$3>6W9jMI}!x6
zcRS0HEVC*RP3+q5MvucQza%{-ce#_ra<|{|Z9z*WANM=?@E>JI8CjJ*RqSu(8uIHw
z6tdBm+EEuF{?$a~c|0;vLA7lC!Npzpyfm?tL~p2=(+7?PU1LbKCc3*wr*&DmEB}|a%l6aJ$
zk&;VD;%GcKay=_MTZy`_uTOGz<8*d0&;SAk15K@IR&SdIj;hPPbeP2cnH
z`}OPT-@cbNA1#wR+wq|7g(B^;S%e`b&b2sg{vs8Q<2ipwW-@b=_A#@)33GiZV;zHKr1#%
zIabs~xi_c`@?dLdXpWxDd3J+hR&Z(;6?eDyA
z8h;0cS|v+BE~3)*cgXE5DK>6CIU1-PFE$;R?}$-QP)JTn`Xrzs0_p3B3qYIAG3`Ib
zM^2`A1p`{HQip{_MG7*eO5a))>5sKfrtxbS-hwJ6aVY-{YZv2^Fri#=Ht=o_rD9a7
zcM&y;T7sCEg?OX=QPO%9rGHj$PX{n&jo(QR#H5Tvx+@Zt=`~}`wF6S~@0E=WBy+dc
z%_{7U_7i2JSXfMBHjfh52p~E-mOg|hArL|^;iL+U}bC%ED_NLrwxJ7L#Ep^4+1x==Rmy3W_XYr>MC8x|Lr`{z91
zw3~JE*)bJo$S0ZhXDi`O1o-%rd2+g!H>J{TRTJucZlj|XY>;1Cl*z0WsP^$#dmtAm
zbp%zr?$c;zrQzYwo=;(WTE)$uogP=)YYzLUp}NxH)HTG|Bh%tWB%6RJ&xjRSW!9-L
z$jxP^4ce!FRN5Sc2~~!8cQHdkLb9@+sDHEIxtYYCb0nvJFMG=<$sqr9=@=wH+3K+H
z@YDytA4zkU7K`mLD;kZ0DxBk14zm56M94>%3L}!yZ|g_#ZluIxI~0Xthw^=7rJT)v
z+0k2X8hQp#y@&I5dr~Eo26P7EJmri=gIazC$sWv*o-gj*9~<|`_@fvg`HM9<<)CD^
z)H30ZZpOzvm-*Gw2?y6|`M9kxx9Yo*YUVZNr&;$ZbFbU`nHJkfGiZPMAf|0^aGQ4d
zaOj=G1EwJ}#AJ|z2fMasL&%9m|oivD~9;VpVph$a^6*e|#G#PESwU>>DIj>35Ru
z&Cy9I84Y$$#V@Lf@(4r^CV)7GY{xMF@_lODze_$B${EQEtt<=cVw@+)({*p9K4h=tF;x}!a>Fe`k
zQmg&_I#{OZWDat)L=?*#V#S;dXx3oWdTDC<
z6OYSg^0D(~a~zfSd%SBm`lo2@cl<7v;|RV%;;C_gUjQ5NZ?=H}HUth7&Ag`2i8>#c
zB(W!7$7~_y@_F}w=n57QM~X133c0SOwBKce1=$ga9c103z28%L{+x|L#b@tM`XpCP
zhX47<2mEr6__j}S+x0ki!__>0eGwdm@)}jVb>or3PW7J(B$Ky=Es!g$&_ne`-zyFl
z#X$vpMs3sFc%O7&^RoH*caNSS+W0}uKBZOhDG>5_&~>FkSck_0#MCra8{4oR;}1W>
z6*bpZAWx;I&?Xw&!LmZGr1}56qo$uPLZ%^ng}X|t9J+ZqfOEC-5v8d>;w)|O@?-l0
zE24tWdjWN72VFV`O;aKooft|TxIB|zgSc)`yU5C{G$vN#2GrXj7eeagH|)LYLG~Lo
zKMXAL9P;ZUYSJNID`9MVMz~POdF@+zRiU&?svFwvNyNte%gET`e^yqpLu%^1Lq;Cm
z>})bXF5fn(lqbPNYBnHuR{R3;GVAloinJ-*tFswA(6)ULKFe8ipO+Jv!){MTT`f(f
zY;tv26d%$#|6UW$M>Rud;8V|OCjDHmoY)G~%b0OAtn%c=p?7+k!SPo2xvd4)u2u5M
z`)ryj>HktQw_|2$-wpp|f7yYD=#}QKup7Zg+KE{ABaj~`Y@+SuoZaN`7~%=(OW8C<
zKN8fS8vWEu&yAQDU+$(+^_|jcZJ*jzVC3!^L#^ona^<4>mq`R+85Z%HkDXkUI~
zh+RT#Dcodk{8Q9mYDGH3kCOv&(bRf0qoQlZm0zY6>^P`IDjV$6+s6wwUA*dR&|NBS
zZOQ8MVa^>bu*@ONu^p7UWG0|`XA!oQfbbcWb#M}R+q~O`4H9!`z)>>mx5SlR?y7CE
zn6l+Z^jS#*6CZBdi+8OjF=V9{xoT9o+64=F)q6NwyHUaUE
z<>iM^@SFbC&^|mo+}SDJJ+D<_rlzZ_YiMZb;7}58x00!(q~w<}JTkKU=g+M28SwLg
z9JS=1Ze0#avqBOQ5~89$ClC1wvTYnv(@`8#alyl%Pf?or{=Ivt3(ncx0d=%Wpk=kt
zx>nx}7d*$&sn%L3#>`9Ttg@F<4BuYp3OILlaano75c;yltvpM9scFBj;ICNkHD)
z*c`V%PbewVQ&X21H47{$rDJb%F$x?ikw3Z4ARwSE^C9-2`}Ga61tl?iEEi2Bio^Hv
zTKNs2Y~rfWxPFJytFyyiE56QL442-gW|r~C_m)ApZlNq5R64vyyrtq@{i(6I{hh6_
z{S#c3K%h#rjNY^=c{{)L)X*F_9e1`$k&0go<>19gMuE(`F<$qgeEWn6+9`Qp{T
z9wbElV@SNH<7P0x71Y7R3ls=-)NTCVCox9Rp?0W9wy
zMg?DcZgs$(-TxVMir_J(Xh|T8z#aE$)#)N$Ryqt>sxPgr1%3Qjd|sTJOV7@(q-9}l
zZof$l_4l@07k!7SihHacY|eo06A`JQp;2sWPL+H=i%05{XVRyOQ+f$y#0d)_xNK*@-E?_Nk4sx4kiAGwex!%+VofmM|tKuSs~FmBGn&E4`8
z^>dxxTZB)o1i{QoK3+g$O>9`$j1}?RH)7Op2uTSHWZ>$rM4`PoP`r?ul#d<>KDhCL
zjgxbt%2~mK6&5s*6c(0HUW|*=(c$zqa1BhLqq$7y4tH5PbOn$fBKD_aX@}XMn-ma`&3(-Px_}%pT3opw5{*&
z?+^6#0nZ*jcLAmq?1*Y3Vo|W3vErxxn?!V?Jtk2oNfw2hnwWeO-`(HG$Hg5S=(dpl
zYq_~mWD4-HM*kb)KK?|&^34aE}`=uY>$zjk(ZAWisWx9&%^tR!=J
zoF7l9C@G2SDSTWTE$^N3HY^&d$t`O5JI^s-rQ|m>G=Rm#+4=nJ6lUR+$$IsEygL^)
zwYU})149JLJSsPCK?^|$C%EW)eu4(D$cnP^sS~}<;tcXyu
z;TR?olu3{La3~=y^RdW-ju9VU1I~no2H`?{)LSv#x;@F{JvcZhrN=wSVGyWF1-1~%
zzk%a!Sm4F8{!`>eyju3vwgK4i@88nMVqsGuzqOX=-YknbFN%EW$dy#tC#(U`x{FvJCV*aIZ3f!`a>X;9sl=0a3jtTlEiJ6w1
zoQ^gF6%`d7oo1~EU&vp(WEyR4%)8{05|lzJE-nsY+ZJ6#qC6P#oVVv8X%rT+1T;Pi
zxmdVNrw4LgGmvvzTU$X^(eg7jULCLIVPFVi`U{JCgSAJKdVc@j19L!|y=F2*31(*I
zM~`%x0tvvTR{5598}gVX$T|Qk08`Z4IjoPnFaAmd2?GxgPyXbh@sijIM3Z0DbJwf3
zrPb7;>ud4u-26oTvHPlj{SYaT&XTtySOe-xN=tWF`?pvVsJV0Cll6shFyR
zUtu{pIXyi+YikypwOgm47WZeX1n?!2Tr}mCu>!|iAuhb94{n%OogFP_jYztE*DWC8
zwlm&e8*Agd_QP4$1m(Vju(Znjw*G0_88r=9xr{nvsTmm)-Yb}!G+x0diG}LBiu^XHevKPN2qOPRT)#6
z9FNd!EK+VTe8O>4zl{WE|kRlaq&B@&-gCBulto|hT$V1%z0uibMb|j(SKpW
zy-aAVeKB!sRgs=&Ra>XCv$Knf#;?tu-FktGy3DKjA8kxzj`H$SZ#qWzq1(
z0Ol|>GRoJgcIo)cE}3@`bnEnf$e{#hm|kEB#?R5s_gL7hu_`gjr`H@E(Gj
z6)IVibe9jiX~4%;TwIKmOb%TM`R6C^-{rY8!w9AIKtdQb5UA76d=gu_eCg@vJ~jP#
z0y%25*0YwS=TQVUF}I?;{IkrzkLth}G%KN=@GB`P0bk!7k7y84h|oP8onm!tQvNE)
z*K;vo(!DvoQB{F~F&G&W6Vuz%(}HvH5~>ms?NE1GWjsy9yk&HvixmXr6)J5o2uku+
zJc4>3bhbiDnp;s~;v4yk<@xIKW&ol&Qz3n&Jr$~F&dyqrnki{j^mAZ+{lxvZYXY?~
zkbovu+EH+7pqG(`rjT)eXGiwW#m|zg3Z#?9rltxtl9G};N1{}{W|o%eeHY^wWq66S
z6kRz8@8T~+Z+#yoa(a6D6JxG&wv2$ZbLB-pA)-jq`0El~j8Rjf`s~ifj~_p={e5&4
z#Ev8)B{?mvwcVZbopgbrNLw45KrKT+JZ2oOCFU9$G5O6c7bi0vo{-fQSkF8^wgJiu
zK>{BKKT}CjaZsCrl9I3>Hb>diz+euL7;r;q1b~@_w@5r|yDT;JICF?`>ILE^CMEz1
zsuCM@r!K%bLJ}K|Bc_AYWj$#i*Dd|amq}0`rNzag#R`)a&YK0!TcBw%#H1k1g=wZ3?ISYk=of288Zg
zi-B5yP+Bj3bj@Hv(}wGv_hKoGC{?qmvBE|p25C)a#LkW#*L?^SQ27WiAPHzJgqi1>
zX7A`oYh-qBq-Li_VoT3jX(Y==qc}19&$A2oUpMm};qwOLKxWf-?dUVRsphCJ^PS6=
zFZ*DV1_cJPDQ}|8LNrApq?nxj)mc?|z*
zu{4TPd^ulvVP*z)GX-F60}33*c0vzs$PZ$Fp9&;z<6K@|4)=6{;>SxfTAP{N((%wp
zSW^wr(8ClTJ2;SRcKcKHgux{C!GSyCJygz@5K(2XYKIBCm-$_GG8X&SM@qYBg}DAj
zvt}Lyip)OO&=@(~UYMDgX)aD2GK;X3zJsDFR&fgno?2SB)y4(~qr$@*58)ARKMjk=
zSJ!GBmVbXdI~$*zoOIrv#-np$p`d`w8as-HkQDw(x~8C`GX+Kj{*#UR{Rz*BaS76V
z$SbIdMT%a-8^RaVdaQ~P-Wqp19sr!c^RFEyW+>gGEyz*()
zZ)568&H>WB(J_V%Nr
zCJ0?qN4s^R!9SioyRy(hxVBOi8g9??_%SQ9wXQ{bQ#H=yJyicgMHo)(f4)
z7cYB*V`MQ`L#6g8>nu5#A81!?t()2dB26ms)=*p?Hu9tR?&@mdu`v}FSJIC`F9Zd@
zx3*Ht$+5O_N{%irE&`*0bO+x0(Q;c6m1ie1f#^|9Z(A>+XJ%x`Rx3cRk(X!LJhleQ
zdy5wI?TvTus)>os?d^?fPqzM~O570=l6fKTO`iKH<#0MU)Xv$C?d0s#@&TczZ=hLV
zKn$Pd_-IQ@hL_jFLM$9+Zf+N#6}{;)p1b`j025sQWTr#COC?vG-F4551v4rSR*Obs
z6zqvW@muGBHgcrX#w$(D*pdEmk7INHYmk4-V-6<;_dnb)pK#OTh!OJkj*#dn3jOvX
z^zM__-sB&}dY*~<|C4eyK3;^+pjly+=-lX^4qG>FUMH(V>-rcNXy@PnrgM+2R!ZPJ
z=;-KRei4?Dk$LrMvZ#xn$Cg6qJyTG;grg&8v>vYaO{)yU2FVvMSdNnA?Fxs?+9ZMe
zG48ETFy@WjyLWGTYYdQvb>L%8&d4yx5(jk~)vggB;z4xNEA9+SxflA0UcCJY^$sbm
zu%A8ol52NGx#PM|wn_(Zc_IRW>CA$SpD+%|qQTtU+z_o~;&~5u2ec<@J+;@8{r91L
zLeHMXJI_Z0@Z7o{<#EDSr&FN%IVOftt7;Hp>e0qlU{ohaKTlx2YS-|B>3vv0M8v~w
z1tpc{Yfo?iVdn$x7@t}KCY6gh6L6Ncs03zTA8gDft>+Rwnj&^WcwBpo#>R_so}LN)
z+)Uiul1<;y0ek~}#wGSaZ8E8;smaZi3bGK>dlS63w+C?on%&aU0%hf|Uzu!fMj4*4
z)jg`Y3@jWxZq4kR?`{13|Aq+j_6Yi3S1VCn-Dwbl0M=5F)|@`SXW%BPpH?LKOZrdZ
z1UU8q2OvKHz>*LIKG5AQ*WI1?=FPk0WWLZoKD-&`^vN93=OY;0ytfodTk
z-DqfU^og2G?d*0S9V~Pu2-yEogz6ORi!i=It8$-!pxkM58Z7_Jo@XafQBjQn_?Vcs
z_55d^ofdLHce!Be&!OJcvx7O1TMa#4-iy?pdE0(K(BJA~252c=NLpzpuR%8lmXdksWC;3tZdGU)L
zE^!tg?-w%s(Pd_8f8Jh}xq|5vYJEQ+s*_Ok)~c|}ggpU-WB=T`c~i5>X%iOW^m$DU
zKg%uXQQA7#$x{jz8z?yslqLlRh?#?zg3O>k{9_pvIKq^`9Dt9Xoknb(hLUTvt!RtDM5#+wJx>qUC2
zjU}dI%kHk041nN2BbK$fd3hYa8;Ahmp%gM37Z;ZoFZ}EKKXDn7c039K5wR2;1`i1D
z6oG$n)jPp`FWNmiMhXT!`2BlfM(ucRCMLUu&Uf+gYhXDXH>{)*FKSN1Ck{;+_wq^<
z3DC8*QJ$aUi~RhV1P6ywocGz~89ZFvZ?C?;O*omQMD-KkAP8oYlV2Q)fBpL9>+1{i
zw40eXA2Uk&%35$pr
z9&xQL9ndWrJKSuJsjqj0MNIx$b%$Z0L*uK9eb3SE`PNENS3_eX<`wUM3^r2YFJt&}
ztoF(X(7WIz<+>j4nXf)vi@Gm&uNRnFxz*GU$O#wI;Yr=5kHCo_;TRP)HTcKy@gMTR
zMRaty=aG?-0XNjZ&+hP6e$%EmO=`>J`Q}>XIs_v12RDAfrmkhj+T%ErJ=qXT8(blz
z)ub1TbOE@mz{c2GUg5lLIETP1NEGY1*aLzDJnkja5yfoTpQR)ugkEIiWAET_^X5+Q
zt%>^|eSKd@vKbiUw*LI7`qgXk3I%LL7u1i(%sz{(8Yioos0*@aHO;`K+wv?59xOUBNdx7yfmZ2DRm3*&RQlo}~!ggfs2?!C1
z`S~(zy1l<<3jypQUp+P=TT3`f5XRRj^0QBkx@
z)~SF|Sd|~avTVbCYyW(9kkGPfipdJ{6pF7OQ(=c&i*S;o3N5dGxOYuWeV>|o6l1QR
zbB~+GCF=Y4L_xtsG&J6?I9jm()oycIq7*`VgSETu-m_A)SNUy@t?)S+I-
zeu?M`L^pDjtJb|dBcmmt`_^l-!5`(e3oA3o&Uil4GK47LHc(F=Ja`}-&-y(pITW(9f&@!OMmw4nJ}vp
z$SFmJ9iiw%0*9?K@$P#=A8z1>a@ERrA5q~{xVsMbEOaIaSD)a{R
zfnOxGS8$8D3UEZtCmrzjyzB6wH^9kOHSo-MDW5I%fUH8&Oe52vJ4FK79{OK|!>O
z2OiW;O-;de5;uSbP`m-Y3@I6MAm~dJ6o!CAXR#6Cnb=n36cjYtAh)=jGTfVc$z;3G
znR>w&1vrt&!O_u^(%RG2zD$%Jq@2x8M<;nAVEQ`;&^S~`-~0H4NgzI*=vGD8C^o{x
zt%?Un;EB;Ogi7weji8U|fRc_Q^yT^4`uW+i_PNX2C|7nr&A2Cc-c(cuBDFmZ8}YRP
z#$aJ#g{r{afH#8c`Pc?DA9M3u6mJ9#YvjyksVDV<1WzW+igTVVc%CglU8gyS*woUJ
zl$f~qd>6vqbX=Ff`3Y(}
z_jZ=hyKCds$G|4zk=E0-XUnxPxttHT3=HgqK>n(Rva09akP&LH8EhyjrbRfJ9g288
z=HP%5i11-&-pk6K-d^yAWw`j}NbAxTk~KY*v3bPJFg=gp*^W)>C}mX`R-H?gt9-XQe9dlZsdR_`hUbp{dcl(+yTHNaXB
z0pBB_c-7997ORN2s|i`hO-nO5@8e2KO421;ijhn^KL|d5b%2s|
zCRNNhG(h_V$CtW>259!C-CLv&9@td3Ryl9OBTE330C=jad%AVo>t`?nCdhx&Nro)Z
zRUq6HRaB_&@~Xpa5DE<7!9pUDOiWfzP6rTc@{$Sf+_@tW$#6Q<<*~Qb&S+$4*wonQ
zXWlA=U^(}9OiM{&V`Bp_=nMkUXR)xwi`FCnoW=vVXt&e@E7sfFn_I&irWfpS6*xca
zx^d%%=U!0)Jzz%)3JNMJ-COg@o$Ce5$w|
zT%oL}`0ekO%G(2|7rpt2j7)c^&;T_RKN51T0s4g`czn@t22Eh9#X9xgv9Yo5-(yTa
zKoFq{&)$P_0gXLlWAp+vB2~EOob2pS|L=-o7SehIkzVt->|SH(|EYe~(LNUy^*osJ
zQAn3Qon!Rma^1@rUBSl2)~>Kyg3S+rZ=#~3xxgvSay{%nY9P;-1O?)6vObYnfhdC8
z29OF7<#7oeJ;7<(Zz0}w4eB^TLPF3{_4V~Ke7lMs9%rZ(!N2{JbuWPft?to0(Zw*}
zLllhwU%kia5rC5S@85&2kf&PktjZ0R3UpWtDIyPSxNuA|{;019XFmx6LG*2>-c2&f-q^4TYyD>2O%~IEM?^$~hxc6i
z(yw|18dgA~&EeKuP*4zP7V+^Uo6;g8A8bAVz;P}~gnm6ZI7p9o@y~n?!P6^qck=r?
zlounA^!|O{fB=mG-Nq!506Tt!NDdyXPLfOa@z4JcDL!uiq@7Uwl{eV%d{`S0qoT#d
zQFm+Ihr2;~0i!cK8|&6Bz|Bz9WdhGRi0nVnCLf>ON9k|J;G4^MkjBga0#s!)E-r4>
z>E6hDF6a#}aS)NV_rb~!GCe@XA>gcyJTO*Qv9W`}S{@W+XnX}hdTl4Wxiv{x_cpC3Nct943
zICx9?5vA3SlvVj2aU~i9%6uk(iTFgkK6NKh9Fd+m5G1eR;rKQau
zuh%*{;P^M{zBV=%6BAPfuPb^5n%j9Pz`HU)Y9S)dG%gw
zyB=F$6ikgQL%{H0)yB&2S5;6Yt^DsQVx8WWR-uF1h=_=AT9sk#BO&Yuod=EN$&iKHn1lrd1r-!}F?`fP0fv$a
z2OFDj--_jLuvfG*K+e=+Cl^N#)elec(Q5~Jps}R|XiyhKI{xDo*6yAfm))%8#phO5
z8#pq&%$DO-Knfu8vfTD^JZz+=K^0pWp{VO(&GBn+P&H(@bi%_F`wL_)PDrP?ya>tB
zWKnm=wG*rTwT`nh%p?&)SXjh-rfZ`ILq+)Sy`P5(K!xM-l`F$$C6HQBHlB1`dn#`3
zqs;VpbpTAZU3{g+-AO=_FPyz)?k=tGnfJNArlfzC;z4YkOsM;+=uO3X`lZ{NLZeTo=o-;KN%(3s>FjoR)Iydm-#v4Jd7U-#U9
zxeY>KdAf8~7%kOcqIrN
zE0Dnc{IMzPgwUW2We*7F31>U$x?H@xu{r3IH$YWiTw7DF*;(7TW&RnYlC5oJ1R{QE
zef@B)GUD^+S^x+iA|j^F&M?I9O7(+2N3y%i_uxSV;e%mZJUkL2qOVQ`e%3??rfLvZ
zLEL~`qg`$@2OML6eL|(UzEK;@C6(~lpFe-X{0h@UxGfYA-j9fhk;p{%Y9`_PV+mXN
z!({lg^DIu+cpx8Fkkdz`Tn@#h5#J|oH7n5Ma?Il)Phn>3!@EyKuN6y#+rVg#V2bOA
z=L2k#wt#JXN4G{h&m`x2EPmts&ZIFZac-^k%(CsmPgX-Q
z+j(J8(JtQr4RUe8Sz?5w%A-e*0`TaMmSjASAbP%e^9Bn4!zRUm=y`xurABIj7Ahev
zjko-d9Kx-G@wpX57g!Ii?WnR0Sn?fv&%w{V+O8EGkEol`KUf>nSY4ecF4gwfc=d+-
zi8x9x+aaBxkkiu%I!;a&fc;LDsdI&`Yy#l;UK_oP;{S+O>W(yT-$g>k0xARy1hgIq
ziGU*xV1lXEdQ`XSPy2mEP%Np>V)JZ*DmIKx1a*kvGV5gg`rC#@&H(lIBHJSwp_)>s
z@L1V&Vyx2f`1tqa_yfYX>ZZy}=ge*E|W
zJFCn&G+-|hlu{ec0Y?A{7v@ArKBz4ltvcCiZ;OP*25$bH7j1yG$%-Lo9rFOxPK4(X
znuW5Fi@!TRNpo5VA^-S7-s^yqo900UhmFaDfj8aV-$O#sV$7{__z_XcfQWMRynTG^
zE$$K%pYDJhtx+n?ww~a+R{lgH!pi8nSL-bPW2C&iJd`wm{m({1j>=ZaXP}`u0u&J)
z9zLh`8LB>>N4*IUs6Sak9BXQ7lK+F4%&hzRwI!NW???S(7gtR3r8M%F;VEi*GIAkf
z5ho^UIfq
z;4B4D)bmp;OP?bKh5&@J38?yp$_EYqx66A4Ld#;8FzO;c6
z5}IP!G(YB~Yxbb~IJA#Od_uhEW4W!l3?I8^YiRoXPe1JINxeL$H|-p?msia2PZP$+
zk0IhoN^2Rir2dRQ#lUI1)LRGn8bW_92&beT2ah0wF)~^L{)9?OZ^EVSTL^_-#oe$|
zF>!G&XbEhQP+E6%Z~$+P^W0;Y=V1Ir;NaZHDT22+Z42iS5{d+7$Ii47POjE$NO&uR
zJb=7dqG!LzNTat0Pv5{GN43DFGxiV-?YsV{-PWR97gQ91iI^)WEc9o?1jI~AdK<~G
z+WB(@lC1XES8`%kv9DYSY%?qZo8IbnmwZ~
znK9KvWLatTX{AKu|Dx%-1F7!Y{z1c1@$zsxZB
zfY6|ulE9z{o8cTNDIh5*B{{i61BE!?JwJL}SW@yxSFrhfgi=WimJHT=_rz1%FC#v}
zkhL`%r3kZTQ{Cib{qNuFoO(xgD{3r&N;GcI4{H^~*Ez59c1xy}dK_-SQ;dP}Z%*ZQ
z7|nRK?bOP|*`Bxej#{7p)rZ$_GYwf@wfctBbGgcHCUN*=d>~&CDrKehxC1mShxsPr
zQ4IVn*u8*btg1SKhj--D7y{@84SU$M4#{vhhVDuqOv$Gr-2enq`rOrB-_M
z_`m5^J?$KVp^Off@{8d;iwh4YBq4c7N$KOgH4!+`%>Cs6Y~el!5`ed`G1pKvWf-O7>r6$7!6S}*KCmX+nlp-ni^=kVIpl#7kcer>Em
z*kL{(K-R(L2OlpFkL~HvK=4iP3U{Z9I?3meWD32k^1s5f7&DmUda2}>D3gMk#ke*a
zQ$%C2ucL?4a2p>C!Y`I+Ml^g_;{`KI8g%V(4;sdrTukOdt8JlI=
z%sSo4ERRPG8#jf!keC>=0Nn(_o2ly$8vn1bMQ2`FXHo)=q*rPG5@vVkG*VKSmDu%?
z7yFRK_zgxA~(iqkvTXtq<^M|>``52u4_xic`#ceobrneXGlCcxZ=s#(e`CweUq0HOm;j{y
z=kG^#4C66bv8d6W%efsnk&&il7`RhnIAM^onK=g`okC&kV%II2Zf
z{d{MGsnGk0Vc4YW#Cxc^^kYSlsQ2W;UTv}C<<61cD@pf>Y3XpE$=R($zfgUfKmUM6
zl{GK2Ft38OD2rY)%jgMBmS#@!XS-ACWxANn*1W(L1(~2YxmZHvRXI5yZ5?Dm=b!t6
zitATv#?E(Nc5wL+I)8O++}F??)a$Al_f&b9wmriJ!j1miw4%?SN0O40+olXm$b7VO
z2h8D1Nq}+(1Ue%lOU~7CDvP^EiHV6oU7>*1=I3`hH3S7dH^zmqe~1vJ9TWHDyUoP+
z_Bm^-YeTCu5);}&Nb%b-PZ}iwCH=SSZcK`3x_SXG82B<53ZOoJ)?t{QU!atc#a?mF?_QYO
z^fNO{n45bX6H~36gONwtbIqrMjt~dv6g|C^iS=Bw5hIjo*$8~>b+7$u*xe{Xu%2Qf
z>=>9ZsQO%9zSgs6&ii(Y!+qz?}Z
z(ytf>6>1t-Y5T+z;$YH8y!X-j>UL)_Tip!Ig*t_M?lpM+^o)$sd7AW;muT0}=0gNx
z0$&;@?(~w6Hc_Ay{23-Dri`9X4F*8||26pVuuw~pfq34YChRV;;SC1Fd&U2mBP_9|
zY+VfuK7#D1ygaUZVSNadSyd$h^YfiSdm$>6_6IRcp9(UPOQEpBgMo7ynjSNJbHFof
zXsHMwMODAT78;(Rt?i@qN3J!`Lu48)*oh8l3o?vFZn3cF2qYE39e$PP@bT2cy2b|1da8o^HqPOL|WQ^3`t5#=bRDWErg{P
zH=ooT{i
z0f}*hTy$jQTXJlKr8|lrTUJkR9Nx;<7NPi6XnkOhCB2X+*4x8n0iJhhARmN;ZVnFH
z0GlfJDZZj6XaOmxF;BvM+M#L}8+CQ!fW`+om+G0w9K2^ho(16_H7Bi-=i8E;Khx2-
z1>sYYpWOkUs;unvu-p5r`~0LErh}sQ)@)$0ur@b0>Vn?Xvg&+i0%70~+)TT6mGisp
z$`C4BZ$4}b`?iNq#(&~!OpG^xWx~9EhTf-OV2Td`a&n;O8kR%2@WA*unvVcclQA{I
z(wcijaTVBiAYJrE#349v*iyy}{bB0KWc$93TiXC-?6lMmD5i+0Xo|{$$RbNnkWA*)
z0y&1a_?SM*Y%-Urhy!QOPwURhPg<+jYlC~ypTUQngCYd79ANz67Ze1%5!<)HiP)iX
z3{>+Vuv}TOtkex1yX@1+?!0gdHV7SwM{`YqBmi;Ue{=EIwa7wbF2C{VTikIKTh1lL
zgN@i9jg_LI1z?6lWPIgiF2O}uth-3kYBSauL0_{_3^ZQl!>;GKV9P)(k3{}B66fKg
zP=?#?>3NDq)L0T%+<
z+`gESXoa~YOj7CWtSqp6oX^GSpFw1SK7`&4F1v}*d?7#xoa?uedwWhC|J{#unTB|=
zGasJ+K1OiHCqO+x+i2st{0zziPlDy)Q;D>0&D6T>l=YK7$y1W;__VaJJVAuP^84LK
zMN;&_purqmmj2IM#MNYk>M{KwMekK7Nr(fgG4`$&I^sYWztQ@Lb&my6m=NL=vRm&V
zhSaA&7VDUpF#Wm+Tr~)M#0-zp-)fiQ#;FbW8bE5rXu^cI3gMGfE~J8RAKv{|M#PXg
z7x~3IN_+NRiXPxDJw0k1Ot?kHJWrwaXsC+Ez~=*0-BLM;wcfCN)JlM|6u!BW2(`k6
z0)JXAy4lc*p+=XZyS+V=`Ex;mQl2Ky=;GocGM!Ku7x7G^09(jIB29|k&EN~{ooKr<
z$feq^(@1z6z+Mj^^q|Zd+%zbWm~J(H^YU2c)iQg4aoRdO!G1F5_8l@3bBZYOu@YqG
zkp;0Bh-Xhf6lE9*B!N{XH7aTwRLbV3(GqFv15fnPuX@lwtQmNeIyM2RCJ1gvKaKa<
zwq3)wa3I4-k4m4={ab8_O}wgOfvU<-|L`)JQ>x}u$YDWWZ6_Cm?Hn^9%x(lt1s?E
zJ;{`<5NMVG%qxXL1iBE3wA(nC{pMu~*}uBFWHvCM2N*HeqeQAupHL{f&U(LLOLS_^
z&vkE5VFM=6(Q;8vxQ*=Xw?I_xeY&h)tXFMPrgJ9($DyRU`WZ*uy%+^3nz6C(-as{^
zB)#WgJG8p@MBmeCck}4zC`Htz$gK_D=4y{YW1bW-w_cOd9=_FGcR(|1jV#;YD*ync
zHhXc`nxyGr`AbK?onhW5GidDz&|c)@1|6N9<3RraWEZR!W-Ihz1p_hkUON!GZo5kq
z=;`(_DslIn5W&9{6XwMLo|vT){E!g@^Hy3yLS@Ch2)WPN=-(O4SzF<_0J~Q?=l2Z^
zg$vJCYP2cel6@sGpx}RW1dj<6@*5gKy?ih%jraEc=r?=GlkkYSe|eWwnr<0^_;Zuw
z5<&I27ii1pWYKlki(wjYvZoPVELA97aHhbrpslA@Q!(1#-y}A8`j!d(%@ARlT;x=@
zZ-dzV)lxR>Zx93Wyx7HwCo!i`%i`6myBf{Pii#SnG4v5QmDq@q+IaGeA18MDwZ{+(
zPDbRTvvEP)L`tB8f|KfE7!1i3VX*$oVKbW&Q+TLHNYu*aCCL
zW>vTOlk&Rmzbtr?%tnoQ#BDdx4y)|d%}u-i^u%H&J*JK(CiAdJI2WgBGezAXBLhL8
zrk0k8vGMz6BV$^Kj}=D=3&j>EeDQGaft=b;rKJw17ID~8T4UzQ;Av1Ch043mPS)PL
z2E^uI^7jkn^dwz|naHnc`^sg87hOxcN1*WqZHD-6zedM9g>2;7C4?nr^GTj3k17=<
z$petP7Vvsw7igG++zH^F3k9`Lh=KVyL|@(He15W>b`C+u`~i(9kq|iscvE2H{G69J
zjCvufqC#+FjS#bg8UWKvyLVi~UGCrj7%$<+wVyetcX<~IDFox}x{ASE`Wz)vpu_|<
z(k=0^u5Q7A`Jsoz)-`zRQnh_Db8}yrB^_R^{pxwNV+Pz$mp^#3*1)4gRt|{&g!^(K
zw!|RFrodbIWu8$clj!zEQ+CB~GUC?g36aT6f5Z&akfY;)M{To)d6_%No6t`;BrWGb
zqDF$!J9tkHs^Cw(IIItc(gHPrU$yYh=xFuV8qny3;B!?1I5AjrA$XolkCJ16MF%)d
z4lQqQNe3=Ey7Vt!wnpJsf_@32V@gc$5cPtv^=ih~Z7E&~1q6{(f57QV>F{?kQgt;o
zRK&6OPLHhOD3#MwnL?#WY`6pk(%ON&
z#>#57cMVkY&)w#3puc(Nf1yB7j?wky%xcwH)FBNv$Lu?jM?GPW{;O;yzxk}nbih#x
zoHk&HdK`l?MH$QrOi@6*0)YaLKW)_|#KxnhUpy#uU~lYo2H|FqN_BR3-(6|SXzwO=
z=8lGk@OZp)VH-`qx`BWoP8Q@?efzch;-qM<4v@^1b}p5Sy@b;H}E}Mu3|(M
zr&n2mrc1*E5Qyt)1s8h$rR8Oa)-5|RAhGD&u_z+25J(ag5s7bsj#Vsi49;K)Te%BI
zNIlk5wpifIfjNAobc2sLP)S8aAzM9L9Rz=&!=Tisk$k@LJ$fI?6s$$GT(PP<;k<
zmv({V(&hb%a%~e4mq33wga8L|AU**B-0D35->huVFUd;+EZ+waatv|pS1=yHSZf5N
zUf5H72pJU7gYg%DLam({?Wx(eD9C!z+13OGGOBTRlyorwmQ}*#Kw4~ju
z&U^C!_A%hWr09tP8i&g)ZvOWhEl)cK79G(L6wKZ5<)5U9dmPvT({-9b`2ps*;#y-@
zS8{+;;m4I3xOq^6o`A-G6FN7*Ebh+8rWY1H$5_7
z@-r!gLldTF(6?#B)wSj?)Nt^+qahJsU%(c;uPEQQ18Y7AEwA4|Qy^TzH5JBsH)*fpcfafsi?>*u#`11DboJX#wqBR!3@$(AfI`8
zVZsDxxvVO!KqfN}AYu?+fd9X{8>+^vtx&57+(0%03~)QS*`bE!(3=5v5k>XU4={2;
z+^!I7DiFM{?Pi8hFD$w)|N2f1O^Y0Jab-o<%Y1R->g&Cg25gwB3>4EBuOwM*{VAk`
z2eQh&%))i(TM6Ox<^c;!)amKBgj@Tyo>M0$MsM!F`#yq$(oRlEsVOO$+&+ZyN25`f
zX2!rg9<3Yzg|Wus$e6|9B}7w&5RNUEJ{_p3w}O0OIJ=H-TTr_J#Q)}vNmsZ)Ku#YX
z1K0`AaGgHIJT*I(ko)V`akuq}*3l0dJ3YlUxHCoiHm574^Eo*Un|9Vh$!&j*PWIO-
zle-?&dB17Nl%jvGrFAJR0L4m454+L!Htdb_sJ>UecIc;F4V478yUNBJXUJxWJcb5&Aw#)^uI^?8+{f^M6lv|+!F`&q~}(HS2P
z4~YS9(1_&>@V#c{Ro3MexOog&q2WeIOg|-(NTt3Xd3mXOdwG6-)*&+Od?O^p>MVGD
zhSu+434@ut%py)Je{RzikZYwBRtPQ4R;NSvsV2I5qKQx#OTO0djsD93M1;*6lp{6A
zYt@R?ir}R~FADI9=_t`JMnp*?w5a|
z2q)jafS?2YrCL#ZELm-Iv-n6qfz;2cZ%pfu#B8C;*gQuiDpG8cV-U8*S&HFmv6_ffQ#uz
z@ht#OW=KP1%o0rmg)Lv&xOuAHfA2@gEgkq{%9NJSkm4}?HwN8~Ry*T-2n@7e%gd{E
zivSaWi5qmJ9QzGwG)y5M{8cIHnH=h3gF8(g&Nl_aJH)2)^-zfOgB@A$+$+iB;jKJD
ziGxYs8=iMMO}3}swHb>*SJ+}SaS|Daj5*kc95yB!n#o%LMB0WqU@8u7sDZ-vKU>ms4+Z{{U{njQwSvTTikhd9FE0=vNH<%mn}m3?s08eb3CiLyk`o
zA~PS+y#QdQWON=Mmjn!ef%SwjLVdq~mw2?cfv6K53^{N|61E&*m7yIzFV=SuABR4s
zf3_7D-2M;nTo_5_9uUIKegBLq{n6*1e@#Y}EhG$03avPF>c|5>S6mcfuVU*b%_V+v
z$Hm1!ch5+vj3MAa?IEF_B$|
zU=tuO{M+XMr-0!Yst5hgOC?vvZQd)mxaU8tgzn_VX>a|64L?PL8
zFW_F#cG)>q_5b>%$IJTwd4z?<*=^){Gpr++Zr>++9{e`TdwRNpR_N$TI
zXABl#i7eKw+|oba)rU>AW3Sf^y@f7A4?*u0b!gm0PVWAP%Lp{cOLRL{R^4oDV2W;(&jv{3`?8JejcvmD85s1wzmqLX$oH8jT(u%XQ=YU{?
z>wUUg?Cn`+$Oh)Ir^<4n9)OYzQ85R_MMtwnwBEp*r%cV&D&N_^est=E(#{!N-rD*C
znI-hLECh6yV_~cg8{OUq3AakIg9t6-XBpN138<>+s=nBwFEGQmBrN(
z=yVMV@BrB{pJ7lrS9^ke$SY)T;&jagOutXi}4xRnybXFsZ7k5qUx7KnUDIX(y!VXY?^bB@`#zxQdCa
z)GbtJY&E8k@K*ewwCO4aUk1c`hoC*tx~}+CIkyjH5qJ@P8S|idjA<3I-D>DAP+bR?
zchM&u{86e;)}tObNEUJWWy+V>IbU%vHSKieRWKz})FNaj4j=eSo=jbj6M0Dm;Wf>#
zU)gWLi5w96tTT4nrt0-}0(zm3vOI10-MdLa!TByLuAjd;#`S1tY2CGn_=jb9nF_XV
z2;{r|!FuEH1cnn&wj5%{7=_KLONjTP{YR%eMgh%6h7?Nx_ykwy>+iwd6)PfI5O`R$
zw6by{`h>jO{Y^&?bC7=#JEo5lPu7q`4$IyyNSCTPQT
zdjAqI1@y`v1`1@TZ*F3#{Czl>7%>VlFq6PD2((0wJ1Fkzsif8})n~wv4Txs;xU1O%
z8|6)Ish84@FZcn~>q|RxJWb+?J0Gn(eMVI%`Nd=Ri;d6WyS2r|!#MB5xaL%fTEg()ZN#sy^ybbgqJjwNwq(Ir+
zxP2)Uy`8@oh_h5$;u*r!zqIA}IuQXyBye>E@wFW>0Is$J+)2A*!{dC1`GnuV5Ji
z)bR1+8ycJ=z&FUqVA`S4*`g2YIp7#&@AE;?XQx?AmLxwjMSKXKZfN6>6EX^jAhgC}pAIcw0
zS4~ECVAB9a9h^ACMGhdpdD)0D54cER4RQh4RUwax(y_}{NUTPp)09m~xig}j1ZRpin1&-L1Hh34k#r#4j!z*5
z3uKPKejB046E6SnPXQ8Vbz8#2wNn}zWKGpqcz9~&J<*G8F&!Es+Bmp^@wc{iwA`BC
z#c}M5wtLOrTSy_16jXub6DKD~c5nlhPs-^8QDx)&ox+27eQZLapkGp3%`@G*;+ycaUcv(u%y+
z#)hxn)aft@?pu5>Q#0FsL;S7F8k=^Zb=^dr=j-g}X}_j6BJ}cm_{4>UhbJc19Yy#l
zLV8RAVD&ij-42q^)XKk^JNi+(RSBvE)7rUkiIK{+c}45f9l-jTo#4y4(r5Jex3#^Q
zpH~FdzuL`VY$1xoh+axb&ehOxt&2LY+a*f=4xugUy=H}%#P*huEA~rs0qU;+7)@hi
zzrp(knq%10w_Pbe|FIV$KSN*EW>0uL@ToyWWD#me_pbu|aH-O)I*+dXwX(6YT3$@p
zJS4`=W6BC5q^6@ocJ%xkn3_7vePj}VvDrWL0Pm8J?bIsYlIYFoWe(f8;L|ti+o<
z6W)r{f&{lEKKyred%E_ORdhP$t4~h_a-+-^;)u4`k>)rNr3<{nQ#WCXZU`lCke4^q
z(yCR;30rVc3P7$M9_B4B%IEfx;Q7PZWLild`xx($CKgjx8-6i?4~151fi%m)V!5LO
z-|$tYOQkLqK|ssQ<0ns+9Yva;34Hsaeckro?)h*C@
zvl;q^d@1xSALWN7K|nxMR8f{*2WgMfcE(!OAZHR5e|pB9)CvD>)xNXcSOhu!wV5U*
zi4riE%>3oOjg72!X(Zi`1zBQ}mu_yuFJIn}c~L8u^>@;pn@@RvZ_f)BIw-?d78cKH
znNtVMYg{)o0P<7F2494E83i{1)R%jIE>nr5bQ$xohdwl_~7dl**Nu)hC#eqmhYl@K{8Nd|+|!}pF)F(l~l_9`3=-^^^X
z9h`b0={JQx3W@OY{{7>eoj#>&VG%b#frB*{fwL_$#`9E2aFC1JP~4U_K24vF^fQes
zXIM+$z`!olZFo_>)zzg9>qQt?S{4A614(e{k3clmYRuy?0#`Oi=-?NmW$7>FY=TM_
ztnIsy@XVi}1S-F&tu;yu4*KQoLx31#=179)=jSufCaFnOrmGl-v|Xkefij76@3os6
zkDtaGyfHf`na-^f>{L8rvKHxGV-5$=gl02Lx$-#mnDSuEsO<|)50kZ+<&0ZQCgSa72Ge`xn
zqh}hh@H_`c(cGI4Bn1O)&%skSS4|e|e@O3vMkBkCzlH#DyWmx5L_;+{YvvEwSBAIm
z_UvHLo%-RE7#TcKOUF%MG7b+9H0^Jnl9Q%K$?dpwwj5?*VibwGh;*ga4E_EsD8vkr
z<~W94J1ehIL_A!Ql3vH(WNH6tvJR-{LApj*`;Ef)^HP~=Y27XT)1YVEflF8R?OT;@
zky9$v5zvw^E}E5(cIvjz*>AqNj2L=5O2&sLhHw`dv-(zRUkFquCcWNq&(>xeSmtF`
zC^=!WE{C-Fq|>`m>A2Fd77+`S!0y=ZG3~9F%b1Rq_^+AIiDA-dn(yb4BPY#
zS?CE*sK7}Ea%PbW^Fu05&@=^p9wQ^XTsmd$Z^G@6Rk)SXa+JreNrYFW-89rmo13A<
z$^=$<0vi;nkhhQC~g1c@P8nUpWt|
z22llAgy1@X_^JLMkSMHdYz3b_8Q5#(X&QL|{1AKN_JcK8%YX#94ftlWYm_uJTL_`j
zu`Buh-J>}I+IZ$MjO+-p2lkZ^tZ#IFW>+rS|5pNL>>GIF^s_W{hR78>X)bp5yd0+d
zZ{L2J@@*bw2zdk><~sZ_PqDB3?uRoJ!4kM~k{67*5}wS5{2GA+T|-jb%B3=SYUAz3
zIS0i(LY!HswdsJ(G#G4nsmiE9=mN3E@+izLFweFb8*u;!dXNPSkg{E0a4}%$kej++
zkj;g?&A(TCepC!x;E$!9_Q5y+!%p{MIRrgMG@uJ`#^T%l{;|v0wT%n+oT^g0x+)_g
z?9w=;)TnBn>uN@$99|uzijP9T1b!MjT{e1n@h98m+286qqyM)s(!N6oJ(0p
z@sfFG*b@5X*RLA(;X%sXrW44E
zPK$|2jE&9FvTzk^2rLn8^iVaRBsSCWR4O7bU``Q3keDbn*n+!V0)9Gbx@D8zlMI
z-J1PtppRcX7+itA0cpv}j1h7qB##*x-wh87bHv3(My5t-K<*wRslv=*r(INJ
zFFK`bq3dh=+>WdJP^EP45Q>!wX)@&6LL2rcuH-XUvnWn_9on^7>gyuW95xR_D;L?yB)}cXu|4v=BXE#)v}aE)t`;O|iwr-X(Jl
zWo2nKwLpa!Ikl7HfjN+{g9#2qj3CH?o*CCZu)GUf6WFE-VDW5kZ;XeSD{W$IeO$%M
z>NujMKc|PHikmOCO8q)7PcWU#gh|SvEk*a)nlSv3G0!>gGW=SzpLXaCiSa`|b#^w?
zOW`ENvlSXVKC+ZZOUhYYL6&%>|4xc!%K!XJ#MO2olzQ~qJIx>+8;*hI8|nZRylt2S
zbAeGS`T+s}779eXDtwCAU|&QF93r5aEQG4?1n>!3qUX3M{Hj4zn2NcD6-2QW(t8tkRAemX+y4U
z?x?qS)x7NU_pv2M_mi`KKafCn1UD!5YkJz*$=loi#JVG@ko^Tj*SUR_x*R}rSb{3f
zMvRA%0?=)Ox(UTTq6j&rn9r_ai}U|P;YvQU?$2m8dT`;>5;M|``9&M^nU@!aum*qs
zl9rj|q$K!<^bw|pZ&c|H7(c!
zz%*3zmp0%IS#S)r60uZrX)FX`E^xFB9;g~HqEO1az1`gxi_dnTgT$LE07)410>Pk%JKun^oFma&Wp?88V;&!3(iNzr`9
ztPkPhezQdMj0{TeQ^F;XRmoki%Wb-|vmF2JvL+~HJR)btTmB3sF-<$ccLv-)uK1Ti
zfkpyg;lHb#`4Fv+6HMwHdow)gBMhpbzsAlIQkCa{#alPLe|ag
zFw-jtM387W`ogpABYT$|A8<#||1N_v7``}IVO4T@DME@8T)n(%i;LGmhXiT>*xG4b
z|Gjuf&oKxOxD34)($7-pP9P!2>mZ{>syxg1hqv(wx;iRWoU7aCZ~`8R(I^n3uk^3m
z>)@O|Rz4s8{hN!6tE58j*|T|u^;XIWD7yK$gnWhC=XEkC7vw8k%f_>AI;{xvl_Li@0A0_0Ck*3h=-WH|Ps=ii}+
z5)U4NFz)y1g~E@9ASgqKieOu=Z|8^w;6;ejZexX0XyoOmwhzN5Z`fUX*Ri#=>ar%J
z%c08Unxsd)M?gpH+$hsZNcRGn4v|0U85xjaE0xP@TZz`lHZfjki4l`iADI=32N&k%
z;B^O;DQr3XfLMNk!f|^1zqDraG98q52Q2T+_j;H6Sns)ng?3fzuDY!61vHW&zxpu`
zAp%muZy_^arq!$dFfbqrq7Er~#!)l^G<_Y-3PWlB{craOvKXt!*LK}OOYJE!5roMa
z6C}R@VJk4M2m<$${zxpbf#v)mZTP}`tl0JkPEwsoTPm{l`0iIBQVe{`%)joCzS}v<
z8qw)HI~|1xJ7b<}Op|ck_3a2JUDN#0l2RWbpfr5>sMDD_0`83A>0Ji&22uuS2{&BD
z2m)rHg()h2V%u9E0__ZBu8aeOlbe-=&BXV{N^p6T0f|23%>nq=Rg%`JuD|?s&
z8UxMCrZec#|Mnj1uNVbzxgn-0-7gZ4#qb=NXH(P4g{ex@f4|jcd(7&jke%8>VtwSo
z5g`Yo8=wF!KYz|IEC51VTj03m3P1}ugLXg;`$$g@g7Uxd$$FMLy*3xRX}uUI!eiVsphNSh6lJU+2|TsAC!
z-D|XXo9e4}VQGVbc3w0&{!sy&hC+}U>p)ST1})Wd9L(=tb$tsC0mw^C*^iiG+M?C-
z6llYn+K=Pf=OA2ED}P`Lo#1LKR4}**B=4D#hy$(Xevp`-o
zejJw=8XpIZkkfjqmAeQP9!yF`TsT*+u0xC&DXFF@AB%-nBUNZZTN^46x4pl=b!^O$
zc9Pz&QY#ALL1JSex+i;J>2|02o$LAlfy2-MVp-s}v3zAR?VzfHD$1L_CnWoG@%@j)
zIMFNknSRvVeuq+*5CUN!AS?Ly(e=M6g?+X5Xel4g3vku$9_Z_XoEyKl05EB@lWsjN
zy!`OtzKrbMG3zjGHYIuP*?F>@?3dezc(dIyQke}X)L$TFgKri)IVveB6BR$X5rTK%
zQLHdm`??&OZ^z;e?0K@ein*WWYOqY>EdE-qf#=Ho$&>D;ruflS9RIf+b|~$P0iG*r
za0GqLiFR2TAPQ(9A;gnc2&(!%ruB5Oy^}p!uD>-K8&_3@0FrvVjux9^V^Mi5
z4}=QtGWZh`(E)3azPZVgRM@z_@cZk>FX~|QR#HnY-kJ~;8*|w;->!6c(h0!Ytsp5(
zzE0hPxslttMcZA}qa7arw#nDTi%~chnt3{nFj7|T65X(+&kI(H8cH0;-F;Q{ejnYUUQ<5xyxIH`
zwf@yq2y3%`U0qrI+Sr6iL5_@0*pGpDIz;LSnV#OzU`Dg?ETg@njMWZ?1wE)U1{34B4|Nvr9SNkEm_AiwY&lnl6uZSSv@@$;wD*{09zS%r-k
z;RRgtYfZ>0Yk%ofovT+w7T3PKkFB8C&Yvj7adS6-UyA-sU|{+;&ZjxK2|vAW(H-Nk
z&`EXwsYv#Vk6*Q|Xf{ePwOH1>FF^i^Ica!7q(1ExT69h$2-8=Y-Xkr6z4BqIKbdb2lxU#!%Y6RITGLUNvLq0x4nmly=#THbysZU4`Y5@tW)6G
z1V#%QAIQ=xeOa~i$y~|*tV2w9)lUiA*Ci)sB`S)9W3WIf*s-0tPBI;*U)}tUPxe2<*Si4FKqiEFQs)~!~Ee_fn!&4$1_$6XS3u`9v2gd(*D91
zaz(i>LXMA$DV=claR+_X3X?}YfuSt2jC3^WJY{10o}v`i;X65>RM
z0Dy~%j0A81;&$X1kc*dLLA<{TFRH=4tFOh15)y_hg>Cq%hU{q5JasK!@P_F)hjx%6
z8Lam|j9YKJ&S&;;@mTXiv|)0x3C~d7
z_LadhzLHg_KW%@AOqZf1v=>t15v6NX;@Pw3e*IUb6?40F3iAp^p&SDVP7_sEX5#se
zIeR$m0a9YnMw!*sRiG=S--0H3baWKXd(mWNB$fxa0MiV#cWv|mZisrc=fW+K`E
z*HY?XiFvm&Sv!nd3%-!U<{<8Bi5wy2Q)n*E#<
z@)X}zh*u^v2ToHcC_rW&rVT4$Vx%i%|1l+1XNjum)4ygyRJtAMjt0B1=^Ay5^b2Dx
z%0v>Bnx}AR)(%MLGYRpr!2K>O+X5UI0RIrHBn}gu$ut15ObIHvim*P>+yLeoJ^6r^
z1)hbH7`rATGvtpr<^F^Oe_PkcaH4N!?8mGRd{$j1jYsP2595?AKoX*+&El-=5yIrz
zLNK!Up<;Y0{|RYP}0Yg
zaPGWl&@V&AI}bUJtJozTYh@||Np9{J>(51~2sEPWGBaJQyU6fEW#~zjIdL!zQ&iOS
zQmVYYpPHEwMQxMrNv7l$Nf9G|kdd-aB^)id{gl`0YZxrl&qYsk**hxHl6r#m4wkk93N
z@fw_KU2!$adGK80;mMgC*FQ6>)y+fqA-WqU&HiGpVmVV*BCaJTlMOY8htkA>OA#E(
zRk)8x0WOfuk1=_b3!=P^?$>V{t`G!7Dlp2+!vmBcqWAee?Q_q^NaU}slmT4aql^qN
zoTKvc+=>P3XVh3@#26X5MMvXPQmnYLg>DKKMzA=5>&o*lMRR{9(3e_p
zM$Y5MASVTri8h-|I(!$Ue)H)$e~5_r4g(ml?99CIoCPS-!?DLn$aH`ID}rq5r*Obo
zr|(gB_+XfbBhS1nl!YMQso$L1MTA<6Mm1MaNnU<%`I>s(+r}xi{yVr_c>_yu%>iEo
z;TLejqYK-GaTS8G2mGNc}9M|OI*wix++xdqt<2Hp|Q2fN2U*G
z3G*~X%0!+XWEVS8hTfrsh?(>`^jZIyf|D}{
znf`#RuyG;jHYMf1)f!N4uWhs^DC^6F<^cw@}cJ5
zX>FU^g7iN~OoE?A9Wjm=1xSE`qruQRPe@dXQMkc->$a1KRb!(kS$lndbV$x3c+NiH
zzc9&Rp=;Q1Q6VECz+Txyy?Ij&{*|bxzBl*p=l1c`-MMmw5$hpS*xes3Gzi*1K(x<*
zS&6ADisSWFU@_%8*m!MLlHC(5GG~ImegnJ~_t2Oa|ElSkc|L=j$gYlSgan7hsWi
z11AHeh~_FP1UXfa(x{#|Rf|0$O>3EvoZrvT%7^2o01X+pt^;>FGbwSP6x6*7!^7(}
z;raeVarM|(UAN?M5mON!QBgwyUSaS2+*eKJPO_QNDtFnL$qPQkv)#*=Q|_F%uQMd4
zC*BPEFjnc5UshS!V)+d~3}pJ1G97hY%cNB2Cy)Jkc}x9}xDqFTAv1y~7PQ9mL3bc`
z%nPC|R-Me$J=B67x4AVmL3)EVobX=`B8r?JF24-(1-bwJM;lgg7@5`W(I~Q0#3e3SuO88?Hc7>?Ty~1Zji)Pp8
zuJ~ErZE8Jx;$6R9C&6dzTwRT%3(#R#lJ5zY+G?q5wHBfZm7)jcyL;lF&&@o|L{R!e
z!Y2-9e15!M1haEa^82oCRVPP2?@j5Mn0uZxGwQ{0Z5v|9-XVV#U=7?{51w;b
zazx58Ym>Rnaq>n;bkkUaX#^4
zEycdxNJ8l6@2Ty`Cc%K^bz%7Qk?pa}S>zHOdRvYnm+GI2Ut3+ZwyNptoB1|cW=UBc
z8IFfk9}<25;!_^wQOj@XsWeZ_%zhQ=ff|9A#$nY05K~9T{#EC8V>o_|Aw}gbp{41P
zGELY`#i+ouVp}0DiN7w(e|9MaJA8eCA4}`p<3UCaA!J49f^6e?CH}tNp0CgvO-)QJ
z==t=LXI#db246&01`9ICtE(4UTITpV$4Zk=S!kt{-oGK_qZQt`hH%1nOYXYK^Ws
zgAQ`Qd`6@mRYC|zG$fA^V0!p5`%DiRfrkBr?nmN!|@CX%K9I=F279DmdbRtv((As@K@QEhx^
zcox(Kgy;dDypb;%qsKIwdX`hlxhcYSXkfy-x^Pv?MX--}4-11&njMC?Om46+XMOz0
zCM^7rA##F~p@Ay*6SK7caIC{@{>PucG&@xJ6iT-Z{LDm-T>p+hLLyi>(T6dDhhxZ6
zV7~R_L@c1OXA#7?i@+oKUVdyu5(OflcxrX2A=>_+eR|^=YB2#5qHF%~1=npD@Eb@0
zp`Ej3CV2JcFgs`Q%3gU=^`CIY`5PX>mGXQP4eLY*ID}rm@j3_(|oQ7&68@WKK_*>WxCSvOITI)`zgrD$8$X$Rk{Nl${oVVgLjugLG*fYR3&%s{k=mf
z4UIc9Gi24{H2Cirh%29`8FOVZG2R*)xG&tANlr#Vy$W#3Vw9?msEEvo7mM=U(ka}W
z{+ypbnb=}eQ7E?nUo%N>;Vbb{U+k-tIi3JEr30rG*h;VX3NydlJUjs%K}c~v
zv1pT#n~si(eA`}at$$IGE$#0Xl@RV0iQbi;Ty!RH3?z6pG&G}O!_Cti2|1Opk5SNb
zc7AS_*J)%JG+>Y3uLUnIc%t&Kbu6{mKt
z?)3Eq?vn%QK7_!25gTrXG$AGynwxtHatJuQ=P@&}z>v$kmZ+>O<0qO2ckeC~{sEF_
z>QQU63}5e%3YAg<0TE9`;^)zF&blgh8zd6Xg!~GWznNu_B0b>%fCU6JU~Ys{r99vu
zvG_pX5K;+8mYw$ZC#vl-cYlU}ypCzbIme0x$3MQf|D*QGz+%PtxZcFkpTFX-Q&kSn
zSH_=OQVphXo@ppPSwF6|TW4Zf%aW7-O7`r_%E1}vS3lBn67bx|7}}(D!y&Bq;$mtL
zlk>eb`;yBJUx`cbz5ZL=`Cl$3JSuF%k?a-eJ~Uv+-I#iH}z;ZpL1-7!r=IHv9SE3V2CF3-7N9Y2uVY5SAkEN<6U+6Mk2O%3#I
zUFe3N&aNsM8Edkciqh>X(rrpiPxL3&bc-TY7J{0W(|+Ce;{PO*LIyAcSTe0vDR*%(Kkq#EX*+$gLC=TmG4H
z5Xc_3(N-{s#u~kr~YMYF!3LF{>r@KaDJ|UM*EroYD*;YR2+=M?^6!P-Efg
z(X`5B2Es0lX77C4NlgO3~b!@T}=-$|nOMgV%42{5%fq1Us6EiWM|KD{RN@}au
z^9fT84HDJk@{#3E6NFdNf7;!6Fp2Xv!%TQ>%VEOqVWlq6LultA#H~Uq{+&~|{ka$g
z(Di_J8uP*X-gm@dFR*0g^oz!;1GN8-rSlG?`hEX@Lz2uwRf;z%I#PT
z{`I~G!=>Ku=(SMq?^}+^shg^=W|2D6SU-e2mWT9Q+eX7#C|S4MBXc=d!kiIU9E(n_h|h7
zpBhz_z1=+;3^Ar5^cL82IA^^ZNeV_1z^A*d(#LHw8P5M(oX`-Tg@DzlzVG9I|C-CD
zHC4AFP(2GwViCU1%=G<{^CmK1g#|-F>r-Hm*!R70t1V^%*VToC%mO$k-VHnr3%0ZU
z>FKdsQL!PG@7q)WU}i3TzQ~7F~^eYn^)1
z{pICvd)6-37xp3|6FL_`d*CMUTsBQBzb^nB8PLfE+iu95i%6XMs6(N=uS%V%su+t9
zj*=omECq${A9HZ5ogx^p)qh?Nb*%<*dI=uSmGY7yY6U~g(aC#Py5Lzk+ouvo(sGfJ
zX0eS61$z9JV(}<0WTaeriYr~_LvLq=PyQ#rRq>qA%`Z^R#y=AMz5^4+G>x1I-4+>{
z!V6SzN(3HFRtuazKj&cZAEIfIvVf?pqAFfjS4%Xwq$HQ(zp1WgEp^k__)tiwFD&el
zSoQPX`~Ng9ZIpAZdz{NOn!KVqxYos?UD{`hU+GzS&XassbB4ThtjXnmjD@mp9OjFJ
zkPUOo6IDHi&h~F0i5Th0$f)vmadgy@JyMRmU}L>K=X^Cy7{b1)OsK_DwmB5V(fIyF
z*FT3xaKiX09OtLWz^*y6=1)?O!SoW`aB7|4dAc_1aDmK9R7QgJbf8h3y^qjoG9djn=nmR_h_+$Wro8#nu0
zihSURXQNPMGo2Kbx_Bqp>S=zt5yBFmldO?5#dR_q5s5c?)QMb$HPaKCARbZ
z{jgs@SFv*J-R}lgT&ray%G%~^r;9`E>)G?w9X7vzrw%VA5XPKk^pP!FM#jo{CwsCI
z8V72-kvL0VUpO6J42(HDg~OJ$IJIVkZo83ULZT|<-%IYvpcNE!UMV}Xf8srUpvA#c
zilb-AHRX1AI@ZAX%2XoJZDFRX)BmD#WL8wxsOOf
z;)1Jh(3zj5-bXME+`G2`KotNxiTW?7@Fy0Z3%*pjx-+zjRcJ6kY8oJ|(w9|L5c!Xf
z<8mYqBZ~rT%Lm3JWFAnEWd$`ZO-@E~-l3Sg9j2>^
zS!N>k)W+YoJ$bwk`0OzyQ`Fd^D@Ks!x$frME&i?FOJV1)07YXZKOg3hw{0mhO(z+Z
z$1nR64UA2wE`0u|mp`!b6*<(E=Fh$6^2Ks>X{o~h;4i$x?}yan(yhlL5rqqnDXyl)
z*xI?Q&nS9-`;xi0=ZN2K(g@>;Eccd^la%yY?D*HOSAu!+d8Jjn>Z~dYS0X3xg^1qI
zpEYiWv@F|KjYcEH1a_+3@eN5|gY(eZgHd>uH@`DMa}#ugU2O?0tsw<-Le=`hkhc|;e?s0WZE=d`I>*f0lxhXV1{36%Gj+UABbO>7Hjb66(16F#FneKv
zjiUz;B=?aZ%l1@dq9`NN
zD$tIY2-A{>@T%|q`X#qN=>{c@6Bg?umm5NoBBU2QyZu-F`3`Bs75<1B*S2tlb-bZ0
zsm|SwFFBQ=g(CgFevGekC_VDE#(S8p77Cl)zD+PGoKQ~{`L?t2Kro@_lFQq^P^aA#
zzND&)=rdgP4|qeGIzD|;@%3$7aaXJT7pldqH0H1Y9GIJF8@3Yg^x>T1{D5TSS@&=&
zomqDrSmBtx^WIz`<1Sz6ii9B{{~SsnQX!Ppr6$NZ^xK`h%b8ZX1qMicVZ#E0yZucK
z8MN01#>dfgp@)Y8lN(M**>Ir&mZV4hpz+L1*Bc-n|*D2Q783
zgXW-Mjy-#a&Ko_rZmc%ET!l-=BTgPCHk5rpOd(bykI
z-U$oN%41bZa(=6;^y1*#R`LRyE&;c&^<{pZy(bDoRLA!tamY9Ixo=T_2aSjZ*?kWh
zXw5*fcp~t|tPN~=C#syV)!z;%2?3_G_(Ys!^7ANst!jkrt4lJNCa=g=)+fB(VZJhJ=dT_q)?E63NhQht~g
zO>%;n_%VZLZJYV^%5slaXyup%L}Yv?zJh@EiR4|mZ1g&@WXxoJ
zy*4LzKtSLlqI=eY!cFi^@cHIzC5r${lA=JZwIx%8^MODz*DJ
zvd4y*b$fqzcM_R^{*)4+bA`EdY-~pHV?9Sq8{yu)KCA~-p!G+xrZ0=v@vbqC=P8w|
z_4o^jRvnAG=JB}*>nB2Y=#s`9`mp7cVeBzHq{ox*d8ct}Db+~}27T?gU%R{N4S)Y<
z^libGf69mb;3tBuFt+nKD^<+g+-dv;eu_)o85z`J-9P2Rd8p{Q41|*=6aU4)_1w&FuB9(`;_8KRf^qylFtFhD4*FCLFEIsIPkwZlWuQ#Rc^ZoBUqRriK#Jx#35*ks?m_k4X*gi?{%2&b^vl?*SKHORA`{%i2DvT_V==
zF2#z@{_eT~;l6e0{Co@TC8ni?E&b}R%R3A`JTVIbjOhy$lf8CydpVbfqo1b5%K}Y!eO6&zK~WU
zNJ0hFC!tDbl`gWl1NS0B;fuSbY*{bJls>Ls9dpeH
zZc7Waif>IHjDB5qqli$kF!v~r(_oS*9G;#IIUgg}uRxE+PcLjem9xjJ%k_x7>dZ5^
zxOsFTX2Cl>`AC4`l;3mG+cxn}+42~$=#URG4@|pEUTA`!_^Ixi@}oT+7t(3@X<^|C
z5HeEsXUra$d^>-Jwy?H|F$!;f9U~ZELSQ7z93Lt-&X-V}kG@Fu-XQz@nPMF}nGH9l
ziU)$gTm)ydRBCh<;x{n8PMoM5qd(bJ^g*N{9a^Yrysprd0SL$B-XJJL!8W^fYnpV*
zo`{XY2vvTR+nNjC%utY5xOrEfFhxPlWqJDru8^jGWh)}WLl-WhS!nzdr*iCkt{~dJCZp!PrHGp9S_^RI^TBgN(
zi{wFn(o?@XYz*UO=MK^n@onVMX9z7oFwxC>?&U=Gs~8aaOdKE9Fh@h-^+oD_^#fs$a<|$UA)x!FhO-apSqSu&T-$g9P|y5?a|S=-QAW4f_lheUjBRe
zgOE7AzE@)+4A$5l&S0wE%=U6miA(m1y_B9PB`BG&8;)|r~x1wQY1w>PDA^dj#-(Iw+Uf4v!a)SmE
zJmy4It+z5j({pMpC??ub^whk!!xj;_1xWd$=}g%~2KZ`$4b1!YmOkGzQ6F{t6{p@IW+)omU(bUwG*RRtu%%W5V*xQVV
zH5(h>e>&HcmJV2!B!1IEppm>6)&QCNyXRQWW9ch+I-QBFJn!O!9Vk$}Ya^$E?#Mn|
z-Q0}p1Og~;ByWI0RPSE&wXF^!lt(Vn5aNJ0kfJ+p9ep+801^k=oo
zF~W4O8{Ah`7duPE#q)Ju+{Kf{EJ(f?{e*J0y6QdKIR5kJhlweeBsBC3K`hMo&z~28
zdjKhbhL5SR$QrhEDN@KS=>xA;LB
zhPYeL2AscvwcVfp3o74eNxb5$mP`SFG+D?2KI{P*BCPtm&hw-y&~SVH3?tTZXMQZ!`Z9~c=M$J_}X!p^ParaUJLuLyzI2aOb7)0h
zmfeTAXPrhLb2l7ych0#?2k~B?HN4rP(svMh9z|Q~t?okpQ%`_Ls*H
zrgZWlzr(J0R3F)SdzyR2-(IfgB3V$b<6*{_v3YmVtDR9!hLQA^y1ErAmP@R$lQpBoGtMbd|Owr~-8`Tuu*d&PI!w)gN^)~Dddu67C;r7SR%)boS5c?bt-F@=eQV9VM>lqE
zoC`KHHH~iBzIRXH;>92wPG8CxZ#Qjjv~zGNJUsb%_*r9PFMfvMp38-wN*szG6zC&i
ztXPhzHVF`6lwf{t2XXFRV_;Ggz4Sl8-O09PHNHgW;r|_oN$3`LS!2O%xuWKQ{5|f$
zm^FhJRq`1s2p+f`s)jaKcXfT3+R#N_@jE`HYsnMe`1|)Fu%^Lt@@i3o5028iPELU~
zHVso72~y8_`QPNIC-A=T;n$h#9#X3W4Kf)ff3VtwDO-2ZmEQGf{R1%knuno`FlvOM
zKYqhaN~%sp0}ck@eTNNwZ0vV5TYgImMgj>p8VgedQtBq#1I(LPmD@cE#w+VnJc(0J
z+DgY9I5~wHlG-g{Oy9E%SMgz6=+hjCrF>m+=ay@t^y4EfN(vc;HfZj19NYIMxYGl|
z^w$~Fs+toqDih_G%Wl;sz&gR9Z{YQO+rmN{U52pb`UIRzAz$6A#|+qVrr009|J5-m
z1LS23vdR@aR{KXs9e6KXA~PinNlF8!)!N%shhW7Tt%=DsEs|z-mk?@JmPY*^Hc|X0
z6J?}od!Iqv^~Pf{mNc!pzPzM%GLWk?zvb{3^9muad^wUf~8w>Tvg(%-%n
zBoFB@>E@@f(T4=v@5Ne>u9MoZ_ZzmNohIc=U$iYW
zw1QS-H5U5O-$_W0%KBX)9Qw=*Ja2C`%CPSp9ls!ZA~P=2P9?Wgh8;$bQB9AI3zoJF
zQ=DJ0_avXm3_kl#jrw4Hfd>)l{@djOmnlY%&T-mVHA1_9CpB7?JIL8v5*L}&`Be9g
zY+7}3A7qPUj@;Y~7-}lPmzVz;$W?@ch&}Z+_|h>k;%aMOE#I%W*FX5km3)uw$Y_D<SptUW=QS^ba@lD8BpBRz;;VK#TE#~hzJ_bs>N_JBF9bG|gh8BPJP~$1#
z_rK#Qlq{3b!;j+D+*$E@{>JAUbkusjY5*)az{f|7!%QUEt?D?eIy?KgF(^0uxeC#M
zR;f3Gu_zRE9x|%Uu4xB2|8bQ{arkUu$?AL@AB_S|mE-N~6e(7GeB4SzB0$XOn*C1+PsAg&jV+XZdc^
zqsZk20Rgtf?bcQmE(S5U3{vcJmCmX?atMD3lFLzIK*Zuq6mmTK<
z^-@S{u3jJDhw68_Ga!%B*o=0^FPc-WT5ff>Ra*MIV3dlgl~k&)YV`fSHBAof>>+IC
ziW;#ZvR9`2yot;b1-JW|%rjx!_T{S|O#!^3kMx+RY%uBW>e0@S_noWT7uL`gS#)Jl
z%H#SRZ|Q2DMMru6?o}612+jQrz_#iVmq0@A|9fsMB7&{`-RVoxQ?WYI0a1*hgDvLk
ze|M`|#GHzm)%6N>Y{9iyI(9)*+pHm-DvU`+IOM=epFUDY|6OrB3x~n}E*wrzL|?y7
zIcHX#@W4#E)FB)ZGn}1>zFJl60zK7s%S^OYsScgJBp$))+^)AzL}&4_m#dx4G$EYJ
z*T2fDnKJ;510(!jx5lQDf?tV$0c-vdsDg%tCJ`#x!9SNvKx$^?>1lx18(Mn_Ko@bU
zo!;(D#O0q)7}Y8KQdB=(y70eOLOUi9FmE$QHa0fP3%G7lV1x0w7GTp>#;V+aaUyW9
z^Ij!`h!FXfDD<_B!ZRqt*Sfb
zJ7AeS-ak(NGmybFJYtnK8WYDZ?E&IafUM{uC9&nMwl8YjUN;-EI>WWo)5BA%r;8C-
z3UoeKX!o5*0`=(LsMtz_O;@TBT<{$)jeVs5aGSYm!x
z*ZtPE+ce?11j5v&Q#?&}`#b3rM-8p#&2zTZZ*k*0SjkQIH=dgnmu0^JlIDY8a=UY;
zj)z-f-q2Tyb(AfIDwi7FuNL!6eGDgs0o`iz6RdZk(fYMz^}cy7QNDyE&+1keKcYbs
zkGmr}cK}$kfLU$=Br-_t`3|2>6spI*jE;`y&DTLdfnaOvJ$oqQUH?YoIV$rOk`YE@
z!JNHi8pPr8b<@gP_1w~bXNFBkjg6CS7r{+%_-|Qp=12{a=;7z);4x5DN@xKPaKJ9X
zOddG)yNZFpyK>t63_Pz0qNSz4R9@n++yAajj-la%w=gTdE~E)t+fB{l*UW4;k2jBn
z4;6hqo@ip3Y3HBU44Nm8PoGRTgVDw%VL@;!*(YzTU+!ITpnXy@bkHoinv>J*e~?ZY
zepm43MH(|zTaM%mPUrf@l&;l{jhv&SjU2uP6^rS}6Az@W(1>VjyoBsuY4LmAmXqGo
z28t+-w?9JZ-@I&F2CCw7jna3Y-F%znH-&oD>N9bNU^
zjvI$ADoW;we>u}rJ!P8KT{vPa$W%IVv-AU9m!0nClo0wM}BsW760_@59f)(cvtU#ci%jIZ(Ta+Fq}UG4a4_C
zdSWRxKD*X^(WFc;aFhCW6$xb_AkqvHS1TvL`M2sU1NjuE