From e504fb0f82a3be50b06710c91ecce07358d4e625 Mon Sep 17 00:00:00 2001 From: wangwl Date: Mon, 22 Dec 2025 01:46:45 +0000 Subject: [PATCH 1/3] add SEResNet --- .../SEResNet/SEResNet/README.md | 5 + .../SEResNet/SEResNet/Se-ResNet.png | Bin 0 -> 109948 bytes .../SEResNet/SEResNet/model/__init__.py | 2 + .../SEResNet/SEResNet/model/resnet.py | 379 ++++++++++ .../SEResNet/SEResNet/model/se.py | 19 + .../SEResNet/SEResNet/model/seresnet.py | 186 +++++ .../Classification/SEResNet/coverage.txt | 3 + .../Classification/SEResNet/model/__init__.py | 2 + .../Classification/SEResNet/model/resnet.py | 379 ++++++++++ .../Classification/SEResNet/model/se.py | 19 + .../Classification/SEResNet/model/seresnet.py | 187 +++++ .../Classification/SEResNet/seresnet.py | 28 + .../Classification/SEResNet/seresnet_loss.jpg | Bin 0 -> 35249 bytes .../Classification/SEResNet/seresnet_loss.txt | 29 + .../Classification/SEResNet/weloTrainStep.py | 692 ++++++++++++++++++ 15 files changed, 1930 insertions(+) create mode 100644 PyTorch/build-in/Classification/SEResNet/SEResNet/README.md create mode 100644 PyTorch/build-in/Classification/SEResNet/SEResNet/Se-ResNet.png create mode 100644 PyTorch/build-in/Classification/SEResNet/SEResNet/model/__init__.py create mode 100644 PyTorch/build-in/Classification/SEResNet/SEResNet/model/resnet.py create mode 100644 PyTorch/build-in/Classification/SEResNet/SEResNet/model/se.py create mode 100644 PyTorch/build-in/Classification/SEResNet/SEResNet/model/seresnet.py create mode 100644 PyTorch/build-in/Classification/SEResNet/coverage.txt create mode 100644 PyTorch/build-in/Classification/SEResNet/model/__init__.py create mode 100644 PyTorch/build-in/Classification/SEResNet/model/resnet.py create mode 100644 PyTorch/build-in/Classification/SEResNet/model/se.py create mode 100644 PyTorch/build-in/Classification/SEResNet/model/seresnet.py create mode 100644 PyTorch/build-in/Classification/SEResNet/seresnet.py create mode 100644 PyTorch/build-in/Classification/SEResNet/seresnet_loss.jpg create mode 100644 PyTorch/build-in/Classification/SEResNet/seresnet_loss.txt create mode 100644 PyTorch/build-in/Classification/SEResNet/weloTrainStep.py diff --git a/PyTorch/build-in/Classification/SEResNet/SEResNet/README.md b/PyTorch/build-in/Classification/SEResNet/SEResNet/README.md new file mode 100644 index 000000000..ab4a62afd --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/SEResNet/README.md @@ -0,0 +1,5 @@ +# SEResNet +SEResNet Code Snippet +
+ +
diff --git a/PyTorch/build-in/Classification/SEResNet/SEResNet/Se-ResNet.png b/PyTorch/build-in/Classification/SEResNet/SEResNet/Se-ResNet.png new file mode 100644 index 0000000000000000000000000000000000000000..7b0075ed38061ac48689e44ad944f9a0c4bbdd77 GIT binary patch literal 109948 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 aKBC61;`=3MT{}K|dgP>(B`d_=1^x%iMU{{M literal 0 HcmV?d00001 diff --git a/PyTorch/build-in/Classification/SEResNet/SEResNet/model/__init__.py b/PyTorch/build-in/Classification/SEResNet/SEResNet/model/__init__.py new file mode 100644 index 000000000..16ed6037d --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/SEResNet/model/__init__.py @@ -0,0 +1,2 @@ +from .resnet import * +from .seresnet import * diff --git a/PyTorch/build-in/Classification/SEResNet/SEResNet/model/resnet.py b/PyTorch/build-in/Classification/SEResNet/SEResNet/model/resnet.py new file mode 100644 index 000000000..b4bb1c2ab --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/SEResNet/model/resnet.py @@ -0,0 +1,379 @@ +import torch +import torch.nn as nn +from torchvision.models.utils import load_state_dict_from_url + +__all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101', + 'resnet152', 'resnext50_32x4d', 'resnext101_32x8d', + 'wide_resnet50_2', 'wide_resnet101_2', 'model_urls'] + +model_urls = { + 'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth', + 'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth', + 'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth', + 'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth', + 'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth', + 'resnext50_32x4d': 'https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth', + 'resnext101_32x8d': 'https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth', + 'wide_resnet50_2': 'https://download.pytorch.org/models/wide_resnet50_2-95faca4d.pth', + 'wide_resnet101_2': 'https://download.pytorch.org/models/wide_resnet101_2-32ee1156.pth', +} + + +def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1): + """3x3 convolution with padding""" + return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, + padding=dilation, groups=groups, bias=False, dilation=dilation) + + +def conv1x1(in_planes, out_planes, stride=1): + """1x1 convolution""" + return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False) + + +class BasicBlock(nn.Module): + expansion = 1 + + def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, + base_width=64, dilation=1, norm_layer=None): + super(BasicBlock, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + if groups != 1 or base_width != 64: + raise ValueError('BasicBlock only supports groups=1 and base_width=64') + if dilation > 1: + raise NotImplementedError("Dilation > 1 not supported in BasicBlock") + # Both self.conv1 and self.downsample layers downsample the input when stride != 1 + self.conv1 = conv3x3(inplanes, planes, stride) + self.bn1 = norm_layer(planes) + self.relu = nn.ReLU(inplace=True) + self.conv2 = conv3x3(planes, planes) + self.bn2 = norm_layer(planes) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +class Bottleneck(nn.Module): + # Bottleneck in torchvision places the stride for downsampling at 3x3 convolution(self.conv2) + # while original implementation places the stride at the first 1x1 convolution(self.conv1) + # according to "Deep residual learning for image recognition"https://arxiv.org/abs/1512.03385. + # This variant is also known as ResNet V1.5 and improves accuracy according to + # https://ngc.nvidia.com/catalog/model-scripts/nvidia:resnet_50_v1_5_for_pytorch. + + expansion = 4 + + def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, + base_width=64, dilation=1, norm_layer=None): + super(Bottleneck, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + width = int(planes * (base_width / 64.)) * groups + # Both self.conv2 and self.downsample layers downsample the input when stride != 1 + self.conv1 = conv1x1(inplanes, width) + self.bn1 = norm_layer(width) + self.conv2 = conv3x3(width, width, stride, groups, dilation) + self.bn2 = norm_layer(width) + self.conv3 = conv1x1(width, planes * self.expansion) + self.bn3 = norm_layer(planes * self.expansion) + self.relu = nn.ReLU(inplace=True) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + out = self.relu(out) + + out = self.conv3(out) + out = self.bn3(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +class ResNet(nn.Module): + + def __init__(self, block, layers, num_classes=1000, zero_init_residual=False, + groups=1, width_per_group=64, replace_stride_with_dilation=None, + norm_layer=None): + super(ResNet, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + self._norm_layer = norm_layer + + self.inplanes = 64 + self.dilation = 1 + if replace_stride_with_dilation is None: + # each element in the tuple indicates if we should replace + # the 2x2 stride with a dilated convolution instead + replace_stride_with_dilation = [False, False, False] + if len(replace_stride_with_dilation) != 3: + raise ValueError("replace_stride_with_dilation should be None " + "or a 3-element tuple, got {}".format(replace_stride_with_dilation)) + self.groups = groups + self.base_width = width_per_group + self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3, + bias=False) + self.bn1 = norm_layer(self.inplanes) + self.relu = nn.ReLU(inplace=True) + self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) + self.layer1 = self._make_layer(block, 64, layers[0]) + self.layer2 = self._make_layer(block, 128, layers[1], stride=2, + dilate=replace_stride_with_dilation[0]) + self.layer3 = self._make_layer(block, 256, layers[2], stride=2, + dilate=replace_stride_with_dilation[1]) + self.layer4 = self._make_layer(block, 512, layers[3], stride=2, + dilate=replace_stride_with_dilation[2]) + self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) + self.fc = nn.Linear(512 * block.expansion, num_classes) + + for m in self.modules(): + if isinstance(m, nn.Conv2d): + nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') + elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): + nn.init.constant_(m.weight, 1) + nn.init.constant_(m.bias, 0) + + # Zero-initialize the last BN in each residual branch, + # so that the residual branch starts with zeros, and each residual block behaves like an identity. + # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677 + if zero_init_residual: + for m in self.modules(): + if isinstance(m, Bottleneck): + nn.init.constant_(m.bn3.weight, 0) + elif isinstance(m, BasicBlock): + nn.init.constant_(m.bn2.weight, 0) + + def _make_layer(self, block, planes, blocks, stride=1, dilate=False): + norm_layer = self._norm_layer + downsample = None + previous_dilation = self.dilation + if dilate: + self.dilation *= stride + stride = 1 + if stride != 1 or self.inplanes != planes * block.expansion: + downsample = nn.Sequential( + conv1x1(self.inplanes, planes * block.expansion, stride), + norm_layer(planes * block.expansion), + ) + + layers = [] + layers.append(block(self.inplanes, planes, stride, downsample, self.groups, + self.base_width, previous_dilation, norm_layer)) + self.inplanes = planes * block.expansion + for _ in range(1, blocks): + layers.append(block(self.inplanes, planes, groups=self.groups, + base_width=self.base_width, dilation=self.dilation, + norm_layer=norm_layer)) + + return nn.Sequential(*layers) + + def _forward_impl(self, x): + # See note [TorchScript super()] + x = self.conv1(x) + x = self.bn1(x) + x = self.relu(x) + x = self.maxpool(x) + + x = self.layer1(x) + x = self.layer2(x) + x = self.layer3(x) + x = self.layer4(x) + + x = self.avgpool(x) + x = torch.flatten(x, 1) + x = self.fc(x) + + return x + + def forward(self, x): + return self._forward_impl(x) + + def load_from_resnet(self, state_dict): + loaded_param_names = [] + for module_name, module in self.named_modules(): + if isinstance(module, nn.Conv2d) or isinstance(module, nn.BatchNorm2d): + if module_name + '.weight' not in state_dict: + print(f'Module not exist in the state_dict: {module_name}') + elif isinstance(module, nn.Conv2d): + weight_name = module_name + '.weight' + module.weight.data.copy_(state_dict[weight_name]) + loaded_param_names.append(weight_name) + elif isinstance(module, nn.BatchNorm2d): + for param_name, param in module.named_parameters(): + name = f'{module_name}.{param_name}' + param.data.copy_(state_dict[name]) + loaded_param_names.append(name) + for param_name, param in module.named_buffers(): + name = f'{module_name}.{param_name}' + # some buffers like num_batches_tracked may not exist in old + # checkpoints + if name in state_dict: + param.data.copy_(state_dict[name]) + loaded_param_names.append(name) + # check if any parameters in the 2d checkpoint are not loaded + remaining_names = set(state_dict.keys()) - set(loaded_param_names) + if remaining_names: + print(f'These parameters in the 2d checkpoint are not loaded: {remaining_names}') + + +def _resnet(arch, block, layers, pretrained, progress, **kwargs): + model = ResNet(block, layers, **kwargs) + if pretrained: + state_dict = load_state_dict_from_url(model_urls[arch], + progress=progress) + model.load_state_dict(state_dict) + model.fc = nn.Linear(512 * block.expansion, 2) + return model + + +def resnet18(pretrained=False, progress=True, **kwargs): + r"""ResNet-18 model from + `"Deep Residual Learning for Image Recognition" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet18', BasicBlock, [2, 2, 2, 2], pretrained, progress, + **kwargs) + + +def resnet34(pretrained=False, progress=True, **kwargs): + r"""ResNet-34 model from + `"Deep Residual Learning for Image Recognition" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet34', BasicBlock, [3, 4, 6, 3], pretrained, progress, + **kwargs) + + +def resnet50(pretrained=False, progress=True, **kwargs): + r"""ResNet-50 model from + `"Deep Residual Learning for Image Recognition" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet50', Bottleneck, [3, 4, 6, 3], pretrained, progress, + **kwargs) + + +def resnet101(pretrained=False, progress=True, **kwargs): + r"""ResNet-101 model from + `"Deep Residual Learning for Image Recognition" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet101', Bottleneck, [3, 4, 23, 3], pretrained, progress, + **kwargs) + + +def resnet152(pretrained=False, progress=True, **kwargs): + r"""ResNet-152 model from + `"Deep Residual Learning for Image Recognition" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet152', Bottleneck, [3, 8, 36, 3], pretrained, progress, + **kwargs) + + +def resnext50_32x4d(pretrained=False, progress=True, **kwargs): + r"""ResNeXt-50 32x4d model from + `"Aggregated Residual Transformation for Deep Neural Networks" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + kwargs['groups'] = 32 + kwargs['width_per_group'] = 4 + return _resnet('resnext50_32x4d', Bottleneck, [3, 4, 6, 3], + pretrained, progress, **kwargs) + + +def resnext101_32x8d(pretrained=False, progress=True, **kwargs): + r"""ResNeXt-101 32x8d model from + `"Aggregated Residual Transformation for Deep Neural Networks" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + kwargs['groups'] = 32 + kwargs['width_per_group'] = 8 + return _resnet('resnext101_32x8d', Bottleneck, [3, 4, 23, 3], + pretrained, progress, **kwargs) + + +def wide_resnet50_2(pretrained=False, progress=True, **kwargs): + r"""Wide ResNet-50-2 model from + `"Wide Residual Networks" `_ + + The model is the same as ResNet except for the bottleneck number of channels + which is twice larger in every block. The number of channels in outer 1x1 + convolutions is the same, e.g. last block in ResNet-50 has 2048-512-2048 + channels, and in Wide ResNet-50-2 has 2048-1024-2048. + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + kwargs['width_per_group'] = 64 * 2 + return _resnet('wide_resnet50_2', Bottleneck, [3, 4, 6, 3], + pretrained, progress, **kwargs) + + +def wide_resnet101_2(pretrained=False, progress=True, **kwargs): + r"""Wide ResNet-101-2 model from + `"Wide Residual Networks" `_ + + The model is the same as ResNet except for the bottleneck number of channels + which is twice larger in every block. The number of channels in outer 1x1 + convolutions is the same, e.g. last block in ResNet-50 has 2048-512-2048 + channels, and in Wide ResNet-50-2 has 2048-1024-2048. + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + kwargs['width_per_group'] = 64 * 2 + return _resnet('wide_resnet101_2', Bottleneck, [3, 4, 23, 3], + pretrained, progress, **kwargs) diff --git a/PyTorch/build-in/Classification/SEResNet/SEResNet/model/se.py b/PyTorch/build-in/Classification/SEResNet/SEResNet/model/se.py new file mode 100644 index 000000000..53b4bbef0 --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/SEResNet/model/se.py @@ -0,0 +1,19 @@ +import torch.nn as nn + + +class SE(nn.Module): + def __init__(self, channels, reduction=16): + super(SE, self).__init__() + self.avg_pool = nn.AdaptiveAvgPool2d(1) + self.fc = nn.Sequential( + nn.Linear(channels, channels // reduction, bias=False), + nn.ReLU(inplace=True), + nn.Linear(channels // reduction, channels, bias=False), + nn.Sigmoid() + ) + + def forward(self, x): + b, c, _, _ = x.size() + out = self.avg_pool(x).view(b, c) + out = self.fc(out).view(b, c, 1, 1) + return x * out.expand_as(x) diff --git a/PyTorch/build-in/Classification/SEResNet/SEResNet/model/seresnet.py b/PyTorch/build-in/Classification/SEResNet/SEResNet/model/seresnet.py new file mode 100644 index 000000000..ba649e822 --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/SEResNet/model/seresnet.py @@ -0,0 +1,186 @@ +import torch.nn as nn +from torchvision.models.utils import load_state_dict_from_url +from .se import SE +from .resnet import ResNet +from .resnet import model_urls + + +def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1): + """3x3 convolution with padding""" + return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, + padding=dilation, groups=groups, bias=False, dilation=dilation) + + +def conv1x1(in_planes, out_planes, stride=1): + """1x1 convolution""" + return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False) + + +class SEBasicBlock(nn.Module): + expansion = 1 + + def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, + base_width=64, dilation=1, norm_layer=None, reduction=16): + super(SEBasicBlock, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + if groups != 1 or base_width != 64: + raise ValueError('BasicBlock only supports groups=1 and base_width=64') + if dilation > 1: + raise NotImplementedError("Dilation > 1 not supported in BasicBlock") + # Both self.conv1 and self.downsample layers downsample the input when stride != 1 + self.conv1 = conv3x3(inplanes, planes, stride) + self.bn1 = norm_layer(planes) + self.relu = nn.ReLU(inplace=True) + self.conv2 = conv3x3(planes, planes) + self.bn2 = norm_layer(planes) + self.se = SE(planes, reduction) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + out = self.se(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +class SEBottleneck(nn.Module): + expansion = 4 + + def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, + base_width=64, dilation=1, norm_layer=None, reduction=16): + super(SEBottleneck, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + width = int(planes * (base_width / 64.)) * groups + # Both self.conv2 and self.downsample layers downsample the input when stride != 1 + self.conv1 = conv1x1(inplanes, width) + self.bn1 = norm_layer(width) + self.conv2 = conv3x3(width, width, stride, groups, dilation) + self.bn2 = norm_layer(width) + self.conv3 = conv1x1(width, planes * self.expansion) + self.bn3 = norm_layer(planes * self.expansion) + self.relu = nn.ReLU(inplace=True) + self.se = SE(planes * self.expansion, reduction) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + out = self.relu(out) + + out = self.conv3(out) + out = self.bn3(out) + out = self.se(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +def _seresnet(arch, block, layers, pretrained, progress, **kwargs): + model = ResNet(block, layers, **kwargs) + if pretrained: + state_dict = load_state_dict_from_url(model_urls[arch], + progress=progress) + model.load_from_resnet(state_dict) + return model + + +def seresnet18(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _seresnet('resnet18', SEBasicBlock, [2, 2, 2, 2], pretrained, progress, + **kwargs) + + +def seresnet34(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _seresnet('resnet34', SEBasicBlock, [3, 4, 6, 3], pretrained, progress, + **kwargs) + + +def seresnet50(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _seresnet('resnet50', SEBottleneck, [3, 4, 6, 3], pretrained, progress, + **kwargs) + + +def seresnet101(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _seresnet('resnet101', SEBottleneck, [3, 4, 23, 3], pretrained, progress, + **kwargs) + + +def seresnet152(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _seresnet('resnet152', SEBottleneck, [3, 8, 36, 3], pretrained, progress, + **kwargs) + + +def seresnext50(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + kwargs['groups'] = 32 + kwargs['width_per_group'] = 4 + return _seresnet('resnext50_32x4d', SEBottleneck, [3, 4, 6, 3], + pretrained, progress, **kwargs) + + +def seresnext101(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + kwargs['groups'] = 32 + kwargs['width_per_group'] = 8 + return _seresnet('resnext101_32x8d', SEBottleneck, [3, 4, 23, 3], + pretrained, progress, **kwargs) diff --git a/PyTorch/build-in/Classification/SEResNet/coverage.txt b/PyTorch/build-in/Classification/SEResNet/coverage.txt new file mode 100644 index 000000000..eb3ebe943 --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/coverage.txt @@ -0,0 +1,3 @@ +all api: ['_amp_foreach_non_finite_check_and_unscale_', '_amp_update_scale_', '_copy_from', '_has_compatible_shallow_copy_type', '_local_scalar_dense', '_log_softmax', '_log_softmax_backward_data', '_pin_memory', '_reshape_alias', 'add_', 'addmm', 'as_strided', 'as_strided_', 'convolution', 'convolution_backward', 'copy_stride', 'div', 'eq', 'fill_', 'fused_sgd', 'is_pinned', 'linear', 'matmul', 'max_pool2d', 'maxpool2d_backward', 'maxpool2d_forward', 'mean', 'mm', 'mul', 'mul_', 'native_batch_norm', 'native_batch_norm_backward', 'nll_loss_backward', 'nll_loss_forward', 'reciprocal', 'relu_', 'set_', 'sigmoid', 'sigmoid_backward', 'sum', 'threshold_backward', 'topk_out', 'view', 'zero_'], total: 44 +fallback op: [], total: 0 +coverage rate: 100.00% diff --git a/PyTorch/build-in/Classification/SEResNet/model/__init__.py b/PyTorch/build-in/Classification/SEResNet/model/__init__.py new file mode 100644 index 000000000..16ed6037d --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/model/__init__.py @@ -0,0 +1,2 @@ +from .resnet import * +from .seresnet import * diff --git a/PyTorch/build-in/Classification/SEResNet/model/resnet.py b/PyTorch/build-in/Classification/SEResNet/model/resnet.py new file mode 100644 index 000000000..d69df5d88 --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/model/resnet.py @@ -0,0 +1,379 @@ +import torch +import torch.nn as nn +# from torchvision.models.utils import load_state_dict_from_url + +__all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101', + 'resnet152', 'resnext50_32x4d', 'resnext101_32x8d', + 'wide_resnet50_2', 'wide_resnet101_2', 'model_urls'] + +model_urls = { + 'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth', + 'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth', + 'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth', + 'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth', + 'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth', + 'resnext50_32x4d': 'https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth', + 'resnext101_32x8d': 'https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth', + 'wide_resnet50_2': 'https://download.pytorch.org/models/wide_resnet50_2-95faca4d.pth', + 'wide_resnet101_2': 'https://download.pytorch.org/models/wide_resnet101_2-32ee1156.pth', +} + + +def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1): + """3x3 convolution with padding""" + return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, + padding=dilation, groups=groups, bias=False, dilation=dilation) + + +def conv1x1(in_planes, out_planes, stride=1): + """1x1 convolution""" + return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False) + + +class BasicBlock(nn.Module): + expansion = 1 + + def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, + base_width=64, dilation=1, norm_layer=None): + super(BasicBlock, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + if groups != 1 or base_width != 64: + raise ValueError('BasicBlock only supports groups=1 and base_width=64') + if dilation > 1: + raise NotImplementedError("Dilation > 1 not supported in BasicBlock") + # Both self.conv1 and self.downsample layers downsample the input when stride != 1 + self.conv1 = conv3x3(inplanes, planes, stride) + self.bn1 = norm_layer(planes) + self.relu = nn.ReLU(inplace=True) + self.conv2 = conv3x3(planes, planes) + self.bn2 = norm_layer(planes) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +class Bottleneck(nn.Module): + # Bottleneck in torchvision places the stride for downsampling at 3x3 convolution(self.conv2) + # while original implementation places the stride at the first 1x1 convolution(self.conv1) + # according to "Deep residual learning for image recognition"https://arxiv.org/abs/1512.03385. + # This variant is also known as ResNet V1.5 and improves accuracy according to + # https://ngc.nvidia.com/catalog/model-scripts/nvidia:resnet_50_v1_5_for_pytorch. + + expansion = 4 + + def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, + base_width=64, dilation=1, norm_layer=None): + super(Bottleneck, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + width = int(planes * (base_width / 64.)) * groups + # Both self.conv2 and self.downsample layers downsample the input when stride != 1 + self.conv1 = conv1x1(inplanes, width) + self.bn1 = norm_layer(width) + self.conv2 = conv3x3(width, width, stride, groups, dilation) + self.bn2 = norm_layer(width) + self.conv3 = conv1x1(width, planes * self.expansion) + self.bn3 = norm_layer(planes * self.expansion) + self.relu = nn.ReLU(inplace=True) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + out = self.relu(out) + + out = self.conv3(out) + out = self.bn3(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +class ResNet(nn.Module): + + def __init__(self, block, layers, num_classes=1000, zero_init_residual=False, + groups=1, width_per_group=64, replace_stride_with_dilation=None, + norm_layer=None): + super(ResNet, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + self._norm_layer = norm_layer + + self.inplanes = 64 + self.dilation = 1 + if replace_stride_with_dilation is None: + # each element in the tuple indicates if we should replace + # the 2x2 stride with a dilated convolution instead + replace_stride_with_dilation = [False, False, False] + if len(replace_stride_with_dilation) != 3: + raise ValueError("replace_stride_with_dilation should be None " + "or a 3-element tuple, got {}".format(replace_stride_with_dilation)) + self.groups = groups + self.base_width = width_per_group + self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3, + bias=False) + self.bn1 = norm_layer(self.inplanes) + self.relu = nn.ReLU(inplace=True) + self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) + self.layer1 = self._make_layer(block, 64, layers[0]) + self.layer2 = self._make_layer(block, 128, layers[1], stride=2, + dilate=replace_stride_with_dilation[0]) + self.layer3 = self._make_layer(block, 256, layers[2], stride=2, + dilate=replace_stride_with_dilation[1]) + self.layer4 = self._make_layer(block, 512, layers[3], stride=2, + dilate=replace_stride_with_dilation[2]) + self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) + self.fc = nn.Linear(512 * block.expansion, num_classes) + + for m in self.modules(): + if isinstance(m, nn.Conv2d): + nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') + elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): + nn.init.constant_(m.weight, 1) + nn.init.constant_(m.bias, 0) + + # Zero-initialize the last BN in each residual branch, + # so that the residual branch starts with zeros, and each residual block behaves like an identity. + # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677 + if zero_init_residual: + for m in self.modules(): + if isinstance(m, Bottleneck): + nn.init.constant_(m.bn3.weight, 0) + elif isinstance(m, BasicBlock): + nn.init.constant_(m.bn2.weight, 0) + + def _make_layer(self, block, planes, blocks, stride=1, dilate=False): + norm_layer = self._norm_layer + downsample = None + previous_dilation = self.dilation + if dilate: + self.dilation *= stride + stride = 1 + if stride != 1 or self.inplanes != planes * block.expansion: + downsample = nn.Sequential( + conv1x1(self.inplanes, planes * block.expansion, stride), + norm_layer(planes * block.expansion), + ) + + layers = [] + layers.append(block(self.inplanes, planes, stride, downsample, self.groups, + self.base_width, previous_dilation, norm_layer)) + self.inplanes = planes * block.expansion + for _ in range(1, blocks): + layers.append(block(self.inplanes, planes, groups=self.groups, + base_width=self.base_width, dilation=self.dilation, + norm_layer=norm_layer)) + + return nn.Sequential(*layers) + + def _forward_impl(self, x): + # See note [TorchScript super()] + x = self.conv1(x) + x = self.bn1(x) + x = self.relu(x) + x = self.maxpool(x) + + x = self.layer1(x) + x = self.layer2(x) + x = self.layer3(x) + x = self.layer4(x) + + x = self.avgpool(x) + x = torch.flatten(x, 1) + x = self.fc(x) + + return x + + def forward(self, x): + return self._forward_impl(x) + + def load_from_resnet(self, state_dict): + loaded_param_names = [] + for module_name, module in self.named_modules(): + if isinstance(module, nn.Conv2d) or isinstance(module, nn.BatchNorm2d): + if module_name + '.weight' not in state_dict: + print(f'Module not exist in the state_dict: {module_name}') + elif isinstance(module, nn.Conv2d): + weight_name = module_name + '.weight' + module.weight.data.copy_(state_dict[weight_name]) + loaded_param_names.append(weight_name) + elif isinstance(module, nn.BatchNorm2d): + for param_name, param in module.named_parameters(): + name = f'{module_name}.{param_name}' + param.data.copy_(state_dict[name]) + loaded_param_names.append(name) + for param_name, param in module.named_buffers(): + name = f'{module_name}.{param_name}' + # some buffers like num_batches_tracked may not exist in old + # checkpoints + if name in state_dict: + param.data.copy_(state_dict[name]) + loaded_param_names.append(name) + # check if any parameters in the 2d checkpoint are not loaded + remaining_names = set(state_dict.keys()) - set(loaded_param_names) + if remaining_names: + print(f'These parameters in the 2d checkpoint are not loaded: {remaining_names}') + + +def _resnet(arch, block, layers, pretrained, progress, **kwargs): + model = ResNet(block, layers, **kwargs) + # if pretrained: + # state_dict = load_state_dict_from_url(model_urls[arch], + # progress=progress) + # model.load_state_dict(state_dict) + model.fc = nn.Linear(512 * block.expansion, 2) + return model + + +def resnet18(pretrained=False, progress=True, **kwargs): + r"""ResNet-18 model from + `"Deep Residual Learning for Image Recognition" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet18', BasicBlock, [2, 2, 2, 2], pretrained, progress, + **kwargs) + + +def resnet34(pretrained=False, progress=True, **kwargs): + r"""ResNet-34 model from + `"Deep Residual Learning for Image Recognition" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet34', BasicBlock, [3, 4, 6, 3], pretrained, progress, + **kwargs) + + +def resnet50(pretrained=False, progress=True, **kwargs): + r"""ResNet-50 model from + `"Deep Residual Learning for Image Recognition" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet50', Bottleneck, [3, 4, 6, 3], pretrained, progress, + **kwargs) + + +def resnet101(pretrained=False, progress=True, **kwargs): + r"""ResNet-101 model from + `"Deep Residual Learning for Image Recognition" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet101', Bottleneck, [3, 4, 23, 3], pretrained, progress, + **kwargs) + + +def resnet152(pretrained=False, progress=True, **kwargs): + r"""ResNet-152 model from + `"Deep Residual Learning for Image Recognition" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet152', Bottleneck, [3, 8, 36, 3], pretrained, progress, + **kwargs) + + +def resnext50_32x4d(pretrained=False, progress=True, **kwargs): + r"""ResNeXt-50 32x4d model from + `"Aggregated Residual Transformation for Deep Neural Networks" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + kwargs['groups'] = 32 + kwargs['width_per_group'] = 4 + return _resnet('resnext50_32x4d', Bottleneck, [3, 4, 6, 3], + pretrained, progress, **kwargs) + + +def resnext101_32x8d(pretrained=False, progress=True, **kwargs): + r"""ResNeXt-101 32x8d model from + `"Aggregated Residual Transformation for Deep Neural Networks" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + kwargs['groups'] = 32 + kwargs['width_per_group'] = 8 + return _resnet('resnext101_32x8d', Bottleneck, [3, 4, 23, 3], + pretrained, progress, **kwargs) + + +def wide_resnet50_2(pretrained=False, progress=True, **kwargs): + r"""Wide ResNet-50-2 model from + `"Wide Residual Networks" `_ + + The model is the same as ResNet except for the bottleneck number of channels + which is twice larger in every block. The number of channels in outer 1x1 + convolutions is the same, e.g. last block in ResNet-50 has 2048-512-2048 + channels, and in Wide ResNet-50-2 has 2048-1024-2048. + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + kwargs['width_per_group'] = 64 * 2 + return _resnet('wide_resnet50_2', Bottleneck, [3, 4, 6, 3], + pretrained, progress, **kwargs) + + +def wide_resnet101_2(pretrained=False, progress=True, **kwargs): + r"""Wide ResNet-101-2 model from + `"Wide Residual Networks" `_ + + The model is the same as ResNet except for the bottleneck number of channels + which is twice larger in every block. The number of channels in outer 1x1 + convolutions is the same, e.g. last block in ResNet-50 has 2048-512-2048 + channels, and in Wide ResNet-50-2 has 2048-1024-2048. + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + kwargs['width_per_group'] = 64 * 2 + return _resnet('wide_resnet101_2', Bottleneck, [3, 4, 23, 3], + pretrained, progress, **kwargs) diff --git a/PyTorch/build-in/Classification/SEResNet/model/se.py b/PyTorch/build-in/Classification/SEResNet/model/se.py new file mode 100644 index 000000000..53b4bbef0 --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/model/se.py @@ -0,0 +1,19 @@ +import torch.nn as nn + + +class SE(nn.Module): + def __init__(self, channels, reduction=16): + super(SE, self).__init__() + self.avg_pool = nn.AdaptiveAvgPool2d(1) + self.fc = nn.Sequential( + nn.Linear(channels, channels // reduction, bias=False), + nn.ReLU(inplace=True), + nn.Linear(channels // reduction, channels, bias=False), + nn.Sigmoid() + ) + + def forward(self, x): + b, c, _, _ = x.size() + out = self.avg_pool(x).view(b, c) + out = self.fc(out).view(b, c, 1, 1) + return x * out.expand_as(x) diff --git a/PyTorch/build-in/Classification/SEResNet/model/seresnet.py b/PyTorch/build-in/Classification/SEResNet/model/seresnet.py new file mode 100644 index 000000000..4a576468b --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/model/seresnet.py @@ -0,0 +1,187 @@ +import torch.nn as nn +# from torchvision.models.utils import load_state_dict_from_url +# from torch.hub import load_state_dict_from_url +from .se import SE +from .resnet import ResNet +from .resnet import model_urls + + +def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1): + """3x3 convolution with padding""" + return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, + padding=dilation, groups=groups, bias=False, dilation=dilation) + + +def conv1x1(in_planes, out_planes, stride=1): + """1x1 convolution""" + return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False) + + +class SEBasicBlock(nn.Module): + expansion = 1 + + def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, + base_width=64, dilation=1, norm_layer=None, reduction=16): + super(SEBasicBlock, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + if groups != 1 or base_width != 64: + raise ValueError('BasicBlock only supports groups=1 and base_width=64') + if dilation > 1: + raise NotImplementedError("Dilation > 1 not supported in BasicBlock") + # Both self.conv1 and self.downsample layers downsample the input when stride != 1 + self.conv1 = conv3x3(inplanes, planes, stride) + self.bn1 = norm_layer(planes) + self.relu = nn.ReLU(inplace=True) + self.conv2 = conv3x3(planes, planes) + self.bn2 = norm_layer(planes) + self.se = SE(planes, reduction) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + out = self.se(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +class SEBottleneck(nn.Module): + expansion = 4 + + def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, + base_width=64, dilation=1, norm_layer=None, reduction=16): + super(SEBottleneck, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + width = int(planes * (base_width / 64.)) * groups + # Both self.conv2 and self.downsample layers downsample the input when stride != 1 + self.conv1 = conv1x1(inplanes, width) + self.bn1 = norm_layer(width) + self.conv2 = conv3x3(width, width, stride, groups, dilation) + self.bn2 = norm_layer(width) + self.conv3 = conv1x1(width, planes * self.expansion) + self.bn3 = norm_layer(planes * self.expansion) + self.relu = nn.ReLU(inplace=True) + self.se = SE(planes * self.expansion, reduction) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + out = self.relu(out) + + out = self.conv3(out) + out = self.bn3(out) + out = self.se(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +def _seresnet(arch, block, layers, pretrained, progress, **kwargs): + model = ResNet(block, layers, **kwargs) + # if pretrained: + # state_dict = load_state_dict_from_url(model_urls[arch], + # progress=progress) + # model.load_from_resnet(state_dict) + return model + + +def seresnet18(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _seresnet('resnet18', SEBasicBlock, [2, 2, 2, 2], pretrained, progress, + **kwargs) + + +def seresnet34(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _seresnet('resnet34', SEBasicBlock, [3, 4, 6, 3], pretrained, progress, + **kwargs) + + +def seresnet50(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _seresnet('resnet50', SEBottleneck, [3, 4, 6, 3], pretrained, progress, + **kwargs) + + +def seresnet101(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _seresnet('resnet101', SEBottleneck, [3, 4, 23, 3], pretrained, progress, + **kwargs) + + +def seresnet152(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _seresnet('resnet152', SEBottleneck, [3, 8, 36, 3], pretrained, progress, + **kwargs) + + +def seresnext50(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + kwargs['groups'] = 32 + kwargs['width_per_group'] = 4 + return _seresnet('resnext50_32x4d', SEBottleneck, [3, 4, 6, 3], + pretrained, progress, **kwargs) + + +def seresnext101(pretrained=False, progress=True, **kwargs): + r""" + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + kwargs['groups'] = 32 + kwargs['width_per_group'] = 8 + return _seresnet('resnext101_32x8d', SEBottleneck, [3, 4, 23, 3], + pretrained, progress, **kwargs) diff --git a/PyTorch/build-in/Classification/SEResNet/seresnet.py b/PyTorch/build-in/Classification/SEResNet/seresnet.py new file mode 100644 index 000000000..a91a463b7 --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/seresnet.py @@ -0,0 +1,28 @@ +import model.seresnet as seresnet + +def Model(num_classes=1000, variant='18', pretrained=False): + """ + Simple factory returning a SE-ResNet / SE-ResNeXt variant. + variant: '18', '34', '50', '101', '152', 'next50', 'next101' + """ + if variant == '18': + return seresnet.seresnet18(pretrained=pretrained, num_classes=num_classes) + elif variant == '34': + return seresnet.seresnet34(pretrained=pretrained, num_classes=num_classes) + elif variant == '50': + return seresnet.seresnet50(pretrained=pretrained, num_classes=num_classes) + elif variant == '101': + return seresnet.seresnet101(pretrained=pretrained, num_classes=num_classes) + elif variant == '152': + return seresnet.seresnet152(pretrained=pretrained, num_classes=num_classes) + elif variant.lower() == 'next50': + return seresnet.seresnext50(pretrained=pretrained, num_classes=num_classes) + elif variant.lower() == 'next101': + return seresnet.seresnext101(pretrained=pretrained, num_classes=num_classes) + else: + raise ValueError(f"Unknown variant: {variant}") + +# 测试 +if __name__ == "__main__": + m = Model(num_classes=100, variant='50', pretrained=False) + print(m) \ No newline at end of file diff --git a/PyTorch/build-in/Classification/SEResNet/seresnet_loss.jpg b/PyTorch/build-in/Classification/SEResNet/seresnet_loss.jpg new file mode 100644 index 0000000000000000000000000000000000000000..45419a78f1ed1f8ff87b8cf435c9c00a9ca033ed GIT binary patch literal 35249 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 literal 0 HcmV?d00001 diff --git a/PyTorch/build-in/Classification/SEResNet/seresnet_loss.txt b/PyTorch/build-in/Classification/SEResNet/seresnet_loss.txt new file mode 100644 index 000000000..f67229c8b --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/seresnet_loss.txt @@ -0,0 +1,29 @@ +=== CUDA === +4.612500 4.619000 5.173300 4.753900 5.103300 5.242500 5.253400 5.376800 5.227700 5.287400 +5.225600 5.315900 6.274400 5.618300 5.944600 5.011500 5.068500 5.123900 5.286200 4.771400 +5.243700 4.860000 4.901700 4.972000 5.217600 5.257200 5.172400 4.954800 4.766100 4.733300 +4.817900 4.636500 4.600600 4.679000 4.723000 4.554800 4.635600 4.738800 4.598000 4.688700 +4.503400 4.537000 4.530600 4.524300 4.748800 4.348600 4.677400 4.480400 4.628000 4.406400 +4.279100 4.536600 4.501700 4.544200 4.625900 4.618700 4.645000 4.531900 4.632300 4.532500 +4.444700 4.552500 4.445000 4.595700 4.423200 4.563300 4.466200 4.277400 4.460700 4.536500 +4.452100 4.384400 4.355400 4.371800 4.386600 4.504900 4.364500 4.567600 4.362700 4.366000 +4.266800 4.490200 4.527800 4.241300 4.365700 4.196000 4.123600 4.373100 4.352100 4.619600 +4.412000 4.571500 4.294300 4.252300 4.580000 4.244400 4.426400 4.422000 4.171400 4.378200 + +=== SDAA === +4.602800 4.731700 4.830000 4.766100 4.891000 5.397000 5.432600 5.317800 5.863900 5.501600 +5.457100 5.346400 6.533400 5.124500 5.276400 5.267400 5.038100 5.121800 5.358700 5.454500 +4.813100 5.272200 5.198100 5.094100 5.284500 5.408300 5.481300 4.846000 4.872300 4.808600 +4.660000 4.657000 4.653100 4.599700 4.572500 4.637400 4.947900 4.489300 4.650700 4.717900 +4.861600 4.580800 4.686800 4.619700 4.634500 4.542100 4.379000 4.431700 4.826700 4.346300 +4.705800 4.580100 4.716400 4.448000 4.369200 4.503800 4.443400 4.491000 4.508300 4.872600 +4.615700 4.301000 4.593000 4.433000 4.428700 4.405500 4.361100 4.385100 4.493400 4.370100 +4.424200 4.407500 4.355100 4.535700 4.399500 4.194800 4.240400 4.206800 4.275900 4.276500 +4.489900 4.542500 4.198100 4.294400 4.433000 4.338900 4.693600 4.418000 4.445000 4.181000 +4.365200 4.454500 4.264700 4.420800 4.562200 4.226300 4.210100 4.245600 4.312500 4.325800 + +=== RESULT === +MeanRelativeError: 0.0037770064676498137 +MeanAbsoluteError: 0.01585200000000009 +Rule,mean_relative_error 0.0037770064676498137 +pass mean_relative_error=0.0037770064676498137 <= 0.05 or mean_absolute_error=0.01585200000000009 <= 0.0002 diff --git a/PyTorch/build-in/Classification/SEResNet/weloTrainStep.py b/PyTorch/build-in/Classification/SEResNet/weloTrainStep.py new file mode 100644 index 000000000..13297c11b --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/weloTrainStep.py @@ -0,0 +1,692 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +import os +import random +import sys +import time +import json +import argparse +from collections import OrderedDict +from pathlib import Path +import numpy as np +import pandas as pd +from tqdm import tqdm +import importlib + +os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8" # 强烈推荐在 shell/最顶端设置 +os.environ["PYTHONHASHSEED"] = "12345" +os.environ["OMP_NUM_THREADS"] = "1" +os.environ["MKL_NUM_THREADS"] = "1" + +def ensure_cublas_workspace(config=":4096:8"): + """ + 尝试为 cuBLAS 设置可复现 workspace。强烈建议在主脚本入口处(import torch 之前) + 通过 export 设置该 env。此函数会在运行时设置,但如果 torch 已经被 import, + 则可能为时已晚——函数会打印提醒。 + """ + already = os.environ.get("CUBLAS_WORKSPACE_CONFIG") + if already: + print(f"[seed_utils] CUBLAS_WORKSPACE_CONFIG 已存在:{already}") + else: + os.environ["CUBLAS_WORKSPACE_CONFIG"] = config + print(f"[seed_utils] 已设置 CUBLAS_WORKSPACE_CONFIG={config} (注意:请在 import torch 前设置以保证生效)") + +def set_global_seed(seed: int = 42, set_threads: bool = True): + """ + 统一随机性设置。注意:若希望完全发挥效果,请在主脚本入口(import torch 之前) + 先调用 ensure_cublas_workspace(...) 或在 shell 中 export CUBLAS_WORKSPACE_CONFIG。 + """ + ensure_cublas_workspace() # 会设置 env 并提醒 + os.environ["PYTHONHASHSEED"] = str(seed) + + if set_threads: + os.environ["OMP_NUM_THREADS"] = "1" + os.environ["MKL_NUM_THREADS"] = "1" + + random.seed(seed) + np.random.seed(seed) + + # 现在导入 torch(晚导入以便前面 env 生效) + import torch + torch.manual_seed(seed) + if torch.cuda.is_available(): + torch.cuda.manual_seed(seed) + torch.cuda.manual_seed_all(seed) + # 强制确定性(如果存在不确定性算子,PyTorch 会报错并提示) + try: + torch.use_deterministic_algorithms(True) + except Exception as e: + print("[seed_utils] 设置 deterministic 模式时出错:", e) + print("[seed_utils] 请确认 CUBLAS_WORKSPACE_CONFIG 已在 import torch 之前设置。") + + torch.backends.cudnn.deterministic = True + torch.backends.cudnn.benchmark = False + + if set_threads: + torch.set_num_threads(1) + torch.set_num_interop_threads(1) + + print(f"[seed_utils] 全局 seed 已设置为 {seed}") + +set_global_seed(2025) + +""" +通用训练模版(优先从本地导入 Model -> 支持 DDP / 单卡,AMP,resume,日志,checkpoint) +保存为 train_template_localmodel.py +""" +import torch +import torch.nn as nn +import torch.optim as optim +import torch.backends.cudnn as cudnn +import torchvision.transforms as transforms +import torchvision.datasets as datasets +import torchvision.models as tv_models + +import torch.distributed as dist +from torch.nn.parallel import DistributedDataParallel as DDP +from torch.utils.data import DataLoader +from torch.utils.data.distributed import DistributedSampler + +from torch.sdaa import amp +# from torch.cuda import amp + + +# ---------------------------- +# Helper utilities (self-contained) +# ---------------------------- +class AverageMeter(object): + def __init__(self, name='Meter', fmt=':.4f'): + self.name = name + self.fmt = fmt + self.reset() + def reset(self): + self.val = 0 + self.avg = 0 + self.sum = 0 + self.count = 0 + def update(self, val, n=1): + self.val = val + self.sum += val * n + self.count += n + self.avg = self.sum / max(1, self.count) + def __str__(self): + fmtstr = '{name} {val' + self.fmt + '} (avg {avg' + self.fmt + '})' + return fmtstr.format(name=self.name, val=self.val, avg=self.avg) + +def accuracy(output, target, topk=(1,)): + """Computes the precision@k for the specified values of k + 返回一个 list,每个元素是 tensor(百分比形式) + """ + with torch.no_grad(): + maxk = max(topk) + batch_size = target.size(0) + + # output: (N, C) -> pred: (maxk, N) + _, pred = output.topk(maxk, 1, True, True) + pred = pred.t() # (maxk, N) + correct = pred.eq(target.view(1, -1).expand_as(pred)) # (maxk, N) bool + + res = [] + for k in topk: + # 把前 k 行展平后求和(返回 0-dim tensor),随后换算为百分比 + correct_k = correct[:k].reshape(-1).float().sum() # 注意:不传 keepdim + # 乘以 100.0 / batch_size,保持返回 tensor(和之前代码兼容) + res.append(correct_k.mul_(100.0 / batch_size)) + return res + +def save_checkpoint(state, is_best, save_dir, filename='checkpoint.pth'): + save_path = os.path.join(save_dir, filename) + torch.save(state, save_path) + if is_best: + best_path = os.path.join(save_dir, 'model_best.pth') + torch.save(state, best_path) + +def set_seed(seed, deterministic=False): + random.seed(seed) + np.random.seed(seed) + torch.manual_seed(seed) + torch.cuda.manual_seed_all(seed) + if deterministic: + cudnn.deterministic = True + cudnn.benchmark = False + else: + cudnn.deterministic = False + cudnn.benchmark = True + +# ---------------------------- +# Argument parser +# ---------------------------- +def parse_args(): + parser = argparse.ArgumentParser(description='Generic PyTorch training template (DDP/AMP) with LocalModel priority') + parser.add_argument('--name', default='run', type=str, help='experiment name (log/checkpoints dir)') + parser.add_argument('--seed', default=42, type=int, help='random seed') + parser.add_argument('--arch', default='None', type=str, help='model name') + parser.add_argument('--deterministic', action='store_true', help='set cudnn deterministic (may be slower)') + parser.add_argument('--dataset', default='cifar10', choices=['cifar10','cifar100','imagenet','custom'], help='which dataset') + parser.add_argument('--datapath', default='./data', type=str, help='dataset root / imagenet root / custom root') + parser.add_argument('--imagenet_dir', default='./imagenet', type=str, help='if dataset=imagenet, path to imagenet root') + parser.add_argument('--custom_eval_dir', default=None, help='if dataset=custom, provide val dir') + parser.add_argument('--num_workers', default=4, type=int, help='dataloader workers per process') + parser.add_argument('--epochs', default=200, type=int) + parser.add_argument('--steps', default=0, type=int, help='max steps to run (if >0, training will stop when global_step reaches this).') + parser.add_argument('--batch_size', default=128, type=int) + parser.add_argument('--model_name', default='resnet18', help='torchvision model name or python path e.g. mypkg.mymodule.Model (used if no local Model)') + parser.add_argument('--num_classes', default=None, type=int, help='override num classes (auto-detect for common sets)') + parser.add_argument('--pretrained', action='store_true', help='use torchvision pretrained weights when available') + parser.add_argument('--optimizer', default='sgd', choices=['sgd','adam','adamw'], help='optimizer') + parser.add_argument('--lr', '--learning_rate', default=0.1, type=float) + parser.add_argument('--momentum', default=0.9, type=float) + parser.add_argument('--weight_decay', default=5e-4, type=float) + parser.add_argument('--nesterov', action='store_true') + parser.add_argument('--scheduler', default='multistep', choices=['multistep','step','cosine','none'], help='lr scheduler') + parser.add_argument('--milestones', default='100,150', type=str, help='milestones for multistep (comma sep)') + parser.add_argument('--step_size', default=30, type=int, help='step size for StepLR or cosine max epochs') + parser.add_argument('--gamma', default=0.1, type=float) + parser.add_argument('--scheduler_step_per_batch', action='store_true', help='call scheduler.step() per batch (for some schedulers)') + parser.add_argument('--resume', default='', type=str, help='path to checkpoint to resume from') + parser.add_argument('--start_epoch', default=0, type=int) + parser.add_argument('--print_freq', default=100, type=int) + parser.add_argument('--save_freq', default=10, type=int, help='save checkpoint every N epochs (rank0 only)') + parser.add_argument('--amp', action='store_true', default = True,help='use automatic mixed precision (AMP)') + parser.add_argument('--grad_accum_steps', default=1, type=int, help='gradient accumulation steps') + parser.add_argument('--local_rank', default=None, type=int, help='local rank passed by torchrun (if any). Use -1 or None for non-distributed') + parser.add_argument('--cutmix_prob', default=0.0, type=float) + parser.add_argument('--beta', default=1.0, type=float) + parser.add_argument('--seed_sampler', default=False, action='store_true', help='set sampler epoch seeds to make deterministic distributed shuffling') + args = parser.parse_args() + args.milestones = [int(x) for x in args.milestones.split(',')] if args.milestones else [] + return args + +# ---------------------------- +# build model (优先 LocalModel) +# ---------------------------- +def build_model_with_local_priority(args, device=None): + """ + 用参数 args.arch 作为模块名导入 Model() + 如果模块不存在或没有 Model 类,则报错停止。 + """ + try: + # 动态导入模块,比如 args.arch = "rexnet" + mod = importlib.import_module(args.arch) + Model = getattr(mod, "Model") # 从模块中获取 Model 类 + except Exception as e: + raise RuntimeError( + f"无法导入模型模块 '{args.arch}' 或未找到类 Model。" + f"\n错误信息:{e}" + ) + + # 解析数据集类别数 + if args.dataset == 'cifar10': + num_classes = 10 + elif args.dataset == 'cifar100': + num_classes = 100 + else: + print(f"[ERROR] 不支持的数据集类型:{args.dataset},无法确定类别数。程序终止。") + sys.exit(1) + + + # 实例化 + try: + model = Model(num_classes) + except Exception as e: + raise RuntimeError( + f"Model() 实例化失败,请检查模型构造函数。\n错误信息:{e}" + ) + + return model + +# ---------------------------- +# Data loader factory +# ---------------------------- +def build_dataloaders(args, rank, world_size): + if args.dataset == 'cifar10' or args.dataset == 'cifar100': + mean = (0.4914, 0.4822, 0.4465) + std = (0.2470, 0.2435, 0.2616) if args.dataset == 'cifar10' else (0.2023, 0.1994, 0.2010) + # train_transform = transforms.Compose([ + # transforms.RandomCrop(32, padding=4), + # transforms.RandomHorizontalFlip(), + # transforms.ToTensor(), + # transforms.Normalize(mean, std), + # ]) + # test_transform = transforms.Compose([ + # transforms.ToTensor(), + # transforms.Normalize(mean, std), + # ]) + + train_transform = transforms.Compose([ # 2025/12/3 从visformer模型开始 + transforms.Resize(256), # 先放大到 256 + transforms.RandomCrop(224), # 再随机裁剪为 224(更符合 ImageNet 风格增强) + transforms.RandomHorizontalFlip(), + transforms.ToTensor(), + transforms.Normalize(mean, std), + ]) + test_transform = transforms.Compose([ + transforms.Resize(256), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize(mean, std), + ]) + root = args.datapath + if args.dataset == 'cifar10': + train_set = datasets.CIFAR10(root=root, train=True, download=False, transform=train_transform) + val_set = datasets.CIFAR10(root=root, train=False, download=False, transform=test_transform) + num_classes = 10 + else: + train_set = datasets.CIFAR100(root=root, train=True, download=False, transform=train_transform) + val_set = datasets.CIFAR100(root=root, train=False, download=False, transform=test_transform) + num_classes = 100 + + elif args.dataset == 'imagenet': + train_dir = os.path.join(args.imagenet_dir, 'train') + val_dir = os.path.join(args.imagenet_dir, 'val') + train_transform = transforms.Compose([ + transforms.RandomResizedCrop(224), + transforms.RandomHorizontalFlip(), + transforms.ToTensor(), + transforms.Normalize((0.485,0.456,0.406), (0.229,0.224,0.225)), + ]) + test_transform = transforms.Compose([ + transforms.Resize(256), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize((0.485,0.456,0.406), (0.229,0.224,0.225)), + ]) + train_set = datasets.ImageFolder(train_dir, train_transform) + val_set = datasets.ImageFolder(val_dir, test_transform) + num_classes = args.num_classes or 1000 + + elif args.dataset == 'custom': + train_dir = os.path.join(args.datapath, 'train') + val_dir = args.custom_eval_dir or os.path.join(args.datapath, 'val') + train_transform = transforms.Compose([ + transforms.RandomResizedCrop(224), + transforms.RandomHorizontalFlip(), + transforms.ToTensor(), + ]) + test_transform = transforms.Compose([ + transforms.Resize(256), + transforms.CenterCrop(224), + transforms.ToTensor(), + ]) + train_set = datasets.ImageFolder(train_dir, train_transform) + val_set = datasets.ImageFolder(val_dir, test_transform) + num_classes = len(train_set.classes) + else: + raise ValueError("Unknown dataset") + + if dist.is_initialized() and world_size > 1: + train_sampler = DistributedSampler(train_set, num_replicas=world_size, rank=rank, shuffle=True) + else: + train_sampler = None + + train_loader = DataLoader(train_set, + batch_size=args.batch_size, + shuffle=(train_sampler is None), + num_workers=args.num_workers, + pin_memory=True, + sampler=train_sampler, + drop_last=False) + val_loader = DataLoader(val_set, + batch_size=args.batch_size, + shuffle=False, + num_workers=args.num_workers, + pin_memory=True) + + return train_loader, val_loader, num_classes, train_sampler + +# ---------------------------- +# Train & validate +# ---------------------------- +def train_one_epoch(args, epoch, model, criterion, optimizer, train_loader, device, scaler, scheduler=None, train_sampler=None, global_step_start=0, max_global_steps=None): + """ + 现在支持:若 max_global_steps 非 None,则当 global_step 达到该值时提前退出 + 返回: epoch_summary_dict, step_logs_list, global_step_end + step_logs_list: list of dicts with per-step info (for logging to CSV if需要) + """ + batch_time = AverageMeter('Time') + data_time = AverageMeter('Data') + losses = AverageMeter('Loss') + top1 = AverageMeter('Acc@1') + top5 = AverageMeter('Acc@5') + + model.train() + end = time.time() + optimizer.zero_grad() + + iters = len(train_loader) + step_logs = [] + global_step = global_step_start + + for i, (images, targets) in enumerate(train_loader): + # check global steps limit + if (max_global_steps is not None) and (global_step >= max_global_steps): + break + + data_time.update(time.time() - end) + images = images.to(device, non_blocking=True) + targets = targets.to(device, non_blocking=True) + + if args.amp: + with amp.autocast(): + outputs = model(images) + loss = criterion(outputs, targets) / args.grad_accum_steps + else: + outputs = model(images) + loss = criterion(outputs, targets) / args.grad_accum_steps + + if args.amp: + scaler.scale(loss).backward() + else: + loss.backward() + + # 每当累积步满足 grad_accum_steps 就 step + if (i + 1) % args.grad_accum_steps == 0: + if args.amp: + scaler.step(optimizer) + scaler.update() + else: + optimizer.step() + optimizer.zero_grad() + if scheduler is not None and args.scheduler_step_per_batch: + scheduler.step() + + with torch.no_grad(): + acc1, acc5 = accuracy(outputs, targets, topk=(1,5)) + losses.update(loss.item() * args.grad_accum_steps, images.size(0)) + top1.update(acc1.item(), images.size(0)) + top5.update(acc5.item(), images.size(0)) + + batch_time.update(time.time() - end) + end = time.time() + + # increment global step AFTER processing this batch + global_step += 1 + + # per-step print (controlled by print_freq) + if ((global_step % args.print_freq == 0) or (i == iters - 1)) and ((dist.get_rank() if dist.is_initialized() else 0) == 0): + lr = optimizer.param_groups[0]['lr'] + print(f"Epoch[{epoch}]:step[{i+1}/{iters}] step_train_loss {losses.val:.4f} acc1 {top1.val:.2f} acc5 {top5.val:.2f}") + + # collect per-step log + step_logs.append({ + 'epoch': epoch, + 'batch_idx': i, + 'global_step': global_step, + 'lr': optimizer.param_groups[0]['lr'], + 'loss': losses.val, + 'loss_avg': losses.avg, + 'acc1': top1.val, + 'acc1_avg': top1.avg, + 'acc5': top5.val, + 'acc5_avg': top5.avg, + 'time': batch_time.val + }) + + # if reached max_global_steps inside epoch, break (handled at loop start next iter) + if (max_global_steps is not None) and (global_step >= max_global_steps): + if (dist.get_rank() if dist.is_initialized() else 0) == 0: + print(f"[Info] 达到 max_global_steps={max_global_steps},将在 epoch 内提前停止。") + break + + # --- flush remaining grads if needed (handle gradient accumulation leftovers) --- + processed_batches = global_step - global_step_start # 实际处理的 batch 数 + if args.grad_accum_steps > 1 and (processed_batches % args.grad_accum_steps) != 0: + # only step if there are gradients + grads_present = any((p.grad is not None and p.requires_grad) for p in model.parameters()) + if grads_present: + if args.amp: + try: + scaler.step(optimizer) + scaler.update() + except Exception as e: + # 防御性:若 scaler.step 因某些原因失败,尝试普通 step(只在极端情况下) + print("[Warning] scaler.step 失败,尝试普通 optimizer.step():", e) + optimizer.step() + else: + optimizer.step() + optimizer.zero_grad() + if scheduler is not None and args.scheduler_step_per_batch: + scheduler.step() + if (dist.get_rank() if dist.is_initialized() else 0) == 0: + print(f"[Info] flushed remaining gradients after early stop (processed_batches={processed_batches}, grad_accum={args.grad_accum_steps}).") + + if scheduler is not None and not args.scheduler_step_per_batch: + scheduler.step() + + return OrderedDict([('loss', losses.avg), ('acc1', top1.avg), ('acc5', top5.avg)]), step_logs, global_step + +def validate(args, model, val_loader, criterion, device, max_batches=None): + """ + Validate on the val_loader. + If max_batches is not None, only process up to that many batches (useful for quick checks). + Returns an OrderedDict with loss/acc1/acc5 (averaged over processed samples). + """ + losses = AverageMeter('Loss') + top1 = AverageMeter('Acc@1') + top5 = AverageMeter('Acc@5') + + model.eval() + processed_batches = 0 + processed_samples = 0 + with torch.no_grad(): + for i, (images, targets) in enumerate(tqdm(val_loader)): + images = images.to(device, non_blocking=True) + targets = targets.to(device, non_blocking=True) + outputs = model(images) + loss = criterion(outputs, targets) + acc1, acc5 = accuracy(outputs, targets, topk=(1,5)) + batch_n = images.size(0) + losses.update(loss.item(), batch_n) + top1.update(acc1.item(), batch_n) + top5.update(acc5.item(), batch_n) + + processed_batches += 1 + processed_samples += batch_n + + if (max_batches is not None) and (processed_batches >= max_batches): + break + + # 如果没处理任何样本,避免除0(不太可能,但防御性) + if processed_samples == 0: + return OrderedDict([('loss', 0.0), ('acc1', 0.0), ('acc5', 0.0)]) + return OrderedDict([('loss', losses.avg), ('acc1', top1.avg), ('acc5', top5.avg)]) + +# ---------------------------- +# Main +# ---------------------------- +def main(): + args = parse_args() + + # handle local_rank from env if not provided + local_rank_env = os.environ.get('LOCAL_RANK', None) + if args.local_rank is None and local_rank_env is not None: + args.local_rank = int(local_rank_env) + + distributed = (args.local_rank is not None and args.local_rank != -1) + if distributed: + dist.init_process_group(backend='nccl', init_method='env://') + rank = dist.get_rank() + world_size = dist.get_world_size() + else: + rank = 0 + world_size = 1 + + if distributed: + torch.cuda.set_device(args.local_rank) + device = torch.device('cuda', args.local_rank) + else: + device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + + set_seed(args.seed + (rank if distributed else 0), deterministic=args.deterministic) + + save_dir = os.path.join('models', args.name) + if rank == 0: + os.makedirs(save_dir, exist_ok=True) + with open(os.path.join(save_dir, 'args.json'), 'w') as f: + json.dump(vars(args), f, indent=2) + if distributed: + dist.barrier() + + train_loader, val_loader, auto_num_classes, train_sampler = build_dataloaders(args, rank, world_size) + if args.num_classes is None: + args.num_classes = auto_num_classes + + # 使用本地 Model 优先(LocalModel 已在文件顶部尝试导入) + model = build_model_with_local_priority(args, device) + model.to(device) + + if distributed: + model = DDP(model, device_ids=[args.local_rank], output_device=args.local_rank, find_unused_parameters=True) + + criterion = nn.CrossEntropyLoss().to(device) + params = [p for p in model.parameters() if p.requires_grad] + if args.optimizer == 'sgd': + optimizer = optim.SGD(params, lr=args.lr, momentum=args.momentum, + weight_decay=args.weight_decay, nesterov=args.nesterov) + elif args.optimizer == 'adam': + optimizer = optim.Adam(params, lr=args.lr, weight_decay=args.weight_decay) + elif args.optimizer == 'adamw': + optimizer = optim.AdamW(params, lr=args.lr, weight_decay=args.weight_decay) + else: + raise ValueError('Unknown optimizer') + + scheduler = None + if args.scheduler == 'multistep': + scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=args.milestones, gamma=args.gamma) + elif args.scheduler == 'step': + scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=args.step_size, gamma=args.gamma) + elif args.scheduler == 'cosine': + scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=args.epochs) + elif args.scheduler == 'none': + scheduler = None + + scaler = amp.GradScaler() if args.amp else None + + start_epoch = args.start_epoch + best_acc = 0.0 + if args.resume: + if os.path.isfile(args.resume): + ckpt = torch.load(args.resume, map_location='cpu') + model_state = ckpt.get('state_dict', ckpt) + if isinstance(model, DDP): + model.module.load_state_dict(model_state) + else: + model.load_state_dict(model_state) + if 'optimizer' in ckpt: + optimizer.load_state_dict(ckpt['optimizer']) + start_epoch = ckpt.get('epoch', start_epoch) + best_acc = ckpt.get('best_acc', best_acc) + print(f"=> resumed from {args.resume}, start_epoch={start_epoch}") + else: + print(f"=> resume path {args.resume} not found") + + log_columns = ['epoch', 'lr', 'loss', 'acc1', 'acc5', 'val_loss', 'val_acc1', 'val_acc5'] + log_df = pd.DataFrame(columns=log_columns) + # step-level log + step_log_columns = ['epoch', 'batch_idx', 'global_step', 'lr', 'loss', 'loss_avg', 'acc1', 'acc1_avg', 'acc5', 'acc5_avg', 'time'] + step_log_df = pd.DataFrame(columns=step_log_columns) + + total_epochs = args.epochs + # global_step计数器(训练过程中跨epoch持续) + global_step = 0 + + epoch = start_epoch + # loop until either epoch criteria or step criteria met + while True: + if train_sampler is not None: + if args.seed_sampler: + train_sampler.set_epoch(epoch + args.seed) + else: + train_sampler.set_epoch(epoch) + + if rank == 0: + print(f"==== Epoch {epoch}/{total_epochs - 1} ====") + + # 如果传入了 args.steps (>0),则把剩余允许的 step 数传给 train_one_epoch, + # 否则 max_global_steps=None(按整 epoch 执行完) + if args.steps and args.steps > 0: + max_global_steps = args.steps + else: + max_global_steps = None + + train_log, step_logs, global_step = train_one_epoch( + args, epoch, model, criterion, optimizer, train_loader, device, scaler, + scheduler, train_sampler, global_step_start=global_step, max_global_steps=max_global_steps + ) + + # 如果启用了按 steps 的模式且已经达到上限,标记需要在做一次验证后退出 + if max_global_steps is not None and global_step >= max_global_steps: + if rank == 0: + print(f"[Main] 达到 max_global_steps={max_global_steps}(global_step={global_step}),将在完成验证后退出训练。") + # 我们不 return 立刻退出;后面的 validate / 保存逻辑会执行一次,然后 main 返回/结束 + end_due_to_steps = True + else: + end_due_to_steps = False + + # 验证并记录 epoch 级别日志(如果在 step 模式下很可能在中间某个 epoch 提前结束,但我们仍做一次 validate) + val_log = validate(args, model, val_loader, criterion, device, args.batch_size) + current_lr = optimizer.param_groups[0]['lr'] + + if rank == 0: + # epoch summary print, 格式与示例对齐 + print(f"Epoch[{epoch}]: epoch_train_loss {train_log['loss']:.4f} acc1 {train_log['acc1']:.2f} acc5 {train_log['acc5']:.2f} | " + f"val_loss {val_log['loss']:.4f} acc1 {val_log['acc1']:.2f} acc5 {val_log['acc5']:.2f} lr {current_lr:.6f}") + row = { + 'epoch': epoch, + 'lr': current_lr, + 'loss': train_log['loss'], + 'acc1': train_log['acc1'], + 'acc5': train_log['acc5'], + 'val_loss': val_log['loss'], + 'val_acc1': val_log['acc1'], + 'val_acc5': val_log['acc5'], + } + new_row_df = pd.DataFrame([row]) + log_df = pd.concat([log_df, new_row_df], ignore_index=True) + log_df.to_csv(os.path.join(save_dir, 'log.csv'), index=False) + + is_best = val_log['acc1'] > best_acc + if is_best: + best_acc = val_log['acc1'] + if (epoch % args.save_freq == 0) or is_best or ( (max_global_steps is None) and (epoch == total_epochs - 1) ) : + state = { + 'epoch': epoch, + 'state_dict': model.module.state_dict() if isinstance(model, DDP) else model.state_dict(), + 'best_acc': best_acc, + 'optimizer': optimizer.state_dict(), + 'args': vars(args) + } + save_checkpoint(state, is_best, save_dir, filename=f'checkpoint_epoch_{epoch}.pth') + + # 如果是因为 steps 模式达到上限,则在完成 validation / 保存后退出训练 + if end_due_to_steps: + if rank == 0: + print(f"[Main] 已在 steps 模式下完成最后一次验证并保存,训练结束(global_step={global_step})。") + break + + # increment epoch + epoch += 1 + + # stopping conditions: + # 1) if steps mode enabled and reached steps -> stop + if args.steps and args.steps > 0: + if global_step >= args.steps: + if rank == 0: + print(f"[Main] 已达到指定 steps={args.steps}(global_step={global_step}),训练结束。") + break + + # 2) if steps not used, stop when epoch >= epochs + else: + if epoch >= total_epochs: + if rank == 0: + print(f"[Main] 已达到指定 epochs={total_epochs}(epoch={epoch}),训练结束。") + break + + if dist.is_initialized(): + dist.barrier() + if rank == 0: + print("Training finished. Best val acc1: {:.2f}".format(best_acc)) + +if __name__ == '__main__': + main() \ No newline at end of file From cd7c91fba01bcdc973e5bc69b54effc0ea49eddb Mon Sep 17 00:00:00 2001 From: wangwl Date: Wed, 7 Jan 2026 06:42:50 +0000 Subject: [PATCH 2/3] fix: cleanup code and update --- .../SEResNet/SEResNet/README.md | 5 - .../SEResNet/SEResNet/Se-ResNet.png | Bin 109948 -> 0 bytes .../SEResNet/SEResNet/model/__init__.py | 2 - .../SEResNet/SEResNet/model/resnet.py | 379 ------------------ .../SEResNet/SEResNet/model/se.py | 19 - .../SEResNet/SEResNet/model/seresnet.py | 186 --------- .../Classification/SEResNet/coverage.txt | 3 - .../build-in/Classification/SEResNet/readme | 65 +++ .../SEResNet/requirements_exact.txt | 89 ++++ .../Classification/SEResNet/seresnet_loss.jpg | Bin 35249 -> 0 bytes .../Classification/SEResNet/seresnet_loss.txt | 29 -- 11 files changed, 154 insertions(+), 623 deletions(-) delete mode 100644 PyTorch/build-in/Classification/SEResNet/SEResNet/README.md delete mode 100644 PyTorch/build-in/Classification/SEResNet/SEResNet/Se-ResNet.png delete mode 100644 PyTorch/build-in/Classification/SEResNet/SEResNet/model/__init__.py delete mode 100644 PyTorch/build-in/Classification/SEResNet/SEResNet/model/resnet.py delete mode 100644 PyTorch/build-in/Classification/SEResNet/SEResNet/model/se.py delete mode 100644 PyTorch/build-in/Classification/SEResNet/SEResNet/model/seresnet.py delete mode 100644 PyTorch/build-in/Classification/SEResNet/coverage.txt create mode 100644 PyTorch/build-in/Classification/SEResNet/readme create mode 100644 PyTorch/build-in/Classification/SEResNet/requirements_exact.txt delete mode 100644 PyTorch/build-in/Classification/SEResNet/seresnet_loss.jpg delete mode 100644 PyTorch/build-in/Classification/SEResNet/seresnet_loss.txt diff --git a/PyTorch/build-in/Classification/SEResNet/SEResNet/README.md b/PyTorch/build-in/Classification/SEResNet/SEResNet/README.md deleted file mode 100644 index ab4a62afd..000000000 --- a/PyTorch/build-in/Classification/SEResNet/SEResNet/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# SEResNet -SEResNet Code Snippet -
- -
diff --git a/PyTorch/build-in/Classification/SEResNet/SEResNet/Se-ResNet.png b/PyTorch/build-in/Classification/SEResNet/SEResNet/Se-ResNet.png deleted file mode 100644 index 7b0075ed38061ac48689e44ad944f9a0c4bbdd77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109948 zcmeFY<9B6E_$?ZB&~eA=xZ|W_+qP}nPCD$^wryJ-+jhscb63B=bM8I&%l!-P{<6o| zW3Q@ORS)KTo>{-;WJKY=Vt)kz0f8466H)*H0ha^;0V{aRe4OtcpLeHg~ zE{~1)zi0UOD=--R|M^(X|3BFO+W-IWJtId4(`>TB`l-hk{hfPvZx5~9bUythvL}H; z(c|Ha-FmfQe}Dfa5+X7SIJ^XKQ0Ko#Kkn-`36RjxoDarR$H&JrGBP|E&9F_UJ=$2cz;S*F_M*9WW+s& zTVY$9T z9+az1*#=sPKX_=j<~ARZPOIizLrVp@J}9jTkN31Z%jU$&Dwj)IX0;HlURBpkLl2wF zXg(&31$R~8FN>|xwI=kHG&hGAJK;xfX!hfV0|WE)j>EDAwYB5Y59!Px zs=f|Lsgx^q99BndY1&TjjxR)+fQ$K`5b(LUE$~NP#NvY~FU{UacXIeL+s8EL5YQka zv|L}qTw~#)I0{3@~##G@FG*Ud8L0kFNcTy+f7S-P`o;J#r_c=ACfvfgt#eZw5 z3;H{EoueQX9{j3+r9)gv6(s>k6suWZNz>$@KvY@*`Rzqg5S8o(N2}9j)~-tS9fA`h zT8vH8S2G29AcmE|ffb^jI| z>E0%&Bb}JUy;QBmjzxg2a6<$Zvk8u%UG@WP8JiHy{o~F3?39?Eo}Pl@`0rTq@{iQW zc;t|TufjC}yL_IDi;K%b<$tbvuARJjGMTUq;@%b5bv*6@FhG-3L{_=JZ7DncP<~+9 zFKlr>RWUOoXHZ`6^kijbMoU0|TK*pOIL&5~sDgn(G4yIPU+7u?xGp|SLF?sX^|$T& zgq4R!TGErAQnN~1^nW%HhC~poicINL6$b4$#qD+la)T(g{hikb7Y`5qM@VK|?0Dkn zVU7K-+0Jeo6ciMzJUzDsV)t#gnxS^+C|6!~M9rgEV@prw^u>js>s~kCIVa`6$ZprW zf1Ym-WivUP?@yFFZ29ssl9QnfhNvZ3(yjINclP&{ah6ZB-JXcZWVI4}OmF)VX*!A?2%?H_ETbXCpyzpjUA4e> zR5nAlPzmL;x> z9gRk%Vzu6a?9g@6SCD&(J3Xy)X*569;U%uWS_xk>bepyq#HQm6s_g%oy4 zMOYiq5=H1T{*9TH_3`@Je7*$vqphVy&-liTYnts~yMu@CqeenDVP@bdk$vZ|x4*&nXW#=L52cl*U&V0g9pY z#s0ZKr^f2oyiXWVfgH$xmIF>uW``CtzR_Y&OhU51`zL(5-^9dZ7cLaf$T@=l+q_y= zS65b6mX40j#l=OA6Oyyv6g}WMMuY^8i6No6t_!5@LGtYf)#7*f3}qprWRr9HjE}-3 zjJUSKF^5XKZi(5Dq;#nn86Cc#ALnb$Tiw3+lQpfatuf2T$H$G9OI3m)2m~%jB!bsr z7~d+UPH3Ab4M;|yUmv6Q-kP#qEzZo!Ca|A2l5<^6&kWeUJ2m?2%z3yW4V4p>C}jW+ zuo(a(!bd+vUpoDOz$@?riDX)BgYm=~QHBZxCwL-`8V+Ay-=ikJ;~MFkXD<;5FbT3f zpAn=X3uPkl?lyy7`bt_uj@K0&%TjL!cd6kGtXHBq2f`uE&$X{9oX*Za*t5c_E!_HS zRvTa(+FM%KgxLLiLD;l_JP+WB)h2683yZJ6@l-0jjGfW+wC?V<-?pmLe7LHDLK2&p ze&$yV`N8DVZf3RO@L&X)H)DBrTnt=O_C(1bg9Y;4|2qKgb){Qc2#|o**;>P)D&1}b zNlrJ(pM8iCi<_HW=5s|8>8!TvE%ekUHKGD4A%ZRvst6LnJBgg?snx>tuLqNe_1GM( zLFuhYO!i;a(a9otd_4zwp0rSlHXw#zZ$4_nQS3WLb4mk^kuHqxPZmU@aC;eo1<-A{ z?b44H%2m64-mhf9K)(mNG|HS|;)d@|zCG_{WTtAXx~XHq>bSdva;|RsOtI^ZQvHz)R zvC+m%opg3~rq?-u)J|!xT^=H%Z0sgnTZ}H1)yUbrrC}@Czf>E!;M@rr@oYBrSNJfy z2t$H>bDdOL%lBl*Mk{Wu!UHeA9Tf?5p!W4~%eU4KIRi=uRc@HYYWXT&mgji6mKc}9 z$;pXeusq*Ja`qB$qt7; zp>Pl`yEheW`PBk?S{UZ=7AnuX%VbH@U|ZVd2}q_Y5d=Y1!0mmNb~}<6vh5EwF1cX@ z92PjqWclI6*y$=%futtI@GirSHN;d6C2Ey9q$4v+b8})o;;&Z~*v?puB`ZC;_QIpr zb~UXUZIF;{Uf*`<-KKSc>=gq8YT(AuTU@}(>;2;Nc(LL6c;S7sFJ6k*R#j#5`f%Rv zbPVeD*c zBltywi!_t%#DxNEx}T_QGL6}CdoeN@g&L=(O+H_wHwI)K;Q?G34Lo^Ks~(??%NiWz z&9hyFMYY5-!q-+em+?OaH4pJG34jTcmVzgVUxfwrzzT2%^7MA8S%hr1yIyW@>sduc zP&QSO;wytD^e?gW@Xj?~_M(@W{?8Z^5g^03Qo^5ax3X^T#M5{Jc|Cik<083v6x0uk z?q5ipckp1CUt)W`pf%cb%AtFd9{_{n^|&LKy4YTaznz}R7d6BpUcrkHGM|_~F_JU< z2ke*sQM2rAWpf;C~uQ8(HGNT1H9i~6F0@znk2G2&qI(}oa&&wrD3 z^#sBo&`P>&x4O2xZX=tUSxb%og0Luy|8GK!mOAt67nsl&L93r6yF&8@Vm#~X>pZ~0 z10Dk)%sw-5b+|;a;9?>wg#&$puaDK;A0Fqc%n%~{T7wjdMR#W_DBzrLPJouM7fR3j3e4bpZ4sOMy11T(x>KlarN+3DrV9Wxdg6 z!(+Y0{^J8!FY<*9MTk<-oKcu6WW>u2a(vV_PpAo8wz^n8@}lW%fw*0n+iI^8ZfTXm~I z=%eTaX=q(ISSPeSK}r@}V-2ImO;rf`EDq+uKbWR3!vSDVD%C1J$+aSB9BPNPpXP*4)^!Bv0NTQHGN zA?0^!_I`CS+7Hw-+#UEG>U_ApEhig@ODUyq>4-+5r>S=Zy&GCW9vd6`vkBOV0sBC^ zw4+Qg8Fc4=VUR31Q67xWf5 z6De5wSEw;~@7Y8Mb_JIGt69!lZJ8N@P+1TN0)c$S$bi497g$uTZ?wC1zh1P*#2{gA zK0iH;r?XZA(XOmAl_s3V+$=J7-LavWS;_Vt0&>dd z`=f4w9FSeU2mAfplcOTGhVv4Nk(BP`td=+p8T`lYm4yMKt&ALR>wbn0{TH!23@G>v zpPP)QfX0QKW!zXRgIY|DkFU2mQ|+<~I{c1M#^h;IE;!GWgBw^>hV5ZM8hNcfMdgYWYB?-s-rc%#I}31xa9b zW`6+Frt#GVpRoD7v5m*sY;{E*xz@Dd@cMAYjhCslw7c??qJBkY21nLM`b4(^fePdn z5fKrSlt9uG-UaF+CzMT>wN>cLr_Ar5#-?D2$Q|^`#D>5f4W4+#l^+Voe7Ey zO2PZ_WZ2iJ}_-lrdKw;bDN-={bQ zM9gT7NJ%s>4FTQ1unfC0y5zY#02Aob>HEpUg4ic)))|ceF_pg3uKsATGX0zQrGz~#)gUpb4h8j{|G&(P z3tHD-z6bNm@(XciKP_1ISBS@IGI@E*0ld=knC7n!p+Cofe+MB^%!~jVAF%UhVBqH+ zLX&Ig20T7CDYk&QYOe~Amu)uM77D~s0zLd2&5lV)U;G|L0;PtcC4aw2X_EqV9}D81 zzWDN0*11RqB9PXN68ZdXeULrI(CaHKm!mq#%k6Lti-{kGh?bu&~gPszgFZ&K} z6P1L={yIFKuZ5i1js9Z4j|X1Uh~Ll1tuBXbt`iBI;6fXqx?H9^8lZ5dX14>Dpdu$q zL}v=Wx~Y#MJSh9Lzc{gMk*5ri@<$$pc|jUaj6>D7a1Z*iAL1SK?#WM%*e;oZ>Q3OM zQ@=kr5nF3<0&byR1-T4T{{3Vn$Gjzw&s!Am@{J0Rqsp8pp*tnE7$UK+T&BjVlU>|# zAMdY%q7M)59K>W02zVS2ScnE)!=*lds?k|2#9CZ|s>pEI52+NtW{iPID#^>AfjvEZ zBvkos4vp;Ta#4bQWd$NJjWDQi)E{VB^9;F`Wj1S>pARy2i zO`r%RQ-va~sFv>QJ6_WDl@=E-%?9z?__dkI>-${_Oa-cjN?0kjSyx-{INFcm?m|92 z9KvjDk5DmPFsBJWiLxwg5POhrENub?r2Vt@!B4nh81M>_Ahw@nWxB=Gd7 zQXkY&O-#K%(Vj076J^d5bk7k|smbHzR`hrujb>Beb7ls~To~e)`Z1M~|&u%neS z14%TRF-^DvQ8Jkv@ZY&wGQN0Jx&&bpLs%ey26nC0=nFbHFobRZ8NRc#^R$w>{(!GA z?Z3{+{~{}@h3T;^FxT(;<$)=K@no`1jg8)GLZuRD3i<+k$VhCi7wZ7ZN*O>4jr=w5 z7}{P0jhD~!9~qU){+A{^>!TquLy;igsb?o&US38=-l`r31!<7MEG)znL2U_z4*f^) z6e#0&Kxw}Im)KDufK=7Uge<1zPu|7O&JK+>(`>8z^lee0e;$sIfE6NU53~Zo5=Xwh z`{Tv3pn}h6&!JX+f00dD>R)mKA-v)NLQN-PW?CC0rxVGM5Etbz`?jH(wYBuiN?Kpi zNhuWs(lvsOAel^tpEgAwb~GkESk*v7&8Y=PiS~a>7zNNuH7Q5iT{X{3O|)n{P#4EACNN;L6nG-f%LXj zP(YHBO$>RqM)+Y_08mVR25L9> zPF_RFX>)eLA)3Ude9mlfIAiu^8(w0Xs+w(YyoMG1p z^WKO*Ir79}0{*lk(Re&xi8Krh&h@Gd|5Z{dAwR!9H^ntorLyjVEYAZ=s#ty2_4>n^@iF$LYA1+P|i(dJ4zYg_9AFb89_pA!8a}r^B zZLP*CFHjnv{zMXcHrcG(pJe4M?f%IJKZhT|Q~%?`!h|c3vxr=Baa*#;S=Ir6v0Mud zGdk`2W38=jH8(t-h&DJ#yUU4_wmv6iMU0sZ8%$df=duT(5?kZM&UiyiP*p0cgOSng z;Y9r03jWE~reLZHceUR5eX>4!BDnJPwmujg8%?1HkuGj`;55X=cBSTh9y~KTi3V?D zKtgt}pH=>M9dyszMY66B3_LsyIXNb$3pE_#3Cky@=G0R^Z78nO=z1tKYJ-;#5gg0@!N242@0w|G`kecKIR1BwzVMjVNOh6P=%~ z^joH1USEj?!oCf`7@n>%TP;qizHeT4u0?aPB3y93jl~9Va$xA_a9a-yWq*2H>04~J zC#WR~#vIPQmfOdZ!QZjY?j~)mF-dX%;&eA79U2-eMhhKSPz~0{x1MRu)zJ{J@+xz} zFU%hW-XEcrs-`9&AONUL!O&RabvKxqogAgNt{jEK-iAA$Z)9fTW_G5z;4|y{C2O2L zCpvy`puaPSCZ(F3vO~FCEUu18g+DIt#ZAmH)HE?K{VnZwE)DCcV+w>kXgcuVf>*aJ zGwA=XR;Yvy>XA0=YJm)gPFcCTy9?A)DcvDq;r*lhQ`;+j?0vG-rh4ZVW@i4ht4GhE zK(%0Sv)5Z4#O+PZ-WsimX=}Qi&aBP}4SQQE*SW6-H@O^eXsNR*psSAc^i2xLKH#Z$ zor=g?hV&ziU)B@=P}k>a2kMWwbg(NKdN@2AmZ_sqeF?*f* zu)P}?sEX9{W0Y$A!0fb~Y3H8C!a-~yZDpxQS(!$^QW_9jmA-+_&W^fj#O70Ta^j4b za=M(6qkjFnmhxt4nrKx(eI``RqM+@VP1~yzE{oUZ%X6nM0>ueF(Tu8|c$w%#?Colf z-W=S-Yl83XD(LhV4?2OdThXrCu0r09L4{rvZ@rq@GH!ox0}ckpH${!S;Q`*}FRZ21 zecY+L{f_CRR=7m`k;dwYCG7DccaOh;J;`Yr`U+jcuw44@Wo8)9q6X ztt#+tSkHef6qsw+-j6$%jogfCT7n;{Sc1XqZ}Nv*?mCEIM5hM(H`NFl>Cj9E1GPJx zI8THTG?$9><;q1KUecsqFa0uQ{i*91a9Kaa083&K6zwwp;x5WGm75!F{85PF&{X#MipSvactvBz&p1$^6>B*q(L0@|J zy$Ot!yssgAWK;n?K;;$zm#rsdi?GFhBYmqge{L6Od&ySeX}t6o6tcENioU(whN3sU zRKp*Ay|C48;a(|pKHcsq;@=SQ+8q74(-*eI8bVfZxXw{STF_He+wHsOx4lUW#lq;H z-l*0`?_|D7Gp$3z$xTz9(=zbMALr$=LPvF(?sB%)DL8ge>EX?j(^}Z{LzBoka{E-X z^+m0;_{Tu!aA0Q%(8f-cG!(6jz_5o=c$H_K>F>vJ$@0v-#F;L!pL2QVYzfQGU~~I$ z_lUCkQE}<_>!0`Vaf<@L-9ZavXJ-d#I~Vk*KBpwnP_j{%nPqnWs9hD&R;%kFspdJ^ zaVXl%r0{lCFmHRa$X#p=HNzz>d}A?s>6j!g;T+@ z=mw5jUHo2F_b~N9Q+bu)4*E8Mm_NPIQ~}@bK`+>uUDnmzxk`8TQ_5m%P~$osPu2tpk_7 z^`A%R+vc_v_Yy7@MMV(Au}vcX zwQ@zfgnq+by)mkfQBqn?BX`*05pROi`qX@OyjGQ)7@Jh20a@^pceYEJ{cT^2X%jV zdyiBTQEqOgZwM(HcBX2FzOmJ5aVR~pxy9tt#4`QMYMSNe^pIOW-m%Kat{rn@<5M9_ zUBPQfRuo9lRdqwPmEqE0rN&WsfE#HVI{NQv%OjxsKHHFs;%;W2>xgd4~y$-8t+EU%*KnCCpf^s5TBPI@k8sE zHT@q_^8+AYWiVRCHl9ycgba0_?(XL1=AGte+Ntem&2W-qjpsR2V2%&(SLa*FbhuqC z6{-Y?Ss2xv)E*v;Z{}Shg3@RC<02=o*N^pWXgJU6M`r4-NBd5C6F2sP0&5RgTuyfF zDm0BwIux#wEVHVOp?Q;;9kC^w%e_iH#^clKURDKXuFs5l=d%wB^UER=!QPkZ)E@Tc z{p*tSL9J8zy=17rYht@Dh~IVHAr>n&UEiMUh2D-=8>w!lPL7Y2KQ=XJM`jqB>YVHG zx&MZT(j8{&wA*PL7Tcd^!aYYoOJ`)o>BP|ew4J9O9#eSb1yB5@s_s%xclfE_^^vX2 ziAeK#{kG%%P9}x3HnO2c?k&*e}5{!FBTHA_Y#=W^d^JB};!@UHD^)nYnb zXF4T|t7Fqd3F3FFsE_wZ7TzVC;~Nhd4OqcXJg2Ew%}xf6Hnj^8(J!Jl77Tw0#1$ zTDFP<84x=Pu$>H8m^`+D{x;>rDeQL{=pkdpDgk9YU1#EN1bP31F16<1{7iQ(cFcujEZi_V(hRVHeq4cE|d$tRzRZvP54r;pC}(=&bJS@Cyal++5X*%1Q8iI=%9#+;OpcAvqD!Wt zhg)thxb6mCg^I7SesV4KI!zXXCTU=|P4J#9Y)@Y%t4Mw5&gS@7cSZdWvCi`}|D3e|b@zc#@it>E7zF|F2m|cT0!o zntVWQC-|Lr`@Xn1SXmCX2aC8sw;XL`eJbE~u0?PGRE{o^rP zi6pUU|5c2j@0&TNb#Sr!c;)RYolvoHq0VakVamr)Cs;+}bJ)EXtys9M*jVg`)C!m& zm7;bRWHAA}zn(*?q6lfR5gInCDcK*={>~PmliyE_kl3xMtw9PWRNmVqmg#Cozvtp+ z9ky9X^)0d0QjUp1OeR7FNuNieFE`yW<1_jfYaJ}N&wFGeMi}bp=g^0dhB`O7+01&v z0{slQ`B7o8)L#L)N&l6SkT8`@7ydW&Hq*z*gtNExv9-?)+N1d*?VNf--KoN%C-J3A z?{=W)UaffXFetKG+&E=A=j+9OzXYG$^kM%R6GPTu^)V7SB3={5zd0$rtpSH)enTMLm+s)K2ygSPm*!VHq*c48 zLBA{b)bgv-OM#`KY3G$B)WN4dr(qj2E0dG0n3Rai!5{7Rs8g@`{w;}N;?LEaay*Cj zAXp3@k2~n^0@G6-o}N@^3?`>5Zp<_FYV$|&>qPXLIkpBR#pSBIhog&iwyZvXKKMiX zhZh!?Sbs91LNj6CrCl|<7GIqr*Q#qdy6WoUvvL|jdxUGhPQ2AC`k1)*_#m&f+^4Mc ztf(?Hu&^NEW5HcDwE>b$bKNi7Y? z?~Dv;@*6XFMaXRL`@0*NA^^_1CBhT+g@u&6qz}D^7=~{^M2ccL zhII#KIUdu^*au$3c;n5k3@xDGsa1dN?dQEP$otF^VoUrZ8F#ziS0(LPWrEqpdS~C* zq-V;t%4jNn6d)B%4?E=Sf^tQviJV9bf%+9F_1>f*oP|bwQfJWYFNjz#j?LEJo9CH6 z7jMOM5Ydb3=@|q@CXAqzTW{I#c83HTp-HrGKte(Wd!z}#Z}G$@Jv+f5Mu$%9Xu2D) z_KSq=OZ~Zc_x&i>lvi=l;YS{-*;wjcHXvr69}qd2b2;03g*rsHJW3Pb9$b<$U2A^c zWnDYiQN83ETd1?#zRbtDJa}vks*ewdZ2kQs`Sfw+&3B!4(@n$Z?BZ~#hknYc?cLO6 zGRj5e0P^KT&`14vo%BsS_jiadF}`P3^7M|3zj8kaFDGM``&xC<84ii{FvKf)_P0*e zhAj2Ki*F(#y6ipeQOk$4YD0Absu)H=gkps~J&D z;fGl^&>Ld7QWHd~Sy_^kBS#X;v2>H0lPD3)5)NEG7N>;dU|>Tv|zQwzu4SfK`XaY72H)77VoTXCmO2L&b>!Sv7@)-lRNq&py|+aI*-S9M z&o_!$Ui;66`KAU%&Le$}Qyo!?njM_IA0Uh^(mPt2neD8%09A8?d_xums&2h<1|0L_ zFaBAjcpr(C8HMI%dst=$hnjNZ2e4nXe&^Q`r&m9F5dXzwhjjXROBrJZU64Bx_REvA z#L}Rjc12Y8ymncvHl%*RiSxlxbx*vyPR*-JZfQRl|T*%c)jvO(!>qtjEh3hbuYrWR`pC3WX0nwkA) z`?$g(jI)HWz--i;tMm-7Ju|FBU0Ca+bihVs#51WsWb50njB$f1$vFa6D&hmBRQb@k zzGkZyoAoMDM-0VE2G2;g^OvOi9g%ZS{&by(jyo0fCuU6|g*|nS))Y*?soFT(On-U9 ztlZ4_+Af4&rbXI3nMc?1*^80d6Q7czLrli=RifLP($?DeHlepwwoW_Fbfgr?pQ+rQ z&VlEqb1%*|7bXRzlO?HNG<;~@0^Fpj8v;poec{pHtDT^SEtqnhz^fV&h^;X9^kS2e z23xe|HRi%*kysS0wYjxBz9kQG#o83iYAZ>KUQWPX9yyMPl$DqN0T&#wAy4?w)ktVn zQ{bis`=T*znW#gvBIevsAZ<9uC)&V-9Q)kuDM^)!XiMbR*k(492Pnn8p0++e4)^x* zEoyx>ap}CvxxoI^J`(Hpptbm?CT*kXqHuSA{$$@$@+c#5(rXnV!D0wY8EI zom8cXwm9>ZiS730MOmL|d9s0ib%1n3R)_J6Gimftz!i91jK}EJ{ui1BDp3f8?_6#` zWgj{Vd9=oKDr@7vlWjOA*`@HLWwsOG_A9v%0yKI#W`cv+M_@qh5G&F0z-H82!Ga_s7QYy!T z#!d`j1az?6>1m`NXeX`BkC~JARy*f<54zvZ;vfs9r7`iwTkn?cp4)9YY%B)vl$$3! zqCW}>GIyO|=wy=va_u{1R;PWh<6Hx)rOF9?dh z;1U~=5np4m?E9ka^ZP;}4iD{H>fZE%wyqi>ioz1Z~x<%*`4UrM8L648wW4Bhu&W|LT(okFB`3PB3uGR~)-*4Jk zk1@fh%~L&{@i+teQ{RW`ux`V;EK<8Zv$bQYqUIb={9)kDL=dcHl;J0y?PVwI&Kl@LMzE!JQH3bm>n zS5Q#Uuee(+!H`l5O5go=mpPHI-4Cq0v6zRaG`a`8U#P(^|#*KPCjbgD zIMqLlU5$K7iQGW8kYlw(%3o4XF1{ytk<{G#Pbpo~K`4A?r&WQx!RCf})HGkRYC>ij z?kABnuO!hldWQpb)fKwff!Ffox{9Pr^sKCIikf`HV-n!?~ zoYuCiepO{w*00Mih}C4PUtT!WkGf=6RZv|`M#i6qU;~EeKHfFW6>pohy?;!YD$MkL zGqdcSuT~38AVo_qIilqdg(gS-Z{O92_b8CW0_XyRgNYhaa5eMFU_e)pmb-mnn;~kyV)*O=r(D&V~kMAK=z}ESERex><}d`p^=dlqoSf=vz{UC2m6g) zZq|Lx&eq^^o_tVyB;1O`TXyXEG?BWnMy>UDsMf4flDbh_g~xWshMC3RlpLOfyVRUY?9s7?#e7~S;NKo z=(lm_Q78y%G51t!BsMp^84=*;cRKLkShNB%q82P> zc|mqw&P~fDfbhZPpPDIZhtsmh1PK?{>v~ssd1s@|d2DwnH)#4_|$+83dPI<8X+*I+@KDDOrRWrp5 z%^K5V(+s+4r__i7qus-OBP-!!cr#%><7f~_I5pBfhkmo|*2Qcg?DuNmURV~RDMH24 z-&I^icC){QlF2o){i&*(?anlCqQBGJo^MEnnuZl!kEU~7&Q~eEJRyGP!elZ-LI?1| zDWEy)z1knHWC6}1{$EMnzEwdQ?a38VKGxOLwvH> ze4Pz0FMQDCq`-C4_{#?UrNBHEc6Kbyk3bldyZd`fX%Iiv2cQu*>guM{9!Knl(b4_+ zfdlG&1qw5|f1(HKas7OlO-4#eL16;uEJ3}YETIBIUX@y14WY+k_a_Di2Ul0IM{S-6 z$+v&bP#GHTmAOi353R49PIv`jbD&S^pyQW?0d*>+SYa~Jxt^B1+mh%%tWC9)ige+o zR)*RKukAc4`K57XY(PnYtiO(?tNaTGaFGuWEbIwWfdgr4PXEjTP;L%+G7h+zPGu|^1JYHGSLofJS?-AW)+J{x=zRHfxNfE)?9nm`w4e7@O^`nJPJozQt)H!;q5_-A45SQd%0ui4Rk2AGzbJYTxHBgRAr?&bC?0ZA z1W19VFZtr2ZrM`)j(Fl%CJ~8TuqoAnT166wAo=-!HFT}m*H)^)hQtWxN?&;P_!a)y-}Rdjb}Uc9+B6SM&$7|F;%kN!a)mq6z9D z7~E=VWd+NsTC>>(ZY=;TS>Ll}HoyRb7<^5Tz)7SD(9jRnaECq;v?ayU)z|fkzXM84 zQ1yR(JE~uat@t0Vx<1c;fnI}te6!I=+z;tAK2gO~oKtC3ey@YOxfcnFCcx zMBNXGfD4UbOM23w;DkmUsc(Bk20>yzU!u;6cdLD0LiCp#2X> zZiNHl#9SO4*a9l3Ah03YP+^8qNM%S0+zC*J0c3QyL`tdXrEve0pPE3LTiBf6!{T<> zA6}_9-SfsHxdfDvf8yI7(p2M;YMlM|kvrqJoGP{3(FvoFlM%{iHaD|$826#>UoC@= zl&bgn=xeN77$1-4psWz>@AZgAmd^>Zt<;;K%Aoq7YN?jL8~N*bPS>EUdGby=B_fqH z|C3O5mJR{(hT#~%!HLGtqVPC1nygj;72qh2rVW^cvD@Ftxg~6V0-ynHv+)xeJo{+A z6y=T2vOuFuNCaZEj@#As5ePrNcQc|XKZMl5)(n|ip}WDhOqn3)HUJqhV;vs`28Kuz z6erTOuz@Fo48(@a|A<2^oLTgxZUNbz;PW>W6h_wzEjl{7{ZJA@i4}IeCi1wQ#6Ja) zyw$qh-z^cNsCB)rzpPV-BFz&tF)O1jedXy1~6re6eU6VcDHK- zMa8+*i$JhuRmy(iIMuy+h+97Zl?xy)SE$!-Z*Oae<*4onme`^Zg~8uM?DX{Lx2`pq zE6QFy5c?(PN&X%Jb`&6)0f&b@zuXU@qNZ;mnEe+=IYadoTKSsF`HWXL{r z!}BTI#4XhZtSaKhz~A3%yujh@L?jg_yNB<4M;KsW>}woZY>%l7dwdXmKIRlxW+^S1 z|L?y2i%Csd0Z)EzW80f{t19XCf?`f?X#Dl>#h9jfsCnI#4IDAwF>S_&4dH< z$2mJ_BW?TL+i=(DC7e@hVhr5&?f@$Y=gYM>fQgdkrw~suWJkA30iw80? zFwbKD^FjkHq#sZioq`3hI}Yr6O+h4rVq)YA{#S>pNVkrgt?haQk6E8%-GcDcIITE z&Yr(9y4C@YtSCSN92$-fvIRh;G|+}xy_zKrc|MBVUtzNmf7LEY6ma#}cXpl8^LDNQ#51OEO# zgAW;7HF4xOfF;%}QPHh4hSnfmIwG{T{0+dzo!9y6 z+j7i>M3x4aC1do-Ih#_ljzvXA4(7tF z?FVq*z*xgg4jXB}0fVnXSqyDqjyO+GPv^F;HR$k6IG18T zY}P3l>Vno6L%KCq2@yJ9sWBMPgV~UI&}c@al>oI)=SpB&#RbD6{;EKsl92&`i2wH6 zLn0nLZF&bF)Wu=;47z;qXJ-5RrNPFFYA)}}!=mwi@Hg<~JIZ9?ndg%Oyb9f&C8Q!2 zUF00;gkFGbN%4zr0RO9r@2ETAVPy@Vmj*C-X=q?d20DPITkgPoNVJud6f}h{l{eDS z^rzQyI%Pg4X~{O=B9~%a!8;%&MFA`mNXJEYhwA}~rv-?cdR4~sUSqfri##=uk%+ze zd83?=egE)KS`HPSY>Pm|>(AFsgd5XUWqw7hl7a#nIp5r12B{3CfnKO?BS?)!C!dCf zM(-`v(m?R19F^wd*+0*1>8-LEr$h%j1RmSoD8>gtEZYVo%+{&PsPY}kr|7M~N%|RQ5cnh%Kf8$Vc(UzVLXe`LKdZ(tQ z@B>TABEz5nvO5S~582rDE8RsTWq_oB3mH;0T4pCeHywbL2^L|Qsp0YjTSIR|gEl_A zwD0N#GmQW>GK{Bymq%*euG4s3WCbJ}G55TLSZ0%L)?=Q@ORg*w4yHHevZ6k_)Ic)6 z5TAdhWGKU4QP;Tt>v!gatv)JDrva{MnX*m*FWWCGU;oIGyOq-Y*uzeppccxaZwDw? zJk!)ON(CJqAAhQ)>l+s;SG0juKs>no2!`xHyZ>TYk*CDw_SgMoF+m?Gm2)M`)dK# zlId)o)Q!o(BA%m%7ADyTATL18`KUu)Cf`vv8H!E)i97{O2m;-+J)i5$&+>6nA95dV zufhE!-$nEPqyntIL88Lq;nC8tdEv#Ikt}b4*rJd2a)dJQqxW`<#tcrwK(fUPkg8xp zvl;V;Gg)vQ4E|w#=iu(dP6efA1@MHC25j@IGi>{TY~mVGU(+|iG*UKZF=iHQLqh`>E2*Gkm>TzIH5eF}tyB)Be8$>8BHvO{ z;Ee3=K>)a0&~cLpC#wAn^~eA67t{p-X`)(3=UTr?=enS8;ss^T7lCgJ^YbAyh$@cHBhX2ATwsFf$B-*Tya1OdXReoU2sohr49(On zxC#{b)PL-2>AbCfR7d0z3d00Qm!uvq78MXI0U{z{vai2lIMX=pkMkp4w5CV-J`ml%Mul0Z(T#3>(75t~PZWTW5RgcG3fohYGmez1JUFE{X2*p(>}sX{r~8^|*5 zjm(rJdz>sRhZ6{VdlBq(Y_VTU%FeDf-}7$lfRF&lVA3eIeNSg5=x_AU zTbW4yJEW5r089|^3t9l$lsI#%L=d6De?Qd&n~FF`W18KZH^E5?aRtaY0dn?cn;T+I zb3CPlxcf2Iro9WYi({&baRNw+7dS2^oSd~l={O0hwjvq4(+dsOr=6Wtp!5%0Z5xcQ zM4|fcen|pr5K&sCIfitFby_7AihvZ*?D$ip2vhp-0?3yD$}kCySe6a}Hbz#+Kz~0# zQ1l0aPhkH|@Dv?hZ&r+CP!0fq{n1fmJrlE4_0&P?w{I<0GZgoqdc}$Xn|VVwW#B-g z;s7Ld0OwcsALqAVtRk;c-I~UftSKFmAqyp3)F3yR_)l>oX&@bl6Z`M96TK5YyE)7(PS-WrJsgA(Od#!sCX{6m93qRMVWWlk?khy{x&lfgQ7EkaUl*+@2Z`fl;wVG{gjq7H znX#O8hv2=3GAum>viN=ksrf$Wl3XTTWPv)Zo^lrMz}ZJH0uANaeNP%o(a9G%;_Y5f ze>A<8^wf;FN>W3yFC;SVgX3c6=JUli?sB?E&Ou&VQI@w67j`GGsak(|9{nrKQ@q;9 z1G7a7+Cs6{r!lwrtcItHEsGH~hMLQTsPoMKZD0ekuZ|Zs@67Zx#;$`@ zkYofF2azdA_G9pg7?Kg7mjWD+L^5e9_iQAeNaFyiLTB7yM{Jl<;9vu_IOw$SJO(sk zxlT;Q%RC=(z(=rMnVOpBb@>C3&0jFLr%RQ5W#b)CUBma{QVrz!$`0`;vWr$Q?Azq+;DGQ?Ol0#!qJn!`cZbdL?`@)X{0daDYf%B-nca(hpI$Ff^BIR=HB+NYHf0%t+R4 zaSxA=0(Q&xqY2bVa7Y$^0O}~v;KJbNfEmOZW9{(l3+)TqHG{@y=UGqflFdye3w|E) zC7ix@2(<0}eu3!jbZE;mYy55YyQu=JrqrK>i}>J5IR$1H%*s;RslE?YQtND%{N49ZGU zQVyG6=fy?wh71afmH%dbbY;4FVM@0PANubMKTw0tGdi;VN45`|R^|1OWRAO}>l~9t zFo>h$EBdzYmu`>f;=XF>cTPV!7Lc2&UoCrdPcu?FEK_CkemQ8-N9t`Oz%!yj zKoLYz#3-}^gBs9dph#$d{o0)PobO zlRq-@(#gX0db&*Am{WrPY^Km-8Ec^OqmAy(Hx}cimIf)M#tWYq6TOfO2J1*t8!=}E zU@ikPVb?$mgmv4S!49aC1bl;Z%ie0N9t9ss-O@Upv(x+{IzHgRqYA2cG@v?vNgsh7o_Dp{B z!y8{{q=An;`<(v5Zw{N$K=*B>S%C)DtGT>_bB}o2j~YICsb%KF?UK`$O^U zb~R38K-dVpn?F@8iS?#vMN8L^IzTo>NbGH*7(ef!r4WMS2*$57{K*1 zCHm6i(K~e;!`Tf*46h)ICpkDHq-yl--%-(ljLq%hUr&_!zhN3R@Ae@S`fhvk3QQMk!F{( zIi{M9TBGE{b00)qi=U!R7tf8?S-VJ!U6m?3m~+yI|RdG;XaG*@7A)!Y?%>oU{T;PU60TySr$RFW%Rlx~&Y>tdrzJ70oTtdkj3rNtNi0flmRzn}_e$40Pp z!dGE?FD3Bc7YNlgd0Eoo%Gqa&+i89>T|Of(`|Lo}4_wT=4LS3KF5kP5wG>wM?e6|` zgd9GIc(6%9e*P|^*47O=Widr99Y24UI-N$Sw}J2gZ%$5IIMtuQ24T(N_&19cv*@(A zAbrC?J?Ep|l2E~=tW0lVJyL7CvrJ$2=c1U*{k6XyzBTkEN4yv6Y~-SEdA*jZurM&9 zn7P+lR-!)`6)++hijK-oK6N~K9k2DxOv~!T%-}=XhKQqE(b-PB5MxTsO!usdYsVIv z?KVY(nCfgKuig&~qdVA8M~l1equ5S&xH(_-W#W{+JudAgbNs0~VqCdER#SY}WALZK zH?lAL=VDIoCRGLGkp-C zC*C1U(@l^12crve3PYff)PQvXi*>UAR=jCkZ!nt4%4$g$GmYoqKQ5_mC-TN$efO3DpzjaSw9P`(PdAY^;voF?d8Fl3$r{n zzQK&6;*&Az%hcV!yrL`W$IcRAM11 z`Ez*agAvvx-REb2C9p-#Dw_v8FRoZkM0-hhefOb04CtPvGwR(aGaJ@BNWt}~ zLG(~d6W4)V)PhFCm!dx{2bgieZOB>F^OvZDrpS@{&(Dir9K0U7tMxtWRVRe&Md2ij zf3#e%7`>C*ZcAG}gg{26rsR-aqJ`nZ$W zop`{5(83xfKfKltnl|=9$7!b*y*#lS-@L*iy&sinZP8cT`;GQrlcJ+-`xt zYjIi_9~R_Fqkia}p9Py|I1vYB4Q)EN8)V1g-kNaA{Xj?M3L6um2J5HOHz~Q;dz&C% zB@0sqpN4=;X?j5|jfhcH2$ennJw_?3tSA%_uqP( zUMHLa9)cJH0VmxPsDvl!(V;N1}8 zpt4}gJ_EwQ-Im}`;n0qx@CA8ub2^wGRI|vAk$t(1jl8Rd4?4dq_JH#leCSMx zlaWuIFkP{dkK#op=7X2?L4{c5q%TLyM3FC|0m)em-A^ZmfiERWTHJ%*R3;mf_F>hn}nIQ~bvxOnfJK9BR|)z6WH z{`bAU8f3K3B6^rskh=z6{% zd<%q~8WuW1blEg;DY(Fm9v61Hyx<3uVniKNbzNOu$uOWP9!fIwZsie$<8oM2^0iU< zB~bTG_B1INJGF*CpeX2!zU4iKn@|c-c8A2I@K3XLRaQ_cpGkc;683)8{sE9-DRyKk zF~*oaHYJqutV7l>5PmSJ!3p_LbdC5^<_hfPn!O8XT+Y0;Koq2vlA9MS!KFDiq^J3i zND>gr7FzNmVH@DO72f4LAS#k+O={O5S8pQtD>mfO>xyr|w>U9n-@JD8rq|olsKLXM2Q{^G)L5kn=J9D2@B5v$w952|CVKu8&bOP| z7k0eCay4v4PNO1*MfHhzkcW8E(Mn}yOL|U;;lk@nM)sqG?-4ZNK{_AAzvXUv-uHq@ z?&C-MRsOl}w$UW9CtgY%-#RAz#|}8UzSl6=e$Dt~%6GfvODHQ66{N_C`n%yJ(*nBu z%OZPY&vXAD{loMJ3C=%UGrYXHS<>RR;!Z< z+9^jBGEbH)NoooZbvzhl48t0C{LQ5Z)kEKa|6%-bPeL}YFvq+zzi)SuFnj%WBwv#Z zz8uHLhwr`(F5Q9LShwa`c*1JeDH-}&AYvW zu#x9lqD!Yeex;zFIr=xz+w;8AYf|$~ozK{omdyWQ0Vpu+tCQ&cL+JG&nSFgjWT@{l znj@D|8Ez?i?t5Tb*n7@FFF*B}70mVuq&J7m<#Y`%+d_4aXYNNB!#DmC(S?HUF6aD@ z+$wD+IM08&saQ&Q)N%d(EBIzu@MwAAMY({&I3iTeJDqFxUa#F*PiV0zbm_hB{b+0N z+#bMw`}1*WIcM7qlBFUb z5VUuEGPo6B{QJ z?yl#7!HbiT+?*_?nA5z#!%O?f`mrKIFJ#h%0(8DqKeN6j+R;AVI!s{dY4|~{tHWpV zOs{=)Z76-J2>avHEHkIyju?+{V_8m>RXbYx&9l3p6Q(G|Poi>~7~0(Dr-tM76JdJg zhBP{ibS|&2m8GS$O#win3SoSE33q!=B`aQaa(4d+B^q^>_=y!YHui7bQJHa(mMZO< z6o)P1=-97W3 zkP#M9)!q7)gJD@ydNAxKY zu60%!<@7gMu|0uhvAfgw;|<3(WVO>A!d*rHOzQL{0+j=#&n@FBw)fi?fY2SmhOpA4eZ)_xgSc(K=!jcfA75chN zi`37EI+cXb*Sf@JHd+P09(0D%yK46J1N7g~q^WW8XVR0BU<`r$!CF!AF?f9`$kM=3)-B8OulwIR7d_&c`%5b9k(003(&*QZ{ zyDpNNmgffkZ03+W{Dhq5FS&_#|GwWJ9v#MN8~EfTQ8#1r0H}`a!3m-`EC9?6QivvaeA*T)rkw zD_E%(nIUTfKMy(+Iu7`>^yMuque7GpU10J0G#Y=A(sj1EbLx3+uH|~3iZ>!Mo20Ut zFF2AQ4RiW@x3MK^;^g=IYjq3X@#9S1WKXNr#-Dcg`)D*BziKujV7aJcRS?ycLi)J{bTeGt(Ro9==o0rI* z8C{ECTM}{E8kz;a`o+#WNld?l<##i=%0Se6z<2;7Mhz)VwKhPDVKG=RNCwH3_Ugx=&Azi1ZObYIB!9 zznC5s^Ai8f%k1g%LlOk!x=M1fyUiXui zqJT&}5?%mCx@Z>Y#0tdpri-LXd1p||MC{-=+)>bVR@NdhO|b6Urgm0Uy@%Z$PTOFA zv>oJ_uxM3?CGp$&CN}Zv>5?4N82TNyI02s|&gy!VS<|$0uqtjjvxBYkLE1rSnLYMs zbR=Q~eSM;rw`U@%H0eo!4MK;W?X!FmoJ)p3Jz;BRW+u8ZL5FgM^llAaOt2rDd>O#5^ z4uN-}E&LV69k*G-=)O&gyNwPNOyDLCRk)Y1tduA0xH1od4EGWSSA%ylBsb8?ayK1j zegiWUW-ZZq-16rsMs4<#o5>dSwq;ap7I4`2h4yf&e@r)ouNQN??{F8+#^HIz_G;#N zm`CU4oQKV@bU)m^Zb`*E+P&I-U^#s(o={4kh5t5AAPhzTt}Hy_g9tK-0M%`T{KqE< zH?EB|b|sZ&e?jWj4A^6-TJtQ8^1adXGHS96nM%O-?qBP}Gvd#}Lw0jJbE;bT7v*v` zSR7aaC_P>UFMweCbh*b9W~tcSatu}01|+<;wzd2373Rv;^=B^YkG{L=?+(X@5A5#t zh1l=yl|M(BCHq>XsMdAKs}S5z+!OWN#jmr)=S5njEttkC_c^vP=KA3*6ZDNeJpyj% z;gIyxzWtTUL#DP}K@LX4z>2@qi>Pm&b0U#$axjcLMds!oh~9!6xGv`)z6pj6E>McWA66kS&P z^8#gTKOtuIdXJ|aPT+GA;h_rIW}>tI)>`P1+xR)oa0I_4NsGDctiz9Hzjr7E*A!wP z)C{&59sG=q?uWz7*={r*6Y2=WY%TyBu_6E`hwgLQb3vR%4n9xw=&gKuzM2UHs`+ID zFga6zFg5DZCpL=l0a7TjgS>n)x{O{=`PIls-6qUYi7ec_~KWVQpI92glHk4GRtf(hWt{16qm z4YUFnMFo3QrqagY)XnP(J-!m$xj(R{9vw5~m$QN{ zpUeY&>|mqg)6>U3M9N;cfKd{|Lqk$7qDDqWpC;j1 zQd3iBUjTsozt(VqukX{X1CtAyR?6GsN{@7`QIx@&F$%kJ@D{bY5XtF~tel+Git)x~ zgtc!EpLP8Z4wn`JU&5cgs&Z7d>eu51KvI|2@bj~5CnNLt!-!h9(aYa&MLj*@yz>v; z(Uo_J>xz?fer{=3*MtNT-0R6vo)0HxSlyG5yPoL~OE(7?4>&;~8p-w-bx$7`0|Tn) zrHbIp_JYrSyKW~3~|` zj7Q-0&=F9g7SLvl{@!`*5V~7PsqO!ae~`UG8SNb6*-75@(c(aU7oUo(z`yE!Sm5=^ zMaw3I4c>dkNHw2VhtOAA=gaPr&Z`v#+OJ&!`kmH)kkwSTT`Ycf$4370{~hTgNxB=+ zsBZD_>x9k6*c>W;?lgkn?w5WeZ4gDynrd_`6WmgKVPRo@+Q#+C0wy57ng~K#{MqH( z68nHv81mvdyGf8{VS-7C_o;rW%WLY>`z#@7*7XDfZrepBj>8}PZuQTC>N}7DOo`uh zX+;O5R%-;k0ZG%h3GTMvIW7hxw&M-E0uD!0L%vj0q+Yz9$y?7t6pmEmoN<~@mt;y7 zzE2nC`kHTk&kw%MiZ~y^tI@nqDGp?;e`QPj%d~&%TmH4bg`&&nd@^z30beVXb?e0{ z6!JihY$Y6T$Tz^Wxtrr$h=|;O-nMw#e}XZP^D?sWn40Ms@R0j_KUd$!0g`c$lgkdi zIHf$MKj3rc`?F{dGBJdk9pJ5fsAG1Z!ayXqHz~*d+`^axhIv(wu+WX#mzu@c6teyb z&DxB01j~sfa6V?v^Eok05=Pc1?>$NawD>Xlr-chtI)#BNCsl&ACU*1aH%Rnz5Orbc zjNt9h5~9pk*J4K+&kYjjFe>n=A7`5EXfVOR)F{*EBPmS+;pKWda*s7Glw2yLsFN=c z<|`2#3T}%;8LNI_j?hw$2Zh=1zc+^XS+b?e@uh=h@+GY=s1CTx@7(RR3AVqp1L5SP zr>(slH)NxCER?Vc6mkKR*a^TN2DCw=!%z|k1T+pH>y=C4(eZH@MyL$$uYmq3*4l3k zk9Q1duN0?0B@eNF%h$QfWZXo?HqNGF;S?E9u)*zAmtgZm5T-xJn0`goiXefFq% zX@IjutQrwp2~$Jydmz*u{^AvY% zbWYAW-s6jdAyi;6B&9!>MjO{ALW19cB``OS+gqAJV3K=eyPo4LjKc8Shuv^R<2>Y` zNF5y=#1FZEICCFpsKq=*ZFOMt?u0d`9&SJ0n$U1G6gGlo{7b)JOV@AgEwg?P5HY6%xor){ZUxgH{nO zM1L!Wf*Gd8+_19@xAIlY1ElV zbvl|4=fI8^=Qf*HG~!;+AZ0P^@I)uM>Ho&$*nid+8q#u04Sio}_HSUy?QbPDwa9Zg zu6ck@j2al*`TBUK-b5zWDJ~mdkSNIrT-`G`G>T?47z8<&+v;CmeA44HgQ}{SCM&s4 zRn_HQ3oU_Pi#)F{Rq^1b(|R=UrW|ZmnXf&8*W8XBnvZpZ$^l>gDJwQQ+N5!fAdkDk z+7}K1lcLk_!PWY`84o#%yUYR!CMG6Rrl~L2tSKEA1b8Lsy|5&@k7N*)O(pMbtzIK% zTha9D8fm8}FlwU~B(@bkj4kT(Sb1ja`PS+8GgUg3&h~L{VMM9Zmupq>CrZBP@fCC? zByTJ-IT_c}iL@-b*X2SD$~6c8ZUJN4c69j-kbfcp>g15P`IPW1uY5F z@+A^iv3R{^DTZm9IfFr)xt~E>fIfXnv^O70y6mnnIP%ej)%6RpNpeX%rTD1AaKs?$ zyG9-f2?;?#LSRFoFa-p3Gak!otFeOcE&$zMDO8)}KCIqMasPHjx(58Gx%YI&mj4W5 zBeIkSMG{mxwKE!7%YE%tL^~4E@QALFx6RR3<^c-7>@^aLf!mo6hS%g(puUKkY*Yt% zyiN3hM&4}wXO2k4tpsWr=jdB%O03RKBjjH34@i6I6%WQxwMKJ$#)^65zzJQa?t>*z z2r}*%WCuI^Q5U4X2P0_Bg?nr}3hAg<&)Z#47&VHE?v%^L$6kMHVB?<%aR=1D72k)c zf`O{L_VVuduN?l5_pfjn17M=w4hg1zOBD?DXW$HRR7f@#m+KLXYLw~Ad{sHHhR-6` zm!8{WC^6_^x^`GiFU5NpAMd<7$9^AAtXLFoX#vdHs(Xb$pLxn+z?hAP%fpxkz^MkG zKX1mH-JYx0A!EK$1^;PEcn2V**SpE9D2pQ_BE(;=7c|P7C`ShK6C~q-^S?st2X0)$ z0$x1REpjA1yuv_valMYYrR*M`b#s|w(v1_to&*D)n3!;LbzQXe0485FH*jShRj=R$ z_tU7G(DCv%uFz!!Q-MF{J6!?;R;tRKX`dOUzjMQifq22)>ftpwl9;uXMGz4;#@SYF zU*-X#kxHF?BXKFW%$q<%o*H-p1)Dw*divt_b`pVIDQ1+<1rE@|%3J-D(t{Hzek52} zLE&;*E>Smy|dItxIpR$@_6~_rtf7y zdd@$*&?+&bVFav1nl&{6kM%5-N@Lw3Fz#Y29vEf-1jXD}O{is$Pf16)f#S@}23CsSdY;Ml5Cu^#*N{1NFyEO3CN9OCcUE1%x^m#U5YF_>g?lL}a zp;dK@*5BLPh%|Sc=%N<*!p$acnrcx~BYBOXZDZoi#Kwlkva7pL!_XKIr!Gtv1eXwWfGdePb9sct zZcURnCedUoQ(-?j*;f1J_8}{Cc7HGX@!`yfeQ6{V{l2b;)bnkJp|eD3IQM@ID?MPW zJ&QR*B9OOv+EJO56fQ=Z_igBkMd*MRHmlMw{8mMMH{Lz7{bXok0V~Td~R6_3kxZ!VEIC142)qO8|}N_1ycXkFSwgNh{ACD zQtrfGC5ZWo7~~qU=(WEFL7o7Ro#`bBv=i>3Z5_2_lN0R76ZH zO7seafj`}=Dp1vy>TN;>8j(IeKBgJrS}M#WbFxtVr^i%$eOxoS2nX4$h@QVY^oBhz zFWpoBjvgp&bbrcDqP@#`nl6|VS5bN9nenzO#`ghNJMSRU8H>ZI{D{lfVNP2V%vF+7 zy~bbDsWIyCVXth`E-sz5{^%N7X*p}dr`Hwyi|1Fmg4xd@driHBcAB%xzcP%Dcy^=i z2%!a9Oz0p5FGL5!*taZQnV-Lfjt|q1aErTr1NJUcpDu)kR4D}c7B_VJtr9+JaqL$m zD}3=!M?l%H-JO8>cVeKE!&ug-f=^FR0fLKSBNBk1Rs{>(Lw&CvgVR4fB>e2`{!>lA z#;(xl;qKYw4-SI~mo+{;bL7gKYl1M1_~g*>Zg~ucz3$(It zgRQQEQrK@oGhfrWR)^xukeSsiMe+TMzjt4*4|7WBdI$4A9Gol+W4a#BF{5K-tCLYu zdVD6^8{Eq~n$>~$>TpbJUR=uBDCT(~nOj+{EG|lBz%$I>VyLIgzk@?6>D>w^{nMwj zq|JOB7eE~ zE55x?8aO^+elBFTtCLf`j}$|X@y6fAt+5k>f#}EOt~{CM4T#xB(;h zuD;EA()Ip;yiAKan%27P_`Vo-#AXOczdM*EsUS-4DHkZt z@7~$$Yt*$!sy7=jFg{&hea{7c7Knrt3gb%ZY-U*@dNdlqsH3SBYqYht0xR#?Soia& z*OYCAFjpANP%AAp%T%;JxL4Y!Y&#UZ`v=Am5!J`sM7F;Sin-<{efKxZJg(*!J6-X7 zLsJUa7g*k`{78-R>X=t`!M&k>K{7ma_WN&{nU&g=)IlT0T#u$mDba8~?tlt1fuW1myGGHsIZOIerMXS>Tr9Co{%AA{|y-njUYyzn)RkNWXr&ds1d zInu@b#tG?argk^h6v%2S(O8G)+pcWI>NSozVxcr|mt$w%uElBA-^>^EU;=n(VTcBJ z3&-j#wDw&efEi%6c6I=x3u?D=etzCzqj}7{0Vu9ZlEo_VBRNYN*%xGetOT6T4UIiQP#zPe zE=?TRL3*3RXBje}I)Qh^f*vfz?Q#CDdiy7vxRHSyH`XaJqY9htK^e{a>tlTKpTY!7 z7CezX-wb6B+eSbQAITEZ(sfD}mnQ7WrK5fG7>)Li*>Jf?QFQKVrG@nF{>3oKSzslLa>ZpRfsAHy0LpkFui>s9|)i^H|J#Jt1F z?cp!B5BuYr%8&T;r}1A^9Y*AOZ);Y3LrIJyk%Bk!>N-W)BF;4*MZkc*^Y_Fp%kq=9wLMKCfer85z54n<*b1_9 zQM2L{$0M*3WwAGe1L!Et0PzgqKFjcG&#F*iO=gSgun}Z_OY^T))z#JY_7?W@2eQz+ zI+w6WhP>L*wlqJFyI|5{{+r9nj+Wm9V+!$KuTz@zx@m3S?+f2MZ_v*ZL(B*8DNXgC& zBkZnVywG?Hc$nasz+NYgXs|CJZufj;dUfiGoLEIpI zUFQ=3e`A76K?WDe$;LK`z^gO^Y)-l%x5bzrn7elf^ zpUKaAb?r#EslPV_eP}dtMOGVCQJdkY(!fTm8O3PeAv5TD>Bkb66%ouNVT+BRvs9hLdi3yCkgjr$TY|6W|b2vs>Z_V_VQvu6KTE4Q&rwoW2H96eWI!| zud(k%L)x24=T%_B1I7U@3BZE6#^B-M889*R(oATo(Lp!bjx@P62 zuiJW#hIBL7DnktdF=nJ`Duh>CS#D6N`Wr2uX`cv{eztSScDS|OVh1Gy2`!mUKh*U+ zep1u<-D7h-aE%|`!})YSvJg?GP$KL5<#EX*y}R1n*Sk@7c?={vICW zT(a{uhOspQtMPV+VJ*G09HWWG>FMb|MsJTgfOf`|qg0365e68njvPN`uDA7^KMZ&( z5E^s{_1{?EXDt+qhX!<3@g+L~^hC->i!1tZi1*A)Cc!zgdGp4vd#riYexrPi%&?JV zvPX*r`tiE9cZaGmf3bMgEfO1}08Ip3bF(*IWvneYf5% z&}OY8#mC2Aw5xQ^|NpQD1zIx${u3%UDD!8uHEVLL=Q>Pq#H}Nw=P6}i0WVwsZHTaE z3oA~)>G2w{MfbB1Vf zdCZQTOhOkF?5Qh4;Dk*A0HD4H+2B$T1#yE=bL2jfBlF>?YkeH&KRvBrNo`I}8fpJ^ zbq0()ZNXFOcYAlJ^2Hs0&3kwfyc-+-A)~QU{K;e{wqU&khvhu4VjO5kduUl$y!eL) zn&5RGKL{ryc0`kg^|VpxxjEh(-4Sj%@_~$l;kY8Kf|Day^f{rEBNed10C#4o_vr%U zWxNJZd3KmmMo)IgC`i;{{s}DAz5IDena9ssYuGb4oll3=x%j9(rW1I-{k5)lwOlP0 z(*ui3uci~{W2hn4%VNwP<5x6~Uvsfige==)mc#Fyk^;6qOk4F!Ae;}|Ug+n2slAs+pKP8SPgk%Oqf!0-8FO%cih#pqOT#=c=VX+L*d@E3%H z8BZ^IAI67zbOjg3L5_@>0h;N`2CDmQtL16zXNurPjQinBJ&-V0>&Q4vuBp zA6UHus$gxt$~#{8XRxM+T`N+SFZkz$?K>ev2FYeDxGo{GIFG^nK0tu_z?HH9MmYTl zhwKDrGaR|_GW&nH`s%PM!f#z-)7{%aKS%$``^`rh@%>LZDv3=Xd!B0n!`lqgvByMpQvodHQ_qD!K3cyk+>i0(%K zwPN;rQ}tt_Qq|UmB_&M_7}QNj`|V)8H*E29QurCUV#mWPWPn7(WwQqeOGK0kDsUmZ zA@zr^9qv$y$O>(W*{i0qivsCm05A>?>Ps*PHVL8%lohijM~zweXiO}chs(j8^SkLM zBM#630Ul#aJ!G5~@R?R5W`eQcbYBHIBdO8p0GSjn zKgiBzX)(T6Q2<~F433i^4*?n@(FF0r;9VAY98=_4h2aZI0D$>e3=_VFOXa!?tHz44S~^h#&QeGnkIbsPYHLB z(b=?Tka0)RW%k2KDmz2edRKx5(b#Rpa<(sKN`HyQ2#KLXncPyl>&9)nTVu$edwkZ@ z0X!K-rKNzB=hh>MfO1LNoGprn-VK#X{2g9B*<12LhSB=lbqrPWQPh<*+9jsYRR8Q4 zmUr!=tBzG;_eZzP?kZ)^-NKOTM%0o9!&e+C@{*u8czs~?96dfDg z{MyrX9|eA>?O$Jnq`5-h9BckwaiJWXp(VS;pJ$w4?*Tcr~hrDA<95 zB3^Yl!N2YK*R=Kb^R?z_q@*GuK1gZVRd-#FWl!L9U#b65GS=;7(y{YI)1$4Fla&#n zh%B8w+(fp}-xTghfZyT(UdgAt;6naeE3bH7ux@Z?(!7BJc0ldNgsBAJ6+BJS{S6tQ zw6ykR=F1HK2DA!@>t;Y&Qv@@UreU2QF!PI9ic)gkmu z0uR?mo#vtY$Umc42%p+w{?2^)JIdLrzX+our{i*a5fUIrgL*gFaVJ|=r9|W~C1>Kv zbME9Smt{;ohqux8vQH+HPjbw<$Nl8;^mlf}`>RrymW<`R_M%ON6W;tsUK_OYEupWE z0p1^g(Uv*`Ihl^_Gb*S285L9#Lg3DD@|Q1P;)!^GaN$0B!1pBraUBSI2CTlAaVrxC zrG9j(h~}n!)mHXKxj}c+zuh=^O;-K1@ekp3e#{Q@h|w4y=bMCGo<2sDkcDx6aVw_3 zzG-d9&VuAbjh)i6%mrlT4xhYS;}clj5Mq=vxjB1kT<5j)z`MgC<{9dU6?4E~ZgJCf z7ORiq22Pp)TF1iLIq|6D@Pg%9d)|Rsk3s$E@Rbtb|=d7vYx@9lw-rcW$pvW}okX)Lo65 zZ6C>awA9MD%A+9a4$yBo5tl|S+~+4kyK?$P#8mFgRT_GYOkP9syWP?dRC z!KW+1kpIM->i`8sIJ@iSC0nKIkIRL;m6=ravZ&eBsTYZ0^Fgln9;)k>TC7Ty|9kyL zf>E~?W$j`zf#DCoF7}sK8Qz(}4WFNDQ*t3sN~O+pZ(UaV4F|>jM$2#J1#F!c*K{UT zBH+iomo>OamX}3=>rV$d&94`0cVjf{RfShicQ`(9x{%jGlpVheeV=_5G^1Kv;yyiufvUPX7#aa@f8p<=#r!bj?Wb|T; zdYy>0KbQmsQDPE`VBTg4WOTltHqG)}GhxF<+MJs?YX=fI?ArTd2aoQZck_R##J|ZX z5Tz52l{rwDaC~~pF>f8s?2dR6xLUyxn$IxOeLe&%e+@@l%>NG8uXt{r^aZ`z8&@&C zQ(UntatMZqLZGnJnSDojvC_|pc6D_HqC6a&#vly{PEJodJ3F@$aqYS0vrngWN>)2) z@IattcfQl63ElcFZ5twAur_bGqax?9vxz`Z)0a}#mWBWoeo$kkF_jGL)lx&Y0#Wy) z>vk6rW4`TmM%)$U27ldI1{EDoQ2Qs_g&>yb*GRZT4)@5!bK0r4LH)kj<{2f{g}ozkL`=#uWKsF*X4Y^k1%Yp2uq^a zKp(6I`?wpwQT3h8)CaCox1ow)hAZQN5h#6NTHQC*XBFEmE-9E8b280D=o9D% zak(yCR#8QG?Cqy7lzUp#jBUCm(t>B~>2NB;@BIIyPiMA@&0u{yD9t1A+uJMo zb+aboocrMl#w8`&Br+QSBl3SUtF;T?y(lP<#zH-sRiys19Qv6^+@=0BJRTjJZs!i% zyqYS!NPwz1YJ)~6Ll+3A)I3$+x5cK&8#t!3%q6U z?(bEG)Oa&Gn7D4@`Bz&@1HE=BoVAl<&UnSVL1UNG{W3PzTBd!vvQM*IZY;rqOvtTx zXIj*cw7JqC&EDRgV)pOWvWb_ROb0x|4IJcWp~)<+{mtI6i)O@=y5Mw6z-Vgs68y^X zF=5&s1fT9V$9r##6%`7!h`wNG`0o5j+F=jcFx8#iRmPfmH{!LZUN4@{=>+PSwfl>6 z$FkYqm;@GZNzIc`ZW(CgtBp&C+l^{w9${elTqm%xOV5q(lm{X(im*zQ2`N5Jkq$+XiQhbO$Cgl zVxK*H7HfCM()8sIrY_aGCMa3sH>DNv_ug+qs%B!w8~h_eWtG^}$~;mFlDVX1`hT*o zZC3C%njH_k*h#gkwY&9Ll!`0-#W7jCRk)O+bx~xAe2r++r;_=A?gNj8_6fYXCC2kq zgB-s|4(U#XPDscf_yUIC4oQiE6m-uanHyU8xAA`EQohW4Snjswoy&VYTdPIe!T!3^ zdVZ8@DuCMjvqK(wK=>xjcIX~kT#TQ*u)N4^;LZV07NbBelJ#Y!@`Fg#>-9}qn88d< zzChs3+^qAP{WLwAnSzC;+z!???Md6!*zT$Xk(X>ZqPaq3WJVX%&N1Omz71Wzf_>xq zipOL?pgOTkaBMRj6~pyZ7uEVv0KqPz?{Led*ca_`0_p&%h-pSlE$ZYch7z$d%;+Tf z!X)IFW&YfzpB2(bSzXva#`EMp;4V_}ip!RQbpx`sKH#6u9ico`+@$!Oe{}usB6;V< z>P5WWG{o9X9tlTE8r3g`Ry#J%{3f1xnVn6jkwzTLQ_>q;u2Cu;8W9_-ps9&{V-uo1 zwqS-Q_N`K4mSh0V+D*8xL)qcH(^+Aw8W_%AgzCDN5qQsyp(DD(3l_&XCM zFF;U?5x)xv*rvuRD;oy?x?6l9?TWmK^s{f+H0gz*4r@BBGp=4Zpb#kD#>3+6yTzUi z&oIe9p)uo$*ogCj{oMXF7PeA=UZiTg(|Nzn#LV14h($5`t)&HD+d<@E z6B>X3KX^$=OS2laVY|sx4N`LdIs(9A>syUg8}eQkd`>^Ro%6+*`m4nEKyuIQ+Qh`t zVArmKrnZDF5&s)qmfURQTW-V?jKs~nV|Do>IRK|6)WzR%~vfunf zXctpxAEB?OVwL^1R=FhnlZc?%=dpx_83CTzo(;@6Mf_uX2hr)#{-U-g@KqKbg3m%k zee1kg0+evI@bN<{vQKX02|DK4;Fi3gVJkABT5f>bd0MIX2|-(`2oLdaSxbh3f=dfC zB6G^obqeeLNI&&a70EGLNybKdL1W+`2F$qo4&mkjkAp`lR&z*EQ%OTM`p56A&0Ssf zDypVXf=U6cBa>#-I>maU++4DtkKZC_L8wJy?=7K6?2IMxW~BP z72=TP&G5s8`>tTnSl64$kWjc?C$TS=wqqjiCtv3!h@`fiT9tp}n~_RK&f#3Pey@%Z z80zx7fB(51YDBoZkv{SA5YLc@e)7}1u4uOGsUp^X{c(&h`TEb|Mj&NJ*aEH+Zjxm` z<|m`(()5J|!r?E&(dPb=w6#ADp&sP^pyXhl2V7`BuEmN3T?AVCCu!z*JM9-%$v2X_ z?G;IU1v&I4O;0QPxyvimI6fW38>~nkh3iX|_)(Lr zP?e7ux6y20xc7qi{oo)!VWWm|oHvkvo2@^J&Bxq!7q8OWSg6fs{=?@=48mf=n)-Yp z1Yhsu2uk0}G$A?_l5KVbOR20-BKFfq7<0jJRgQ>}PqPIugm8#dIqAj-ftzsy*DA#U ztyGsap$_}x=6zis>0N(5#24e3R4se%{@Lq0zTXk~h_TZjuX+AsHtIc3^NVh(hm9X1 z%c^6q{cov5!k$nV2f{RY>-sDd+@#Y_bOX=lBlJ28V}DBq{ScP8b)AZT^0E`BjaW^a z`lRh~F5ArSS9%!>Jw8`hKuR#NWu%Z4raoX-U_4Tmi7GprG;rs5tGzYZJuanil+oG~-5(0JW-^p@v%8P%GJM@hE?4_a`P zSs;eZvs2F7?zq>Apn09O`1_9?9g80F5f`sW6#nGwjkd>2_~g! z8ME8Ye9tiUMIc1Yv375NdQ9DqTf?(!2Ea zHJ?(^ZOBdxGo>%4*eG2YflxYKz!Y2?PrCT-!hE&zLtZi2gsaRG+)Q)9LvQEpQ|dIc zObdmDr34ftPpd)QWZIfVyWoLv*`>i=gsqF>{OYgti}KvIfrd`t|2GfTKv23hKCX14`f?vNzt_3(#re-w;EX;~4gQ>M>UugFVT3%-A z*DM`%Bj*CwfrPX5z%2=*i2E@#r`H2BL}vLHzN2UIJ;1X9I~ zD3qjxNg14RB%Uq@WSF#?5lyXztsFK#(iaT!3u{I0;0&?SR2}Wbg=2c;Jk?(jEm|2= z>MUSS)(voSm$9*$p7~9T1H6*CtYN@IZ$eoId&t=!1I zGYj1?Z9OBs;wkmkZ>;)G4fXoQIvYL7D?OKHReV8jFIXyq$r%~<^ExIhhArropFgM+ zXLUp;CW-*oqX*MPI@S8SdwUB8`nx+j0Qu>gtZ{$$@Q@0ElK#6vB3Y zdwV|b#W1>i&zcLS~04JyZt#!T2)V6KwCzWAIr8uW0_)T;>^a=uv}A|l7+ZWYgyay z0{XwGu^zFaiyuS06}Z>KK}n*E2%_-_8logQGhQTw#?k-SwW3hD|FBRlPB1aT4HIP9 zfGJ@jqGu*i#>lf4Br)=T5tFK-fdaL_onsRV10-imV)sL%O@{s!o&W!tP=5qN(n(1N zFC5-nMIrt}IRdz2HexCWe_sLbWS|9HWWra22hQ0k+fz`}m68(BUMDWM#}9t=5l|hA zO~uU090~vQ{ejc_-vH$qxiIjfc!3WYDL3yBeqOvHe|9uzJUzJZ?d-PbIl+*vc%`+4 zSG0P%eeq4Oh4r{;)$wj)FaG9JcAG|a^;219GH}%o#N?3m(BOOPGL2|ZFi^VB-i{rJN1Lu{_FIY~+9&AmZ0tpPwI8@4t=do<= zF4!{`j`o)oQRZ}Z*Jb5elT-B!i)IMmLlq0v8MtY6EY5Lou@3ip%vDKS*sYWHHx!jx zlQRRG3GIS3d=dbDV@Oz^P%-gSr_x5`vOqbz>Zj#gMjAtEms>RWgkZ=PTUx3T?S;p!-0{olr6p6tYkI> zy16@kzn`71LM%QDSzrgN%Xpg|E^REbzB~D4i_yEgVoDGlFVqzN2rA6^e$}^NqV3;& zs81rpoN|?2Lvi3QAj1=QS?)OGcHO-lUc|4gLJ&)u5y@~{WW^Myk3t%A_8}>f1yAU2b;8?FLBE48JSMk`a+?g z1b;a;lLRx_o{w6?0;F%8V&Z+(ATlzUz}Y6&PzDc|eVND4Wvy>!Z(VtuHm`BDZ&U?r zf{m7ATblZF?J3^^zE>@D@hx$Z7l4<$bc?keAlf-93xhKptcNm{AsJY>*6J3_OQ6G%r$K7JF(sIA0~uV zXNsuElo>RvX#ojfbl}bV4V!vO0?LAODOKG5NO?uV7A$~yKpWx}y^5ZW)x*!EXH+}$ z!9&>z*P)EQntVzlx?7Q;K3ia z?-@^EJWmFid(5cW)nqz=r25n;*|A40@440bTjV{EwmF@Ahrurpe4bDC;>+5tKOcc^ z5=0+w?vWVW)$|?YW)Y5>Uf&=rsbur)EODYV1Z*PU zH{5DP_%K-CzqRf8cTUb_;4%}RQki|IDYbJ$t6KlUOd@3I5|=N#Z6+&pIni{^4Ww&M zCVJw1bSx(V6RCzpQHxIDD>4!owMYH3YRUlQMok)FF-y21dz1{DTTAJ?Hr0<9>~kd~ zZ;qZNoJ<@Hjk?@kZ#gO3+u!_8Ta{>3G#Q>hl8mDNj$@vXt0_uC2KqzlZhwpS$I!#V z3Gu>5f^b65c!*vk}iy za%vY5s1|uY5q@w@KEl*5r;sf*if_xI9jkFGx0qoV$12ye_r~dklAyw6BI_dqD z;@kXJBT{V4vhYbRD^3&VhL>IfZ~BIIVb{ov%NJV!qcFLJE(t)4wNKz2*CY<(6RNKK&QFE1qSZdM8pCMLgB-c zug@x_3pFoPtM1eADr)8=+yQ#7<=^t`$T)dv|3ur5Mtu%DK_t{+Zgb{H(|!^Yvg9HN63s<*>(=H+^VPayQK3amsd=)M_QuyM`xZ3d*Ow5@$RID!B z=+>$YM}(!n_Pw^I#`5~ngE3HIEy{A^D@>MRUe9!DrywzmjIM1??d6Nb5EnciZ+@^z&mBs5)UgY-raH4{|O-G7|wl zy*5#!?#F=-r#IDz#p~cNe@{*szO4$ixjL(hrB!U9%bB?Pyhq<4wzfT5ZKpY!jNWKu zI5Xi8hC)yX=V9V@^76&fAY()K6Y3>chAna3Y_+{pu76xJV2NY-RaTHjvk3 z%+W{hzoA0*cAak$?DE)&;@(NQN)KYxjy)j;EQU`9rr7Zp$NW$nf)M-g!9g>FKaxaC zLHfSnT;p)MB+(6wDV;TCWhH(W-qxy;F2=))8mfs~*Z#gWDdwTFB{o*MiI?-c>ajNs zZ@;HMYL`V+MSC3`Ee9#P0$#Nf-EAtPmX~YatOfB-SvatZ4O@I1HX1Q~Iyo)RRhSyB zb3y2zxel~EcVQUtCeo3g7P*L(`vZkz0>)=+JGEc?_n^l_Du3hSkZg`qF~~cYmhNjM z2hfUej?0WT{b8e*Rc!IHm<(~}Nl`u(P94s^ZTX28P$#{$?@XJ!>P{ccXWt~g(wBJF z4hNz!0L;-|VSe(?l(A#ButCCxnT@h&mTUf5_}f)>VX=WujxSgqwpiEt?w0dyPBr2z za6LhsJ^_}m+GD9e#`snAV~J{w^-6o2K&-Au;rRhy?RCJXNt53#1~O^BQ9}vD1lz0@ zM>?7qH&xYKsw(R^%)&N(k%La8LYzO1R=dSF zRkYOMwq-^OQmvi@h)Z;y@G3RxJq@l3r&TbGDKeP@LVs`7)s{>>1e`toF@ovE?_}%w zte<0$+_8AHh`1|CYLx{%$R+UC?s&i2VUzN$7qUL8TMY#G25}>hksi_75}-L^uHS+4 zImNbKRe%xln{@&eWe6&~3oo&aAuJs>B8)GX1fowOKq=TXI#+P3dlMD*n>>_^5|Tqe zpD?>qh0O5Os6I*r73Q^`v`T^`CVyLhP>6(q$;t@bc0#S#rBm%M0*7^<_Ec-hSLX!cZ*YQ)rK z7%*_gkY8rn+(b(hk%-ciav2-fSGkhs^w`?9v)B8fG_iyYyt|~`rxVz^_j4^pSWT>k zrFQUsK^o$IOK&Can-H#i!BT%^Wu*k#q&VI5-dsstI42#RwI2p|O=muydk{N{Ko_wQ z!1OdEJ_RwG|CyRGvFM6zZYMe6^)FxmO^TT9+33Bk?~W}HE3-s!_CJm8kcjwq{k1Vt z?Q0P``*ycx7T>pa@~{c#O-SIdvq#UVDk1jO63`{J%s9p)fh*p z&+k6hEd;Csjn<(uNj(tgqG-+#1=~sgWPIp~dKZ7JjSJN?g6@Z6EPYSwryFG!-@W8< z-hTbHwnn|is3$$4_Hu%PMr_Lgf7ZSUvLzd2%ox#J#ZqkB)3>`jWyHMt1i*oos!>sN98+=lu~z z$m?7YUkn_q#_RdmoRjhHjRsFO zg`*bj!zUF6$@W+wpnF7nC)JX)GH=T(7mqvE`Km9p8Zhj%Gorief<5^XZ3TwJk@a^>HH9va=tkp;)Jh*~DEP z<8FL|ltIYdcO%<#B9taYoVcY^?W$Gm;Rwr9sV~TQpBfzKW@E60{*{S|$&cL6);irbh7Fh=Eww2$6soXg z3oNPN9k*Q_Z)men5xo8U-buEgKOAQ_VGbl{I{yp`yNIvsrc8dDSs2L? z^l`J_dKmeOV9HuOph7`t`T?Y9a0zgSvJs>t9P)zO03^F8T}P+VGgp&lAdv*!&Q{0`q%uaTfpLQo-Y%!%yiV4sM51 zKX{rEs6?@TAz05X)QaKX26Mfh+{x|EGDBPH=%gIuRNumKmPx-Mu60B>qV?@R!=G>3 z30jo@BaO`go*C7N!Me<_Xtm$I{hKZ1tWGe82L1wQ5bU?PMy9Sq3i9%Zh=_n3&eW7V zf3le{A7?zokUlmCRr62!KM-uJKCvkW4>DO61fv0D1*XZ<{6enUtDNqj&&m3T8NKtH zXCs_|hpV%#7L}Q&RZM_pFAoEF*#T!lVDo?bQ7ttJ)TYpb-5&-)%Ik9xRQYIk z!itvDg4QQKJw3f(VJ9sOo9lD~4VX&E#Nmq-O;?TZS2jzTBtPs&8ZC0wl8Tu4#mXaA zb{nZ@d)ZCueX=`f`6DV&*}Tz)4EQ~??O|2_uz&){xXi&3`qkR8qdrOZZC?d*CxWD7*GCJM^g!CU|SrWQb3UcS8PYt+L2^`r}f`6~Lz0>nNJv zlZE&MF6s1ck+)Bn4dbVPB%&yo=*rTTc1OCwcFQ`T(!Kh=%~(w{NqXdD1S%+n(Ub|J zWB`!=#b3+eA5=H2XG@g$`1t-=omjZkJpz8zf`B_R5T{9Agq!D>Q(%fCeRM`$id}I! z^cdUf5Vxs!llm>ndU`f$)Bpz(elrW#PC-GzHEp4yWZ`2R0~3=$cVK{*SJUBPL?5_R zITsNPEy~!x39^U3id(ao+Iq~VD+E;#RlDuS3EzN;;8>o>-1;c|um$JEbxcf5f!dd} ztjIlG9$C^mQ8g%h`3nnx zdP-7V{)F)OKe(Vq%}&~Fx&V(T6M(;>RG=`~si06%QS0Q91}+K$1e^xAilW7|+N2@+ zz#65>IEWE|7#N80guQ5sM5z^r3J?eOXwM)fL@B5>D$|&)-cEp)7*P!_dCObFityG0 zLH+^Ed4vB{P*du0~G z|BTq;VD&K}AKut;ggy>jFw1$)H5vdLB=5tS;<>r!~he9-yf8ayfK833XW26{6D~ zZ=LrGB=rOXwa>X{YP(0aKnPNI{Zsu?U0uXs!|9gpeR5r0-NOU83fUpDzQgJ_;X?qo z#DFRdwM!6C64vt3@}!_%Ex{?V}c@JNXZ zNt|}V0;S7R+${Tzn0iV8RL}#GyfQ_@+R^#g40k{>O%L;bWtx!yuK1B_-li-9-NoHK z3|TTlJcQTW50h(q1CFO7peZ|7$`tfHVI2hpwvJQRRfGz+a3XFiv?0_ zHoxY7WUQvr{~D{J5mBuq2=vWMa7idbi+t?lf5W~xz$LCpNAXaG2vb0K5|A%J&Da7W zEvznjz%K_-Y!dxj8{&PWnOI_i8J3_B0rAbeSughgJN*CjZAqeB07Dw?_97-W_D8)G z7p}j#5D0m}98o_M0AnHU8rWCL#ReQQMBVwTZ3}U=9UL=Y^qm0Nzn0HPIRlS|vkpBs zEN7ZL1r{jUV(PeoKi62r>vMJ<`>IZQs*@FM5yJbw(m@yB8Aulcz4;z-2mKf7w`nNnxaMuAHTLwffOOovE z;aJd8?l+|T`>Ud`+z1bsOOKeJ<6Htwc{)+jPfJ8Xf=af3yEXz>^37as&=9T~wmEFW zjcM2v`RZ@)HFWS3(GpPV@ah>lD~aSKfYZVN&82=%58&h@2rs(L$(n)0fCr?AZEj^n zsh7cEvIE)|bsiD3I6N6OwJKAvG%6X%Ukl^`0`A5w;~RlW=VKK8+};AkrPh~N=lk>s zq3gaK8R-cA%LD9fsiRR*y3sWvos?a-cx4&NLZCX}U>*oSwV>6W|M_O|k9OQZ znTiTpsKZJ8*UD28U?FU&L0{b^3{SYoVbQlbv@KL@_>Rz zAKVkVN3zaIkpgaiTCPyL z25Jb%y>zmzPBAr&BC}`YNEed&y{r5jG-I|VB7UFDM4_mKC-u;M0jDQ+HsPokRAZvZ z2MmN8R^TrAX3zn5tW%ir69vMm~ zT}``&hI{_p5_f09iQQfn&TGPvxW0UQEODyJjaerL+=EHlQj++Oeo!U&q(BQ$4epOb z;qt8b;8(3CwnACJ+MVWqs%|7KQA;m)Jtq9g%=B}8rX-`H97~njL2j-QZyYMIpl%gT zOUp7YLjx`XG6=Xt*iin2Xb`F7zn-EJXp0Ndmcq_@u4N0l5p3)guAKJ|Di4;AZkTK% zAQ`LGpaZ0&isdV5e((`9wg!M|yVHJMCI$cg_i0;|lA`d~L*3ooVMbE}#ttbgWy8+dQ09PlC`*U{JTyH_q( zFFp*=Q2j)P-lMfF92`TLEb5F7Eas-1S>y~fG?uF^t|j-K6!?|^CWy&Sk1c;7Ua3}o zGnnh;XyUO5FbVQgv~IQ^JvZKZfM8w@%APz0`_FVX74EG09h#!IZ$WqK(5y#XEAQ5s z>xZ59tTFVVol@~@_~vteKKU-CueJM~2fW^`ulc>-JDr`;{vaxvF5|Fc{&61}^UbtZ z98aoTA{R>IJ>Luj37O0fZEf7nzxy1JcioX6?a#Z-XJSpz@u3iOPBZML$67~ z{uA@->o<_dP>o@o>&35aI5dy3%|RoMIovfR!5naNI7O3pUCKq3W#akQwbuu^i0f39 zb@>a|@0;x~{@!w1dOfts(XS~G-x@HZLB*D?gn%k|>Cc}V71Rd1dP>tWe}A^^vr8m2 z^x$emfqCsx!x=XOW9C5=EvOZ``0Gu{jPV;>(L)&rq0$xHC;{8<}7vI zNS_nXyl}2{19Y|sG-141zY4nFPQ-IPClQCPu#>4 za8h&5E&f(EEoN*gZ|icFQSPH|)FNBwuYanot{+V5J7yMZ%ZK;Cf*cm0HXxscLQMR^ z(uTl^@;nOC6-J!q%8=rDA~!Bpxm&I(<%2_Yk=rUlU7iEh-9@C~DSD6pVmQEHi) zYEu`FvIKwRc2+0#I~XN*cql5g_UNB{aPdg0YT2gU>EP*FwA8JwonK=j;(ol+5WMj4PDYH z%si|%#Z5fs5g(uE(S*@qs$MTOt-wVgDlEvg1kV`;-yqua{o(==su2kM2wk?{qV$c0 zM~951>Dg?TRxy4dNNKg|FT7>CU6u+3+GO4X+_sKk z6Sa*0be*O$n?C*Ay_Rm~Zt1#M{!xD)^XsykFjUp|x|IM*z%Q0&jSPh@Vv)={cfo-H z{HZDzmo8yZtY=QMwM?3fr8NFf;P zHR<21nzs)sCo&|wr-gM^Ti-&}8jKf!nLp_{K!=mtHV>(7qitJfhF48pU~USDBZp$a z1fnq@AtB3RGSbr{bsb|Dr*b5N;dS{TVTU-Vt%B)Fcg}Vz?=7IZ>CF)(-O==A@N9|w zRa5awZ_WUdPYeHzvMFsio?)ceQG4!>PEMa#Gj_yeqH}%+G(=d{<5<9B*hE7>HI{`( zP2d9fhkk>5DKOQ93P=dn_OgF3A;a7Symha(kk3Q0R=o1sO{%86l;muX15Ibq@OBH` z*;`bmM@~g@9X(xWbNa>IoQOuc0}=vEjL{i7x;ok$nuJArJg`-YrUk(l5U(sxJux;2 zk_93d>=oP|5VjIkw(?GACeQOFNR4X1Xz{#g^8KPxZ#{zUW6i4n)w+U|F;S7QxdXBP z+9JN7+uhYY$HRWTKcb3%v)gQR`v6PowE5>S@c_riD;Yk{xdx{urR<7PyT+!+_TQ}E zG62s?>^#0x*d=k0F*!s;lrGD9m(MjVjGal3gflv%J8eNtRg(ROc`Yrw+#1UdB`Ism z&1c8IGdzK6*?tng1vx>AvAzDbvz=uOL)T^W_V-&hTPW`B6Q zHF56x9-Y_j|7bY7c`fn?PS@!jiT4a+%0`>GB;&C+%p|{`D`d)&y4p`mRhy$>;X8FL zK6*5$)|GP3!GIiXU@!VjuJO4i7PNXyibf{f;kpf&f%{)V`Ib7P(=#&qzC3U^{vbFj zF=SmlHn5pkNH1^eOD!r*nLVc??a)wF(|?{_o~MBhg^SN3B-?_3uS@TUjU88~W=}MjYM=P*LaD7ifRfW23 zmSDL;aOPNvJcHwDdscun;^g?p@No(#B?K4VuVrOrsj1i=r7Uc0_ZJs+g9HS=H+)b) zss$4ZOYvF1Rm+do)>hbGdM1axn=vFtf_67Wc!3!A>FY5xb&bvS&3Hf5`fCpRmuWq& zKA}aIR#qoH8w!f;#G70sdq?~lOW1fp)g;}MCpKK`L@B}zr=-se&y=WG> zt3mf`;^v)Y_2}zUISs2V-PNibL(D(;McJ_UqtW{U;l?dE{`Uv7+1)9odP-5m$*QKX zI0`5hbRdlM0&srX+yhth0SD zrgV3B4z5dIA4*zif|MA7^>A`|Ux1AY-r)reD&3Lk8fj}6suJn?m*X^nkvtTxFRQ9zPIdm3HO*l@ z$SWXlPmpmP3<+JQ7hsiR+=gyn^QTwqm|ET$X~lW((w| zC%EgEg(#XnAwv=ouTmC!l z)Njhe!;?~ReRqe7f?`>}|Y9SpB@Hkm`4)Czn{yLGV-&&{`pIH zX&CRpM@mu9X9x^10kGV%Q32LrkX+=Z>R{Oe33V2nIrcCV3M}By7PW>)CgI1Hxm4ArqM`~*`0E)-y|$tRn&N3KIWv1g0d1&v z^yS|m$?-sznnjDQfao)t9EEQfFxc^+E-x>|3(+0X0G*k19DeVv+wTF+pJDL2dSZi) z8(pu!){2&gE2+w$`7FaEFpJZ2w8eG%NsET>i60&Ee=TSo;i4`s>_^`VPzQ~KSQJP^p`Na`Y7|YgXHBlS-d3q`6JZ=If@HUDk55Yn z4A3FNZQxLeKQDvn<8;*3uSTnj4~0iB`dYq#^8$DKQucmpK?Zk^jUK z+KTWCd_ye6?o1OBmXRcAJOpBfd1~|(NHIDvx;vPrQc;-{o?TcYzPO7)acg}60$|Hr z|1i~i4}I6gn23`vp6Tf50Fu4#2qL2JJscdE6XZPLxCv9>J>Y=rSQASdq=s6Pg7~2E z(Q!Gv2yEjN@(T$p-)2us*enB|nvnryh2L%UM+tEns3?a1WUwiSvlAxz=y0IW9a12v z2EgUO-FrZtCN=_=9AmtY?`EGx6VdUxZP1l};$dSK&24Ng<`~xZhAKcF~ zl-fut(Xp{e+4FaQPPoy=c)WgiS%=nWw2y5`@gd!$Xg!_I~O^ z>3@e4B?GEgEt)ecOZ6lsK9?0THmUjxCKgtCt5p7)l|DZ3wMrIX0k63y6zQ5g$TwP4 zQZl@Jm4js9xR|8CHv0do493(DaHPI-l(Ba}9knAR?X7X00iz2_rd zQ$YKE;2%7s5|wx_tU7%DffP}--dlw%e#g#FpPmzpAGSop{wViZ-&aAS3Ct|)FcVFF ze#j(;+oBmIJx??-*1u-LJa{yjGM*M~`wBe&1q4MPf}?jSCI%5?$57PdseB_R1Q~V| z_;&z~GqN+MGq|5~l&54WU~10W3g!0aF3*dg>4n4BTt^rOtHfgg{F^T$dj7&g%WXW! zmDaLBSdd5*qTQDU!_vuFk_9yX76bsT1x(H1=ehs`5)bTJ8rd6TEGYg?WwvhblT!1r z+zrAr>;AA9bNDb!X~`Wq@T79%p}mFA;e9M`2u5H6WsTfDft|ejnaD6pnQFb`DpY@{ zki$cjbqsnI8XwvWQ?Z&^p5X4b-#yvr%^jp#A?ZiKrZ(pN^|h0~`pMpssrf}ovn~$G zrS#*zNsnc^PBb1@C@7arct7*wwRs-HD3wKvMyfqxLdX3G66I4B{U#ZU2Ti3AYe!0E zkSM1xfw!MUt?(YOJVkf$@Q^$-_bBaj-Ig{sCWWzMvDomPRD=~_Hp_f}`>o?${g%@~ z?tS)kQ6{qOGp|GUw7Da3v43P*jo|&>yvFk#X}2-gN#c9!oc6C>T|HX`C(_j)B3iqf z$E@W(9#1{%LLY0^-||q;lKUlEB5e2X$#~O7^RG(Fzf?7>FqAiQ$!8f;;RU^=tMm@c z;yJChW?V|1vV+&H^M4cW&~C9;-Qb`ppNrgzvbZ+vR^%D-x1AUG^;P+3!1>56r45eU zp9|&1jl7#j+q#8uo?mqZ;N`KC7@hvPS^+Bi7@H3NJ*jwh7Q8NE2yAUfF}|V~Ch%p4 zLvY${wN+MCeJ5>HYMF{nM_?C{W_>dqX@Kmbi*8>Cd|Z6L&kx!FWFFgg=^6Q@NpOz? zraygNj;g*Z$Tho-*>n5u7~?Z)+*cbkZbuGsF$SJIAea|b&7wLOH#4CX97mb&~$@quW>~cHOkI|WAy}_zq#hP>8OH5*@8<#1-&1`=#U<4+u5tb>y_A2j| zC~^Pi|6%GYqq6F{XaSKBq>)BK0i`9RyQI6jJER+=L%O@WySp3d20^;JxtsSJ_m0ay z#(?KJJI>x~%{kYaE8UwyVT9i;8_FMt!e%_zoJg|eGmFz7_e+EPA>^3G&#)TbZjfV1T zd=9#SrBP}k%f%dQCGRpt6bvl%tz#SvP7>w;#Q}q}6w>|?H{0i51|MlsQAiZ@4GKAQ z^G94=JJ~6@k{EgxBHS-L64i6(w$c{bo}4Oo3L+~vR>#IPBRAJHzm2sr?&XgLSYZx2 zA8&N~`!(yH8`&PDksU9ei=|!c4(j>)IyE`@|4w;Ysp|B1>9nJ=MS5 zKZND<$JXZAsUju!YI9)8)G{%trh;H%@ApTBPe=|dGW~SeCE~pb3HZ#(I@DK)*ESfo ziHQCKQ!C#68;cMAPV?_rXBDYnm5fl;$_o@t>=z#?$;-B;=balvLJ9dflqKo2bvf?- z&5f@PluPeMhz}d8%t@6|inF;~r**M@n&9mzmva|qHxd?z-4j-_@(eNdKp^6INmPD? z1qCuJpa35mEt)$sGXu!eu5=46@$_peDF30Xtgp3w9rkd+>20@DYcETlj}Q6PS+{;l z4&@IUc5x#Vm7(D~=Sa9Cv>xIy$@kB9#jL$R8=WWtPAh;q2`C; zu@|F1o_(F`x`xU)mux<~(dkbWe7QPw#DCL9J5lbOn%}Y13Q7%`&9E)Yzd#;OZ?8zv z%HTHq656Xao(a&dGWmKR{ojcj(PftU-klGc%9jURA0TQ<9_0emC}_?U{VeyP3i?}h zKAiCd+IW7fV&Q&^jrxOELtzN_!&CWcpiP~N(?3;*M!uDdVO**z2i)`R;QGG;QnVlM zO_pY<)o!>@eyd+jc1?OX{JPgR?XIPDg))J4&!dPRWJ)s9MJsIKgNz=;48ALv0 zsKg#J!F62JV5aU#!E5?tGiNgD9^L_b901>0qe{K(G*Eoxijae8j|u6+c5_(fGgoC` zAB1V2T{J94X?o`kZ}VJ7Hj_8S>$Yd-5*_?!ILdRi>O@u2MB%q$_N1vo)pCq2`Pj-p zWFezas`13Z0gW)qY);cpV_R>HJJC*2dK~gNf`gVo4Oq4*5h*EhwK=n^pix4P`}sQ+RI9nGOvy5&n85bD#vnlDcj1R^;mtardXvyDo>{a(;*_)%z*95)?#GQ zt*>{jIa|#h6zeQ6KA)wYD-QH?!q@mNT1yJS zHtrr)N~P)6VWX%up#6z^VMVSj%;CD|Tkcp!i{qYbaQZ`mb`ZqX{m2C%5JnqZuID4s z7mg7;IJw7QRVXx!3QSHng(dYH+ny4{-Xtg{pS7o#rCg63HXl&DY<8fV`kpQzvF z7G#V#EC;jNtcKaYmua%(WR!J8A@Z9ekT(%0nV5oR!5;&eLRgd&2xc39{tIqzZx{Kr zZ$fI!g+SC{NBG$H00~noYNVldy`>Xdt4Updj$duO7>GJaD9c#EBf-WyVRrJQlM#Hf zY0xihSyJ24%kDHVO{ZjpCl`R=BUxHPH73qwLt-F$DjmjRx}EQdpIQ6fp_-QuI%L%L zhw>@j$=AB%^60=(ecXnwio%c2VkxSJJ37M#sv$mo?H8>5Pls0=3No5$l0DXh*V_#Z z^F+eLA({F%(B9FCkE<+=`J8J>I-^(OP6wOZ^Ka8yT}}%5`s=Q67)KPSgLRsrU0F{@ z>s%8v^LC$OFR-GlG&t*aPTyaboKdQ>tj$kag=FU4di-e&nX}a3Y}=Wzzb>&kDLUXk zCLpM~bH^>%@OjiLRG@6YLlja^yAi-!86aHJz)>_M9Ubr}8tobBZs+#Ab0FtSl^ajAhTJj}~SJ z`yZL=Ch^dO%Of&>YpSWR3QIas8jJjh6fe^g!%sQ%Me(r5g2R7;0iTA0B z@jLC);UMR~f!im^WpwgJDa+@hLq2}QR&Fdts|7r+Z9gU&UFIcOT{jI&@|6cXxIS<) z=z;8X#L0Gmk>vC%GzTZ==HI^{X#(g8z=Bd!QX(`SzP_2Lee#Czp^cp_js8;Oh`HGA zHdu=s_EfQx;^Ckkq<%zPSghKmy^Hzwrn;0Qz;|AhP1$WeiPHW$s;>SHJKAbzTkmE> z8TNbU@aXXhB{tODX`}~X+I8=u-dei2mBebNh|jl|#kTkLwlOMe956jhI# zt5u(oSoNL!a<^ft+|%8Mx#?a1+_b4C$zkkzTHMzuOv{Lb6i{MAw7I_Y+ehj}BBDG* zqPnvbG58W)ZPwjWhVvTv!tfLH^f3Eo>Z`Q%lT1!@!dzcUAHtpv8Ax9f2ZbVV1Tw0j zrM1laLU9IacrvbmsXP$k4YckaX4rYQlWULG+Styd&o^HWr}UtFH2RWmFp=R4Ip zz~b3_ALaCvCWj6o-s~l^>FL(=N2vEHNnPgU7xCrqkC<`iPigk1sn1W&@XrqFf@E7O zi*KB1&_4t;Fxea?TIw#|CBwwm?&G*IH`$y{W)`l!w0M+`oj$9L!@hhTH+W>vJeI(B z&2zo{Ja=u$9aHrF<>+#Qm_mL?5>_r>3$kuf4i-=8c zDUj3bE5?1ueuJq4$KgNXcEj+&b~LZ`U~a$G3c0B9aWk$vT!WlOrPA81p}L~5&!u)S z)Mwl&eo()3wWi$iG~vDztG(Hp@0B`=4o_>8Bf>tnNokL6xLZcd%-$?k;ZeHz3U1NX z;B+!_C=F4FD9fRkFF=PgHZmg6<`*9yFHLdy2gkVLS=eh6oB4Xwt26sN9V1R*4p$ip z4^*@7?7-gKe~hHjr1v>tcDg^8N*tNNyD5EI>#ibEoW3+Tu~%J9Ea_RNpNe|BqWiZ4}WA?SFo3JJf*SC`t{qHZ|D<9;bYcmUL{;R33bKKv*o11-=;^n6% zSpk?#1R&!7u}d0)MBs;uD{Xv7tIZ9Eng(b;m41tFz5*K(&~^rn;g&CZvi2R*|HQ}} zu~JrRY3Zxw3y+e5$FLvguT$fT9uHt>IjUW?bcM`(7*r;X`?$JptCK-@)N6b&<(&OV zh9pp&JPaC2SWj-VG;QBe_LLQLK(n1cx=6zl&|Pdr;wRnwiU=;6u-<9;() z-hR8;AC3PL$wIyP$lS$@twg7YS;*btJq&l1^Nc_Gx0kti_se41=i9+g{md{%fp31f zn?ujsIU5uuZELVF&M1Ib_OAJT-30mtDH!bIwJ#M3R4S>LTgb$O^fb?_oz1=4w0-#g za-iLJfc6j&XA~C68Z({me|@i7S<3=}Zyw>emRg3G)b`kVm(8!<3M;8{zV{G)SdHY~ z?C{`MQgwgaO1oNG*t4$cY+u{-yOa2YIjsyXsm`r;Nsn*21y)ki9G~N1qTZ}7eLUt% z@&S|Ndc$7!uRGTKaLr*FMGi-jtf6zCY1cbUQHkMUr%5)KendFwJU<+Bs6-y`&~IG6x7ltlDm)xnf%{mtW96H&sOS*TsvjLK$z+zPZJ#9ZP9`cA%Kwdj2l_lY z{+vTxT*{7#jcq+I|Ize!$%tlkL{y5yrM{r*_I`CVxd;{-StNn(Q%9MJ0~J5zFy)8d zF?ZYJ5hu?SD*^MEO>8FTK_i&%ds569rrL1@#Ww*>omK|9S{zA=%HMAtX9|hmp!N0N zFD2i!w~v~RHEZxH?*M;I7YBATybjdhihUvE z2_el1dlR#5Ws3KKZ=+EDYjoEELu%y3`FTYdv*JpZFrpcAJUPmupOnhRciwUBki$a( zHyXSn@+8g@3qJDJO~cJi9a_t2dngjCp+8dY!#QnrdEa^^j&9%N(qB=U@ePk?MRYM- zyeGK`Vw_M@#M4*XZiuB%1OCuqQAC_6q%Qwt+Zc6m3<=-8c z;}@>e`w*rltuH3H%@RiZM%Cpbzv@yzSjry_pKSZLb6?D-4Q9e^yu{F#|~cA>HLebzlQj;&g%{8x=O zH`XTjWRR3DzQG9&`x5?<+v9Rq#@X4qdj4}))ooIyE8#o(rsn3G$~@=J&d&Lg50#gL z-%Fik$&m}?($&@4RWQD^cvR2SOn3-sTd%xH{IIJH^WOW7Ce??h8%qZ*D1A=P+l_$H zoG2BQLTL(=Jb`vS4wRen($X1Y#`iG%GmTA6T}FpHI|1CB`-BmW6hrg<7=+Ikm6zB} zD(>Y234|bx{d)tUpY#jv5(@H>@fRL)esda^d$3{cE8v+|hgG*>AlJ3@^+Sl3gMyT2 zShd~hpG0{A-6v_MyZ~{ssXe<294MqUis&N#ui=g>Z@Q2IAPZzPrA|JK3PYde}lNtLc(Vz`f&i;rc`ydgCwt*l>5Z?-9jH7u?S#FOc4%7fEFE-n4M31l8 z5u)iD)YOMF@EQMpFet$OfYnh_S1*|{&0NCA$A@{33;iPij;f8@sY4A`AwZWRXJ0e* z`wB0#OAG)g2zw=>QN0Pt=qwg%sMYG$Z>NFTp$y+!NZ$L-=1oO3}x{e?!(~U2f`_HKt5`F z9M#T!V_>jaZ3!CsVrgl4+NS(iWDHp@0)fPe-*29`zg|X3K|yCvBh)4AMBmgsX##nIt}1DJ;}I`9cOD*y%alPS zBQ~V~?k@=WE1`RQB-->KtWp_KjLa0s(1VulH|zZMmRu^Wr?D82l-c+6y0rv&!N=eD zp(ZRuLcK!GSd;>GCLAU%MZ$aYS-4@}8-=#d3TorY6OdH9=h>Iw93vzOK)a-Z#nD`Y z`UbcFcE|!YMtc5{V{k^XLlz(#XKbj0)u5AmlY>7{GYFTQhb(P^;PXx=2C8?m02(3exwufuW&KB5&D;d-XU~|aXZ?cjz)+f=fdkrFwW+QY2GAQ8@ zi(QFQ0>}(cS}u@8|Jksll%;s}?Gr*7zr54XbgUY?4HyJ7HA(Uz|F|M(_Y=MT07`T@ zQq>MW^Up5+K2zX(}b?br=KSQMwdsPtl5+o&b{;M{dqru?tG0SIo^QU!1 zIHRiS&om=q6p|$S)SIHRqM~<2NKcwJQ9su^yz_`ke*7VZ{qUsopiBwIAx?_!{mk>q zvCJE&lA_X~VRN~$q;MMZ+3!veZ)vV)aKb}f+!@L%De=$n{vp=M(wxRYC;R&KD|qV+ z{k%d#L(K=`=-}B!IL~{N#>t{S3v`qKs)eEWh)6Gx2l%~RE&3r~k$wK0DKnGC=_H)uJA@+W zdbyvOGz4DB@*4cmA81kO1B$wd=HGr|NtP#gW)#$xIfl+BUt$%ME8fHWkF#=fx+EZi zdJ65hJ=+8sRTw^NmFLUzLbXx$%3Fdh(@jdR4@B0seCVWErcH?B8+r^(=6-s}t?jCp zK76=Y(Y`-s5}~txEM@LMH}&XJgaRw5l@XZ^=cV7sM!Klw-z$5^ba=Fd|59vhCqJ_Ec!#Nh~0LABo$Vl%b+Xgh^#qX<5 zZ-`YX>VUN;;a8k8X*m3mf`bgj z8|n2>gEY27K&>!`$`%fn6cOo=;cz-%b-R#oy4v0Hz+(@N4k3cs^S4t{XLi50`&9U< zI+|3A2^U(&`+^G0kjQlAP<(r@tT#7YMD`~pCSW+{PNAuFZT8E4JMWQ#P4TJ$pc8M8 zbuff$ihq@ok$N%Lf+ywLf;*>vJ`49G;+*;$HxUh!9kvdrxs5*l!KhNT`mVJ)U>EBH zi=4%?GLgwoyeOWkgBm9&34`e40wR^J2d8!E)IBKO705Spi{r#FFVccvZC&GLsN(@1$>W>6M|O#48d6siXt$c!Clp*^DPI7 z$hKO|^O`i>ZZwH$fY4%w?BW?>uwo$BFW&OsP%I#1^WY9c$oRYddgo!7*oR}$?)EyO zNIY*vOYP1Z&{{%DNW7{A?oM5zm`4SnM*<-jhk(&om_EXMjp@u+edG>=8TV`6OQHa* z{<$WrcesrfP%IWfhqF{>GhFH^IQ`&8TNOM5uX5hgC z23Dwnkr9>77D`%`!El6U>uj;sYygjk03`>?u6`6O%<~Zd&rPjYIA!X?*2Fh9)>B#I zF$H3`tBuCHwk-|#d|nY?#n)qX#vy`UAVU~FBX|isRV1U=I)UV7<~{vap9Iln`*Z^7 zS1E&_RoQX!FCj}I2w0lQ@PuWj(TWK%l8JhFX{Nlk*7h1Ul2bG&US3`xtzpKs-tfi0 zPf(DTZ`p#mPk3dGd7!DhLFOzr|G6p>&W_xh)pmOwh45Es0nD#B^}Jxq6;|Tk68|I4 zSAfz*vz{~$J`hkCJa>pO7xoSgG!zs(#9A1PysgL#^@$^-|D&|)z(klOBZE15yqjWH1u_6a^Z{uJaJGm0btpFn;;(MaGIFhmh zJKh(pU2b~N75@16=b796v1eZKK%>p)&&_<}x+*4SGvYzj4DGTe-%Xtwd=mP12OjT> z`c1w^m#d35l?JPxZCt`B!9P_mqK4TagKyCg_i}U6K#cJxg^H7e_&xlAN?F^?%=KWF z8h-$2qpB}4ndYqu##ky1y052h-W8iMs+QK(k?j0Qv)6h)nMIKLDo^0hhI4tJ6pGGm zzTmLiH?^7o7&?3M7JFAO@lF65&VjZWDk2QMlfRj~_wH{7CtwfT7L3bj`&! zL$zT0k(lpTZJeIZOCfQffR}WPSFZ4n=_SD`pIM>f<-o1A5o-K1>k*wmQzSS@%gA|N zKG}21;YPmdNP#Csk0~%N1^DG$iAr>0;sVytCQi)FSZW*PX2Ts@Py>~oK-`yWLT1N> z65?Z7&7J2jHQN`?;s;~Db@sGytJ1-aW*`M0nYiE|!7A`-hu7N+1UNQSwDk0qGs$17q=X1NIsGp~0VUyDdz#ZRV%gXi1yc$SGeRwkDv&~8LD_w3 zXg_2ujfQJM1M;WIk`G_7jK)%chXbB0O`cSGSe;=xW1zFf2#Rk{ugl59#-CZMXP^<@ zJ~To93xyAD9`=$@DeFqV_G!ZI-yW8v=2-E@xpJ+P75NGCZFn-fr*2G0f`aqOZP}Z- zV)NzHxBHJv-_y@wM^(RlU!98^H#bRCU0Au;If*eXy&CF*{bG_ERq*9v6`$ZQh5mP} zU(_oSCqOO51I;D@woIy!$Qu-IE>Tbo&C+a2=MhvTT@(v*hn z@E`jCi?MmKn#|PGcDXoi_Hxtyd_LD+x|Dobk(EcYuA1!Zb}>tN&$}u79_h^P8lTRl zZ;QnZ23}{ij3$kkcvaS&*F~tXDlhlCH7R9^`%qHmhsFH85@f3@6s{EJ*kQezlv6sW?d z{WKFbvsXd$et+~`BTDV1_gbex)vJkGP8ae&D-S&~WlIfa|I($O*=baF6t~^pH)15x zl>MFT9{Gx-j3a=mmmgTHk*i*Zi78h(Pm7Er2~8CW4tj(ox^MAtmvoQn$&BBc0So(8p&m zxU<&29=*oNv^?M@CJ$T`8Qdrt6c+yr%6BomZ8rNd`O<#>mXMW2!_~mRz_1fcFPBW5 z&P=vPrqya8FD|2Rn#AVFpP01rxP0LDV7B$jrn%^fEqT}I?;UV#VkxO0adfe1pY%QJi2%t&Kj`<70;G>w9>Ik$=Th8H@(KzD-e%LWxv5<7id5x=@m7dw zYKJ3p0Zt;$iY@|biN{=Nx(Olqe1gzIm2jq*b<}28>@%-V}(U zkDk{HM!@10)NVc9U+s*imlqc9ovSptcPt(7MHaf+4DN#>W8$?iixck4do@TI9O zHxP4mbzQ7^K6J0j{V1%Lr6G7ad(irZIqSlIm)&nrwEs81cZTUaYQzi}Y+%$D;VRg7 z%BhqJndQ#yy@yHFG&1n|RqcSwVVOWnezWV(gy)Fg>a=-Xda#3RzLcu!UtoC<)^4fA zA@LfnzL4p(y8mKR_Wc9;H=n3~%9^PgzSxX-#?CDr~Kioe1_s?QR$ z3Bo2UjO*gX`x&X@6jqf(PMfnOy~m@s;+7r0y&>g0o)=S*?>#-8SUY|UY{M-F(57wD zpe_jrJS?uZoNXqRi)Op0SX{x>F>Rjx?hc?4+h$W8K9^$%j%BJEiJ5lwc0luFPp1!w z8*y$q@7Ke7Nwfdl)9tS}Y7?0DAmf!9xI{&n-Mz&79VACQ(2Hapj~D4L%h#Ad3`PVc z00C_+L`_5l;XZP_+8VOxBu-`vY`{q(;ZEuUq%16s`hMftum_We<1pkYq5X{g_j4(O zNSKCSsW?h0b~rfXojzN=4#Qd!;f~(0-nWtxK}*PI%PvOZp{2vfP?c&>DG>jEj7rTHBfUg}yg$E2b4rSXQznCy z7rVQhk^+@d&{C^OOlF|aG}60s^NdP|3DLW>bWpM~JAb}XAsR;=?>l!g7FXT&lI!i# zTs!s8Yt$KTt0Swr`32!+B@RRXqLiL=&&C*;tPilEiA;|2fj$u`k?uMtos@~Wsy`;? z7py|zexg*V=}nH^*cVkT=WGho8pYW>35N!T!$-<*ue4a7t4e;R)xHg!hkV0#WOhzN zFz;C^kBiH$>*SVzm%Pvj#RyYN#eStKYFN0K)V=vrdDg#VDPAA*vq9EINItSdeSUQG z(K1`p$RnKcEp6;JYz$x(+|wX*ON>xlyx3T zI|^zH9B}N7VlyCG5r<~ueGN3cgzM3~J$^teU;;7q!06~ojS0GoMnhxc(?k19GcfzA zWqRtH4`@e0EG#dt4kW+)c-1#e?Cs#TiHxkKWhD%$w9D;sz18Uv=mjrZ>MzPA5w zgoqY7ef^|kcZQSQlWH3a09^B6>;y@@bF?^@=H8Mj;|9_ie0+&6Kn$gr-6hY zaCVP6jJ}+w8~YeiB{La0RYX^K2#MQoF6zmI$bH_~bZ^fio5nGf-bz`jyg%SvNSoqv zGMa2af%P8L+Sxmjj&eFMEQuG?6`8&@yw9h9j_oPG6SOK&%uQpFncGFj#@68nQF6Fq;UU42lU38Ewz<6o zrC1zL{HsWWQCN+&Wku@lLprauig0Yelhe30IhtELZhtOVkUvneU~_5aDf7_z>hta4 za&~4dt>j&DtM&2jIw;6v>|JDL@%VEpB8*yYOV~v=oP{Nj(f^ts*=#Wqqwb6_+Fjz51o(#ldJenx1i1QdvVke-f_6@ zFWO*Y{|-vB+3d^5I(xhujp5>w8I`?aTiRpQ`kzL)o1jy*&x zL6o++(s8(LD=A{HS~!3;WL{##sHyjNutP0soxWCx^{xbob{O=&`|`Fi-hu!)7FE!( zna#1QXrv+j0dZA9#Ln?C7pQmPO1GL7inby6l;NJ@0Ms0t5w6c2WmF~_w|}G^_V~hv z3_KEiBG!J@dl6sau)dIz*{&2FahJ{E*+q2-dvvqP^bb-qybtmt{DN4 z$#XdIWagv2seI3erL_qAGteBka|#I8eQ1p0>d~qiETCLeR2TVK*Eo~POX4t#LVx|x zN^;{ACQiiIBmTfRCo&G>V@17D8cuw!X!&F_y2+o59Lt3s@6lj>?xnb;u~Lxx54UdG zo3`2hERM@b9okmvciLxrl-PU?(ZcuG1V>lD+KQ7$SY|k~2hJQEhi(V#FQK~O18u>g%OOnYRjQdIQQNB?XB?{g%;`>&8IFc5@TW^ zH7gvS9m0o2U&udQ!?58i6t;xl9F!xnD@>$oo@F=JU%Dbu)w@)sm&xETcMGGG; z%nkGVbaxW=KUmfBD|HauZ($Ukb_F!?~@YB<(|ZI>k3qJT%yfN84hVI9m9izLh6o4QmM(Qqznz=aMf6K|K3h1 z=%=hye=i&|`uo`V`Gzoc#q-mIjpZ*b4dloVR1?FZ`b?@CgFfv0gJQ7GO9;cF!}7R7 z&Y(iTSMZJd;)J83Vqc-hs%!0#Yu6($`2TcvYsLW+OO7Zvt&+kn?R8F=kkS1pTw3Z9 zpH&j5R;kzOh!aQ^01TxXm93JOY%p1zmW3suC%_kKq*{%Ccd#ctv(I@n?TUFN_(OvdVXB#g-nnd4_-#i36< zi2|0Va;@`?zg20;YHITOTGqf+Y+T%osj2DRMz;Sg-}v5?*r{r+KJ4$nD_f_Hp5+UP zf@IU9Cav?7e%c3ZkDRYIOGOgndBHbUH0Ri8FFaE4C)?5em`oxU|CsI!1SsQ+o!tmS zevGy5IPE2VMgyEtP_qy-I%G8|3MS^&(%N%fQ`0>_)kI1$Lwch{*ZzQ=TwB^;QR^zit5pOM#g=wK?;IMzEZ+~XRjy5wfz|^R0<^~L3&pR|UG>?nq zwG2a1z|{jJa$``f#fg4wC(&GRf|-pC*Y9#<^3q}6m&O7##xd>+`9@C=FM5Yu0@6jilr>t>0U-aaA~oOj5`C z#(a6@%D3ACL=R0ryYS;XZC77vJ1e%8HEm*L%_5lV`=p8GTthW0oc4LX2c1Euw#h0U zu<1Vk#i1wsvpo}uw_;Y{oD^4vl=yty^<9`LZC?q7Qd~hkcN*I~*=|-ZkVI3fjYO&O zVn404Yrm4eyYkKkrr6AmdSo*xW2nI(sfjJ}-SS{IeW1IiVRm!r+RmF-E2MGewVlJQd~NVvdO* zCyTw#V(QNa9xd`8=r4&17M(|GxelF>G*K>dDo+H8_m5M}vgQHE$hOtR!(J2ItWR=P zj2;3F`R-zGRdA0FI^-4olYXh~NT#)(iBQ@&*gK#gG^is9@1o&j`sU$Iht+vgb5<(9 zF0#YHfHjGB9JDlqGhpBg($7yfx+5YYXxnaeuMZdC7L#%-%eAL_g3u$WLead`>dbjV z>XaIyY24p}me@t6K0E`Z+|U7Y3NDa~lMZSF^7&tBX}*>gRqBQurKaXUU5A+9lxuTq zh`vJWf+nN?BMf2Th%g$gH~4x?BPAiFR$rdhUO?kFv)K|Q2ZBT#1m7d;yozX?Lc=;T z2F8HS;)`2mW&b%^fuDF>hf(C>ZKcKGrDpM=f<7pa|6hr#yEg=qE45Y|zRm)Go?d$( z4%4>#GAFUx<_U&y$Z1wc=4VG!yKk_IngLSj6^Qhx7_0$F`X+RQ;n}L|2`?h=7O^m7 z8pmx1K-g$7-nlNvl_jFQLuSK#S8nE?E%RT2<;rWN)%Q1f8$mptpS`G5137$|0MZCH z1A)^y4-{C+>1ZR-vYwv<0drdIlQovFg-C$So%fGy6zKQ`H@~X zI2SaBfbzUsDq~DCxxoM<8#N&qbZ?JWpq%>!YT`VI=LU@j5-9!s*UUh-7!>D$O2N(; z(6C|i2`hxyvHVLaUMh%;H-#Mm=nwR;0O(@0NeYL%{Qla>1%#2P0o~pMpb)7ikwbqm z3;SEqP~smfDyYCO@o{4tDm{jgkpNZ(^TBbC3qab5BWR-Y^+Eomw=Np``uc8HGfJmh ztpL;}BqStTQ?6H=n1o+<_buu^W6y!vWF7J65VU2kspZkY9{$Pi5Cgd)4B{d|H0|fR zanCxD?!i~^fhri{lZ?Lpr+YOHmrJgaqojC0{C?Z|k)TR$iWk zm6ce1SU1sx1M(XNVLxz3{D6Vc5e@4XpOT_3FYh}<8;5CNX(J3mI3DPGI)KExJK36; zyix*0WO%r^`+xt+s;VX>CnH3{)&{&Av<~VVG;-KhRq6bi;JDG{H#8&~?HoAbaXv_H ztZUd<`!o{407&&fp7>X^=bwlP5BS_g5(qyGZ0y~mqxYW5pk11(D()ZJQ?ga>xNqIj z7N9CcIt#RSGHwj3Svw}lj+VG9cgcTiZ!^8%!7<(`KOrBQGRIFKwyU0q%4 ze_S7LZ4?#b_LK?HXr;*)mSfO?`FQRfsK5;T;`0~wqZ^&U5XR4SfO7|f3Uz@DRxq^D zpb4|r7|0(2X-iO8n4e=K5HIYXM!QFAON%w#o7jCem@U?|qMj&S$7>L$pdk z3LIz5iuayflW^^%W2huCh$p0Ot~nPY$CQFF03w!t4F)*j?~?&kze)sNm;o~UF8(}I z4-X)$ydlm3^0|ox#G!I5Tk{Q-7Pq@|P?(BLz;+2<-i{(5ddQF;T4{Eap?*ul8ROn5 z<{Mi`r)lM8V=M^v%-sMZ10;d4J-q6-kZ>23Chr?WdAgCq(j zb*{VY8w*AxM~IIj7Okdllw6@a1VlT*R$d`Q)n2*;HnaXf1o&d91Ug6s?GXm72I0Ce zGBBMT_+aBP^lK0&gXQ^@A^&xQ!DoQqSto~SyG85tS>hU42W#@H#=&HdkM zsTxRpe0|Ry;U`#I+M4TYzL97rLQ4a5m;DjG(6`&#x`=r6gOqd_(q27<+#d%pqgy@3+Z63lvI2R2`XItyXI2O|nysMLUlQs9(a z)0O>RO3n3yH^u3zOT672HjDMT*7G@5%&ys9M|z!5*)&n+Y*S;AZ-P%VYNdv}3~$4S zo4=2QC8p!kcJIN!1TvCet8>XJ7^%Q-8bT08Dva=|6E*Nn#VaI;D82=pXHE*yXo0OeZusmJ*-;JV50Qd zeV}j}M5-yMs5l%Bv1M)8SyhdwGF`#Qh`_*h*D2&hrlZ+WHOyC0_VrG#-Xrs@6bkw>j<(vZ`$c;8~^ z7%6L`;Nu9$a6(6-vI}9hN)nqTPOH*As01 z>i!jx5Qs&3i(sTPEPT(#%(wzp2(+4bt&`XE`=B8P26l(a(}EeWdg@j7%Z2~`Z4Cah zy+{|2@(0)}lo7ufksKasPB}4^E&dXfY8cpCz(>Q#1TIpZ)-&~3uvZI&`lzFXdKJp} z`eA4qY5!>jL4ut>7{u5__Urrs0a!sq02jJbMmuP*R8Slh8|%l{!(teK<^q@eSK^ae z0+mpJN+5SiBIt|K%Pz8F9Fwk7AR^V`)?U%1_~Pcg7}_l8w=X7)OkpX?I?h0i9p&Zg zYmEgz9;3A+-Sie+CwQlRis5w^fQAv^=%{WndF`jsln(JXCotl#ccFD3(qQRn!N#~k zu_7@G!W`~?5fSE_NR=D|(3k>=Z9K+M%_^zwZ)b1!gXIT#6T~Yk6`Zf%f`c!W!c41t z@elkROB2$fTeG23_Av=zzBj_ND>nVRYq$*k@4aRP6Uo*eehhAwjuv<#=dPGINQOue zgu;Mj1h{5U&fc{Y;I;(rm~0%}u^rx&8QR`O8nG zc0}b1Z!e?%8v?^?EQn~7E*yoYwFyhMpb!G=Ph|tm(RRdFGEC!+BI6!glsr7|Glx`(wyKozXP&0|qirc`@VVj#50^_8gAc_XzFRGOeEL$IqO(K5 zY<;@EOJp=VRh>NdQL0?txVeXWe%57=fn?$Y-tPXU%R>q@TZJUio`lXg+8#{~Sj7$} zkmrMqFMLsRt<P)+g{rr`a;g*t{dRcFM%Qq9 zaJ6rL$H&B6f@a`EGFbg5pu32-CT=-IuXI|hoHFVAaQK+uhP=+JToo0;T4o)e$4^~G zR!q1PMB{8v-9@o$9~z&!AMfmq8`i;% zX;hNb6meA_t+B7_Ol097-7GemviM8hbI-;&z`m>(VU+%?b5(@3-86fz4l~nzv7}hW zs*cO(I=H0AfABAL@`Kq!gidsTFl(?AH4mdE5Ay3#3CQ{u8vY+|Kp3u_`3k-RToDPM z1*Hq=-`V=054TkQ6q5?ll-VVF2$?Ti;Jn1DP&(q}$Zh(|-N!(VX>rX8?M`33XMy z8I#>Gi{tS!*zmOK4PFJ<-PH#O0hl|In#f-BzoECzk9u#x}&zo2;!M*B@rgL#u zE+d$Jjm(E4I{no5TdgLONPo9&arEbq2_>9|2ri!sh{%6r4|&@&)Ad*$mkR{YyyidI z&`D4I%ac00T(1X^mmj)Ujt??mX#vf=s~WOh7fmkJ7u3|z!6Pgz9MfQ?{Bb`sql%uU z;pe}haqgE;n)-s`(8FNv#|>nb?zw^om2LtH4*G#Ve}4W`H-gpJ*gV{a+Kj!gnij*E z$@&qQM#5_wbZP#{f5K>l9YwRa?apR6so$Y@?_2z&7?*d8Eqd+GfY{iwni}=)I2O2} zKWJ9d(BUDvCxw#?pOO9!J;X=-d(Q52SzrzuXPysj6auBP(Y5=@1Zr~}Rg_}|$p=p+ zla_x!Y!^94*geU_+H0G~MEk1Szem}FN8NP>7lun3>!=7AC@Y%RH~vlzmLrGb<)E4% z2BR^a4j?{uIoRBM6B!`uyemQm%2qg#39Qb(;I5E}f^7dDRJhUts7N7fN$pKJq!({u zTAbz>qI%7v&u5=j^U#-1ctv9`|CTqJxgx#Mbntd&u-(di_vFg)Ij={LLw=6ex21gh zI^AgR9H66+n;VN8nQY$|i=ogFbEf%gYe=+|A|ln6N${A-21E8sl8`)}xj-Yw2$O{> z+V-Mt<)ZCsyqu6fTm7dKIx%|>k3vzsgFTDx%|G-RLWp}`UI{=jx+E4*`4Q-~faW#e zLkT336hIC^PmhYK#>fWb(@pRDXNaEHwI_Q z-I+KdOiQ9?xu>L9e74^?WeorMQ}pWiEc2SW&-lP-Lcu_b!-=ACNbmCSG%BJdLtT0}~iuO3Cfc@{#1ZCQu!<7 zK=azm^9?$=q;DNasE1YM8~M|yBv*8P48-|W@Yhk{yHX%>{M-@&!&7otnW>%}KF;Bk zhw~w675rsH$mo7{#Ey&^<&8?{R1ECXJP*EB(Hv^ln<_Pp?i!?1;SzDTn*2lNE)gbf z%`Js1Zz3ucFO?ZgB+lN<*kQR3jrvxrsFHj0k$&W3xtc^b{!W_qf-%euR&x@s~}6o^UvGXs+=jz5Q^sm;H%H_y{#yY6|pEfOu-V7>f3$Tsgt zo)eL0ifg;sOLkD+gJQ3;pAkcG5QY25Kj6?r+n*=((4rmybD>s4Ej`s|H7%N+O{1d2GuV|E$nvllb^5|j@D z1)P4nT>-%;w6wGOEHb97Fa2)K3_5wtsjuvO989)3W?D3BFw7#A+20P1^78rD**0u8 zv4Ms67uRyqOOr5?d;X3oS9~wa%td zZF8ju@JU6~B@fNX6EU}mfK!ovUE{%nIt zF$NEL+n|?qjvBSm(j+P1V5b{oOT^t$ly=AiC`zu6gn0)K)9V0V-XMbibNtl3*eCu~zFyXjKe-n!f$>yOPwNV2kkQXf zqQDhH`~KlE=L$R$50|tZ!`45anFArK%h|aybS@DrZ;|_}uhn5G2g54cO;!@xEPdsC zYd{1ZZqWzu>Wi{2`Da7x?c7wYB~keKg;d|Wy3W$ED_2_r~~EuD)=DHEtCckz$YQEX9mmd$E3`(9WYJOlb;*DjcHMrtgpas!BFMi%0f>lQ$Rv>q zg3`8@X2{)R`L&f4Bt6#6<{y%ze8rs>g}D^@j|WXn0s}3AHq(Nx4+%(Q>Xs97cByg)oSJ&BX}kzVg`Hjm`EK(v$9!WASU; zavIIS%VdY!gfK=W*% z!SOJJ@25{dizkwwPZulny|z@ZTmDu+r%@c>f48DJ5`F?Vz@Ve}!LxkaYqdt8L0`il zA%F7g0UvKoz}0|`z`#3ToU1|n`1qAYr!r8!A5*)6{u#=CWetuDzy=gK3L(P( zyY;+8?ve8P^jyRryhTr|LOpv z2H*e;Iu$@2J}TtL%yd35=e7)2_!+=lmk`*~#T)k;ks9#nEE&w*-A(H2_QxR7p#fx@ z*R%bDg?z(+{`HQL2!{8c;k+~YpZU1oTQ;L6sBWy~&!Axa;LQ*vNA@h$XTgLaC61fA zwu~jbfPe-ApfCc2_+kp-_MboTAms`0yH9M^Gis6z%15Gtj@gl!rH)uhW1~e zqQv#xlU8@dm=x)zJb9^si+FH=*;qO?rvf3zHt&}SDd}Qc^&NsMnwC0%WlJeM%CC?i zLSR4Ix26JHKJbPPzAk1FTESdQD=S`(BB$MET$vMOlDL?-Z&th}DJ{X*aKI&M!f1{f z;&QP)m>lDT#He3=V{akkO~|MT1HjazL-hP0BkBj$dsiOL&5x2 zE<5lbL}Xv{bm1(scc?}`XrkJr%NuGS4h}v_<*lf0Z=c$x^}s@;XPf~9I%&R42Pk{x z@bkU@V$vqRx(Fer3Ib>h2K^VHc%UN~BtV1~JpY@U8z7qdc(H~C6&CdjFgpX4TF1w2 zPL}F`99ynT&#hv)j=|u+zn{Nspd6~e@;F|GHC=B;rm~@(mkF(VBsV38w9k6Q&T&n6 za!}3;q)!qi=;Q115pE#^qje(&!{5k)?)CxLNtE3mNI3{(b7iEVk*ZlFK?d$kbNaqK z02}nz*VoXqEe(11m@O%G+p@T1Z+pfv!RkTAqDuZ^Mng=^GO1jr&$L|YBYqP-gV|oR zBU)pm(YANFJRg0?fpNW`XXEvKNH+^oSXkKK>&JCglR9-Eq#7tOvd-{zE0Yqx?dtND z`L%M{92tZLpk@XURC)O}cDh$8 zUk%sYpE~afkNZvb2@U?x`*R|rU}ymS&Lm*?xEUs6X}F)A8~X7{HiSrxokUrg|D{6~U%iNNf_d-I?i zKBNH+5=i|7xGG7I!+$ja{>t0y>jK5H-g#i|4Oii}3UB*$no6(Z9eQ|`_BovMi^*_$ zb(r*8VTiyuGzUH-{Rbld-xx^Xt|t&$O&TYzTBS*b3VV*}%lK)GcjFa+K+l~ZxuLD4 ztXwp;O=G2^C8idvVJ!Zn@ua)qXo!bDFnuGRo;Lzly|HQ$uadP2YeKvawj=|zh-lHWfCcdI zwhGB;<8pK;gi)S#uz|s8dqyJ1$4CQqf62JJ^LqQ54fl8FwHX2O5yIb(8~E?-6dm&M zV;uo%Ry3mb<1e|bBXt`4rjq2yqKDLY=V!z=pNFoe{26@4SV0s10!|VJh%(6#CL!#H zTnGG=P;kBe=cboA6P1RuWzx@d?jwd8Qsr)aYwY$d(0F*jHKp;omAXIC>JAHJ=2 zAH4V0G0mD3`j};vGn|R(_T^le~h05 zo&VixfA9S7|B}Do^<`^OY49EaH=->bT3rMZQ$H*PXKl%UfzyY*L18X(He@WE;b`u7u zjg9{gpmO&c#kc<=_X7pAK6%3DIPnLH_z)H^q(7j>&l)1Eu+snV|JjZg$9b-u9)#v8 zq-)48TmI#E^jN<9XUwR`_vnQ!#P%G>F!=I;lqTw>(8TGU+`$PSNM-MS&*$p4HzBa&xQ~)g5O1BFtzb zqwDFb5;-7lxa|Jmv1D&yBO6oJ%E8)JsWIt>cpGp3&&{@mDNxp`mQaa`lsJ!o9cFd` zt?)nvREmHuOue|VIw=z6^p7jbQA0Kc)PzPvRCnSXpk1Zz!|D8);4i$D_|o%XHQeX) z+VM7BjT58MRtOyFY|o2#UhcTrle@nZ=ap~`2TEVWG3h@f1`^!OmMP>HCggwCr~ZZbzP~8i6DF#8dqf0tz^rzFx2DFtO^cmu+rcUDP&HhU-D(u%?}FqsNi$ zl^Pv7q(-q9L)`_89K_s{Q&djq4B0#bBKC_ua>ZAvIebelOf|YvXi&7?rmITVFO?cC zu_cq7caN*jv*{4cFE{(Je8X8k$dp`0(juw8qp{nYDuqHhEd9}^E9 zXGI*Xjmq)!#<|aDC6!$uoq6FRNV-(XLZ-v6*A9@Jvj{*&+=3B^0abQkN0^(^|Mqe@ z$fr%!k2@$rf7@78W;qIbrKkv-k@7{#JuyAt=H#Su8@>9V1xyUTpo){!@xr%iV*{_c zs!q(Eew?y~T9Pvd(~F6%Bki((VOiHuG_;0=g(D>5qz_aXwM{;kmZ~OT4|C~Z8xu?B zI0f(0ufe&D#j2d9U2%REa+lM|%ls60x=E3!#aq8RIUh2pf3wg-2-HMOP9sv0KTKuo z;@`pq*3A$KgT~f?RO07zzBewHMs?d6OP2v+Rna8FnC8!+D}J{2Xn=B!lL3T1&W7OE zSKy(I;wLLvCU1_;Y`&SSX5DF^nVCC`%&iAIJsD*?-SUvlp?#WoHk_WfnNKbrhFci4 zF!tg~gxvWlu1i8bU3(X69r?~bGrKdc3@vo0f71KEVJ3)omC{(EO@f1ql5QQV!i5hs zxjfyuwDO4boIJmHm?#J+cpzYtlg%uFYq1j`!eIXu$=4Uh2A3n90ys zbnz{g^SqXOwhjmvI#uDW@#s`4JQeR>z4W|9s78P4Ri6KhRVG1AVJ3%x!_u@Wg9eX> zjxL;?fhd>EKoi50K$@{{FmAX*kH3)Vd88;B9dLL!&M-09c4?ot@>P0Knd znH)K3yxG;+%?-7V^0b<<*oJm|lA+pK9=pt&TdiJmvxDL*LZZ|tP9k|sM`&PJct|jl zPl7bHmArwrmzx(+L)QV)OhbEVEu_QA42r`^wKRLeA1Xk#`oP?%H9Um`e4Ks2{QU?% zCDgZy7%}RjOUFx8$>T(!OVi|7RQRm0PB(c{lh}ZP{Z}l&JK2rc47o+pWp5GzK#pFDa_)5dblelXbJ};7z290a{TN3R9W14S&UV-FNk(i_= z5^H&zZyfgIylw3gQrqgBq1C=X@HI(R&?!CUFp)Ph)2pWLa`5`J!#7v$ zO$JWG=*3T3B}PuiNtsN{1BZyJs*P-}yD?uBlo;^2?f)4|E8?G(#w{C)ZC*Bqf#}d%DKGc^;5m0aUvz=CUt(^FLxMb5fZZgpA0q%lk?|} zr{7al{KLCEU1KoFY~J5}UdB18rd_0m)W3koHUx zoR&0KFqeLq?1b{)$KsqnHkEMEeObmax%MH`&K9}7on4H;o_nEE*g4&qbVg7r(5^Xu ze5jg?HLDQb5O~}27L-!ZJX+RMoEf=!k!v2iLQjXC@NK@H<=Y+w;d)_kTN=&0ZE7Yu z7Jaqy>rB;zMW)x|NSRkhc^M;N{^5XF)B0C*tiM4cTE-~H%RJqS0TFQzv-vpzPcM_Y z-X0zr`j)s^a&{Zh*Z&69_i^n90nI)k&n4hKMgz9KA0~tHF@zCte+7}Be-Lz9990EP zM(1B_XnvB6&vjhZoD&XWPBb$GEiGS6x!bp4grtefHmFU?jnibkw{2w(h)E2qh9yE0;?XNXzIEw?-G(5q(W z;~rm8q4tZ_?59Z?3jxdLbLVmviY;sHVM9J{QK^%|hxjj5?xu5)UW%g4zTaiG$~N!% zcNfx6FnECor(+VG@I4H-j=TLDwW5?e{NJsvQ6vpdH{Fq(DvtTaR}mBh>4&yN(VQ*M z`qHw|^-?!PSr$cRZ(*IPQ~ZeT-lMB>4AALT8TR*SkZT^gy zeMFM@G8V4&9|qAsU3moPQ|j^v$(r+3*7ps*nJ;V*WwYT;#FsI>i&lJlOYF>Dk zRIU8BkjQ0CQFgfYG_BGWs&#YBWl1qM`NhGIR^G=-9hj7b@l=HAH) z2$XMHluQ`z{jctpCg4@lwa@aM z!KQOfdx#FQu-C7))2*sKY_A3&LBmU_ar5f<-2Rzxi!oNCx)?Tw%(ve^?&@qBs>6dE zHn@64j53=i$K`QmYRK!%ugn)Hazlx)pthRh;t848et&KF@#XWmx#D~yCMB&mQPAgM z+wJ)N*`o4m_8s4iIOi2N>)n?Q{nrf$|LF z$|?#40#cTB=?{FoqvvtFSz%94zuoR#G5p zK^qNLrr6VL)|XEdJ;87%N%N}(D0XM>4)0M8XK?LfQicloxIh6SFwoiT34)9uNf+(8 zIQypr`qb+iwur37@M{MN;P$fGoo}XYDf-LBl{bNIDCvV9F~dt|qXI>|R1LabRE&$Y zJm&ASZ8!rc@vei2xo&qasL!f1|K3R*z%IT>iadg6|POjl(=+Ve< zdrHjA-f*HNRN3xIVq*tY{c6!Zzz^Kbrk5 zjG@crQS@*?JQg26JNWam!PAP#j*(-zqEf;Yqt0N&=lmo{3AyfBy(W+60RGkN!-Oz& z>>C9(ZH6krm}I1a{*HY)El``j&#f^128-Y7=%WQz2?OClIXew*0fb}7MqOpn9 zc%dTnIGTsY?Ff?DrwrrL$uX*g3Kz(j2AuE-RINxX%AW$sNs0@YCqo4+#$*So!>mIY zR@~4mEQwLP7@@4H$*kodE)gA9Ls=CowV!8?L>P;ThVw-SJ^T`@6XSTeaoP63k(v?n zzGSs(Z=j{Ycy?6^+O$QqdH#*|YlN)9dM9Q4Y4=d-Oc_x%fpxjLqj)e7>cu;bd_#of@El2qk^d&>=6c=I$`* zuP;~?OBZP_-@K5VWY`&L`dLG@|0E_kyuD+M%)6eyuORPphckJC;K^|v5{H1)!Z@d| zlxJCP-7yLxsl-1>zg4*4#$b$ld}#88#u7a>Rm&?47Mi7GF$#xP-0$IGtR^~KZ|rnh z+dM9swLE@*i%N`}sb(Rp8TRItDP#VM&E z7j~Jb#0j7NP(FIr)2lK4Q6}k48)Y&nOgHELBC76+7h#zC0foU1?(v9}%m!RR0O`vr zZNQ-k(*q2o=!cI)wDD2EgYbe+=I5Vn1)PM~Gp^sO!g&hPTnJC-7@PF^3oC=kkl`)L z;AmCV{Oh^{?Ih>z_Tc9xJ&53D``i?r?u=8}Gi}$A{KdJQl*HkJd4GLOC@Hz!C)WOU zAxq&{*=BdBwp$v_{eIpyzG4n9;oZ!3Sc9>F%NJNzoga{}i@`dlQ(P>>e|=FzSf7v; zx2C5rowDyBJ`inzQAbT=bi5IN=(5>KLl<5xvs#$=O;jZ&<9 z6)f^j{O=2^=s()u4<+G7)`h?en>Rd<@yVeiK7H7qMBzVu=d~Tt2l5&E^IMZS++Dy$ zrnX&$kK>p=Yi@1&keR1zh8a>I+SxHMOvd!~(l}eraj@7`$A*St?cT!HCt3X|OmiA& zy~d&h(;zi0ZDgSl!=T7v`XZ`FM9+F(|b721~Ru-E*ZlG=IhEf-QhCZ+>zSRBzxF=5;-xRB>%<9Hj(Y0U`iJT z>$E>z=8d7}CdC#wVSFR*_tt|&6r;UcRc}*?sTmzUf=q1VLou%LgYHkV)bSB%AM3A# zs<|;$!K()O}JiP(#DCMY63HsQR>LHImhGmaSe(^%ODc=%*Q>9 zl8rHs-K%5XXUN3b4!Sux^^8pghYA4m|0eR&K4ZC>L{c8<%ZFXiUJVj{WaVlG_Qgw6 z8|2v&GRcpp?3Og8Pm(r=P=6Ki8y!K^0HzY}gl?Gy1O?}t8|$Z%oFAKPAz_UpX6Egv zpK{N-G&dbGa1;`8B?-zA&$+o|fv-yHCsP^!@;j-4278)?;SkSz1tOHC>}Yh9=2+|2 zxTz?R`AFh8slHl6RZ+EqG!j>bG+={Wpg>_AHO0nQ-CEA zKUB&8-wgbJ?7aVPA>`_x0vgL_a5ot+W-J+WVW2*B%P}b-@rOzJFFx{5)kFLqTwg`< zEXh3Ovc@k_;>Ao$xaiT+FExA&U-q`JXq4!S5^0@G>Qu_+jf7#d=#V1a;YaMDjbJSVwOykn?XZIqA+rYyVRVVp z%NcojyL2foGSJV)@(^Ip2^HTbKQlF=_6;6v!3u|PIvu|Aem-NOmR3?rOd_eOv{Fo^ z4J?knM`EH9s%i{7jK+C%(d;~*lQ*L`8oE5MlN6GeP|olmYi(IJM*BfFl+6R$)-NCb zovytWR4W7Hh-tW%H)L*LITG2WB42~{DDs8d0W*QY53YMp(Xq@_|wob zs`r7a0IsS(ZjQCgIUZukLQ=0eur}qBt=Y6Tj1dqNkX#pbi1p3zEd$}7U9kP_f;4vW z7S1*fZ=YAElv5M612`c+b3|$=S5om2)zzx@-bX__?l**N5bCEtZLj?(t1K2UKz)|M zI<^?jyTyv>Rj!}YYIXFNt1UrDc_Z-pdSCI5N1uM=w4)Spbi4f%=F``JHfon*Rg3Ma zc1yBVC&RFcFqv1ev868TQ~_NjMP+40O=>#&8Vhp;Bh)Wqv<}Yp_Rg-?_HIZ-45b+y z1L>8=hyAy(KJR5Nx+YvfQP+(J%yz4^&LQ|0kT`vLTu(vGtQpe3Uj;HQ25yhgd5Sr& zt!wF0$Tgm!EQMtP#eE+Hq9V#OaZ2vbJm2@s@csV1-QM%PJR~pjK5hMJ4GQ2&+Hh|^ z#DR6Cb3tLYt8p3B(OeqE7)^IxnagU(3WlFpn{24qd&k;4SM7M)IaK7!J|-4~ebF;j zIqp*Mf1Ce3T0!n|7|f8JiKahjG?Vsnc;27FdT5uED6y!hqe@FxZa(Ln{6lA@1a6Hk zEps`ia9H!~H^&C=rr*En{T>>WtYGKWB)(m>kV=O_0D@)C$o|@lJ zRDE-_T`7KbB+PHDv`#ICP^I1vk8c##VHf9>tkjY5oGTT!psch znOP{N40^Y@7?dXb>es(2w(a_*SJ5l|w2*#yV{4>yGNFP(UhVsS9>s+= z;sQyqLUTTLS!cRLx9QUGFhNJE*r>W7q*9npf1JTebccI)gQs?N95QiJy#)kWq+$4Z zdG)r-i+xIvHFJ0b&-*!8tVHST@ANMdf!miSN26-WH9_3Rb(O_VN;1~8B!>XC8Om3d z7SC0MAk#0*fIMM1tS(a!Jj*=y#(vLG+*+l>95tnN^*V4jz=6faut=D!d9pczclQBHuwM_#B;|chHSZUUt&IB7d zgMes(nCgW6P>(1C{_{;8@^f~AO3uB1_k%Ool?R;!IohdRru+{lp+Y!T&`AtM$xKrAlnVppJ4{d`0JTB>bDl)#euX?&^jYPYbJ6sGz(B@2MP&vJB_K(C> zxXnRo;oAWAnvX|i9LI_nD9Zh19iw247E7lQli6JJc=Wpw;``I6e@lK4&*n)M+i>s9 z;_r2(E|hAb4GPHtdfmw2!}XV-lQ?nnup|D9H|T#>C~qr1O+nnR(}%jM?Oyt((mKDC zmP)5!$$4J(OK^y_KkqB(Cj8*LyXXvDzRP@07HQeR$3L=iNbfW}%a+>2kLu)F9<+_> z<(E5q>%$*j-2JQ;bH@FP$bhbsp{Jp@_t_5G+ESA9;?>S<)~ZYwj$q|xPAGD)En>wp zflX_58hdcuRein@hrTXqg>(+USkBX5!qdV+YpLj%clIf=6j~+{eo>LTl)ZhOOg% zq97q_b)#9PYI%BzHa**KK z>GBkMH6J3Pp8`(Q!2OpoeI+bwj>1KKv_BAEMW1Nlf zQeQ!!z-043KaHC;V!Ifv^f{rTIP4R<*B=LwMVAqO-GQZejdBm^LmbRq{)N9pAPSpj<9h3QYB#=Qwv6*ULBz8F^w5y7j4?sR%QQNfJ$il?B)?>+#VtnB=9``@V8PzP zpM{J-|DZ3Jra9^qVX1-+9K|SzG-YP+2Meni=xC{{EX@@Tp;5^vXEw%1*Rd-m7^;CHPu0uWVAdOVh}UdCWJJ zvm|6Ly(+J$sI0j>l|P3m!Gb*l zDomP?I(dLahVjgHJv9g)Y`llDgc#)D=;ns>-IM;H+nFw@e`Y2koxD|4j&N4pTS|+9 zT@5By_J~or1i1ygXl7>Q>Feh{*J@oKv|4kyhKw(QT4IaY*!tz=F9Fn?0{`|+ge+-k z5|igys6bzkqe(z6w|9<6jL_*T@!;*=L-Sm4-vdeNov!adJG0zyNbzv9G?t@MBh;4I znn~uv$o|54Os#@eUKs2^)ouGNs^N+_+xm3TR!J*i8Ygw{p!IPecs*fuyqY|lr(Q{dX$DkRpbTw;tD}7~#TAaT97hO-vF{*65}!t)n9kgl7;r--3)R zEF&T%jT^^dqy5EAuH?4_FFgbPz(=gqBP+9GYocb|p{o;lapztF6+cTeh(i1%>(dyS z_}dRuEu?Hz8bxD^EvC4UZJObAS5(B^xDukZz9il0g6C0dCQ)FefOWYyz>D0!+wl50v8Mt2N}gG1yEV1-f$( zJaPk%O4Pyb;ZMcW(nZSU-&cz5S0G9iE*}3dHGKc1tjLN2Oak&Vd3#DfCKnk40~4A7 zH`nGo&`9CT)sZNttsG0r^!zBCiQL>=5;|H^o@%WOMqc0iC`2pQ`sb!Utn_sB2`UAK z5r#_gMpR7>&MtA#PnFJ0P)W(T-oO90+(J>*6v|q3yIs|uhvXv2`bt#w1oeJ%B|euk zlU~#e4(h2Ov^58DC<3V)x2Jo)uS~v|tYOi{SL#c7BRS z63aWygtW-X}L3el9x}ZDN(Z-vqkC6p0g+xVDX(G%%yR-K3!RlPd zm8cdK`Pq#oq5Wfx)O<@=>{}mGhKvp|^YbV4f1iS2n=9I?@~ko|`LvvMd*w3}1H3~# z$iC@eR0DZp*rOYJ8_ zIb&~bYg-a4ZIdeYq7~YxlXJyQLMCqVxnE-e?Sk8J!HI;sD{>QCeh zo7rx^PGXf=&-;ECC0)N?aj)tXd7hs!F1To@zuM-`Ar0?ja-Vtr+Ku}^u>eHkjUZI{ zUz_>!=4ZCPqHaYYo-t)6!$9s4UgrxzLje|*Y zfjxCD_h31_`nx>VYr$#S{5waJ#FUc3?4|d`tp)D;RdV*idS6Y4S5|_!f;ZH?&m!>-aUFJ@ z+H_NmHt{i))QYn^ytjtBubZz-O64&R1u6LYZt4&!h&%dpoJ0_+iY(M*@q~+rznYcT z=U(>R=^7CqY!?~E$I_*9vZWp{DKaykMQM!hYNu()&?_=~KW(FpVu(cxL=vuSyvLPq zb~Up{W8bd8p=cW2y*xZmx2zTaU8H}lqgsp8aK9S8|9bFmfcJiUffDK)#A4r+cBcE~ z#YTtN#GqMz39Kjv$CHd^?Oon{buizHw<@*f)8(pFpuAjH-o;$XIl;tq2w$_6Rbl~V zKdZ{X%gtNPFuIbiyFonf;jZ3vNwrzZJR4dA z6U8e9i$Qbkx-2vI-L>FIjER_w##8r)4Ai}{l(!86pA+vN<%`jhc%mker#wO=7&RXD zw*mHMyZSp8*pae+uWxy@GD{2Zt6Zbw$mdeRa$_gQC5UI-_TSm4YT5;Y6+D{oiQ=Rd zs_U(k-Tb~{JI46D4PScGZtunBL^&Vwrt8!GxV?o6ZMfOdeK4Mlx??iG&Yeyp3606> zNKRBzoQ?AS1UWm?P2xV&j&@(8!LotS0q0uIX&z8qzNE+ZvQupEGJx=@iv5k(o|X-* ztfEO@vo$uY?X7GO!^?a|_H5M&6YW7#xk>`p$;I#J@OHL?F75O&O<6@_aS}hA*Lz>m zP!>zmP@I1}K2q)h6g+xqcofn#2Z9UwyW5x3z12sWk6iUVZA)6G-84xDLQ`srtcmFU z0VC%n%PRe0TTD*&oC)5J_D9EYK`+({)1*(k1vzkuk>574f>Zo zoZozr=|^TLBVSDp&RPn0ugI&)ZlBJ%M`Iiy&i(9cM{}m@%F3vc=(q~@XYL7h?dd4& zo^Dz{cOrlFKVf0&Sv)$a8$FmM$lkRbH+K1RLS$Y;P};KFpVJ#TI^SoleE*9t7z4xW zK3BpirADv8Jb>G?fDM9CMeo_?;G7+_lfC>sEzyaW>uI+!3K`V5$dAJD5S7#R6c?%{ zbKhWb?jbO|Kaj(7v*@3YVz-yLNF$?M9qlzVCsLutIfrOF3hT2mT*JrXNkb;GP{~|Q z|9W9C;af2*=ku~g>{sE6#wepQ(0`Lrf|wO8W+Rm_!@ox&uwUtWGd-^pkSi*!n~mjm zci~@fP)(i|8K365l(-yrcLL4lHMhrv3DJz8frT>?VYO#KFDPrKV3QKE&E;|n)THo? z&u9o^EmdtxAq#oECb+n$-H!)p!K6V}XwJR*!-XAMCLq3VHZ{Ms%#XR=z=q?FmSiNl z>^1xPXlZf=;&|_+-0ylAg^&EMe~G#&G}7BwL$>i-XIt$3afs|7!Fe}t#qHanE7t6E zjk!Z-r~zDWH4Z-T^W|ov-+8>>aQ6-=xsWA8P(sstdW%l!imoaY|ItqI6rpY$SfBTU z{rZLByf6hPSdRxKT$@0-3L$#Aq|0k({G47b_a`q3M38erd0jr?^BlWG^LHBFrN`}f z{)&mDWpRJK%~ui?vfBGh7B_ea4L#joaoI2TYL7{ft9p7_2UOoDu|=>8-(GKl;l)%G zZDG4dq(ZXD>8RRY9^k1}7pZmL51=r2jA0Ynk#HZHw(FWLV`tG9s4s_#Jtj;Yn@TE9 z1QTplrC|I<)sQ7^Tc@LU14E)zt#jHK8%hSvp`Iuc-^tWe{yUEX`Sf0Z95;l!1S&o?s zhdRPh)-S`Ex$0*8URRrSAV!8%;U7FXL}NK59Qevc*syUuW@*Zv>pXr{ukm*U!gg|$ zVdpP_{kd^%s#vL(cCUAD8}Mj)+e{X+91=QuF|Z;dmo;$Z&}=cQ`_Jm%?YF+og1Wkv z-_9o0Dkz((ZMQg-SlFdi-47StYWhrmJWt$Fn0mN5K|#%6lzCjHxNSTfId`JFTn9FkJW-| zR9d>FY|FV%q}oM=endiy_j)wx;W$Y+ZnmXVKcZMc^;cZ7=k{>`Y{Al5WB=QNG)t;M zsmxl}bz@fOESk2NTvr(Xr$A%jyK368)|Z3OvVPC*=E;dGbD9tcqL$}lXx%1|L=_2a z`>XbHR8uELq32V$-KP6}2@RStj#_iA_&2y_X%U67^K+eOsT%j^TZ;XMJZj-Tb45&D zC+;qb{fYsN8P6>ihHU+X*0ht8zh4HQ(@Z=!Ffz; zykW4Lk5u8%Ir<*QwOhtdk-Ps^YpE|Lq$8u)Uqn38f?YRuIIN-#H|twtQnwP(m6SYt z%;A-X=J}BweTBNyt2D6CBh}UMzOP2%q^wO5n@hFj%~fn$nYf?z>;OewTy@^w;@Qr; zsa+*A5^v?@X8V33ZVA!9FmC2un`#o`v|rH-2O&~4j-BxM84?4bdstjjoF)8nq8k6Z zQPm!_Yku+BKNI#kL5hl6!tHvn5B=;z~T9(?|sRr3A*Y8<*2<=a*~LetDpO+ z=kJs8MYajJT7z#A?hOIym@h?vVJjI;UqS_YSE*TAepcuEV{rxc7Z$`A-oW9J4l-@o z1~8ZG)a=iXUo@E@M?611fxOitQri3mRP>rS5v)FD@ ztnzUuYKI=hEID2P^U`@cOQnRcN8$`)V?$iey?e{xHiqa>5i=Qk? zW{wB~Lud6`VeJ-lby{PijYMj&>41TgKeRrp`)A_UUe=>eGn5P~>(IJ_A>ICWZZcwf zAJgiqv}LLdzb!}vfz3;KJdZV$4*htZMPG-%eUDPFxJ>LN+>%MZ*@L-DL+Z>)E~O{B2?$ReB{3B^u&lm;RhT0z1xDmN%4grDe^`*?ka_o zrZ2sBs`&vC|DsCdj501Ob%?58@(;c*yY%|^c(UTpE+vAjY<`kO+VI()-sw$}72r80 zBA95@d2RY|^aP6)Xo_|Eme)$m+N8O3QJX9Brk#@)GG&_byssa!Xf%k{SX7B~zfDJg zF(pXfuDF-daVLCtyGJpyS%!D`<5TnE%-bMYt-!8Un6rF4Chf)>J%-bK3PSC`Fy!)X z!|>Pm)KygT;#pKXT*)u9vPn=4E4WT$yeL)xcQgk37u&mmekh{938#7gR&Rn_>KH8| zD=JZiMTM5-7M2=nSH5#3>dSl=Q>dvbt zJ6>Hw_1Y|>mY)|JiQK09($2u8ODK6iEK|j3V-H$f^`4)%CF_;USZL8OPrP3A^neu- ztloF$*s4(9q{`~*DW%PPBvA{^Z8^Y;kzX zR9VU&#R*#Ej5(o9UkGkB@9yat!cK9}Q=_sT4!Tvt2)u%fQ^fA}7C>keMoL$1h(Rm0 z%dSRhU3b@qefeCRhUq?gHHi5AZOmn=N=-oYJG-G9>t3vg zHqUuUB&>ek4i1Fa7N*a<7ea!;xWE-(pD(sPj5u^R$ef%~nLQY`-UrXGCG`C!$pr$= z@Uz;UF34B4RVjX(OuI7xq}G;1s^xRMDrP4%X@U6>STL9jfxE{JC!NtP$2FD(-)HV+F7Sm{_K9uH;KP% zOJyhPhNd_aQ_%^WH|13~UMXp)Mr7nTu1^P`#fbEf@1~mBsWt6Q zxg3+`>kpm{f2pk}`qeitY1?QlQzeg;v>JA4=Us)e4Y`xaa!VS&l_11@!p%tT``PZ3 zP33GG0AI(lGwXATBC#2PbC*y4sdw=KgcvKKO*a$i@ ze_`(Eaz-|-3FW7Q$o#r+gTJsYeN8y?d!9_i-F36rQ_;Zi_1)`4Dr8#qT4!IB)Epac z?!4+*h4blyPhWD|V19Rd07CRD@+FcT-b!pndrssjzI`=&bhBwIDxGZSm=2b6(Y%+! zsgz|)y}P;-cO#m&oks+wm-}k4@1-@<>NK@Lw!f|zHD1PNhk5?TNUA5f>t#JWC;)p6 zwskSzjhCrcYphU1){}^W|Sua*)a6jN9NP?Vfuwl&fv#a`N8wblJQlM0)Xzx>nljj!^dD5%fY)|KlCgO7#na>`T>@QG{jE;zUd3$M{KG?8 zC)4>F2BMt(uHvw3MQ4Y~OaR7NxzsuRZL{H&Ft1b2+s)tGfOK?^1lsE!hMFqOou6*< zn!l{ip1HQZwiTIc#g#XAst4LN;{3L-v)0s5=@1OnM%3A_RuMoZj}u1ooLqex*SIG6 zGP_`s_4s1Y{wpDC;nlrju01KHjO=tVy3}HODP-fmhuv>;NGzUk#Q}=X!!fxAEz*?J z;drAEwx5tKm1$VXZ}s~mLC3;33G49pxo3Q@y@K<5JZ>*CB33cYX~MyrET6Bp%WB1* zu;HYOWOlF4f35j85+4<%1$CoeV&vX=!|z)e6FcdQmeXSOqQqzrp1AUj7jHLT-qwt@ zY&X4%i~G9n29k%VbYp+KKkXOs5?^mbx^}~5Z^$N^{6AEEQ*>rgw`^?NM#t&cww;dE zv2EK)$F_|xb~?5@{9@bA%^COn=bk(2b-(Pr)*5T>nl-EJ-v#tNHR*=m#sg|`CK$h7 zr!x4o)J+{Vv=snzv^Fn?*ejut&^H}R_FnG3sN|~(o6qy5rbeUG!dKW7XMLfH0v;#Z zn3m4A;w8(5Lac{#Z^0@iK}`Gaj%5?<9XMga+nz-+k!YF`t@$$cqB`p~ zc&;xmdAvnCB|%L3y_@O@%Y0r*b31ZYC8HBOUqlNgf~j)!v{}C3z^+#ZsBZ_wBI^sd zs7K+Y!`ZI?rBD?e=;3b|Vu%Sa*Wc)I74TvKSl8oO=Kt_M%&Ourl2s*O;+!GLKF+qt`l}@WE3KxM_WM@k2KpN#AJ2s7c^|sg&!0Z}IH2aFo(Uk=3>~wv(#X>+b8qa@2y41EmKh7hG+r6jcE)@q#GM&sNH!dX%TO z5@E(Da35@-_qgy-6$a&KUD=)wjZ+ zyhw7?{M}b_ZZ(;LpBdN&t2j$rtD%cNzws5-HQu*wvXlJvJbtH^QDy-J+iiE=%r&4^TQH0I+7)fcH4bcFsU&K9oHe_o z=j3wV2bRk;<(+mjIH|sm)T+bR0l8-MsTCcaIu{K5Z~JD{`e@1ei_EF`X-QGtw&dS| zzO&hq%YP*d#;Yo7s!zEEYqOGr`NXRlrr%#g181v6y$PCAHS`TqUGF3`SZC}XMQ7}~ zXMmNqE>nvhbgy;)3MDdu!$Tr3h;DuO;vF?#*@%k!2lz}F9L}*2%?42O4XxP{t0f=Q3$)thxo4cckGpvL z^1BBi=qL}z90diHHX}QWw60fN!LPQ}_G}S3{6W>40(YZ9unHpCJQ?=HTyF*Jn#j82 z6~ol{r!F2Z_-anRU`7aaC0QJT%<%01k2&|O2EUv1-dgNs%XE`Vf42oIHYUirOR`?^ zr-g}&0^#HQ(SRgT+cO0 z4|!MwMKreqt@^Uu&96?&_2{#NEc>uM!Mnt?(BaBkLg*wqHD8F%EcoLd$f-6x zayu&-9t_**+c^f0R5WKv^l_(`CPqHjgC>JKMLst&&kG1nS?`v0ugZ}`ZRdA7#=gKOeu!ircr*#UqQ^~? zW}vR2Ub0xIZ)PHX-oHR|Adm5+uGoD)@EU1L&Z^ssi`@N#O=H51piRB@INaz;RxNJy z52d|zDvexIC0SFYZ7h9QVl_2i{mWQNA`zMMI@x2+!*xen(#lC%#wt`&Us&y&%> z^e*i`PlGdEU9MVhSg^WvkrNx)o|&hWOfyu3f*H+bh2e4NJyBuC`MN{mxcy6ms*|(gpx}uc5k2T%Rc9RhE}>W{*DLa z`8_To*k`R{W^X0FzVKrp&w$BCm^mkOu5l8wz{}I0w0icbonY5WVd81`{b5%n?6j|u zPo4b5zHaTW4cOgUl%v30*3EXK``J_~UScDRzADZL>c=5Qcp3e)ko&l_yQN3ECPtre z62_r<^;^VnZ4IvCcj24`+to_&SkjCEO==Z)(p;{%#bPhMTGYoRz}fe)Of7|qGL@!i zmb^&E_JWQ)RzXxDqLS=RLjpAX+$eWdhUA(`;4yH7wkC0)X{YF~>r0xkQ>MCDYrFOA zz-}#d8>AMC>FOFL-jj9*L!{ifON%3-D2c)lG$_guR{qCWO)o(8!il%#7lhc&6@SYOAK#b zeA)};o5GyHNdTWMum6|RL$lE>vZ zWr0PzOqy*((6y=TNYV7cee$njvwHr#6<89Vp-h_NEJE;B*mRz|TR@>1<&t@SR0X4j zfROp+@AXkrWr4Y|gDHlb6(~N^s9~n;6Uto|8X?2=^~gC3csmDYTL8(byzen&T8TuW zeLZGbTKB`~7E~7z;_xoGj8UMy4LU>Y$&#HBR1K6Z?t}xepzTifPsaDhcu>Qr#c0QQ zDoX2f--+QOJ%^4I#Hh{Yl%@|Pid1P;Rha{4z8YyZJbg;`6fNnD7qYO{91w$0;q5r@ zXWLd&Jn#(j*x|C*aZ{@{Pxg`y^+7oO4!5v0(^g?JFs9!pjS-s-kgknAb5M?<6dAYM zchk`iWIz;rJ80Lg+x!$QE;-f*;bK-Ll){B)DgUZkiI^Xa4Tnk<6q!%I_csCZL&JN2 zDADNfQsy@g|-4o}rkRx_Q4D=|Zf;~R6Ef2~2fa{;?@fbDIn8IG21 zn%C96_PpRfBT~i?z_xv#!(0pMOO;XzuWCn>#Kde@Us<5dN|yTyr89qCYw2FgD51Cx z!eWU1ho7ZWa!&fN`9Y!`mxF#{YMc9SAr&mp(w0Gtmoy#0mI11CG$NL%(%uw;NtdM` z^WtMU1=R~@3mennx|EHYzoyyKFQ5GA5lZ4Gtj!E}*4ATeM5oh*gt4{)skW$!s*XV( zp*Ppgq#u08C?&J;LiRfvBdt@%rrAnl6KUuO~azyl`M z|338U*aSSg6J(GUcJy#9O2upI*yV}gXR$XOR+iMR^Dj?XNx zw+6`p#RC*IiEk!lOX~A((;aXAP%Q4rxupRkS}b+BW!df6cZvYhdTfe8(^`HYKndAR zaV4NH+T%7Uf|~b_{gpi#ua}oo1%GA<2PDrx0n$R$`8y8)Y40c73ui6I(_Dbz>8xQ; zC?tS^NSOppS!z=j6csz64+Un9Q?+AfpciCa)UxoO`@D<6;`ri9>H#KT98;!5ro^gZ zyc5e;daatH#e9}h|I7TfFbM5lk2llbqMov;6Ff8sy+%}2_t%KiSrq*E5|4lLb;TFk z#>;{;*wuV}az65W^BQ=sr6At@f zb3%fltcE?itw^vQmt^DIyr~)m81E7VH)Q@+=epm`m|9krLCw5ji!kZ*xjqo9&=cw< zLQAta_~!b2lV7RVj?RVVb*x?;N5ZyW4YBd+1w(?ju1 zSfAWsgL+2tjNPlPIbC>DS2Z&$GuwIREr-6=W5h&t6GBSO#MDl>M#f~9nGLdaR}GTT zPen&R6KgVpUX_tS!?GD768INZ-yFWS^z!Yvdw7z2ff_=y81Bb^v;b}YS~R8cBM$=J z1o36zWVM&H3uU?1xTBX?!3#|-BA}Ug0EJa4#Kox|%n;5Z6i7`48mR{JkWD0?v!Ov= zB?aE01R{+&!mxa#c=wlEeJ$*62t6Q(-R@1S`dgiALh#+q^$-j>WiQas+6|q&Q*D#W z{lbhJYVp$B-b=?#T2{c|WegTp+|-T-#7i3CGr0p1dy{7BcFAf(;DYAKq(s?_ik z3!>5X9_Dl1X4#53;R_48+QcI9?4#FtLDn)escN?Ruwg5b*Hbi;O_gK8Or=+_DD^op z+g<=D>($NZ~e9VY5(H#pdY+NQ5kAbY%N{t!6Qma&PU7DKu+XYSQ zNV0+1T=X#xw1h`}*hS=k323?qf$Cy zBeR-Ad{J!$fH7LB?`_(;c?yvvfbn9zXjGkUFog_R#lnsM40K&@m+(#O16I5Alc zLF=me-fCZ3kcaPEGY75)MiVFZCyLZX6*x*j%Y(}I5}wqMWymX6S3*TaVUC$xWFTWp zm=KKf_ycbo!je$jP`Ohq^yTr65%AnT z!=F251PVN{<3>0Q4D^O!>S^5Bff=~g*9^7s1i3OrNnzc*`IsSmpZk8dQ@*XB@)&0}2IrY~XgqRw2hM=7X{+#=#TPF9)2+r8!@7qmx@hn-kO| zY_wh?Vq)dJMa!SFe#49Jj5t|VjTtGS{Up%=hGv!$B?&k2k7#23^y3P_ShSi<3fmmQ=eLSg^;u?%Cv#z zt#*UL=2nrv$ij~z3JOrW;GycP^>miDmO-a~oId{je)z@Hkc+~_ra*68Vy=Wky~d=A z)CQM)m%rDjggt3maCo#>xQ>TMW!69l29>JS8knU7iuh&rF=Nm zW}RUA&=MfCKa&#>5K73>WA0^SK})XRk8YSYRv%-5f#BBK!G5#-#x42!D0ZK)oL@r$ zx>giW$*YWd{#Wz?9*#V@i^PPqE-Y>R(9Vld~P2bmT~u_YR93l z>3og;s{kb*9#m~L&3^g3lWj*V?0NdZZIRSeS2eZQaxD>}X%9I%HP2rZjX<;)EPMY4 zrvpV~?Yga=L^i}d!!3fz!sxf4=|$tQ0lKwp6mcoLwDCnoJm>F=S-E~p6dQ8J2I$&evULAm!b3c)6z4o%9i8BrE9 zyj1&CUyRVw134a*$Cg_}aenxI0qA%CaPt?ctD+_+HU$t4UTF^#Dmk{=`y|r8_iGL} zNSbWW_BAubu?)SckG!s4oNWXiI=Yg-DCY!?qaWNDcw(A&d;(hwH`{M-Q91nBobzg{0SYmL?bx?GV+wL0lX_6-&megeS_zT^$?H^zPVdz2T}D6cS@jo9N}&>6WO^D%#N zjiQLGLFPBPHl_}b`vXa1w%!Ndz3hb1%Mzp%Sxq)^bGOXIkeP76yUj)4FL22+@f{;* z`G=TWgnYmjXt>7FgQiZ1b!I7jiy6aDB}7qKtdN*I?X4|M4nwa5US5y8@h~UWmWS8o z8Ae;*wpf2WTYiORPj5wO`%89}bY6LYfZuaQAgV2aFV=~B$Ao+BEELZ1gDEwWchkS> z!8BX-d9QA+PkK-^A0TogH&(4Br}ifW<;c4>&7;Ij@)zaZ!XP=3UAw<~wDP_A;h9f~ zA6X+al%OcV?Hn%k}%B3+CT>ZNt;)fRP}DEH(KE@bEqB?)=Md+Vp4LrCP zo`;NK(;PQ`;a%6JK@X7~XBUM3^%+7UM&8Tm89FTBcWSrVrmBi12266!(*Erv zqxh%iZy{lG;3R<+XEI`UD9-1u zfQ$dEf*~Sj%HROiFJ;&;8yA7pr2jSZ$c5~@Ic5wHk)7i?MN`y$C{c@roGlKcmVqv>TWtQ!z}c1D7iy&-IGpsf^{$L*K8-CeNZI9fOVHKio~PUK zRc|lGEXU7)2h=QF9f7r$r70U!+9G|Y|?MLF?-Ri1ku~~Agj$z5FN%qyPlS|kTpZn7p|vHEGbcpHx@Su-RAc^Ay?JwCln>&gEo@#F1K1tk3OMe z!5kQHAL4%>MTS9w!aB7l07T1jB!Ym#LC-2Z3fUSt+C_rO?0j8$(BsXyEiVQ-Ml!xbbhtZY8(;e1QtIho@QPAh;&?aa+YJ(KSS*=oz#TjUWJEFtGP(E(XafbtXl(lMY zwt(M$YbWJJKvZ^;TvCe4D(Nh&Q}~Ze*2Zz(emWzPBiedF*GT~}U3H|-5ACU?SQ^+D2A>Sm z4cX3?YHuFKz6Q>PSSUGL+VMBp;5Wa|s^3;9}Ge<~7rSE;NXj-id?d~J?+Cp{Rs z+h4|qrve+>;C#)9jFgm}e9U=ahDCWx(3ol_NHu+`%ntPpBzw`$wDUNTe4QVp94tsV~H&YGS0gvcVla9+iLHp z-r)j1ChMu3PaBoHvXTKpncn9Ynw+(tBZA0fP94qHLDzh#^!IcjFy6S=T;O@>kqIF( zT26QOAM;d32I7E-B#)ilobU?B9E#E7sykEmppE)|dzFx!NKnp`NlzG>#X7B6h;YHR zc3V0rrPT^+$ygzmhzS_3w*fWEt$zrG3lB2{!c<*R`_P{9C|%8pH=;_%G*tgWM}#!s zRAlGdqjA-1K8E9E789T{Ew<^j3X({+*8?tK2UVAx0q#4}GbKh*h6Y+T5a+Uo0({;- z+l#g6rg=9QpZs4vR$3T3d%BgkNaq^lq0uS+S^cGOCeH26Msfsu)6b<BUUCiN-f2h-HRVaXWx-jxIav;Kje99<=tisr6Pz(uekR9{(0$iL*=Q z8U+tjg!z%bSO}Ox1M7(xEN~b`aX*UPft`Yqh|+^P*B@#Qp%4>r1*d=eB0E-pQK#q< zv8t1GJ>mb^?t4~iUz^e*lFlaGZ%^FyIiKm;=_glhwc?eAda{f~pU&SGxE|L-NyA6S zjK?8>AKA$C<;Pjq(qykBx*T5Zd=!8aa(s#ogN&|oy@ko))K`1ytym$BSdn&#Elg3{ z6NO@qH>ox?1zu-m%e-Exf_{hBK`}1aLD$|}*FcDBBU0pBBln{#Sypp?0zgEHLc)Ky zF%*shnTE^v^KTd^4YgJvy2!W3fb?{Vs=IR~Z*%`xj{}hil4X_z2+}DIy$unJ!deQn zILfjU4oCk9B@cnqD4)lWX_{?+Aw7`NRIM-~BMq3V{>o)0;O4omx@KEB5_DkbI3!T^!qJF2_dCJ6_r4@JuKfp}l zy-zmsd7lIYVfLblfqpgU6*J#?ok&f>Wn%cXDpKzqB?JxCP?zWH2c$-I57&VgFJ-&D z4&Tes;%l{cc+bm_E(_i0ShhmHs8Ur+Wih!yF2ku1J+%OOTpij#2aE10Nst%Wba2~jjVJFeC$&N&SI2fWko@J z=caqz%T@bc=hEt2EW;U=KH+j;wkj}t%v!ac982!W9BJoyX?-=I7vhXYHZMx5y8Ux| za$kX{k%jQYk2#gr`iiOJM%bWGIF4lxK|84Rm8Q z8j7H}uy@{(Ct}$n*!>7$N%FFWq4B>k13E7L4yV-eH<{fwhbQN+fBy~|d{~tFP^~Rw z3QH8fzg9Z~2_ot+=esoMvk-}x;@<%!j_pI_dh$!I4;&CB6_iy>h=G1_E;6voNqKq% z8NYlfceb&CbNdr}LIrqo+!fRUg1KwO%@LkncE?JW!XL##lO?P(zgPIBUQf=zODoN( zy!w0S)h5sHype`A;bZvHg44l$Bww?TUBv<}u_cGn4CuLQK&DfWqDtg zhT#60fxJ=AzIj40bry_1rJyrpleU4Bge7^g3k<0pfP)T@1WKEWer_f~$CYr1+Cj@e zi>>X71gS39cly8mh`Rw%T&cDoeV0J`9Tw1v8fwV?k|CZ5tDcsGYXaI^f+m zt)p-{Ru@;oHu_CLvU5Tp;)*=N-8Av&{ZsRJSYiF75Kcgc$QMqozvBHG7>dCHo%Z6f zi4M(}6{bf$rxIjmqA0lay7^vTzyQ2?c>6D*fBr_Qp9j8z!<-ZSZ0BDPR-iL%J96j>YVTSbx9Vt}SFl z%MeK2IR-D`sh#oe6#Yn4_{{lO_iW7MeQxW#kuu3-w@F8fNi0Smqk)7Ss$-njzZ!p+ z#5zdTyC!nOefbP=g;94?|Nwp)lG zBT7Ut!pF)EEDHY41q1@(Z&Mq>JOL%fFc<)4+JbkHTPB06B03E@co()JG~qedlU{${ zbEBMO!UhYsa!l0;bA4pY<_N>ny}ijoOs8?9X+E`Bd=?)fmzTw$aD$Y zE-m-8vYtRj%GrZ#CA#GR2H}oPs}?}t@C25Eo+u%ry&dRJFSa1E!rNPIQnB&daD2bt zM+}AS=)bbUo?m0Ko>Z$NK_3y&D3VTW=)0cY3W}t&IV#NB*jn4P=19l07?B6FQEiN| zreWoObY{Cd0^L)^Zn~u0W!tJkryy4zzdXwH3!y#`dnoVG&tKlr9JpN{2u#3=sY~Kf zD%G-(`ki(QUzA}>j^^XeUvg_tvr*3xEUGBpUt?5(M6#8bO#{o*Z~(LTTc0c}?xo!XR1Fl$yUweLRLUedfnwx3ORA~x)a@NZngJQJ4& zJWH9}vsy)UV7WHL?H-MJluew=zkn$X1Tnp#&;ktKe6NnqKfi66*9PPkQ$6^*7L#)A zi6;0qDpb`0SnSKx=rIf3IHCvIb!)?3M|tQ~sG!ZqX;cITv@zGuXnYl`r)>F-mmz$} zmEd>X>KN&HBn4#+g__aPHUDYBmYQ4;&zp`4I<~)6>ypww$9BYnm_e53Ynm&mcgTA3 z{I6HGH2tIkNc4Z&+S$mv+hQ$Fc&+!AF^#YcYmtDMW3Go$Lus;W_TP$S3&~G_p}iz4 zc}jf=8Ff>+_>fy(huf5mCKZpWD7^mT>1)uk?@^M1|E^)&g5w`4Ql6nhR*wX&V=A@eZis=4Na>J##yI0)&e8u@y~4^Et^>oS({wVNMS%iy zfgdaTY+^k!i-_k(U(rv|`6mLOi&NS2nO_|p0~L&Kv>3OD*-z{Bxe>AWiq9=6;L%A& zwKzC0G!OO4SRVdklQcIdJd|N*1&N5ly%yNTHEN8Y_>{HfakP=gZ z!af@%V=O7yYbh^&6c~-{|F$37OxK@}8&pe0{H00Ufm0j#sPGS1>x}#(IMDBAQi@7mBIjJ2qvxqZT zi|^@6OY%!0os*g@#hL%;Sn^731OB0zC0Pir_Wj)p5bK{%Mp9DW{`|Tlnq2!(M-Rtw zakj09H>{JVV@-h=#UrX&vLDRy3$4(;Bba_%ie&kcxn)0TKQ0NdK4e zmfy3}IKcih#UG#O!3;z}*v&Gn0l0`$^$acUOO~W-0-C+?8ggDl+^hEq(ifuu4-e>gas7Lpjh-nOJzNx>O4(7F?>!R z#>(P-X`^jzgoYi72>7MOoskUQ=UJ7RF=6HR0WU-HV1Ug<6zU{YAoVpwV?;J9FH6ax z)AHC?mu3pesi`eR@b5roT{R7XKq5U$arqKXe{P!}+P#*_5e$07bY2rMhd=2!0zUs@ z6K`#N7h-y|dEDX~O6jWOWu7DAIusO`@$Vg1r3i&AO3LVQgk(pZAq;*u8L)BPM*I(t zH9As;;*7wy%0hW3#+`HQugNyl<1-sO66;WRGsozt1ESW~gM+!aO!~Qw3#dG0-NT-? z6zYKwrxW4nRVH_R!PD(?3zK0Xbb7a&Q(C$+9(6VNwDgy{F0jB9tqw*H6tLHA>L=)h zbGrV8vJc*W>o3UK9)F*SM42~Sy)pl zBLr}Lj7jfdUPC0KIlCzCMX|TIz(1cR3wo=DYwX}yUUE2X_n}-GXJB^Q=^*4?8EL;a zFV<{c(txjMQTTBaSxb(7byfNXgUYGNQSlEcH<8smoY#WI{Zu1xQI+Iw zWi*f7BdjV9Ulh@3khDbJnmm8Pav%1F>TxTvNu#IbE;QrPLYsLT&Hgt&&hBs@9fp%M zb!$&)=E5Q)XQLB*l(*YmttR%fYZ+MhCX@P)EMZ4@Dx`mVRj2{5VDu4zQ`wmjka$x( zc)<{~t01t;`Dj8v8th;}(oUg5BYlN7f_^F1#I{D{Hw1-qy2IvhaL#MNGr5}Uc|s2j zlN&F`pzuoF$uqk>HkOT&kR{jG6jW9>cXdS8vAM;1z7FMdYIsSXW_Cc-xT;SzCy4hw zz!;?dR-I8ImW|RbP>JHrJhQ5_&f-;f!JkR6oZz_HxOGXO+z&sUt85Hb9pY@h$z(RS zBFQXQ*Ia#_z7A6h(b=4(JhiE&t+FVFWXj&}Cv#B)FD<`D-y|jKp3Vnp#yw8KL4GD% zK90P^z}UBt3rIoh!%(;2*99#!zv$W%XU0msO!;Qe*H8G9&F_$dLuxU(N zv3yCYnr64wevq-f<+9C{-PT?y9ofifZ_I?=9fD${N{MWKNWfyN5EA{9M=z|57Yc%F z*0H`qgmHff+`WdSQuV$`r)7q$cw?$EiEC=LjcYN=C_*wM7PDs4mR!$Jl6^KAgv}`| z=d1XoAt6-j?M!^Qsy0nzH!qhC!h~AUTeMw@78St0oSc@b&gmL(v>h^p5Bvw1*O{B0 z45zkmg=esshHzKSEG((i8gqilWbqF=M~#&Gj}`!*BJ|wUue=wpV3A&D2A0)4gzFfX zCRaT8o|9~4Y7}DPF#^Tamp>4EEDRclK=#}tT+KX-uu%s_K*158-Ff;zh+pb0k}DJo z6|3i?C+8p&s$GKu;9ODH9Au#B!(I0Zo6-F|jl(t*wxW<17lN5(cSXqMp+?(H2!4&E zstxQ}mVhbFR*B$gi*-euO}Id7*be377|Iw!;jyqZ3qjXTv)MTvP>Uq>&8v>q(bUpc z-lPwy`!wgc`h_inS#kUr=*UX?h*KZJ>2_PssTR=5zyELnnRJK&uo#Tv%)L|Rbbj%% z)01yf-lhjh`lr8H%@R25Ow|_K{B2*!>&YI=(hd?Wv}%Km+i<>eUC8g)bwwz-{zagdk`*qc<5_3o>vEHAf1ORy!+ z-Rkny!_liQT?LKVL4iXhk^H-HibXldXn4B;OH_)74x{J}1LF|XPDj~Qp_6smfjL$G z6qR}Ro_c|A=J9ZBUkgf%OIFWuUGixR_1>?hxxSd&Qw$RD@BqmB7)hGA zii-yq0M8@0QjZmsJugy-pA49a0nPOk(YD zr5oSG_nc2ip8LP#_PN~B7{Pl;-c!QGZnW4JrowGb&VVF{vA@|=6-;zAjC$EtGb9OqBO2)R#UyGs;P0R+IPM_@isIPEBx?c%FpDFdKs{u6M|=F5p$BZIqo` zE&dkOnzA|t_vEehAa)l*&xi)g54Wgg&jQcorda3O^XMBP4CzMprgAaUKJm(%M! z^(6=)virJ@sFh+Zn^BZvEwzkE$<6$0Ph>O{jfo5>WiiywPE!2^nO+H^Dw+2k(ndu- zJdL}U*j3a)!rR)MI+2F1G^_NJK?oR38&?XV>;~wYswQEXwD>a|)%d4z4T*honUiH6 zh~#g6be@KEl#t8gb08SqO+U99EclvKloZEJNkD|4Zpi;awT-@-YK7$SI*c8-MGpsP{VcZsJLC-cX_jL*gF?&h7r+A7hUyqnP8%u-B zJse!1`lvAGgA1d5-So^fO~nD68k8J<-E0KNFY~1`RzQ6L33*d~WreJCX$CK3$Y63b z)yR=y;g57&?h*hWsTZ)bz))ML77?jy_@~Ie?d9N7#%ab|fhE}+U_;5dEU?erh z5aJv%1j6dy0&7&h6=;C!!h8uRH3flwy=b6ndWMz~EO9VJW(F%<+!V_8F(y2QUS^uk zuhm&vwV*=6t{~Bm^SOLoFY7a=a_q3?-7-y$F88Fi{WDSCqgRU&6MQ+L zPO&-VoU9C0-32l=Ykl;Be!JA`*s6U@ez|ely>Xn}hJ`_rx~T}D>Y5n)2%h>;;j5|& z&T?+~=cJ`C@ltT*8G};vsneeY_)1~5u=S9PL_4#1G-(M2D@IXFT_CN}pJTJf>uIs> z?|h<1ke=kA;l`jK76n=FGNrHtgcBP&Xia-TMTcr%3NP?c!P}EO!yQ-^WM3Z&Kqy9= z*W0N@y{^|4ve=f>Q+G+#Q|UPM$J61CD=1dxyMH`A>@tcdh^S#Usu09UuOCvJFc&bT zj-PmMF-I2n0{xMB^UGtY!yX+X@vEoa-{fz;63N~qjs%hD_L!KEzT@tLtG(U;(`u9b z8@)aJrX1tmG|N8u*G>t0UWs-s@NQ~Cb)&->5a(U@3tABgZ13wKx-0=Qv~^}{mqLc% zoTe!_d&(#hZ7M<~&;Mp5I@BloA)9-yrFm|ulaIU4DBBR`{fabzlLTI7mr0kgm%6@@ zY6jl9HE2mzjLO3LN1M~JihkC(&uI)S5|zo*)f+GvE$P`G95iYo#{4K(Va@+a`;fIj zq14U)lrOB3|80JXpkOFj^V{h9BSSjplhftRJ;CXnfiFAos}K-F8-c*5naQAS zOunS>l|-t}Hk;P<-0aFJ{wt^&@jQ)xic#)EdG;m~`pvVJi03>{3!`t8>7e01{ShcN z&h+KflFk2A65I4))10*R#c%Yt%?|@&7>Hb#MhD0jVB%-M=39SJ$p(!zJ=i70!~O0w zRQ0stJz{_FscmUVp}p=vgc~bEoYNePq=aDdu!L}&f`Ynnb5IFugVE$BK^O?!( z85dYabDzGQ1|yx`uHHM{(54=(kw!#^@swsu9;`8Q#Ly6*eDL-J=_69cFoyphj)g(q z_LsroG(t!N{ui!WB|w_4KbKDj(??MH{ugG0`^q2ZE7xWIG+DnS_)@`sU`s_GjHlT-ZWY<@(30u-Df!pFc=vCfa{m_j|0CgvW7eSPT# zFV;|wwFC6HCIT#o>Bz^^ALS}|#}^u_c$01NaQt~szvFLX#AC;&qpGu^3RM&8ax@0u z_%Rl1hQ`{n8UGG2t&Nyf+mv@!var&v|E3~B2PcS;oD5>A_ZHL5OVeWHctUhpBIb5A z1V1PE{-XaE+hdX-xI>CqUuMNMu%YEwl7&jK^0xc~X4O7>Sxq!4ge)aq7#PF=nUxB} z+=QM`sg{_xqn81V(fXS3KaKlYkkh3SP+N7n)%Izp70f<~+H*@PGZht(@?}>P|9x(_Le}M7MzwsNfud1xD;uh=A~oz87Wodxrthcj-@nQrl(2cN*{={nl*9^9n77pts#9xgZX%hiD!HRs8( z|9mJ48qRRQ{sToYu%gVt;Dm<=?GhDLdY|{4UmcN2i?r>-j@+DRsm=$YjU0;LH-Obl!*;BC?;Kk zLPYA1M+?p)BuU=e!Fu!_kA1h!U~a1;xReO#gGx`$-^=p8#w$qJfpyx!Ge8tg#~h>4 zAp4*9@kfV{u-vgMCe>D0e_e``UPh=*RZzgrK?n>KeqL-KQV(Y{}2B`v#Z z3w!TJhn1T65cT$tfAnyzq-$bAT{8hC+`-lte7pld8BDO#QLkm<2w)X{d5d9e>>D8K z*)kh+Ift!}jxk2Iphl;X??jZDy9?aj48reVZ}Q#T9cU{qq)brr)W^)`{-|}_{ zoK4)5Zn%v0W$^mr8BdIkV~PO!-w1S+Fr>#KLYn7X=i%b1M{t?qbic|UC0S^hj}2#O ze{sLkw2KCqs5Dpi>7yD>qs6b-u6bMb0a2}X5p6fBLje!&$Ug37L2naD+493yd$F_q zAa27>JP-$@QP3(xrtB6RubJR)IA<^94Tl0rGz$|$m= z9RttNU%DPkU!gKoBDY`l6C<*LYC1Z=jq&dv9FN98)EryWqhrG)y-LWvX($Jjf=uqv}REZc4n!tm7D87Vdi*iUrQ}!CPuE?TJ zLe--vMo6|4A5HYKmV%5G8W2FDkS#q19li#W1~~q4Hu*r%ojE!_j9-;m8>?mavH+P~ zZMhXHs(g-K^^bwqsHnA4w}u99mwNPIGE3UJgGkh{;BfwD(EEn!)Rq;^mBqn)6mV>b zVKa_tJB7oxWm<)*5Sz>*kEu^p5~GGvw!}xkM!1{{LBFk6ly` zx$kXBs@x}tyjA!cPTaasVO2dX&*Ncntcmka;{-krg$H?Qd$;0Z45T7IyS;WuCvH0Y zCQ3!>vu+0gJ@x&D$Ze?J}PT!wRWeASpY*$waI=WAy(HrSlQvA$;pcU zvjF430Wo@?cjXNIY&1{3N`lM7QZv=$#%P)>)~Nyid5ER*ue&x3LS<3VPlNS}H&)H57!5Wjnt_ z)?EG1^Y=EP@SZ5ce5rQIu@!$ouiM-1m_JbeM2$xq@8I%!em^)xGiJbrpRJ2l(evG% zm}_z;SJ?YLIK{+9E=RRD-Vb0C>y=ad{k+SXO0vli&G;!JtS7t+Q0>j>%t%+)0Fw6O zX8!u;EvaBo?{U+0l6ZNzh*~cJ(XMHC;Ev*3CfCf#af)w3J3V!^C8#Bp^YDm2_x^0) z&*j5d(MJBf2`$M9nW3rsdb;OqIzD;ek8y$`e{=OlE6GC|d z4@mUY|5fDv_w@-YmVb5eHsYarGZ9t!%t9G>aB(D3;$q({wBOYw3+#Eh?5C&=1SB~t z$Ib!3!tL4rzL9R8~JUUz@W8eL|rHEN)zRi?ZwXJYDl z6t!cNbhVh7XaN5JB6fc>5~Tc{k7AE0-(kuFIhx_?bKzUSz)_t$#*3FDZ|FbT2-Vry zK~zxqJIWd|?A7}{FR=By<7@$#qF^4cPk7D_B8xnP5UA-TFP1dY5#ur*EZu1KX6Rh2 z{8F=OiD^0>7oF}NdIyY@nySwTysgI>{o`@3^IcsVvff*m>7Jj>+`|e@DCL)xUC!5= zn?T*F1XjY$cPa=LgvH&*(#$S+U~$R*qR;i%V_9%@=bcZbH~`u2#c<^aI|@Q#nQ;sC z)6ix7c?z=ZtEq`?zEG=J2&WsNa*eJ@B}q2s+ygE2@}6j3IVUMKTeg|NrKFYNJ*D-~ z;5%%$I~aC~f{uD5AW~SZud=4$d>Gk&NN{xX;YR1ItfPr7$yhtK85vc1C+F`i<6j2a zfz)OD?Hv?mf`uevyoM{{PWMYOyzij4yJp9x{6CQ%AqLy)+cRuJ6c>nN(7>ANJi9**OrdAE!)aB`ZsFygxV=6eY|)CX4lr4#iWsfS znpoJTxo?%#pbcF2hXlx~v-IVySE52iTc0zif1K5d;rFILLcB`|lL+Jy!&&@0+Xp}Y zUjgaShzjCfg6jW&s=CUsxV9ZyC|(AK;x?2P8(fOJyE_Gn4uclALV@DN-3!Itid&)R z;0}XNDef+he(&9T-#z(r{v{{bXMZ~@E7>(yMz}K{Xa_u}Rcv~>0a5xLAzsR^o~H0} zDjsQF4&s^IT`bGS@OJ=AzY=JfFVmf3F;{w3K?}CgXqhb`#-i=%;ls^=iyBrRLCtjC zrGxgVg>@^w4fK~wMk-1O)}+bfgRQ-9p(f4NtVQOnV>Rz^t19)5oNJ3F{>y^hOILeK zY01e~B1y-RjHVaZ;BLF3_i3YPR2sX%7)pdlYDqraE4YFPLOe#>VM%#A!w(N{{W;Tw zwaH1|FdZ(J?I3CAXR?gA4rC8Iy(3knbvGJfEC$=*GmI;x-T0mCsaWx`G09l1Svf3InT&(fO175vz8bt1Ak{#dO1X?Dy~3a_N}A5_ z7n*^lh&N_`zxlKgW+7N@IHQ&A;(AzG+xG5v%t7PBY(|njAK}xG0B#C$EP$df9CCdj z?&X^PY;3r>^|Jo0Fgz_$BX57uq?CJH{YNs-t-<&J^pQ^w8ozx6YHI>wI;$>L@@w}I zf-Cwd+j$3IL1s0pEhUx+jQP!+-j5}sFP`A^vw2=@!;zxRTnfS;RG$7?b@5>cz0NxV zvyA-tJyL|RTYkc`sY<6F$BMzqk0*85g>N|kBN;|^PeT;!eH>Q86dLhQc7m#`F%V2> z_lXIH3Q)cC3W{1zu*$G%a!6891?zWL%LC~H6j99A*OOTl-ME82#SpXbt}Aa{Dc(e% zWIRHhEXi;}QS2(O1+bP_z%o7Cvgs~R-!r?9$cd89dXEMSjFolqi-yT3zY+UG6vI3= z)V**EtF?-@Uo-)mZ{d>O_#6Gp?zRhCZ;0lw|Jl9{!#j21M^l->I(`qiV{=swdYGRz zmT@QMGAPNsTKuaW(B3ots$(=ldX)PzA|R3&lH-&f^E z79v-8xI)BXpMPOM4}{p>Ufo-W&1m|bdhA?iCJ+YXKEnNNb;ms(E~{uu{9XN>*X0rj z$xs%5bjQJvjSV^xg6%CWAdr!#&6}?|En@xUk2EZulY91G;!L9JWz>euuSD z1ZZij46T_CT4BT1Z+2QcK5ZHSELnm`ZLnn$bc}_a3yQS*BK2EtGe;&n`=n@U02!wz z-imTYBd=!_K;&)prfDzIZ6hl?T+hVqBl^e8&!aEhSzjQvAeT&h`UP?3(cp3xZdIS4 zm+`#r5pgxxIR+k2`$%-?z(1d`7UiTSPo_0eH< zzkbbzZf@dWTa^UN;5lJCl<;7Q_)MZwwYANS8Um5^L1dkL-J^H=S8Zv^fr}*&2M39L zE=|DG928^U&vTj=gAa7MlHd#FNn){3?P}KcCJQ}D-c`w=PN~W};97Ujj+?#2Cq)Ek zZXZ27$5{6YC1Zd~g9%Iq{+8qgSQg6MMtMuaNw%h(C!CX z%q4h;R4V1OrFS^Xy|F_P9cekB3ZQ7(OYJwIbe88>pZq?0t2Zt=a7x1AB1D5R@#pZMe29iQ=u%Lyv9f|*uI zw`ika<(UPA5TMlR?B>bO8%CnFk5BF=OXDht9*|U8Z5b998c$^g%ISmMr;bn6EF{P`O zn93hYi2Qv8w^=W2Y~gv?^Z?ptq=r-y;t%@us#dImu>L8635T;q2%qCl&)SWJT0*jR z#HM`D$1xnvl7?mU1hkno8faa_mTO{xt9nyoO-Y$NwFZviS9<=*$PdVLy3#?O#Mun? z(`Ku&*jj+1g-x_cU9I>;M$lnnl4=|t336`<(G>j`QamO-7mako;s!3x*YPNR*g2ZA zPz13g=>^U%>td)%FAE3~*YC*Fl?$yyNXidzuc~A?r?H9&mT^8h<6kc%$U4j>is9fIKd^32$o^{;``hDNR5mb8{2TS;?URSXELv| z^4{BKoTYASRf*+6Fe)mKR?o<2qcD<=m(d%XrW~UXVDT$)rFHbUpX(#(Lv)`j3zDCP zK+>;WHF7D)xU*7q4 z3ry3e12egN=>D>T)ml1r2L*}7+nJh6(Ez4Mx|SBYL(3dI^&30JGl~ri7767OOO7ve z7N0S(oDx8yN|X?FW=t?^=s1^X(kY+m3ILP6u{*S-o{{_A}2+F3G=~ zFYE-hXWsf->x14r(+&h05=&IC?<$h5tBVx;^a^UWzo5gIG;M5*w?C~)cSri7uVIa@ z8SMYuj&dXs=GOCo%pB4IE9EK7an!-@p_zj3n%VJ<9qa%Xd&nrGES7YNd_}3dreHX; zUOTyZzf@I^L@ma!tHu;OkkUSFZ!?Xl9%x6vgwN``2LJDe7DPJh=>9qUI&15|5+V!Q z-)wZxF;Fq}jU2J;#(OosU+jOlh-W=bRi`LnP#z<1N`oyvAzq~?xHqd>^saoyyYJMG zQ->i~i7@#3`r3287~S1|Wi;$@4fxGrvt8@Ka@m0Ij7_F0t$8iciZW@xF%c~VWXvG>rw@s-Ew3_5^`kvm{%B%E?*Lo^A~itE9w# zW+XH;oS3Gmec9)wYg028{b7c#2pf-#lDikvlAb3j4fz|xJ))ywJ8SWaG*o}{KIKtV zvZ^yU2TnKu8v?}PQ@aLx3d%Wz)>5X0e&^ZRNnKISk}C>QZ9`MmPIlVe>3yN20S>}x zN|tQA2+z3Q3!$JoTzotZr{)A2YREf>X_gR21M~KWU-AkO+A8eJ@|`XB-dUotPv~U6 zKm0w&LG4}}7=ki$b6(|~mrPi$u;C}`cHtO2ucYUx?G_wzv@f$>m6+(bF zKR%RcBdd*Y`EvW&Gt5FcNij_wE5WjWJ*@j0g!u5Jx?zs~)Le~F4(!_()J>^L#G&77 z%Cz51LMmJ-u;kn*E9@jV)J+mb<1ts!V;!IRJnrv*q@oh~6ce>K6FBlofWe%^01CmZ zJGFhby!w{(;@GGD8rBG4%=TGuD5JB&ceB(6fJn?I86lmz6Mh25jNp30;JcJ|U&=(n zGK!~yz<;HaN_@3i&tsYCbEqu!$0M^&JQ&@3XF59uh?nDznU_U+zW<=qwAStF*sTGt zgV%jT>6T9wEshg>jhCmw_~EXihXjDga{H;@v5xa=OlTD&?@1iVfa$>yD=TIVk8RuK zZMl3qvEY`s-y0^}H%#b-0g2iWZKQhi&kt?q(@K^8SY@&wqRPhi+V}R?V;}JLfaaYx zv2z)Y7tU@FRNGy*$Eo$c$jM)nJZK5SV{)cRT%jO4Qc^No3q{=gYyqdr?`qF-AH7O> zEVAF;=MeQ)AAWwF+YS!RiG3arRbTwg_`41!ikV4o7pjNlQNAM?N&&<1aBm$(mhQZj zY%x+sP|qVQ#LTszPNHmjS(K3uRp+%iMs-^j@T1bq^UCNQauw{zC%OrH0^CU8w2FN1 z+?YqRyZHxa3`l}+E{B59v|PSTVe?)}*4ya$d#&C6&0|#aMF&46K!5&z#(n_&o+8HcU7jfWJk$eB?}tUb8*q(5cF>li^ULG% zr&8_MD9ykiG(?(V)6#_BlQWcH!^T2UTOvFrGTtPkG!U(8`2^4f>T=uRASg9BUhxk% z;~rQ{vXE7k=igP2_Vwbb*RvtIA8y6r@lBDXMS9`yZ`Iekvoj$dJ50t-$!HJ5A-4`k zPl`_#B&0O)6nbo|ycE#TRyqzQ2lJt!X1eVSoo>aHJV&Bj6rOK~ae<<8j6sFD14;QD zQq!gL=s}_K3g90caWXmBLsjk$wQ1QWlPxAI#rxFCb8g$2QugpVzl>X1Gt~bJC@JEX zp>7}>#hwyF{sMIUNa&9-g%{YxOgAMPnEu9=QCW$>7MS9x zymEEpVruz;E1Y})axobEQo%2pmH+wx++=F{#66Uj7t_$Q^b)I$+ahg*Q`H(pMoF)Y zTCBEvoW3|F$=FCe?|yhI=xD&1-YV8J7&YAE08z#OoVrX@#U-gvh1b-W?z))5Nwq~q zJQ#-(uv&CW?WwK;Qq0Ki&Po-;TdsZf27yh?b9D^yKw(eT-z`Ro=&`0xs~fpe5csN4 ztgq^ekL@ng>GJ$C>@!m7Z!%*&bm1162Q{0M<#wfzO`iFWgi_FiJRu3o8 zQfzMBSjmxBzl(zfTT_2dog3(g-^7_>3TkGntzkvxN8V+49e;Se^wIjY*Ugkhkd<`h zLTgFR{_6DE*Tar1Pwu7JE+iYK(Lo3sW+b|niNc$gv6y2q0$vMP20?|@b009!i`!kS zMHrTauZnfD&}+x~ft64OJG>2w9$?1yef15&e!Z0E+XBHnKVDRJa3UwUdj8U6VC z97y~UDfF=I5*8X13sP2VL!4MrN#PX0Tweo3`Uc`rla%V0B84Qu=}4xn^h2LhBoU$a zRhZI5hsakef)4B|N=u41xsGx11uFZS9_N~Fdu>2%?5b$=_7C=4O{#gC16NBoJK^Cw z&6e#8bA7-MeS?q|-VtXj5?g+)Mjb-Oup}rACy}D#bYph>d-#E*4Ma-Oj@;s=Eb#s3fw+bj84B=2NENW{nE6R^1y_tHi zV(GtR#!`pl1eC1%x_H&g5`Ah$a$d2!hT{h@{TjDVz+wJ?v~N_nb1{erf=#eEU+k$0 z5K#A*y@TT)n2RMSY;u@_&6O;qTqV+%`X{&@2PbCT91QT@Pg8Xy_n)Di*V4)LaugVj zE$ABb*ua5`g-5~ZZXHAl;CRxvNJ{B1f6IObRJ~`y<~5hIN>-%Vw=QF3VqmB|q+5_? z@x9L`Lp(AJ%k@1vdy9)jdWU1`D@TzMFQ)NQ=|dqnu75qsNc-oB8l3+Nlp+&j*+GcjUA{OIxDwZO~V|Z&W z;be)-GOBh7F4$xreyvhJar|^k5>C>=j7;EkDU=KRB>Tm;$yZ0(mY;?_4W zi|p)P76TNSGw*@4cXlM7_9Z2kG*eQwRP|N{lWE^GPA>HF(hXzRBu2keiA2zNSHQ-} z=})IU6}U6yjs1cT;>@vVHQ0>~jigx*iOk(KEgf8Bbmnvk2OBhRN-{1&Iq3xF2qQ6l zjpJ$>!ZXgw*7Yk?AwL=}qf&4-e{f9cXe{>*$SDm~+8(H@MY0%4~_iZ)Idq=ho~GQ;xgW1V6p%fL(paO>Y`6BA%eHAezb-^3YYCqz6{F zZmb$0s28o~Z=uex_z7fHUyL0aO=h6<`ApeIQ<(o<@)x{DyCWfj#eYHUTQiptHFoy6 z4{toEG2!>xt|yj(>sqzrh}~3XQ>oa{q6l8@$j`Zq3jojzJ{uhRe>XdC49hFRuB7y# znQ{{)&ypcP!reMFYB>|p0~z=&JWe19gxD{{$k2sz_x!yjTn*uP82Wkmr#{pDsX~uP z@a1}RR3PqFy6Z>9!Ec#-4cm;WD z%4{x2Hor?Ag*g{A_3Ll7=`7C+`GzUC8JE-6`47XbWB^NDioZ&*uSpSxyS?+KPkAk) z-?3YaERbBn+V8#ZCfK~cWggFI+X4`YggaL4N5*eo3j4*Uv$G7YOoxB7tsL-mJooa# z9|yVZhahL!Eo_jqhkn1gsV<$4L{Hc0ealvSGt>9j_k;-_!l*Bs>AU1d6(Us3?D=a|Huo82iwnprV7KHf|7A zM_qt|UIo35=ist{tc}=K%-3FD-pxr#p^zYVOtAN4%^U)|`g{Btt+ z^R^N2%yKOXwS@RDEB{+q59q*qvh|i}{O3*I-|OlRCxsaMNwI^VYOnP_N%J40?-J48 z5y4EtglBmF=feLv(u4X*@kRinH2%K~U9FV-Lw1ort8V}Im-Rh=QcQ-e$)5IaL;YVN aKBC61;`=3MT{}K|dgP>(B`d_=1^x%iMU{{M diff --git a/PyTorch/build-in/Classification/SEResNet/SEResNet/model/__init__.py b/PyTorch/build-in/Classification/SEResNet/SEResNet/model/__init__.py deleted file mode 100644 index 16ed6037d..000000000 --- a/PyTorch/build-in/Classification/SEResNet/SEResNet/model/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .resnet import * -from .seresnet import * diff --git a/PyTorch/build-in/Classification/SEResNet/SEResNet/model/resnet.py b/PyTorch/build-in/Classification/SEResNet/SEResNet/model/resnet.py deleted file mode 100644 index b4bb1c2ab..000000000 --- a/PyTorch/build-in/Classification/SEResNet/SEResNet/model/resnet.py +++ /dev/null @@ -1,379 +0,0 @@ -import torch -import torch.nn as nn -from torchvision.models.utils import load_state_dict_from_url - -__all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101', - 'resnet152', 'resnext50_32x4d', 'resnext101_32x8d', - 'wide_resnet50_2', 'wide_resnet101_2', 'model_urls'] - -model_urls = { - 'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth', - 'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth', - 'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth', - 'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth', - 'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth', - 'resnext50_32x4d': 'https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth', - 'resnext101_32x8d': 'https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth', - 'wide_resnet50_2': 'https://download.pytorch.org/models/wide_resnet50_2-95faca4d.pth', - 'wide_resnet101_2': 'https://download.pytorch.org/models/wide_resnet101_2-32ee1156.pth', -} - - -def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1): - """3x3 convolution with padding""" - return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, - padding=dilation, groups=groups, bias=False, dilation=dilation) - - -def conv1x1(in_planes, out_planes, stride=1): - """1x1 convolution""" - return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False) - - -class BasicBlock(nn.Module): - expansion = 1 - - def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, - base_width=64, dilation=1, norm_layer=None): - super(BasicBlock, self).__init__() - if norm_layer is None: - norm_layer = nn.BatchNorm2d - if groups != 1 or base_width != 64: - raise ValueError('BasicBlock only supports groups=1 and base_width=64') - if dilation > 1: - raise NotImplementedError("Dilation > 1 not supported in BasicBlock") - # Both self.conv1 and self.downsample layers downsample the input when stride != 1 - self.conv1 = conv3x3(inplanes, planes, stride) - self.bn1 = norm_layer(planes) - self.relu = nn.ReLU(inplace=True) - self.conv2 = conv3x3(planes, planes) - self.bn2 = norm_layer(planes) - self.downsample = downsample - self.stride = stride - - def forward(self, x): - identity = x - - out = self.conv1(x) - out = self.bn1(out) - out = self.relu(out) - - out = self.conv2(out) - out = self.bn2(out) - - if self.downsample is not None: - identity = self.downsample(x) - - out += identity - out = self.relu(out) - - return out - - -class Bottleneck(nn.Module): - # Bottleneck in torchvision places the stride for downsampling at 3x3 convolution(self.conv2) - # while original implementation places the stride at the first 1x1 convolution(self.conv1) - # according to "Deep residual learning for image recognition"https://arxiv.org/abs/1512.03385. - # This variant is also known as ResNet V1.5 and improves accuracy according to - # https://ngc.nvidia.com/catalog/model-scripts/nvidia:resnet_50_v1_5_for_pytorch. - - expansion = 4 - - def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, - base_width=64, dilation=1, norm_layer=None): - super(Bottleneck, self).__init__() - if norm_layer is None: - norm_layer = nn.BatchNorm2d - width = int(planes * (base_width / 64.)) * groups - # Both self.conv2 and self.downsample layers downsample the input when stride != 1 - self.conv1 = conv1x1(inplanes, width) - self.bn1 = norm_layer(width) - self.conv2 = conv3x3(width, width, stride, groups, dilation) - self.bn2 = norm_layer(width) - self.conv3 = conv1x1(width, planes * self.expansion) - self.bn3 = norm_layer(planes * self.expansion) - self.relu = nn.ReLU(inplace=True) - self.downsample = downsample - self.stride = stride - - def forward(self, x): - identity = x - - out = self.conv1(x) - out = self.bn1(out) - out = self.relu(out) - - out = self.conv2(out) - out = self.bn2(out) - out = self.relu(out) - - out = self.conv3(out) - out = self.bn3(out) - - if self.downsample is not None: - identity = self.downsample(x) - - out += identity - out = self.relu(out) - - return out - - -class ResNet(nn.Module): - - def __init__(self, block, layers, num_classes=1000, zero_init_residual=False, - groups=1, width_per_group=64, replace_stride_with_dilation=None, - norm_layer=None): - super(ResNet, self).__init__() - if norm_layer is None: - norm_layer = nn.BatchNorm2d - self._norm_layer = norm_layer - - self.inplanes = 64 - self.dilation = 1 - if replace_stride_with_dilation is None: - # each element in the tuple indicates if we should replace - # the 2x2 stride with a dilated convolution instead - replace_stride_with_dilation = [False, False, False] - if len(replace_stride_with_dilation) != 3: - raise ValueError("replace_stride_with_dilation should be None " - "or a 3-element tuple, got {}".format(replace_stride_with_dilation)) - self.groups = groups - self.base_width = width_per_group - self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3, - bias=False) - self.bn1 = norm_layer(self.inplanes) - self.relu = nn.ReLU(inplace=True) - self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) - self.layer1 = self._make_layer(block, 64, layers[0]) - self.layer2 = self._make_layer(block, 128, layers[1], stride=2, - dilate=replace_stride_with_dilation[0]) - self.layer3 = self._make_layer(block, 256, layers[2], stride=2, - dilate=replace_stride_with_dilation[1]) - self.layer4 = self._make_layer(block, 512, layers[3], stride=2, - dilate=replace_stride_with_dilation[2]) - self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) - self.fc = nn.Linear(512 * block.expansion, num_classes) - - for m in self.modules(): - if isinstance(m, nn.Conv2d): - nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') - elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): - nn.init.constant_(m.weight, 1) - nn.init.constant_(m.bias, 0) - - # Zero-initialize the last BN in each residual branch, - # so that the residual branch starts with zeros, and each residual block behaves like an identity. - # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677 - if zero_init_residual: - for m in self.modules(): - if isinstance(m, Bottleneck): - nn.init.constant_(m.bn3.weight, 0) - elif isinstance(m, BasicBlock): - nn.init.constant_(m.bn2.weight, 0) - - def _make_layer(self, block, planes, blocks, stride=1, dilate=False): - norm_layer = self._norm_layer - downsample = None - previous_dilation = self.dilation - if dilate: - self.dilation *= stride - stride = 1 - if stride != 1 or self.inplanes != planes * block.expansion: - downsample = nn.Sequential( - conv1x1(self.inplanes, planes * block.expansion, stride), - norm_layer(planes * block.expansion), - ) - - layers = [] - layers.append(block(self.inplanes, planes, stride, downsample, self.groups, - self.base_width, previous_dilation, norm_layer)) - self.inplanes = planes * block.expansion - for _ in range(1, blocks): - layers.append(block(self.inplanes, planes, groups=self.groups, - base_width=self.base_width, dilation=self.dilation, - norm_layer=norm_layer)) - - return nn.Sequential(*layers) - - def _forward_impl(self, x): - # See note [TorchScript super()] - x = self.conv1(x) - x = self.bn1(x) - x = self.relu(x) - x = self.maxpool(x) - - x = self.layer1(x) - x = self.layer2(x) - x = self.layer3(x) - x = self.layer4(x) - - x = self.avgpool(x) - x = torch.flatten(x, 1) - x = self.fc(x) - - return x - - def forward(self, x): - return self._forward_impl(x) - - def load_from_resnet(self, state_dict): - loaded_param_names = [] - for module_name, module in self.named_modules(): - if isinstance(module, nn.Conv2d) or isinstance(module, nn.BatchNorm2d): - if module_name + '.weight' not in state_dict: - print(f'Module not exist in the state_dict: {module_name}') - elif isinstance(module, nn.Conv2d): - weight_name = module_name + '.weight' - module.weight.data.copy_(state_dict[weight_name]) - loaded_param_names.append(weight_name) - elif isinstance(module, nn.BatchNorm2d): - for param_name, param in module.named_parameters(): - name = f'{module_name}.{param_name}' - param.data.copy_(state_dict[name]) - loaded_param_names.append(name) - for param_name, param in module.named_buffers(): - name = f'{module_name}.{param_name}' - # some buffers like num_batches_tracked may not exist in old - # checkpoints - if name in state_dict: - param.data.copy_(state_dict[name]) - loaded_param_names.append(name) - # check if any parameters in the 2d checkpoint are not loaded - remaining_names = set(state_dict.keys()) - set(loaded_param_names) - if remaining_names: - print(f'These parameters in the 2d checkpoint are not loaded: {remaining_names}') - - -def _resnet(arch, block, layers, pretrained, progress, **kwargs): - model = ResNet(block, layers, **kwargs) - if pretrained: - state_dict = load_state_dict_from_url(model_urls[arch], - progress=progress) - model.load_state_dict(state_dict) - model.fc = nn.Linear(512 * block.expansion, 2) - return model - - -def resnet18(pretrained=False, progress=True, **kwargs): - r"""ResNet-18 model from - `"Deep Residual Learning for Image Recognition" `_ - - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - return _resnet('resnet18', BasicBlock, [2, 2, 2, 2], pretrained, progress, - **kwargs) - - -def resnet34(pretrained=False, progress=True, **kwargs): - r"""ResNet-34 model from - `"Deep Residual Learning for Image Recognition" `_ - - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - return _resnet('resnet34', BasicBlock, [3, 4, 6, 3], pretrained, progress, - **kwargs) - - -def resnet50(pretrained=False, progress=True, **kwargs): - r"""ResNet-50 model from - `"Deep Residual Learning for Image Recognition" `_ - - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - return _resnet('resnet50', Bottleneck, [3, 4, 6, 3], pretrained, progress, - **kwargs) - - -def resnet101(pretrained=False, progress=True, **kwargs): - r"""ResNet-101 model from - `"Deep Residual Learning for Image Recognition" `_ - - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - return _resnet('resnet101', Bottleneck, [3, 4, 23, 3], pretrained, progress, - **kwargs) - - -def resnet152(pretrained=False, progress=True, **kwargs): - r"""ResNet-152 model from - `"Deep Residual Learning for Image Recognition" `_ - - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - return _resnet('resnet152', Bottleneck, [3, 8, 36, 3], pretrained, progress, - **kwargs) - - -def resnext50_32x4d(pretrained=False, progress=True, **kwargs): - r"""ResNeXt-50 32x4d model from - `"Aggregated Residual Transformation for Deep Neural Networks" `_ - - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - kwargs['groups'] = 32 - kwargs['width_per_group'] = 4 - return _resnet('resnext50_32x4d', Bottleneck, [3, 4, 6, 3], - pretrained, progress, **kwargs) - - -def resnext101_32x8d(pretrained=False, progress=True, **kwargs): - r"""ResNeXt-101 32x8d model from - `"Aggregated Residual Transformation for Deep Neural Networks" `_ - - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - kwargs['groups'] = 32 - kwargs['width_per_group'] = 8 - return _resnet('resnext101_32x8d', Bottleneck, [3, 4, 23, 3], - pretrained, progress, **kwargs) - - -def wide_resnet50_2(pretrained=False, progress=True, **kwargs): - r"""Wide ResNet-50-2 model from - `"Wide Residual Networks" `_ - - The model is the same as ResNet except for the bottleneck number of channels - which is twice larger in every block. The number of channels in outer 1x1 - convolutions is the same, e.g. last block in ResNet-50 has 2048-512-2048 - channels, and in Wide ResNet-50-2 has 2048-1024-2048. - - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - kwargs['width_per_group'] = 64 * 2 - return _resnet('wide_resnet50_2', Bottleneck, [3, 4, 6, 3], - pretrained, progress, **kwargs) - - -def wide_resnet101_2(pretrained=False, progress=True, **kwargs): - r"""Wide ResNet-101-2 model from - `"Wide Residual Networks" `_ - - The model is the same as ResNet except for the bottleneck number of channels - which is twice larger in every block. The number of channels in outer 1x1 - convolutions is the same, e.g. last block in ResNet-50 has 2048-512-2048 - channels, and in Wide ResNet-50-2 has 2048-1024-2048. - - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - kwargs['width_per_group'] = 64 * 2 - return _resnet('wide_resnet101_2', Bottleneck, [3, 4, 23, 3], - pretrained, progress, **kwargs) diff --git a/PyTorch/build-in/Classification/SEResNet/SEResNet/model/se.py b/PyTorch/build-in/Classification/SEResNet/SEResNet/model/se.py deleted file mode 100644 index 53b4bbef0..000000000 --- a/PyTorch/build-in/Classification/SEResNet/SEResNet/model/se.py +++ /dev/null @@ -1,19 +0,0 @@ -import torch.nn as nn - - -class SE(nn.Module): - def __init__(self, channels, reduction=16): - super(SE, self).__init__() - self.avg_pool = nn.AdaptiveAvgPool2d(1) - self.fc = nn.Sequential( - nn.Linear(channels, channels // reduction, bias=False), - nn.ReLU(inplace=True), - nn.Linear(channels // reduction, channels, bias=False), - nn.Sigmoid() - ) - - def forward(self, x): - b, c, _, _ = x.size() - out = self.avg_pool(x).view(b, c) - out = self.fc(out).view(b, c, 1, 1) - return x * out.expand_as(x) diff --git a/PyTorch/build-in/Classification/SEResNet/SEResNet/model/seresnet.py b/PyTorch/build-in/Classification/SEResNet/SEResNet/model/seresnet.py deleted file mode 100644 index ba649e822..000000000 --- a/PyTorch/build-in/Classification/SEResNet/SEResNet/model/seresnet.py +++ /dev/null @@ -1,186 +0,0 @@ -import torch.nn as nn -from torchvision.models.utils import load_state_dict_from_url -from .se import SE -from .resnet import ResNet -from .resnet import model_urls - - -def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1): - """3x3 convolution with padding""" - return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, - padding=dilation, groups=groups, bias=False, dilation=dilation) - - -def conv1x1(in_planes, out_planes, stride=1): - """1x1 convolution""" - return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False) - - -class SEBasicBlock(nn.Module): - expansion = 1 - - def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, - base_width=64, dilation=1, norm_layer=None, reduction=16): - super(SEBasicBlock, self).__init__() - if norm_layer is None: - norm_layer = nn.BatchNorm2d - if groups != 1 or base_width != 64: - raise ValueError('BasicBlock only supports groups=1 and base_width=64') - if dilation > 1: - raise NotImplementedError("Dilation > 1 not supported in BasicBlock") - # Both self.conv1 and self.downsample layers downsample the input when stride != 1 - self.conv1 = conv3x3(inplanes, planes, stride) - self.bn1 = norm_layer(planes) - self.relu = nn.ReLU(inplace=True) - self.conv2 = conv3x3(planes, planes) - self.bn2 = norm_layer(planes) - self.se = SE(planes, reduction) - self.downsample = downsample - self.stride = stride - - def forward(self, x): - identity = x - - out = self.conv1(x) - out = self.bn1(out) - out = self.relu(out) - - out = self.conv2(out) - out = self.bn2(out) - out = self.se(out) - - if self.downsample is not None: - identity = self.downsample(x) - - out += identity - out = self.relu(out) - - return out - - -class SEBottleneck(nn.Module): - expansion = 4 - - def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, - base_width=64, dilation=1, norm_layer=None, reduction=16): - super(SEBottleneck, self).__init__() - if norm_layer is None: - norm_layer = nn.BatchNorm2d - width = int(planes * (base_width / 64.)) * groups - # Both self.conv2 and self.downsample layers downsample the input when stride != 1 - self.conv1 = conv1x1(inplanes, width) - self.bn1 = norm_layer(width) - self.conv2 = conv3x3(width, width, stride, groups, dilation) - self.bn2 = norm_layer(width) - self.conv3 = conv1x1(width, planes * self.expansion) - self.bn3 = norm_layer(planes * self.expansion) - self.relu = nn.ReLU(inplace=True) - self.se = SE(planes * self.expansion, reduction) - self.downsample = downsample - self.stride = stride - - def forward(self, x): - identity = x - - out = self.conv1(x) - out = self.bn1(out) - out = self.relu(out) - - out = self.conv2(out) - out = self.bn2(out) - out = self.relu(out) - - out = self.conv3(out) - out = self.bn3(out) - out = self.se(out) - - if self.downsample is not None: - identity = self.downsample(x) - - out += identity - out = self.relu(out) - - return out - - -def _seresnet(arch, block, layers, pretrained, progress, **kwargs): - model = ResNet(block, layers, **kwargs) - if pretrained: - state_dict = load_state_dict_from_url(model_urls[arch], - progress=progress) - model.load_from_resnet(state_dict) - return model - - -def seresnet18(pretrained=False, progress=True, **kwargs): - r""" - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - return _seresnet('resnet18', SEBasicBlock, [2, 2, 2, 2], pretrained, progress, - **kwargs) - - -def seresnet34(pretrained=False, progress=True, **kwargs): - r""" - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - return _seresnet('resnet34', SEBasicBlock, [3, 4, 6, 3], pretrained, progress, - **kwargs) - - -def seresnet50(pretrained=False, progress=True, **kwargs): - r""" - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - return _seresnet('resnet50', SEBottleneck, [3, 4, 6, 3], pretrained, progress, - **kwargs) - - -def seresnet101(pretrained=False, progress=True, **kwargs): - r""" - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - return _seresnet('resnet101', SEBottleneck, [3, 4, 23, 3], pretrained, progress, - **kwargs) - - -def seresnet152(pretrained=False, progress=True, **kwargs): - r""" - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - return _seresnet('resnet152', SEBottleneck, [3, 8, 36, 3], pretrained, progress, - **kwargs) - - -def seresnext50(pretrained=False, progress=True, **kwargs): - r""" - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - kwargs['groups'] = 32 - kwargs['width_per_group'] = 4 - return _seresnet('resnext50_32x4d', SEBottleneck, [3, 4, 6, 3], - pretrained, progress, **kwargs) - - -def seresnext101(pretrained=False, progress=True, **kwargs): - r""" - Args: - pretrained (bool): If True, returns a model pre-trained on ImageNet - progress (bool): If True, displays a progress bar of the download to stderr - """ - kwargs['groups'] = 32 - kwargs['width_per_group'] = 8 - return _seresnet('resnext101_32x8d', SEBottleneck, [3, 4, 23, 3], - pretrained, progress, **kwargs) diff --git a/PyTorch/build-in/Classification/SEResNet/coverage.txt b/PyTorch/build-in/Classification/SEResNet/coverage.txt deleted file mode 100644 index eb3ebe943..000000000 --- a/PyTorch/build-in/Classification/SEResNet/coverage.txt +++ /dev/null @@ -1,3 +0,0 @@ -all api: ['_amp_foreach_non_finite_check_and_unscale_', '_amp_update_scale_', '_copy_from', '_has_compatible_shallow_copy_type', '_local_scalar_dense', '_log_softmax', '_log_softmax_backward_data', '_pin_memory', '_reshape_alias', 'add_', 'addmm', 'as_strided', 'as_strided_', 'convolution', 'convolution_backward', 'copy_stride', 'div', 'eq', 'fill_', 'fused_sgd', 'is_pinned', 'linear', 'matmul', 'max_pool2d', 'maxpool2d_backward', 'maxpool2d_forward', 'mean', 'mm', 'mul', 'mul_', 'native_batch_norm', 'native_batch_norm_backward', 'nll_loss_backward', 'nll_loss_forward', 'reciprocal', 'relu_', 'set_', 'sigmoid', 'sigmoid_backward', 'sum', 'threshold_backward', 'topk_out', 'view', 'zero_'], total: 44 -fallback op: [], total: 0 -coverage rate: 100.00% diff --git a/PyTorch/build-in/Classification/SEResNet/readme b/PyTorch/build-in/Classification/SEResNet/readme new file mode 100644 index 000000000..f56c6462b --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/readme @@ -0,0 +1,65 @@ +```markdown +## 1. 模型链接 +- 原始仓库链接: +https://github.com/huggingface/pytorch-image-models?tab=readme-ov-file#models + +## 2. 快速开始 + +使用本模型执行训练的主要流程如下: + +1. **基础环境安装**:介绍训练前需要完成的基础环境检查和安装。 +2. **获取数据集**:介绍如何获取训练所需的数据集。 +3. **构建环境**:介绍如何构建模型运行所需要的环境。 +4. **启动训练**:介绍如何运行训练。 + +### 2.1 基础环境安装 + +请参考主仓库的基础环境安装章节,完成训练前的基础环境检查和安装(如驱动、固件等)。 + +### 2.2 准备数据集 + +#### 2.2.1 获取数据集 + +训练使用 **CIFAR-100** 数据集。该数据集为开源数据集,包含 100 个类别的 60000 张彩色图像。 + +#### 2.2.2 处理数据集 + +请确保数据集已下载并解压。根据训练脚本的默认配置,建议将数据集存放在模型目录的上级 `data` 目录中(即 `../data`),或者根据实际路径修改训练命令中的 `--datapath` 参数。 + +### 2.3 构建环境 + +所使用的环境下需包含 PyTorch 框架虚拟环境。 + +1. 执行以下命令,启动虚拟环境(根据实际环境名称修改): + + ```bash + conda activate torch_env_py310 + +``` + +2. 安装 Python 依赖。确保已安装项目所需的依赖包: +```bash +pip install -r requirements_exact.txt + +``` + + + +### 2.4 启动训练 + +1. 在构建好的环境中,进入模型训练脚本所在目录。 + +2. 运行训练。该模型支持单机单卡训练。 +执行以下命令启动训练(使用 CIFAR-100 数据集,Batch Size 为 128): +```bash +python weloTrainStep.py \ + --name train \ + --arch seresnet \ + --print_freq 1 \ + --steps 100 \ + --dataset cifar100 \ + --datapath ../data \ + --batch_size 32 \ + --epochs 100 + +``` diff --git a/PyTorch/build-in/Classification/SEResNet/requirements_exact.txt b/PyTorch/build-in/Classification/SEResNet/requirements_exact.txt new file mode 100644 index 000000000..7394b3319 --- /dev/null +++ b/PyTorch/build-in/Classification/SEResNet/requirements_exact.txt @@ -0,0 +1,89 @@ +addict==2.4.0 +aliyun-python-sdk-core==2.16.0 +aliyun-python-sdk-kms==2.16.5 +anyio==4.11.0 +astunparse==1.6.3 +certifi==2024.12.14 +cffi==2.0.0 +charset-normalizer==3.4.1 +click==8.3.1 +colorama==0.4.6 +contourpy==1.3.2 +crcmod==1.7 +cryptography==46.0.3 +cycler==0.12.1 +einops==0.8.1 +exceptiongroup==1.3.1 +filelock==3.14.0 +fonttools==4.60.1 +fsspec==2024.12.0 +future @ file:///croot/future_1730902796226/work +git-filter-repo==2.47.0 +h11==0.16.0 +hf-xet==1.2.0 +httpcore==1.0.9 +httpx==0.28.1 +huggingface_hub==1.1.5 +idna==3.10 +inplace-abn @ git+https://github.com/mapillary/inplace_abn.git@b50bfe9c7cd7116a3ab091a352b48d6ba5ee701c +Jinja2==3.1.5 +jmespath==0.10.0 +joblib==1.5.2 +kiwisolver==1.4.9 +Markdown==3.10 +markdown-it-py==4.0.0 +MarkupSafe==3.0.2 +matplotlib==3.10.7 +mdurl==0.1.2 +mmdet==3.3.0 +mmengine==0.10.7 +model-index==0.1.11 +mpmath==1.3.0 +networkx==3.4.2 +numpy==1.23.5 +opencv-python==4.12.0.88 +opendatalab==0.0.10 +openmim==0.3.9 +openxlab==0.1.3 +ordered-set==4.1.0 +oss2==2.17.0 +packaging @ file:///croot/packaging_1734472117206/work +pandas==2.3.3 +pillow==11.1.0 +platformdirs==4.5.1 +pycocotools==2.0.11 +pycparser @ file:///tmp/build/80754af9/pycparser_1636541352034/work +pycryptodome==3.23.0 +Pygments==2.19.2 +pyparsing==3.2.5 +python-dateutil==2.9.0.post0 +pytz==2023.4 +PyYAML @ file:///croot/pyyaml_1728657952215/work +requests==2.28.2 +rich==13.4.2 +safetensors==0.7.0 +scikit-learn==1.7.2 +scipy==1.15.3 +shapely==2.1.2 +shellingham==1.5.4 +six @ file:///tmp/build/80754af9/six_1644875935023/work +sniffio==1.3.1 +sympy==1.13.3 +tabulate==0.9.0 +termcolor==3.2.0 +terminaltables==3.1.10 +threadpoolctl==3.6.0 +timm==1.0.22 +tomli==2.3.0 +torch @ file:///apps/torch-2.4.0a0%2Bgit4451b0e-cp310-cp310-linux_x86_64.whl#sha256=2e472c916044cac5a1a0e0d8b0e12bb943d8522b24ff826c8014dd444dccd378 +torch_sdaa @ file:///apps/torch_sdaa-2.0.0-cp310-cp310-linux_x86_64.whl#sha256=5aa57889b002e1231fbf806642e1353bfa016297bc25178396e89adc2b1f92e7 +torchaudio @ file:///apps/torchaudio-2.0.2%2Bda3eb8d-cp310-cp310-linux_x86_64.whl#sha256=46525c02fb7eaa8dafea860428de3d01e437ba8d6ff2cc228d7c71975ac4054b +torchdata @ file:///apps/torchdata-0.6.1%2Be1feeb2-py3-none-any.whl#sha256=aa2dc1a7732ea68adfad186978049bf68cc1afdbbdd1e17a8024227ab770e433 +torchtext @ file:///apps/torchtext-0.15.2a0%2B4571036-cp310-cp310-linux_x86_64.whl#sha256=7e42c684ba366f97b59ec37488bf95e416cce3892b6589200d2b3ad159ee5788 +torchvision @ file:///apps/torchvision-0.15.1a0%2B42759b1-cp310-cp310-linux_x86_64.whl#sha256=4b904db2d50102415536bc764bbc31c669b90b1b014f90964e9eccaadb2fd9eb +tqdm==4.65.2 +typer-slim==0.20.0 +typing_extensions==4.15.0 +tzdata==2025.2 +urllib3==1.26.20 +yapf==0.43.0 diff --git a/PyTorch/build-in/Classification/SEResNet/seresnet_loss.jpg b/PyTorch/build-in/Classification/SEResNet/seresnet_loss.jpg deleted file mode 100644 index 45419a78f1ed1f8ff87b8cf435c9c00a9ca033ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35249 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 diff --git a/PyTorch/build-in/Classification/SEResNet/seresnet_loss.txt b/PyTorch/build-in/Classification/SEResNet/seresnet_loss.txt deleted file mode 100644 index f67229c8b..000000000 --- a/PyTorch/build-in/Classification/SEResNet/seresnet_loss.txt +++ /dev/null @@ -1,29 +0,0 @@ -=== CUDA === -4.612500 4.619000 5.173300 4.753900 5.103300 5.242500 5.253400 5.376800 5.227700 5.287400 -5.225600 5.315900 6.274400 5.618300 5.944600 5.011500 5.068500 5.123900 5.286200 4.771400 -5.243700 4.860000 4.901700 4.972000 5.217600 5.257200 5.172400 4.954800 4.766100 4.733300 -4.817900 4.636500 4.600600 4.679000 4.723000 4.554800 4.635600 4.738800 4.598000 4.688700 -4.503400 4.537000 4.530600 4.524300 4.748800 4.348600 4.677400 4.480400 4.628000 4.406400 -4.279100 4.536600 4.501700 4.544200 4.625900 4.618700 4.645000 4.531900 4.632300 4.532500 -4.444700 4.552500 4.445000 4.595700 4.423200 4.563300 4.466200 4.277400 4.460700 4.536500 -4.452100 4.384400 4.355400 4.371800 4.386600 4.504900 4.364500 4.567600 4.362700 4.366000 -4.266800 4.490200 4.527800 4.241300 4.365700 4.196000 4.123600 4.373100 4.352100 4.619600 -4.412000 4.571500 4.294300 4.252300 4.580000 4.244400 4.426400 4.422000 4.171400 4.378200 - -=== SDAA === -4.602800 4.731700 4.830000 4.766100 4.891000 5.397000 5.432600 5.317800 5.863900 5.501600 -5.457100 5.346400 6.533400 5.124500 5.276400 5.267400 5.038100 5.121800 5.358700 5.454500 -4.813100 5.272200 5.198100 5.094100 5.284500 5.408300 5.481300 4.846000 4.872300 4.808600 -4.660000 4.657000 4.653100 4.599700 4.572500 4.637400 4.947900 4.489300 4.650700 4.717900 -4.861600 4.580800 4.686800 4.619700 4.634500 4.542100 4.379000 4.431700 4.826700 4.346300 -4.705800 4.580100 4.716400 4.448000 4.369200 4.503800 4.443400 4.491000 4.508300 4.872600 -4.615700 4.301000 4.593000 4.433000 4.428700 4.405500 4.361100 4.385100 4.493400 4.370100 -4.424200 4.407500 4.355100 4.535700 4.399500 4.194800 4.240400 4.206800 4.275900 4.276500 -4.489900 4.542500 4.198100 4.294400 4.433000 4.338900 4.693600 4.418000 4.445000 4.181000 -4.365200 4.454500 4.264700 4.420800 4.562200 4.226300 4.210100 4.245600 4.312500 4.325800 - -=== RESULT === -MeanRelativeError: 0.0037770064676498137 -MeanAbsoluteError: 0.01585200000000009 -Rule,mean_relative_error 0.0037770064676498137 -pass mean_relative_error=0.0037770064676498137 <= 0.05 or mean_absolute_error=0.01585200000000009 <= 0.0002 From 21b3103f69a386e499677a76cc3d85a56df01a5b Mon Sep 17 00:00:00 2001 From: root Date: Thu, 8 Jan 2026 10:28:20 +0000 Subject: [PATCH 3/3] fix: rename files and update code --- PyTorch/build-in/Classification/SEResNet/{readme => readme.md} | 0 .../SEResNet/{requirements_exact.txt => requirements.txt} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename PyTorch/build-in/Classification/SEResNet/{readme => readme.md} (100%) rename PyTorch/build-in/Classification/SEResNet/{requirements_exact.txt => requirements.txt} (100%) diff --git a/PyTorch/build-in/Classification/SEResNet/readme b/PyTorch/build-in/Classification/SEResNet/readme.md similarity index 100% rename from PyTorch/build-in/Classification/SEResNet/readme rename to PyTorch/build-in/Classification/SEResNet/readme.md diff --git a/PyTorch/build-in/Classification/SEResNet/requirements_exact.txt b/PyTorch/build-in/Classification/SEResNet/requirements.txt similarity index 100% rename from PyTorch/build-in/Classification/SEResNet/requirements_exact.txt rename to PyTorch/build-in/Classification/SEResNet/requirements.txt