{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[33mWARNING: Ignoring invalid distribution -y-mini-racer (/Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages)\u001b[0m\u001b[33m\n", "\u001b[0mRequirement already satisfied: torcheval in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (0.0.6)\n", "Requirement already satisfied: torchtnt>=0.0.5 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torcheval) (0.2.0)\n", "Requirement already satisfied: typing-extensions in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torcheval) (3.7.4.3)\n", "Requirement already satisfied: torch in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torchtnt>=0.0.5->torcheval) (2.0.1)\n", "Requirement already satisfied: numpy in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torchtnt>=0.0.5->torcheval) (1.19.2)\n", "Requirement already satisfied: fsspec in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torchtnt>=0.0.5->torcheval) (2023.6.0)\n", "Requirement already satisfied: tensorboard in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torchtnt>=0.0.5->torcheval) (2.14.0)\n", "Requirement already satisfied: packaging in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torchtnt>=0.0.5->torcheval) (20.4)\n", "Requirement already satisfied: psutil in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torchtnt>=0.0.5->torcheval) (5.7.2)\n", "Requirement already satisfied: pyre-extensions in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torchtnt>=0.0.5->torcheval) (0.0.30)\n", "Requirement already satisfied: setuptools in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torchtnt>=0.0.5->torcheval) (68.1.2)\n", "Requirement already satisfied: tqdm in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torchtnt>=0.0.5->torcheval) (4.65.0)\n", "Requirement already satisfied: pyparsing>=2.0.2 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from packaging->torchtnt>=0.0.5->torcheval) (2.4.7)\n", "Requirement already satisfied: six in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from packaging->torchtnt>=0.0.5->torcheval) (1.15.0)\n", "Requirement already satisfied: typing-inspect in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from pyre-extensions->torchtnt>=0.0.5->torcheval) (0.9.0)\n", "Requirement already satisfied: absl-py>=0.4 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from tensorboard->torchtnt>=0.0.5->torcheval) (1.4.0)\n", "Requirement already satisfied: grpcio>=1.48.2 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from tensorboard->torchtnt>=0.0.5->torcheval) (1.57.0)\n", "Requirement already satisfied: google-auth<3,>=1.6.3 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from tensorboard->torchtnt>=0.0.5->torcheval) (2.22.0)\n", "Requirement already satisfied: google-auth-oauthlib<1.1,>=0.5 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from tensorboard->torchtnt>=0.0.5->torcheval) (1.0.0)\n", "Requirement already satisfied: markdown>=2.6.8 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from tensorboard->torchtnt>=0.0.5->torcheval) (3.4.4)\n", "Requirement already satisfied: protobuf>=3.19.6 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from tensorboard->torchtnt>=0.0.5->torcheval) (4.24.1)\n", "Requirement already satisfied: requests<3,>=2.21.0 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from tensorboard->torchtnt>=0.0.5->torcheval) (2.24.0)\n", "Requirement already satisfied: tensorboard-data-server<0.8.0,>=0.7.0 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from tensorboard->torchtnt>=0.0.5->torcheval) (0.7.1)\n", "Requirement already satisfied: werkzeug>=1.0.1 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from tensorboard->torchtnt>=0.0.5->torcheval) (1.0.1)\n", "Requirement already satisfied: wheel>=0.26 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from tensorboard->torchtnt>=0.0.5->torcheval) (0.35.1)\n", "Requirement already satisfied: filelock in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torch->torchtnt>=0.0.5->torcheval) (3.0.12)\n", "Requirement already satisfied: sympy in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torch->torchtnt>=0.0.5->torcheval) (1.6.2)\n", "Requirement already satisfied: networkx in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torch->torchtnt>=0.0.5->torcheval) (2.5)\n", "Requirement already satisfied: jinja2 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from torch->torchtnt>=0.0.5->torcheval) (2.11.2)\n", "Requirement already satisfied: cachetools<6.0,>=2.0.0 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from google-auth<3,>=1.6.3->tensorboard->torchtnt>=0.0.5->torcheval) (5.3.1)\n", "Requirement already satisfied: pyasn1-modules>=0.2.1 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from google-auth<3,>=1.6.3->tensorboard->torchtnt>=0.0.5->torcheval) (0.3.0)\n", "Requirement already satisfied: rsa<5,>=3.1.4 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from google-auth<3,>=1.6.3->tensorboard->torchtnt>=0.0.5->torcheval) (4.9)\n", "Requirement already satisfied: urllib3<2.0 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from google-auth<3,>=1.6.3->tensorboard->torchtnt>=0.0.5->torcheval) (1.25.11)\n", "Requirement already satisfied: requests-oauthlib>=0.7.0 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from google-auth-oauthlib<1.1,>=0.5->tensorboard->torchtnt>=0.0.5->torcheval) (1.3.1)\n", "Requirement already satisfied: importlib-metadata>=4.4 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from markdown>=2.6.8->tensorboard->torchtnt>=0.0.5->torcheval) (6.8.0)\n", "Requirement already satisfied: chardet<4,>=3.0.2 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from requests<3,>=2.21.0->tensorboard->torchtnt>=0.0.5->torcheval) (3.0.4)\n", "Requirement already satisfied: idna<3,>=2.5 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from requests<3,>=2.21.0->tensorboard->torchtnt>=0.0.5->torcheval) (2.10)\n", "Requirement already satisfied: certifi>=2017.4.17 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from requests<3,>=2.21.0->tensorboard->torchtnt>=0.0.5->torcheval) (2020.6.20)\n", "Requirement already satisfied: MarkupSafe>=0.23 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from jinja2->torch->torchtnt>=0.0.5->torcheval) (1.1.1)\n", "Requirement already satisfied: decorator>=4.3.0 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from networkx->torch->torchtnt>=0.0.5->torcheval) (4.4.2)\n", "Requirement already satisfied: mpmath>=0.19 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from sympy->torch->torchtnt>=0.0.5->torcheval) (1.1.0)\n", "Requirement already satisfied: mypy-extensions>=0.3.0 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from typing-inspect->pyre-extensions->torchtnt>=0.0.5->torcheval) (1.0.0)\n", "Requirement already satisfied: zipp>=0.5 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from importlib-metadata>=4.4->markdown>=2.6.8->tensorboard->torchtnt>=0.0.5->torcheval) (3.4.0)\n", "Requirement already satisfied: pyasn1<0.6.0,>=0.4.6 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from pyasn1-modules>=0.2.1->google-auth<3,>=1.6.3->tensorboard->torchtnt>=0.0.5->torcheval) (0.5.0)\n", "Requirement already satisfied: oauthlib>=3.0.0 in /Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<1.1,>=0.5->tensorboard->torchtnt>=0.0.5->torcheval) (3.2.2)\n", "\u001b[33mWARNING: Ignoring invalid distribution -y-mini-racer (/Users/tgbaggio/opt/anaconda3/lib/python3.8/site-packages)\u001b[0m\u001b[33m\n", "\u001b[0m\u001b[33mDEPRECATION: pyodbc 4.0.0-unsupported has a non-standard version number. pip 23.3 will enforce this behaviour change. A possible replacement is to upgrade to a newer version of pyodbc or contact the author to suggest that they release a version with a conforming version number. Discussion can be found at https://github.com/pypa/pip/issues/12063\u001b[0m\u001b[33m\n", "\u001b[0m" ] } ], "source": [ "!pip install torcheval" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import os\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "\n", "\n", "def read_data(path):\n", " \"\"\"\n", " 使用pandas读取数据\n", " \"\"\"\n", " data = pd.read_csv(path)\n", " cols = [\"age\", \"education_num\", \"capital_gain\", \"capital_loss\", \"hours_per_week\", \"label\"]\n", " return data[cols]\n", "\n", "\n", "if os.name == \"nt\":\n", " data_path = \".\\\\data\\\\adult.data\"\n", "else:\n", " data_path = \"./data/adult.data\"\n", "data = read_data(data_path)\n", "data[\"label_code\"] = pd.Categorical(data.label).codes" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ageeducation_numcapital_gaincapital_losshours_per_weeklabellabel_code
039132174040<=50K0
150130013<=50K0
23890040<=50K0
35370040<=50K0
428130040<=50K0
........................
3255627120038<=50K0
325574090040>50K1
325585890040<=50K0
325592290020<=50K0
3256052915024040>50K1
\n", "

32561 rows × 7 columns

\n", "
" ], "text/plain": [ " age education_num capital_gain capital_loss hours_per_week label \\\n", "0 39 13 2174 0 40 <=50K \n", "1 50 13 0 0 13 <=50K \n", "2 38 9 0 0 40 <=50K \n", "3 53 7 0 0 40 <=50K \n", "4 28 13 0 0 40 <=50K \n", "... ... ... ... ... ... ... \n", "32556 27 12 0 0 38 <=50K \n", "32557 40 9 0 0 40 >50K \n", "32558 58 9 0 0 40 <=50K \n", "32559 22 9 0 0 20 <=50K \n", "32560 52 9 15024 0 40 >50K \n", "\n", " label_code \n", "0 0 \n", "1 0 \n", "2 0 \n", "3 0 \n", "4 0 \n", "... ... \n", "32556 0 \n", "32557 1 \n", "32558 0 \n", "32559 0 \n", "32560 1 \n", "\n", "[32561 rows x 7 columns]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 展示数据\n", "data" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "import torch\n", "import torch.nn.functional as F\n", "from utils import Linear\n", "\n", "\n", "torch.manual_seed(1024)\n", "\n", "class LogitRegression:\n", " \n", " def __init__(self, neg, pos):\n", " self.pos = pos\n", " self.neg = neg\n", " \n", " def __call__(self, x):\n", " self.out = torch.concat((self.neg(x), self.pos(x)), dim=1)\n", " return self.out\n", " \n", " def parameters(self):\n", " return self.neg.parameters() + self.pos.parameters()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# 定义模型\n", "pos = Linear(5, 1)\n", "neg = Linear(5, 1)\n", "model = LogitRegression(neg, pos)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# 准备数据\n", "x = torch.tensor(data[['age', 'education_num', 'capital_gain', 'capital_loss', 'hours_per_week']].values).float()\n", "x = F.normalize(x) # shape[32561, 5]\n", "y = torch.tensor(data['label_code']).long() # shape[32561]" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(tensor([[ 1.2665, -1.7305]]), tensor([[0.9524, 0.0476]]), tensor([0]))" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 使用模型\n", "## 注意,模型输入数据的形状一定要是[n, 2]\n", "logits = model(x[[1]]) # shape: [1, 2]\n", "probs = F.softmax(logits, dim=1) # shape: [1, 2]\n", "pred = torch.where(probs[:, 1] > 0.5, 1, 0)\n", "logits, probs, pred" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(tensor(0.0487), tensor(0.0487))" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 计算模型在单点的损失\n", "loss = F.cross_entropy(logits, y[[1]])\n", "# cross_entropy的具体实现过程\n", "-probs[torch.arange(1), y[[1]]].log().mean(), loss" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "# 对于模型参数,需要记录它们的梯度(为反向传播做准备)\n", "for p in model.parameters():\n", " p.requires_grad = True" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "step 0/20000, loss: 0.6580\n", "step 2000/20000, loss: 0.5092\n", "step 4000/20000, loss: 0.5066\n", "step 6000/20000, loss: 0.5037\n", "step 8000/20000, loss: 0.4958\n", "step 10000/20000, loss: 0.5046\n", "step 12000/20000, loss: 0.5015\n", "step 14000/20000, loss: 0.4952\n", "step 16000/20000, loss: 0.5086\n", "step 18000/20000, loss: 0.5086\n" ] } ], "source": [ "# 标准随机梯度下降法的超参数\n", "max_steps = 20000\n", "batch_size = 3000\n", "lossi = []\n", "\n", "for i in range(max_steps):\n", " # 构造批次训练数据\n", " ix = torch.randint(0, x.shape[0], (batch_size,))\n", " xb = x[ix]\n", " yb = y[ix]\n", " \n", " # 向前传播\n", " logits = model(xb)\n", " loss = F.cross_entropy(logits, yb)\n", " # 反向传播\n", " loss.backward()\n", " \n", " # 更新模型参数\n", " ## 学习速率衰减\n", " learning_rate = 0.1 if i < 10000 else 0.01\n", " with torch.no_grad():\n", " for p in model.parameters():\n", " p -= learning_rate * p.grad\n", " p.grad = None\n", " \n", " # 统计数据\n", " if i % 2000 == 0:\n", " print(f'step {i: 6d}/{max_steps}, loss: {loss.item(): .4f}')\n", " lossi.append(loss.item())" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXsAAAD4CAYAAAANbUbJAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAArxUlEQVR4nO3dd3wUZf4H8M83CaGH3qSXBKQYSqSIKCBV9DjrD86znudZONt5Hh72inLYCyJyllPxVBBOmiBIkZoAoZcQAoRQEmpCIKQ8vz92djO7O7s7m2xj5/N+vXixOzvlyezuZ555nmdmRSkFIiKKbjHhLgAREQUfw56IyAIY9kREFsCwJyKyAIY9EZEFxIW7AEYaNmyo2rRpE+5iEBFdNNLS0vKUUo08vR6RYd+mTRukpqaGuxhERBcNEdnv7XU24xARWQDDnojIAhj2REQWwLAnIrIAhj0RkQUw7ImILIBhT0RkAVEV9r9l5GFf3tlwF4OIKOJE5EVVFXXbtLUAgKyJo8JcEiKiyBJVNXsiIjLGsCcisgCGPRGRBTDsiYgsgGFPRGQBDHsiIgtg2BMRWQDDnojIAhj2REQWwLAnIrIAhj0RkQUw7ImILIBhT0RkAQx7IiILYNgTEVkAw56IyAIY9kREFsCwJyKyAIY9EZEFMOyJiCyAYU9EZAEMeyIiCzAV9iIyQkR2iUiGiIz3MM9AEdkkIttEZJluepaIbNFeSw1UwYmIyLw4XzOISCyADwAMBZANYL2IzFFKbdfNUxfAhwBGKKUOiEhjl9UMUkrlBa7YRETkDzM1+94AMpRSmUqpCwBmABjtMs8fAMxUSh0AAKXUscAWk4iIKsNM2DcHcFD3PFubppcEoJ6I/CoiaSJyh+41BeBnbfp9njYiIveJSKqIpObm5potPxERmeCzGQeAGExTBuvpBeAaANUBrBaRNUqp3QD6K6VytKadRSKyUym13G2FSk0FMBUAUlJSXNdPRESVYKZmnw2gpe55CwA5BvMsUEqd1drmlwNIBgClVI72/zEAs2BrFiIiohAyE/brASSKSFsRiQcwBsAcl3lmAxggInEiUgNAHwA7RKSmiNQGABGpCWAYgK2BKz4REZnhsxlHKVUiIuMALAQQC2C6UmqbiNyvvT5FKbVDRBYA2AygDMA0pdRWEWkHYJaI2Lf1tVJqQbD+GCIiMmamzR5KqXkA5rlMm+LyfBKASS7TMqE15xARUfjwCloiIgtg2BMRWQDDnojIAhj2REQWwLAnIrIAhj0RkQUw7ImILIBhT0RkAQx7IiILYNgTEVkAw56IyAIY9kREFsCwJyKyAIY9EZEFMOyJiCyAYU9EZAEMeyIiC4jKsFdKhbsIREQRJUrDPtwlICKKLFEZ9mVMeyIiJ1EZ9ox6IiJnURn2rNkTETmLyrBn1hMROWPYExFZQHSGPVvtiYicRGfYM+uJiJxEZdizg5aIyFlUhj2jnojIWXSGPdOeiMhJVIb9wROF4S4CEVFEicqwP3TqXLiLQEQUUaIy7HMY9kRETqIy7F/43/ZwF4GIKKJEZdgTEZEzhj0RkQUw7ImILIBhT0RkAQx7IiILMBX2IjJCRHaJSIaIjPcwz0AR2SQi20RkmT/LEhFRcMX5mkFEYgF8AGAogGwA60VkjlJqu26eugA+BDBCKXVARBqbXZaIiILPTM2+N4AMpVSmUuoCgBkARrvM8wcAM5VSBwBAKXXMj2WJiCjIzIR9cwAHdc+ztWl6SQDqicivIpImInf4sSwAQETuE5FUEUnNzc01V3oiIjLFZzMOADGY5npfyTgAvQBcA6A6gNUissbksraJSk0FMBUAUlJSeN9KIqIAMhP22QBa6p63AJBjME+eUuosgLMishxAsslliYgoyMw046wHkCgibUUkHsAYAHNc5pkNYICIxIlIDQB9AOwwuSwREQWZz5q9UqpERMYBWAggFsB0pdQ2Eblfe32KUmqHiCwAsBlAGYBpSqmtAGC0bJD+FiIi8sBMMw6UUvMAzHOZNsXl+SQAk8wsS0REocUraImILIBhT0RkAQx7IiILYNgTEVkAw56IyAIY9kREFsCwJyKyAIY9EZEFRG3Ybz10OtxFICKKGFEb9unZp8JdBCKiiBG1YU9EROWiKuw7N0twPBbDW+kTEVlTVIV9jO6vEWY9EZFDVIU9a/NERMaiKuy7t6zreFym+MuGRER2URX2iU1qOR6/tWh3GEtCRBRZoirs9Y04eQUXwlYOIqJIE11hz15ZIiJDURX29WvGh7sIREQRKarCfmTXpuEuAhFRRIqqsGczDhGRsagKeyIiMsawJyKyAIY9EZEFMOyJiCyAYU9EZAFRHfbHC4rCXQQioogQ1WF/6NS5cBeBiCgiRHXY88aXREQ2UR32RERkE9Vhz4o9EZFNVIf9hZKycBeBiCgiRHXYl5Qx7ImIgCgP+9x8Dr0kIgKiPOwfmbEp3EUgIooIUR32F4uS0jKUlbE7mYiCh2EfATpMmI87/70u3MUgoijGsI8QK/bkhbsIRBTFTIW9iIwQkV0ikiEi4w1eHygip0Vkk/bvWd1rWSKyRZueGsjCm/HB0oxQb9LhwPFCfL4qK2zbJyKy8xn2IhIL4AMAIwF0BjBWRDobzLpCKdVd+/eiy2uDtOkplS+yfyYt3GU4XSkV9HH4t368Gs/N2YbCCyVB3Q4F1ss/bcfYqWvCXQxT/vTZevztv+nhLgZdBMzU7HsDyFBKZSqlLgCYAWB0cIsVfP9ZewBJT8/H4dPBu1na6XPFQVs3Bc+0lfuwOvN4uIthyi87j+GHDdnhLgZdBMyEfXMAB3XPs7VprvqJSLqIzBeRLrrpCsDPIpImIvd52oiI3CciqSKSmpuba6rwlfG/TTkAbE0twcYbshGFx8YDJ3HmfGRVupRSOFV4IeTbNRP2YjDNNb42AGitlEoG8B6AH3Wv9VdK9YStGeghEbnKaCNKqalKqRSlVEqjRo1MFKtiDp06hyOnz0OF4M45YrTniCgkikvLcMOHq3DPv9eHuyhOPlmRie4vLsLBE8GvaOqZCftsAC11z1sAyNHPoJQ6o5Qq0B7PA1BFRBpqz3O0/48BmAVbs1BIrdSNdOk/cQn6vvaLo7YtIUhkVuzJKnLzizDq3RXIiYDfkijTvuSbs0+HuSTOFu84BiD0v7dhJuzXA0gUkbYiEg9gDIA5+hlEpKloqSkivbX1HheRmiJSW5teE8AwAFsD+QeYsW6fe/urPYCDmfX6VWefLITStedsPXQax/LPO83fZvxcfJ8WuvbXs0UlIa9dWN3SncewePvRoKz7fHEp9uWdDcq6zfo+LRvbcs7g89VZYS0HufMZ9kqpEgDjACwEsAPAf5VS20TkfhG5X5vtZgBbRSQdwLsAxihbsjUBsFKbvg7AXKXUgmD8IXYPX5PoNi3d4MhuD96YEDS1rNl7HFe+vhSfrMh0TLvuvZUY+uZyt3m/Sz3oNi1Ybpu2FgPeWBqy7RFw92frce8XwRmB/Ni3mzDoX7/ifHFpUNZ/sfHUV1ZSWobsk8Gp5CilUFJqbpSfUkBRSejeK1Pj7JVS85RSSUqp9kqpV7RpU5RSU7TH7yuluiilkpVSfZVSq7Tpmdq0ZO31V4L3p9j0bFXXbdqy3bnYkn0a7/2yxzHt+Fl7B4kt7TNzCzBvy2HH66fPFTvVxH1RSuGVudux60i+Y5q9icj+5f5f+mGnZcI9WmfTwVNh3T4Flr258oLJsIkGWXln8fh/N6HY29/sUqF7dd5OXPn6Urcz60B4e/EedJgw39Rw6y9WZ6Hj0wtw5HTgy2HEMlfQTvhxCyYv2u14vt9lFM7gycvw4FcboJRC9slCJL/ws1NN3Je8ggv4ZMU+DH/bvbZu5/UDqTE6vOSfL8aAN5YELZwf/CoNpRW8N8/qvcfx3/WhOxsh0vv79+mYueEQEifMR8axfN8LAFixxzba71Sh78pWWZnyq/b9zboDAID8877Dfv7WIwAQtLMMV5YJ++JS4zBzbbMfM3UNrnzd1rSxyEPb6puLdmPJTt/trhVqITIo5oYDp3DwxDlM/tn4AjG7/PPFeG3eDr8vFpu35QiyTxbizZ934U3dAdGb0+eKcbqwGGM/WYMnf9js1/aMpO0/ibmbD/ueMQhW7MnFND8O7Gb8c9YWpO0/YWpepRS+T8sO6Sl9OJWVKSzefhRKKaTtPxGwmwDO23LEcHplWmrHz9yMjk+bb3mO5MEYURf2nnb2jsNnDKff+OEq/OGT8qsl1+5z/oLmnDrn1on57i97cM9nzu2ugero9XdIaFFJqaN8by7ajY+XZ5q6yCY1yz2I3l2SgXd1TV2uMo7lI107u0h+4Wckv/izX2X15qaPVuGhrzdUePnVe49X+Iro2z9dh5fn7qjwtl0t252Lr9cewE0frTY1/6LtR/HEd+l482dzB1pP7J+cx78N/xW1Hy/LxFMztxi+9p+1+3HvF6kY/8MW3PTRany0bG+IS2fef1PLv0t7juZjwqwtXg9OjlF+wS5YBURd2DevW93vZVbt9Xy15BUTlwSsE9PMME/XboKMYwX4wcsInce/TceAN5bifHGpI+zMdBDdPMU5iMx0Twx5czlGf/Cb13l+y8jD1kPOHeJbD53Gwm1HUHihBD+kZfvVF+Jq/pbD2JLtvv6xn6zBxPk7K7zeQMryc0TMGe2UP1A/trN4h+ezzmW7c7Hay+cdsI3qefrHLaYvRjqWf95wGKG9SQMAfkjLxtdrbc/t8248eBKA7TOuV1qmKjxK7Ms1+3G8wLYf12hXQRe5VAL2aNvLzC3AX75MNXVGVVBUguvfX4mv1h7Afi9ly9O2HYlpH3VhX6tqXMDWtT7rpNu0/6zZbziv/r2tTBu2awwOeXMZ5qTnGM4LAEt22sbslpYpp7OLvIIifPTr3koFa0XcNm0trntvJcrKFD5flYV2T83Fde+txF++TMNzs7fhb9+l44vVxvsQsPUfGNXQTxVegFIKD3y1Ade/v9LpNXtn+x6Tbbb+OnTqHD5YmhG0fWmUC8cLipw6+43or8KcuSEbBUXO7cTFpWVu67hz+jqM/cT7fX++XnsA/1lzwDGgIa+gCA9/sxEntf28+2i+077o/cov6D9xCZ75cSveXmx8dvK379Lxz1nGNX37usrKFMrKFN5ZvBsD3ljq99XtGccK8MyPW/HXbzYCgNNNCIe/tdztc/X0j1uxcNtRpBl8z129Mnc7zhfbljfTxn70dJH5UTkArnjtFzw/Z5up+Ssq6sK+Ue2qQV3/0z+WXyaglHI0a+hr7V/aDwgu3+Idh88gM9e5FlNZ57RhdvrO22dmb0PKy4vx+oKdeMVk88TcLYFtL/9py2E8N2cb9Ge8W7Qa/3NztmHFnlzsOeoeZvO2HMHm7FNO0w6eKET3Fxfh05X7KlWmopJS3PzRKmw84PvLrdd/4hJMWrgLB04U4mxRCWZvOuR1fkftzk/6Q8nQt5Zj+NvLMWuj57O67i8ucjx+3OVmaNknC/HST9sx/O3lfncA2i9Gsr93V7+xFHPSc3DVG0uxcNsRDHtrOZKenu+23Jdr9rvVos34cVMOCi+UoPuLP2PAG0vxm3bmYR8t8/mqLLQZPxdlZQpz0nNwVjuoLd5+FAVF5bVye5ifOOt+K4JdR/MN7oNl+4K6HsKnrcjEziPOzb7frCuvwLnuayPXv78SL/603ed8djmnz+OzIN8hN+rCvkps6P6k71KzMfqD3/DYt5ucct1ba83gycscp5dGvNUeRQQXSsrQZvxct1sn/7rrGMSgjrgyo/zq4eLSMrz3yx7Dcdie7g4KAOkHTzldhexpHPd83QGjwMdohNs/XYehbxmPXHLdAwe002b7WUxF7TlagNT9JzFhlrnr+v61cJdT+6xA8MzsrXhkxiZsMDhgFJWU4tCpc3hvSflttfMKijB70yGvQ/Hsnxf9e28PrMe+TXfb32burfLyTzuQqtVYzYw6cV6/7f+T2jbOXrBtP7+oBH/5Mg2A5wEPvpwvLjXsWJv8826cOV+CQ6fOOfZDcanC83O24Tmtxpt24CQe/mYjnpm9FXtzC3DvF6lOfXH2/q7CC6WGge/Jou1HnS5mfHnuDox4e4XH+c2e4C3ZeQz/XX/QZ0d9sO++axd1YR8sh0+fc/vC2kehzNroXNPbnH0aI7wMwRzj5fa5CsCxM+c9ngHYT9VdT5dnbTyEwgvGIWw/QAx7azkmL9qND3/13iF2+lwx9h8/i51HzmDKsr0Y/cFv+OOnax2vu7ax2j3wVXkH60mTN3r6eJl7U9OZc8UYPPlXt051X1+ytZknMEPXTgwA01fuc6zngEtb67QVmfiflyay95dmODWhiQBHz9hqm4VajTKvoMhxJvenz1LRf+ISp3WkvLwYj8zYhNumrfXYDu2rK+fJ7zc7Djrfp2Xjie82O9Xqzcg4lo9Ve839QI69rX7mBu9nMBVpV+/0zAJ8vNw28mn30fLPkdFZ24Kth51qu/YKxMwNh/BPg85fezPLgROF6PmS7/1j3++frcrCE9/516m94cBJtBk/13HF8sfL9rqdqWafPIcnf9jss6P+/SWh+c2NwDVwR7l+ry3x+rrrF3bnkXwkVPO9e42+ML1f/QUA8N39/ZymL9+d67Hmn1dwwXAUTowI8rUvr/2D6aum8bv3V7pdh6B33XsrPb5mZ3SmsNOgDfq1+TuRUL2K07QVe/KQmXsW7yzegym393Kcr/jqSLtQWobxM7dgTO9WAGxtz/ZT6ayJo/CgdjCyv1dmRuA8+u0mx+MBbyxFkwRbM6GCwtmiEvR77RcUlyr0a9fA6SzK1cYDp3x29CvYzr4GTvrVafqc9Bxc0b4BxvRu5Xco2Q0xuFpbL23/CWw8cAr3Dmhn+qKsAW8sRdbEUV7nKS1TiPXzMnX7J9x10MvbupFirqPmAFvns57rgIhrJi9D+0a1HM9dO8RfX7AT/xjRyfHcUwd1XkERbvxwFQDbd7JV/Rp4bf5OvOZlgEBJaRmmrsjE3Ve0dXstv6h8O/d8th7T77rc43oqgzX7ADGqaZ0xcWGFawDos/yWKe41gvJ7+pj7Ah08WYhpLrWm3zK8j8bwFvTB4FrjdlWkhc+GA6cc05bv9n0bbH2HoP4gWZlhskfP2AJi+sp96PLcQkdzRkVqufvyzuKjX/c6mt+UAj5cutdwZMvGA6dMXZSnZ2+j9tSMc+jUObQZPxc/pGXjpo9WOw5++s/gKi8HMMB2Pydv2v9zHrblBOZGZOl+XlT4m0vZS8oUdhn0E9l95HLGu97ggOJKKeXo4/Bm5sZDeGPBLjzwVZrXfo3KNlV6w7CPML4+NvbPldkrXvPPl7h9iCON63fF3qexYJvtIpm7DW5Re8f0dVinfRmNznZcrzYe+U55G+zWQ2cMQ2qdiS+33dJdzgebHUeMr+PwZtC/fsXrC3Y61SDf8jCa5dvUg0ic4N4p6s1JLeRdmxkB4P8+Xo3dWvD9TXe2MHW5c7NadgDuzDjqXd9ngkYqexvyinQW+1spyDl93tRQW3u/y6+7ct0OWqEaMMewjzCHfXy5Xl9gO1U8fa4Yj8zYGIoimeKt09kX1y+1vrkn5WXPba8rM/LQZvxcvLXY+UKwU4UX8HuX6wGMmpBcvfNLxS9qMuocN+vZ2bYOSG9DbP1lP1ACMGzeW7vvhOFB8tV5O52uHH/y+8pfHe0ve7H2HA3syDV/tg0AR077HlU1dXmmx4EGevb32Mi2HP8rChXBsI8wx3xcWKMfNTB7U+DCobK8dTr78vEyz7cqyCvw3NFrv9rXtab0pZdx/N5UJrA/Xenf7RZCfS9zI3n5xvs2K8TNeK7sZ2VG7fLBpu8T8XRdwMWKYU9RZ7LJ+/u4WpmRhykVvHTf20HJiOuonXAIxD2Nos1MgyavaMGwJ9KJlFsuEAUaw56IyAIY9kREFsCwJyKyAIY9EZEFMOyJiCyAYU9EZAEMeyIiC2DYExFZQFSGvf02tEREZBOVYR9bmXvYEhFFoagM+xb1aoS7CEREESUqw74SNy8kIopKURn2CdWq+J6JiMhCojLsJ918WbiLQEQUUaIy7OvVjEf6s8PCXQwioogRlWEPAHVqsCmHiMguasOeiIjKMeyJiCwgqsP+wYHtw10EIqKIENVh36lZQriLQEQUEaI67JVS4S4CEVFEiPKwD3cJiIgiQ1SH/aVsxiEiAmAy7EVkhIjsEpEMERlv8PpAETktIpu0f8+aXTaYOjatjfjYqD6eERGZ4jMJRSQWwAcARgLoDGCsiHQ2mHWFUqq79u9FP5cNmv/99cpQbo6IKCKZqfb2BpChlMpUSl0AMAPAaJPrr8yyAdGyfvVQbo6IKCKZCfvmAA7qnmdr01z1E5F0EZkvIl38XBYicp+IpIpIam5urolimVMtLjZg6yIiuliZCXuju8O7jnPZAKC1UioZwHsAfvRjWdtEpaYqpVKUUimNGjUyUSxzYmIEO18aEbD1ERFdjMyEfTaAlrrnLQDk6GdQSp1RShVoj+cBqCIiDc0sS0REwWcm7NcDSBSRtiISD2AMgDn6GUSkqYjth19FpLe23uNmlg2FqnEckUNE1hbnawalVImIjAOwEEAsgOlKqW0icr/2+hQANwN4QERKAJwDMEbZLl81XDZIf4tHwh8gJyKLM1XlVUrNU0olKaXaK6Ve0aZN0YIeSqn3lVJdlFLJSqm+SqlV3paNBOsmXONznl6t64WgJMaa1+UoIqJI9vHtvcJdBL9Yrn3jiWFJWP3UYDSuXc3rfAMSG2Jwp8am1vnnAW0DUTQAQLfmdQAAt6S0CNg6iS42XZtH/tXvF1uFzDJh/8EfemJwp8YYNzgRzerY3qR62q9ZzX6oP/q0re80/6Sbk2Gm9addw5qYMKpi14ktfWKg0/PklnUxyOQBBgBaN6hRoe2GQ62qPlsMK+Tt/+teqeWfua5y1/j1bFW3Usv7q12jmiHdnifBPuu9vW/roK4/EErLLq6bb1km7Edd1gzT77rcadqccVfiwYHtcVmLOk7B/sSwJDStUw3iMnJ03KAOaNfQ+cvW+RLPNZBhnZt4vT9PW9d1eZj3qZGdDKfPe3gARne/BAAQF+P7yHRbn1YY72FdwWY27BvUjPdrvT1bVS504g067x8fmoS+7eobzO1u4k3B+XH7kV2bYvfLIzGiS1On6QOTyisDFQncO/uFL0Rb1IvMmvCtBmfRPUwcxOv7+VkFwjtYxDJhb6Rl/Rp4ckQniAga6Zp12jasBQBQuksCsiaOwhPDO6LMj1tpvjOmB+Y/MsDwtYcGuf+wigjQqr6ttt6iXg08OiQRQzs38Vjbr6kL0Fdu6GqqTP50VbcPci3S6MDTr30Dv9ahjC/bMB3WRv46uANqxLsfnP5ydTu3aUlNajseN03w3jRo1tInBuKjP/ZCfFwMalT1fFFgk4SqpteZ+eq1eOWGrvj7COOD/V1XtPG6fKPaztsamOT/tTAVCcdQGNmtWYWWa1n/4jmzBiwe9nqv3tAVr97QDe+N7YFruzX1OF+sSw3aU7vdzb1aoHq88Rf1f+OuxN+Hu3/p/i+lJW7q2Rxf/7kPburZHI8OScInd6Q4BYqroZ2bAHCu4X51bx+P8+vPYLImjnLbvl3fdvUx66H++NctyR7XVVFTb++Fl37fFfdfXX7Aq6ntq4pur2GteDyg/TLZo0MSMeO+fm7z1K5mvinJzG8hzHzwCgDAJ3ekYOGjV6Gxh/BNblnX9HYB5zM+17PLpCa2isg7Y7rjgas7eF3PkyM6Oh7HxAhu69MatarGoVoV96/9vT76nRIb18KrN3QDAAy5tDEeGtQBG54Z6jaftzNMAUzfmNBo91/ZoSGqxPo3sm7Fk4MMp9srYX8e0BaDOnpvOv3wtp5+bdPIu2N7YHT3S5yqJg1rmT9YBwLDXlO7WhX8oU8rXJ98iWOopusXDQCu1WoBfx9u+yJdmdjQcH0DPEwHgG4t6rhNy5o4Cskt60JEcEX7hqaHi1532SXY9fIIJDapjRQTp/WuNTS9P+m+8E+O6ISEalVwc68WuLGn4R0uHEb5WTMa1qWpW5vsTw8PwJxx/VGtSvkB8pZeLRzNVL7UiI9zlGPIpbYD4Eujuzhe//vwjhg3yD0ch2sHS1/eGdPd6drvuBhxHGCHdm6Cjk1rY9qdKfhj31Zuy3oKixd15bNzHRTg+jEY1qUpFj56FUZ3b45uLeq4HbD1HhzYARNv7IapLqNG4mLcv/a+Pm9K2e4iCwAjujZDTIw4auo39ij/fPTxdkblYRtmmviqVYnBf+7tg8eH2r53l2nfoTdcmtHsB7JHrknE3levdat9b31hOKbdkYJLmyUga+Iot/62r+/tg20vDHc8f3rUpY7vPAC374LZM+pruzbFO2N6OCoRK/8xCEueuBq39GqB2tXiMO2OFFPrqQyGvZ8eHZKEVeMH46FBHZD69BAMSHQ/nV38+NUY3d17QPqrfwdb80YXrY+gd5vyL1VV7f4/Dw22hZm+nyDt6SF44Xdd0Kh2Vdzdvw1+76Vc9WvGI2viKGRNHOV0pjDp5mTMfdjz3UMfNGiSApw7kBUUru3WFJ/eafyhblArHpe1qOs0bdItyXhnTA/Me9i4KcxV1+a28OuqjWga2tn5DE1fq4qPjUHWxFFonFANPzzQz6mzXEQwbrDzgcH1/TSq9zeuXQ1/ucqgeU732H5Aem9sD9zU09ZW/O7YHuXrdanS1qlexW199tC1S2xsq+3f2KM52jSogX+M6ITZD/UHAIzp3QrDung+U7Wra7AdAPjlb1djbO+WmHTLZejVuh5WPzUYN+kCL2viKLyp6ySfensKHr4mEQDcKh+eDicCYOKN3fDajd08ls8eyg8MbI+siaMwZ9yV2PXyCNx6eUun+X58qD9e+n1XPDY0ye0sHLAdWIZ4OcBf0aGhU/NoD+17YO87GXJpE3x+T2/HWeltfcz1gdjfVftBtXHtakioVgWTbknGlueHey1ToARniESUMBppERsjuERruvF0GtZB+/LZvTOmO9o1rIXr319Z4bJMv+tyrNt3AvnnS/DgVxswrIv7h2NQx8ZuNb0Gtariziva4E5dm+wNPZpj1sZDbst7+jLGxgi6XFJ+NnJP/7aY/ts+n2Xu3CwB+48XOp5/eFvFxiV76gRvWKsq6la31S6HG+wPTwYkNsRkXXNRr9butdEmuvb3N2/V5tXtoK4eytSyfg3Mf2QARr6zwjFN31ZdVxsBVr1KLGpWjXO8X8/P2YYTZy8gwSV0nxjWEU0SquL9JRk4c77E6991/8D2Xpv87DpfkoB1+04AAL69ry96ta6HOF3zyoJHB+DPX6Ti4IlzqBITg9duLK8920eyuZr9UH8kVK+CmlXj8NiQRAzu1BjJLepg//FCrMjIwzM/boUI0Ld9Ayzf7XKjQ7EdlADgqZlb3Nbt6eylqsFNDts0qIlOTY3fmxoemlWNPDYkCfd9mepoNrP3DQmAq5Ma4WovfRaX1KmGnNPnAdiaVH/LyEMVbf/OfOAKzN962HBgAOA+aCOQGPZe9GnXAFViBcWllRtipa8VmmlqMVI1LhYDEhtBKYV/33W51w+bL5NvScbrlRhF8uz1nU2FfY34ONzSqwW+S8s2bBLTM9sS27h2VUy+NRnzthzG06M6o2bVOGx4ZqhhDdi1A7NfO9vZ0QMD26OxQWfqzAevwE/ph52mNa9bHTdqNfAbejTHx8sy8a9bkjHkUs/tvPozK9egmjDqUiQ2roVrXJZPe3oIvkvLxjCXGl71+Fjcd1V7TF2e6XF7w7s0xZ5jGaY7QD+5IwULtx3B8M5NUadG+X6zt2/rmz48dYC70vdLiAi6a8/bNKyJvIIi23QAU/7YE52fXWhqnYESI0CZAjY9O8z0MlclNcLOl0Y6nttPuIxaoq5OaoRlugPYkicGotMzCwAA/Ts0RP8O5U26XZvXcZx5usp4ZWRQr/Zn2PuQ9sxQnLtQanp+T6NvANsoi8Ze2szNEBG/xuIbiYkRxBud4vrRgfnvuy/H9pwz2Jx9CjW1kSst61fHwRPndGUFHh+WhO/Ssn2Ghq8P+ZQ/9sKuI/l4ZIitiUDffOYp5EQEq8YPxt3/Xo+be7VAk4RqXtu4e7aq53UoZ6emCV6XN6NGfBzu6u/eGSoiuDWlpcESNl//uS9+3HjIcW2I3uNDk3DPlW1Nh32d6lUMt6UPeV8HZ3/omzBqxMdh1fjBuGLiEt22PDMaFumv+Y9chdV78zzWpv3jXtrpd12O4tIyR8Dr+538ERfkX9Vj2PuQUK0KEqoZt2ca8WdcPQD85099sD7rRIXK5ouZL3+6VtupYxAi3gzq2NgximH/8bOO6e+M6Y43F+3G/uOFfo2r9nWdwIiuTTGiq++2Z1eX1K2OhY9d5fdykSapSW086WHYpL6zNJLZ32HXMPR2oA/EQadj09pu/RyuXhzdBT+kZXt8fcKoS3GhtMzwjDo2RhAbE/m/m8GwD7MrExt6HNFTGenPDTM1TM3fkPdGIBjdvTl+l3wJluw8hquTGiFXO4X35Kt7+2DOppwK14YoOF67sRtembvDYxu9P1yHUdo/l52a1sbOI/mmrlSv6LbMuqNfG9zRr43H11s3qInP7u5dsZVHCIZ9lDJqww4VEcE12vBHXzUz1zbNaDH9rhQcOnU+3MWosP4dGmKelyZJf3RrXgddmyc4bk1Ru1oVzLivL5omVMPAf/3q9gnxdYGXN2b7GILhvbE9/OoEDjWGfQBdUicwV1BebFrVr4F7+rfFH/q4jzGvV9N20Hl8aFKoixVWgzsFfyjdxaJ6fCx++qvzgaNvuwblHbe6qr29T+SbdQcqtK1w/gzp9cnl14S88LsuEXd7CIZ9gKz95zURfVQPJhHBs9cb31CsalxspTs1w8F+4VHdADZzkbFAteLc3KsFYkzcIyoU7qzE2UmwMOwDpEmA7otCkaFpnWp4+fddHbejoMCrrvXTDPRxuwIz6tWoEpRbe0QThj2Zdme/1rgu2dztC6LBHy+C2+xezGpWjcPKfwzy+tsSZjpvVz812PDGdeSMe4hMe2G0ufuAEJnVop7xnSPtF8SZubNkIEYMWQHDniJO52YJqOnl1r4U/QZ3aoLP7r7c8N5TVDEMe4o4gRryRxe3QLTlUzne9ZKIyAIY9kREFsCwJyKyAIY9EZEFMOyJiCyAo3GIQuDfd12O88XmfxeBKNAY9kQhUNkfnCGqLDbjEBFZAMOeiMgCGPZERBbAsCcisgCGPRGRBTDsiYgsgGFPRGQBDHsiIgsQpVS4y+BGRHIB7K/g4g0B5AWwOIHCcvmH5fIPy+WfaCxXa6WUx197iciwrwwRSVVKpYS7HK5YLv+wXP5hufxjxXKxGYeIyAIY9kREFhCNYT813AXwgOXyD8vlH5bLP5YrV9S12RMRkbtorNkTEZELhj0RkQVETdiLyAgR2SUiGSIyPgTbaykiS0Vkh4hsE5FHtOnPi8ghEdmk/btWt8xTWvl2ichw3fReIrJFe+1dEZFKli1LW98mEUnVptUXkUUiskf7v14oyyUiHXX7ZJOInBGRR8Oxv0RkuogcE5GtumkB2z8iUlVEvtWmrxWRNpUo1yQR2Skim0VklojU1aa3EZFzuv02JcTlCtj7FuByfasrU5aIbArD/vKUDeH9jCmlLvp/AGIB7AXQDkA8gHQAnYO8zWYAemqPawPYDaAzgOcBPGEwf2etXFUBtNXKG6u9tg5APwACYD6AkZUsWxaAhi7T3gAwXns8HsDroS6Xy/t1BEDrcOwvAFcB6AlgazD2D4AHAUzRHo8B8G0lyjUMQJz2+HVdudro53NZTyjKFbD3LZDlcnl9MoBnw7C/PGVDWD9j0VKz7w0gQymVqZS6AGAGgNHB3KBS6rBSaoP2OB/ADgDNvSwyGsAMpVSRUmofgAwAvUWkGYAEpdRqZXvnvgDw+yAUeTSAz7XHn+u2EY5yXQNgr1LK21XSQSuXUmo5gBMG2wvU/tGv63sA15g5+zAql1LqZ6VUifZ0DYAW3tYRqnJ5Edb9ZactfyuAb7ytI0jl8pQNYf2MRUvYNwdwUPc8G96DN6C0U6geANZqk8Zpp93TdadqnsrYXHvsOr0yFICfRSRNRO7TpjVRSh0GbB9GAPYfRQ1luezGwPlLGO79BQR2/ziW0YL6NIAGASjjPbDV7uzaishGEVkmIgN02w5VuQL1vgVjfw0AcFQptUc3LeT7yyUbwvoZi5awNzqihWRMqYjUAvADgEeVUmcAfASgPYDuAA7DdirprYzBKHt/pVRPACMBPCQiV3mZN5TlgojEA/gdgO+0SZGwv7ypSDkCXkYRmQCgBMBX2qTDAFoppXoAeBzA1yKSEMJyBfJ9C8Z7OhbOFYqQ7y+DbPA4q4ftBLRs0RL22QBa6p63AJAT7I2KSBXY3syvlFIzAUApdVQpVaqUKgPwCWxNTN7KmA3nU/NKl10plaP9fwzALK0MR7XTQvup67FQl0szEsAGpdRRrYxh31+aQO4fxzIiEgegDsw3g7gRkTsBXAfgNu10Htop/3HtcRps7bxJoSpXgN+3QO+vOAA3AvhWV96Q7i+jbECYP2PREvbrASSKSFut5jgGwJxgblBrH/sUwA6l1Ju66c10s90AwD5SYA6AMVovelsAiQDWaadz+SLSV1vnHQBmV6JcNUWktv0xbB18W7Xt36nNdqduGyEpl45TjSvc+0snkPtHv66bASyxh7S/RGQEgH8A+J1SqlA3vZGIxGqP22nlygxhuQL5vgWsXJohAHYqpRxNIKHcX56yAeH+jPnqwb1Y/gG4FrZe770AJoRge1fCdtq0GcAm7d+1AL4EsEWbPgdAM90yE7Ty7YJuBAmAFNi+LHsBvA/tyuYKlqsdbD376QC22fcFbO15vwDYo/1fP5Tl0tZXA8BxAHV000K+v2A72BwGUAxbDelPgdw/AKrB1kyVAdtoinaVKFcGbG2z9s+YfQTGTdr7mw5gA4DrQ1yugL1vgSyXNv0zAPe7zBvK/eUpG8L6GePtEoiILCBamnGIiMgLhj0RkQUw7ImILIBhT0RkAQx7IiILYNgTEVkAw56IyAL+H76P7btSprdsAAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# 展示模型损失优化的过程\n", "plt.plot(torch.tensor(lossi))" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(torch.Size([32561, 2]), torch.Size([32561, 2]), torch.Size([32561]))" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 关闭梯度追踪\n", "with torch.no_grad():\n", " logits = model(x) \n", " probs = F.softmax(logits, dim=1)\n", " pred = torch.where(probs[:, 1] > 0.5, 1, 0)\n", "logits.shape, probs.shape, pred.shape" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(tensor(0.2928), tensor(0.5902), tensor(0.3914))" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from torcheval.metrics.functional.classification import binary_recall\n", "from torcheval.metrics.functional import binary_precision, binary_f1_score\n", "binary_recall(pred, y), binary_precision(pred, y), binary_f1_score(pred, y)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "# 通过排序得到对偏好估计\n", "class PreferenceModel:\n", " \n", " def __init__(self, pref):\n", " self.pref = pref\n", " \n", " def __call__(self, x0, x1):\n", " self.out = torch.concat((self.pref(x0), self.pref(x1)), dim=1)\n", " return self.out\n", " \n", " def parameters(self):\n", " return self.pref.parameters()" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "preference = Linear(5, 1)\n", "p_model = PreferenceModel(preference)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(tensor([[0.0679, 1.1044]]), tensor([[0.2618, 0.7382]]))" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x0 = x[[0]]\n", "x1 = x[[1]]\n", "p_logits = p_model(x0, x1)\n", "p_probs = F.softmax(p_logits, dim=1)\n", "p_logits, p_probs" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }