diff --git a/wyk/03_Ngramy.ipynb b/wyk/03_Ngramy.ipynb new file mode 100644 index 0000000..a8cdf75 --- /dev/null +++ b/wyk/03_Ngramy.ipynb @@ -0,0 +1,496 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n", + "
\n", + "

Modelowanie języka

\n", + "

03. N-gramy [wykład]

\n", + "

Filip Graliński (2022)

\n", + "
\n", + "\n", + "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## N-gramy\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "W modelowaniu języka często rozpatruje się n-gramy, czyli podciągi o\n", + "rozmiarze $n$.\n", + "\n", + "Na przykład *digramy* (*bigramy*) to zbitki dwóch jednostek, np. liter albo wyrazów.\n", + "\n", + "| $n$|$n$-gram|nazwa|\n", + "|---|---|---|\n", + "| 1|1-gram|unigram|\n", + "| 2|2-gram|digram/bigram|\n", + "| 3|3-gram|trigram|\n", + "| 4|4-gram|tetragram|\n", + "| 5|5-gram|pentagram|\n", + "\n", + "**Pytanie:** Jak nazywa się 6-gram?\n", + "\n", + "Jak widać, dla symetrii mówimy czasami o unigramach, jeśli operujemy\n", + "po prostu na jednostkach, nie na ich podciągach.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### N-gramy z Pana Tadeusza\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Statystyki, które policzyliśmy dla pojedynczych liter czy wyrazów, możemy powtórzyć dla n-gramów.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[('k', 'o', 't'), ('o', 't', 'e'), ('t', 'e', 'k')]" + ] + } + ], + "source": [ + "def ngrams(iter, size):\n", + " ngram = []\n", + " for item in iter:\n", + " ngram.append(item)\n", + " if len(ngram) == size:\n", + " yield tuple(ngram)\n", + " ngram = ngram[1:]\n", + "\n", + "list(ngrams(\"kotek\", 3))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Zauważmy, że policzyliśmy wszystkie n-gramy, również częściowo się pokrywające.\n", + "\n", + "Zawsze powinniśmy się upewnić, czy jest jasne, czy chodzi o n-gramy znakowe czy wyrazowe\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 3-gramy znakowe\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "log_rang_log_freq('pt-3-char-ngrams-log-log', ngrams(get_characters(pan_tadeusz), 3))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 2-gramy wyrazowe\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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RL+6dbjiPI7+b9N+/X5NoelYAABEDAUQVnIcR1fnddH3J/WTJP349S3aWVJpOBUAAJFBAYTVvj22ty6/sIOO1tbre6+s564hAAArUABhNY/H0VM3DVX75Hht2e/XE29uNx0JAIA2F2c6AGBadnqinvzSEN352zV6fsVuZaYkqFOar9ljs9J8GtunkzweJ8IpAQBoPRRAQNKEgdmaOqqHfvPRHj351plHAb80opsev3GwvJRAAIBLUQCBY+6/ZoCCIekfh480+3owJK3YWao/rP2HauqC+vlNQxTv5SoKAID7UACBYxLjvXpkSt4Zj3lj037d88p6vb6hSIG6ej1z83AlxFECAQDuwpkLOAeTL+qiX906Qglej97afEDfe2W96oNsIg0AcBcKIHCOJgzM1nNTRyrB69Gbm4s1e9Em7iQCAHAVCiBwHsb17aRf3DxUHkdasLrwrAtHAACIJk6IoYvz5vf7lZGRofLycqWnp5uOAwMWfLxXs/60SZLUISVBjiO1T07QI1PydFnvDobTAQCaw/mbEUCgRb56SXfNmtxfjiMdqqpRaWWNPimp1HdeXquisqOm4wEA0CxGAFuAvyDQqLi8WmVHaxQMSj/8wwZtLvJrWPd2WvitUawSBoAow/mbAtgifIDQnL2HjujaZ5arorpOk/M6a0huu2aP65OVqqsGZEc2HACA87cogC3CBwins3jLAX3zt2vOfty9Y9UnOy0CiQAAjTh/sxE00CYmDszWr24drsVbSpp9fc2ez7Tn0BG9t62EAggAiDgKINBGrs7roqvzujT72osf7NaP/7xFS7Yf1LfHXRDhZAAA21l7dfrcuXM1ePBgpaenKz09XaNGjdIbb7xhOhYsMb5flqSGkcDKQJ3hNAAA21hbALt166af/vSnWrNmjdasWaPPfe5zuv7667V582bT0WCBnh1T1KNDsmrrQ/pgZ6npOAAAy1hbAK+77jpdc8016tu3r/r27atHH31UqampWrlypelosMT4vp0kSUu2HzScBABgG2sL4Inq6+u1YMECVVVVadSoUabjwBKN08BLt5eo7EiNauqChhMBAGxh9SKQTZs2adSoUaqurlZqaqoWLVqkgQMHnvb4QCCgQCDQ9LXf749ETMSoy3p3UEKcR0Xl1Rr68GKlJ8bp9bvHqGfHFNPRAAAxzuoRwH79+qmgoEArV67U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448/1ve+9z35fD59/etfNx3PNe677z6Vl5erf//+8nq9qq+v16OPPqqbb77ZdDTXajyvNHfO2bNnj4lIiCAKYBRyHOekr0Oh0CnPITx33323Nm7cqBUrVpiO4jqFhYWaPn263n77bSUmJpqO41rBYFAjR47UY489JkkaNmyYNm/erLlz51IAz8HChQv18ssva/78+Ro0aJAKCgo0Y8YM5eTkaOrUqabjuRrnHDtRAKNIx44d5fV6TxntKykpOeUvNJzdPffco9dff13Lli1Tt27dTMdxnbVr16qkpEQjRoxoeq6+vl7Lli3TnDlzFAgE5PV6DSZ0hy5dumjgwIEnPTdgwAD98Y9/NJTInX74wx9q1qxZ+upXvypJuuiii7Rnzx7l5+dTAM9T586dJTWMBHbp0qXpec45duAawCiSkJCgESNGaPHixSc9v3jxYo0ePdpQKvcJhUK6++679ac//UnvvfeeevXqZTqSK1111VXatGmTCgoKmh4jR47ULbfcooKCAspfmC6//PJTtiHasWOHevToYSiROx05ckQez8mnLK/XyzYwLdCrVy917tz5pHNOTU2Nli5dyjnHAowARpmZM2fqtttu08iRIzVq1CjNmzdPe/fu1V133WU6mmtMmzZN8+fP12uvvaa0tLSmEdWMjAwlJSUZTuceaWlpp1w3mZKSog4dOnA95Tm49957NXr0aD322GO66aab9PHHH2vevHmaN2+e6Wiuct111+nRRx9V9+7dNWjQIK1fv15PPfWU7rjjDtPRolplZaV27tzZ9PXu3btVUFCgzMxMde/eXTNmzNBjjz2mPn36qE+fPnrssceUnJysr33tawZTIyJCiDq//OUvQz169AglJCSEhg8fHlq6dKnpSK4iqdnHCy+8YDqa640bNy40ffp00zFc589//nMoLy8v5PP5Qv379w/NmzfPdCTX8fv9oenTp4e6d+8eSkxMDPXu3Ts0e/bsUCAQMB0tqr3//vvN/j6cOnVqKBQKhYLBYOjBBx8Mde7cOeTz+UJjx44Nbdq0yWxoRAT7AAIAAFiGawABAAAsQwEEAACwDAUQAADAMhRAAAAAy1AAAQAALEMBBAAAsAwFEAAAwDIUQAAAAMtQAAEAACxDAQQAALAMBRAAAMAyFEAAAADLUAABAAAsQwEEAACwDAUQAADAMhRAAAAAy1AAAQAALEMBBAAAsAwFEAAAwDIUQAAAAMtQAAEAACxDAQQAALAMBRAAAMAyFEAAAADLUAABAAAsQwEEAACwDAUQAADAMhRAAAAAy1AAAQAALEMBBAAAsAwFEAAAwDL/D8vJV/y5wMT/AAAAAElFTkSuQmCC", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "log_rang_log_freq('pt-2-word-ngrams-log-log', ngrams(get_words(pan_tadeusz), 2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tajemniczy język Manuskryptu Wojnicza\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Manuskrypt Wojnicza](https://pl.wikipedia.org/wiki/Manuskrypt_Wojnicza) to powstały w XV w. manuskrypt spisany w\n", + "tajemniczym alfabecie, do dzisiaj nieodszyfrowanym. Rękopis stanowi\n", + "jedną z największych zagadek historii (i lingwistyki).\n", + "\n", + "[Źródło: https://commons.wikimedia.org/wiki/File:VoynichManuscript(135).jpg](./02_Jezyki/voynich135.jpg)\n", + "\n", + "Sami zbadajmy statystyczne własności tekstu manuskryptu. Użyjmy\n", + "transkrypcji Vnow, gdzie poszczególne znaki tajemniczego alfabetu\n", + "zamienione na litery alfabetu łacińskiego, cyfry i gwiazdkę. Jak\n", + "transkrybować manuskrypt, pozostaje sprawą dyskusyjną, natomiast wybór\n", + "takiego czy innego systemu transkrypcji nie powinien wpływać\n", + "dramatycznie na analizę statystyczną.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "9 OR 9FAM ZO8 QOAR9 Q*R 8ARAM 29 [O82*]OM OPCC9 OP" + ] + } + ], + "source": [ + "import requests\n", + "\n", + "voynich_url = 'http://www.voynich.net/reeds/gillogly/voynich.now'\n", + "voynich = requests.get(voynich_url).content.decode('utf-8')\n", + "\n", + "voynich = re.sub(r'\\{[^\\}]+\\}|^<[^>]+>|[-# ]+', '', voynich, flags=re.MULTILINE)\n", + "\n", + "voynich = voynich.replace('\\n\\n', '#')\n", + "voynich = voynich.replace('\\n', ' ')\n", + "voynich = voynich.replace('#', '\\n')\n", + "\n", + "voynich = voynich.replace('.', ' ')\n", + "\n", + "voynich[100:150]" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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AAAAUDqxB5aDzGazjh8/rho1ali1Hzt2TOXKlXNOUoCLqTFmnV39k6d0LqFMAAAAAAA3M2ZgOahbt26Kjo7Wzz//bGk7duyYRo4cqW7dujkxMwAAAAAAgNKFApaDpk+frnLlyqlOnTqqWbOmatasqbp166pChQqaMWOGs9MDAAAAAAAoNVhC6CCz2awdO3Zo48aN+v777+Xt7a1GjRrpP//5j7NTAwAAAAAAKFUoYF0Hk8mkiIgIRUREODsVAAAAAACAUosClh1mz56tAQMGqEyZMpo9e3ahfYcNG3aDsgIAAAAAACjdKGDZYdasWerZs6fKlCmjWbNmXbOfyWSigAUAAAAAAFBMKGDZISkpqcB/AwAAAAAAoORwFUIAAAAAAAC4NGZg2WHEiBE29505c2YJZgKUfjXGrLO5b/KUziWYCQAAAADA2Shg2eG7776zqZ/JZCrhTAAAAAAAAP49KGDZYfPmzc5OAUAR7Jm5JTF7CwAAAABuBuyBdZOYMGGCTCaT1S0oKMhy3DAMTZgwQcHBwfL29labNm30448/Wj1Gdna2hg4dqooVK6pcuXLq1q2bfv31V6s+6enpioqKktlsltlsVlRUlM6ePXsjThEAAAAAAKBAFLBuIvXr11dKSorlduDAAcuxadOmaebMmZozZ4727NmjoKAgdejQQefOnbP0iY6O1po1a7RixQpt375dWVlZ6tKli3Jzcy19evToof379ys2NlaxsbHav3+/oqKibuh5AgAAAAAAXIklhDcRd3d3q1lXlxmGobfeektjx47Vww8/LEmKiYlRYGCgli9frmeffVYZGRlasGCBlixZovbt20uSli5dqpCQEH311VeKjIxUYmKiYmNjFR8frxYtWkiS5s+fr7CwMB0+fFihoaE37mQBAAAAAAD+f8zAuokcPXpUwcHBqlmzpp544gkdP35ckpSUlKTU1FRFRERY+np5eSk8PFw7duyQJCUkJOjixYtWfYKDg9WgQQNLn507d8psNluKV5LUsmVLmc1mS5+CZGdnKzMz0+oGAAAAAABQXChg3SRatGihjz76SBs2bND8+fOVmpqqVq1a6c8//1RqaqokKTAw0ComMDDQciw1NVWenp7y8/MrtE9AQEC+sQMCAix9CjJ58mTLnllms1khISHXda4AAAAAAABXooB1k+jUqZMeeeQRNWzYUO3b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5igxMVHTpk3T9OnT9c4779h8zgsXLtTQoUO1ffv2Qr8UXOmRRx7R999/r5iYGB05ckRr165VmzZtCv35XKljx45KSUmxun388ccOx9asWdOmmOTkZH344Yf6/PPPNWjQIJvGuzL++PHjev311zV37lyNGjXKptg9e/bogw8+UKNGjWzq36pVq3znl5KSovfff18mk6nQvENCQrRixQpduHDB0vb333/r448/VrVq1a4Zt3XrVg0ePFjx8fHauHGjLl26pIiICJuLdGXKlNHUqVNtLgpe6cr/z02bNsnd3V1dunQpNOZ6XqeOcnNzU0xMjGJjY7Vs2TJL+9ChQ+Xv769x48YV+5iS9O233+qrr76yavvqq6/07bfflsh4ffv21ddff61ffvkl37GFCxeqSZMmatq0aYGxVz5f33rrLfn6+lq1vf3221b927Ztq6ysLO3du9fStm3bNgUFBWnPnj1WX/q3bNmi4OBg3XHHHcV0pv+48r1h/fr1atu2rYYPH64uXbpYFdauVrVqVU2ZMkV79+7V3r17dd999+mBBx7Qjz/+WKz5XS09PV2tW7eWh4eH1q9fr0OHDunNN9/UrbfeavNjlC1bVkFBQXJ3d7drbLPZbNcXzMzMTD344IPav3+/1e3TTz8tdCaLyWTSokWLtGvXLr3//vuW9qSkJL344ot6++23C30/27Nnj9XzbuPGjZKkxx57rMict23bplmzZungwYN66qmn9PTTT+v48eNFxh0/flx33nmn4uLiNGnSJH333Xf66quv9Pzzz+vzzz/P9xq+0sqVKxUdHa2xY8fqu+++07333qtOnTrZ/Hks/fMFd/HixTb3v9qHH36onj17as6cORo9erTDj1MaXbhwQQsWLFC/fv3simvUqJFq1Khh9XkBa/Xr17d6rR44cKBEx0tISNBDDz2kmTNn6tVXX9WGDRvk7++vbt266e+//y7RsQFcgwHgunTs2NGoWrWq8ddff1m1p6SkGGXLljUGDhx4zdhOnToZVapUMbKysvIdS09Pv2bcX3/9Zbi5uRlffPGFVXvjxo2NsWPHFppv586djT59+li1Pfzww8ZTTz1VaNxlWVlZho+Pj/HTTz8Z3bt3NyZOnFhkTHp6uiHJ2LJli01jXK1Xr17GAw88cMNiC4oZMWKE4e/v73B8v379jKCgoCJjz507Z9SuXdvYuHGjER4ebgwfPtzGrK0dOnTI8PX1LfT5cDnPhg0bGkuXLrW0L1u2zGjYsKHxwAMPGL169bJpvLS0NEOSsXXr1iL79urVy+jSpYtRp04d44UXXrC0r1mzxijqY6mgn+0333xjSDLS0tKuGXc9r9Pr9fbbbxt+fn7GqVOnjE8//dTw8PAwvvvuO5vj7X0Onzhxwnj00UeN5557zmjatKnx3HPPGd27dzd+/fXXEhnz4sWLRmBgoDFhwgSr9vPnzxs+Pj7GO++8Y9PjLFq0yDCbzUX2Cw4ONiZPnmy5P3r0aGPw4MFGvXr1jI0bN1ra77vvPqNnz542jW2ra/1cNm3aZEgy5s+fb9fj+fn5GR9++GGhfa71PmDL68UwDOPFF1807rnnHrvysmV8e0gy1qxZU2S/9evXG+PHj8/XnpSUZHTv3r3I+MWLFxvly5c3jh8/buTl5Rlt27Z16LNj+PDhxu23327k5eXZFffnn38akoxt27YV2TcyMtKoWrVqgZ//hmEUOvbdd9+d7z2rTp06xpgxY2zONTw83Fi0aJHN/a987k+dOtXw8vIyPvnkE5vjDcMwNm/ebFSvXt2hMa9+HEmF/p5UWHxRwsPDjaFDhxovvPCC4efnZwQGBhb4vLyW1atXGxUrVrR7XMMwjAkTJhj33nuvXTF///23MXToUKNSpUqGl5eX0bp1a2P37t1FxlWvXt2YNWuWVVvjxo1tOtesrCwjKirKKFeunBEUFGTMmDHDpveK8PBwY/DgwcbgwYMNs9ls+Pv7G2PHjrXptTZ+/HijcePGRfa7ltzcXGPKlCnG7bffbnh6ehohISHG66+/fs3+P/30kxEUFGTExMRYtf/9999G165djW7duhkXL14sMDYtLc0IDAw03njjDUtbfHy84eHhYWzYsKHQPGNiYgx/f3/j77//tmp/+OGHjaioqKJO0+jVq5chyeqWlJRUZNz69euN1q1bW/5fOnfubBw7dqzIOOBGYwYWcB3OnDmjDRs2aNCgQfL29rY6FhQUpJ49e2rlypUyDKPA2NjYWA0ePFjlypXLd7ywv45funRJubm5KlOmjFW7t7e3tm/fXmjO99xzjzZt2mRZVvP9999r+/btuv/++wuNu2zlypUKDQ1VaGionnrqKS1atKjA87tS+fLlVb58eX366afKzs62aRxXcvz4ccXGxsrDw8Phx/D29tbFixeL7Dd48GB17tz5mkuybHH27Fk9+OCDCg8P13//+98i+z/zzDNatGiR5f7ChQvVp08fu8bMyMiQJPn7+9vU383NTZMmTdI777yjX3/91a6xrpSVlaVly5apVq1aqlChQoF9rud1WhyGDh2qxo0b6+mnn9aAAQM0btw4NWnSpETGkv6ZVbdq1SqZzWbt27dPt956q1asWKEqVaqUyHju7u56+umntXjxYquf4apVq5STk6OePXsW63ht2rTR5s2bLfc3b96sNm3aKDw83NKek5OjnTt3XnP5bHG777771LhxY/3vf/+zqX9ubq5WrFih8+fPKywsrERzW7t2rZo3b67HHntMAQEBuvPOOzV//vwSHdNZevXqpXbt2umZZ57RnDlzdPDgQX3wwQd2PUZOTo6WLl2qPn362LxEU/pnGePIkSPVoEED3X333YX2/fPPPxUXF3fNz39J1xw7JydHCQkJioiIsGqPiIjQjh07bM7XUWPGjNF///tfffHFF/mWR5cmMTExKleunHbt2qVp06bptddes8zMK8o333yj5s2bOzTu3Xffrd27d9v1u9Lo0aO1evVqxcTEaN++fapVq5YiIyNLZGbxZS+88II2b96sNWvWKC4uTlu2bLF5WXJMTIzc3d21a9cuzZ49W7NmzdKHH35oU+zRo0cVHBysmjVr6oknnrBptuNlL730kqZOnapXX31Vhw4d0vLlyxUYGHjN/qGhoUpJSdHTTz9t1e7l5aW1a9fqs88+u+as1EqVKmnhwoWaMGGC9u7dq6ysLD311FMaNGhQvtfu1R577DHl5uZq7dq1lrY//vhDX3zxhZ555pkiz/Ptt99WWFiYZel3SkqKQkJCiow7f/68RowYoT179mjTpk265ZZb9NBDD9m1xQhwI1DAAq7D0aNHZRiG6tatW+DxunXrKj09Xb///nu+Y8eOHZNhGKpTp47d4/r4+CgsLEz//e9/dfr0aeXm5mrp0qXatWtXkfuNvPjii3ryySdVp04deXh46M4771R0dLSefPJJm8ZesGCBnnrqKUn/LKXJysoqcr8ud3d3LV68WDExMbr11lvVunVrvfzyyzbtW3TZF198YSmEXb7ZUpwpKNaWZSGXY7y9vXX77bfr0KFDevHFF23O90q7d+/W8uXL1a5du0L7rVixQvv27dPkyZMdGkeS8vLy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PT09Lc/d5s2ba8+ePXr77betNh6/mq+vr2WJ7pXOnj1rU5G6cuXK+WZ51a1bV6tXry4y9mbl7u5u94bzkvTLL7/oq6++snkp6GVJSUmSZPMX+MvvST/99JNV++WC69VLna9UsWJFubm55Zuhk5aWVuhyqIEDB+rxxx+33O/Zs6dlxsVlRRXfqlSpotWrV6tt27bq2LGjYmNj5ePjU2jM9Sro87uk/wggKd9ntslksnkpVcWKFR26QIkky7K/SpUq2dT/Wn8MtaWgfsstt+RbOm/LVgcltdzeXuXKlVPDhg119OjRIvsW9poqScePH9fp06eVl5enX375xeaL89x5551q3LixPvroI0VGRurAgQP6/PPPSzTXrl27KiQkRPPnz1dwcLDy8vLUoEED5eTklOi4gL2YgQVchwoVKqhDhw6aO3eu1VXcpH8uj71s2TJ17969wF8i/P39FRkZqXfffbfAK7cVdXnoy8qVK6fKlSsrPT1dGzZs0AMPPFBo/7/++ivfUis3N7cifzG7dOmSPvroI7355ptWfwn9/vvvVb16dYeumlOvXj2br1rnbOPHj9eMGTN0+vRpm/pf/qW7evXqNu2d1a5dOx04cMDqZ9u8eXP17NlT+/fvL7J4tX//fvXp00dTpkwp8FLyRenYsaNycnKUk5NjU7xhGBoyZIj+97//6euvvy7yi3thpkyZos8//9zh/VtMJpNuueWWfK/By2x5ndq7XMhWFy5cUK9evfTss8+qffv2+vDDD7Vnz55CCxbF6colfSXt8ccfl5ubm5YvX66YmBg988wzJVaka9u2rbZs2aItW7ZYLakIDw/Xhg0bFB8ff0OXD3799dc6cOCA3XsCGYZR5EybOnXqWF118bI9e/bYVDBp3bq1Dh8+bNV25MgRVa9e3a5c/w0WLVqkgIAAde7c2a64y7P/bHX5PWnOnDl2fwZ6enqqWbNm+fZj2rhxo1q1anXNOH9/f9WqVcty8/b2VkBAQL62olSrVk1bt25VWlqaIiIilJmZaVf+/wZ33nmnwzMrDx48qKpVq9o8C7pWrVry9PS02v/04sWL2rt37zWXzV9WqVIlq20nMjMzLcXYosb08PBQfHy8pS09Pd2yt2pRroy7fL927do2LXO7UnZ2thITE1W5cuUi+9auXVve3t42LwMtDpf3gOzevbtef/119e3bV7/99pvN8f369dOiRYu0cOFCtW/f3qZ9rC7z9PS0eUmn9M++fImJiXrllVfUrl07y9YKgCuigAVcp8uzYyIjI/XNN9/o5MmTio2NVYcOHVSlShW98cYb14ydO3eucnNzdffdd2v16tU6evSoEhMTNXv27CI39t2wYYNiY2OVlJSkjRs3qm3btgoNDS1yg8euXbvqjTfe0Lp165ScnKw1a9Zo5syZRS61+OKLL5Senq6+ffuqQYMGVrdHH3200L0W/vzzT913331aunSpfvjhByUlJWnVqlWaNm1akQW3yy7vCXHl7Y8//rAptji0adNG9evX16RJk0rk8X18fPL9XMuVK6cKFSoUua/UH3/8oQcffFBt2rTRU089le/nZMveTm5ubkpMTFRiYqJNv0QOHjzYshTVx8fHMta1ikiFadiwoXr27FnoEssrXflcSExM1NChQ5WVlaWuXbteM6aw1+kdd9yhcePG2Z23LcaMGaO8vDxNnTpV0j9f/t5880298MILJbqkzxnKly+v7t276+WXX9bp06dLrCgo/VPA2r59u/bv32+ZgSX9U0iYP3++/v777xIrYF1+/p06dUr79u3TpEmT9MADD6hLly75Nvu90ssvv6xt27YpOTlZBw4c0NixY7Vly5YiN7kfNGiQfv75Zw0ePFjff/+9jhw5onfffVcLFizQCy+8UGS+zz//vOLj4zVp0iQdO3ZMy5cv1wcffGDzEux/i7y8PC1atEi9evWye/bW5s2b7do3UPrn8//SpUtq3ry5Vq5cqcTERB0+fFhLly7VTz/9VOj78IgRI/Thhx9q4cKFSkxM1PPPP68TJ05o4MCBduXgqKpVq2rLli36888/FRERUeAMQVeRkZGRbwliSS+JioyM1I8//uhQAWDbtm1FbvJ9pXLlyum5557TCy+8oNjYWB06dEj9+/fXX3/9pb59+xYae99992nJkiXatm2bDh48qF69etn0+V++fHn17dtXL7zwgjZt2qSDBw+qd+/e19yH8monT57UiBEjdPjwYX388cd65513NHz48CLjRo0apa1btyopKUm7du3So48+qszMzCJXD0j/rAB48cUXNXr0aH300Uf6+eefFR8fX2L7hEnS2LFjlZGRodmzZ2v06NGqW7dukf8nV+rZs6dOnTql+fPn270cv0aNGtq1a5eSk5P1xx9/FPlHaj8/P1WoUEEffPCBjh07pq+//lojRoywa0zghrmBVzwESq3k5GSjd+/eRlBQkOHh4WGEhIQYQ4cONf74448iY0+fPm0MHjzYqF69uuHp6WlUqVLF6Natm7F58+ZC41auXGncdttthqenpxEUFGQMHjzYOHv2bJHjZWZmGsOHDzeqVatmlClTxrjtttuMsWPHGtnZ2YXGdenSxbj//vsLPJaQkGBIMhISEgo8/vfffxtjxowxmjZtapjNZqNs2bJGaGio8corrxh//fVXkTkXdElgSUZoaKhNsfZeRvtaMcuWLTM8PT2NEydOFPuYBbH18vWLFy8u8Odz+Xaty5YXlecDDzxg9OrVq8Bj1xrLlsuyFzRucnKy4eXlZRT1sXT1c8HHx8e46667bLqce1JSktGrVy8jMDDQMJlMhiTj4YcfNs6fP19krCO2bNliuLm5Gdu2bct3LCIiwrjvvvtsunR4VFSU8cgjj5REitfk6HN4x44dhiQjIiLC7thFixYZZrPZpr5JSUmGJKNOnTpW7SdPnjQkGbfffrvNY9rzq9CVzz93d3ejUqVKRvv27Y2FCxcaubm5hcb26dPH8j5fqVIlo127dkZcXJxN4+7du9eIjIw0AgICDF9fX6N58+bGxx9/bHPen3/+udGgQQPDy8vLqFOnjvHBBx/YHGvr+1BhJBlr1qwpst/69euN8ePH52tPSkoyunfvbvN448ePNxo3bmx7goZhbNiwwZBkHD582K44w7D/eXTZ6dOnjSFDhhg1a9Y0PDw8jPLlyxt33323MX369CLfl959913L86lp06bG1q1b7Ro7PDzcpvfrywp6Tzh9+rQRGhpq3HXXXUZ6enqRj7F58+Zrfh7ZOublx5FU5JjX+t3hWp9rlxX0nC/s87AgLVu2NN577z2b+xuGYVy4cMHw9fU1du7caXfc0KFDjYoVKxpeXl5G69atjd27dxcZl5GRYTz++OOGr6+vERISYixevNho3Lhxga/Bq507d8546qmnjLJlyxqBgYHGtGnTbHqvCA8PNwYNGmQMHDjQ8PX1Nfz8/IwxY8bY9FnYvXt3o3LlyoaHh4cRHBxsPPzww8aPP/5YZNxlubm5xuuvv25Ur17d8PDwMKpVq2ZMmjTJ5nh7bN682XB3d7f6/P/ll18Ms9lszJ071+bHiYqKMvz9/Y2///7brvEPHz5stGzZ0vD29jYkGUlJSUXGbNy40ahbt67h5eVlNGrUyNiyZYvN793AjWQyDBdZyAwAwA00fvx4zZw5U3FxcUXOeHSmjh07qlatWpozZ46zUyl1JkyYYFmKiIK1adNGTZo00VtvveXwY5hMJq1Zs6bI/R5jY2MVHx+vCRMmWLUnJydrzJgxWrFihcM5wPm2bNmi3r17l7rZpwX58ssvNWrUKB08eNDmmUnvvvuuPvvsM8XFxZVwdiXDlveK4ng/+Tfp0KGD6tata9PFh4B/C5YQAgD+lSZOnKjZs2dr165dNm/OeyOlp6dr3bp12rJlyw27ZP2/zYYNGzRt2jRnp+Hy5s6dq/Lly+vAgQN2xV2+yh3wb3P//ffr2WeftVxFzhYeHh42L6VH6XbmzBmtWLFCX3/9Ncu9gatwFUIAwL9WUXvGOVOfPn20Z88ejRw50ua94mCfnTt3OjsFl7ds2TLL3nbVqlWzK/a1117TqFGjJMmmjZbNZrO++OILffHFF/mOOXJxCsCZbNnX6UoDBgwooUxws2natKnS09M1depUm69uCvxbsIQQAAAAQIlKTk7Wp59+qujoaGenAgC4SVHAAgAAAAAAgEtjDywAAAAAAAC4NApYAAAAAAAAcGkUsAAAAAAAAODSKGABAAAAAADApVHAAgAAAAAAgEujgAUAAAAAAACXRgELAAAAAAAALu3/A59jPaRVZ1iIAAAAAElFTkSuQmCC", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "rang_freq_with_labels('voy-chars', get_characters(voynich))" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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yszMNB0Jxxg9erTWrl2rVatWNbyGDBmi66+/XqtWraL8BYERI0Yct3XSpk2b1K1bN0OJcKyKigo5HI2rgdPpZBuYDogRwCCTk5OjG2+8UUOGDNGwYcM0ffp05efna9KkSaajQXWLC2bOnKl3331XsbGxDaO1brdbUVFRhtMhNjb2uPmYMTEx6ty5M/M0g8Tdd9+t4cOH65FHHtG1116rpUuXavr06Zo+fbrpaJB0xRVX6OGHH1ZGRob69u2rlStX6oknntBPf/pT09HQytgGJgg9++yzevTRR1VYWKh+/frpySefZIuRIHGyuZgvvviifvKTn7RvGDTJqFGj2AYmyLz33nuaOnWqNm/erMzMTOXk5OjWW281HQuSSktL9Zvf/EazZ89WUVGR0tLSNGHCBP32t79VRESE6XhoRRRAAAAAm2EOIAAAgM1QAAEAAGyGAggAAGAzFEAAAACboQACAADYDAUQAADAZiiAAAAANkMBBAAAsBkKIAAAgM1QAAEAAGyGAggAAGAzFEAAAACboQACAADYDAUQAADAZiiAAAAANkMBBAAAsBkKIAAAgM1QAAEAAGyGAggAAGAzFEAAAACboQACAADYDAUQAADAZiiAAAAANkMBBAAAsBkKIAAAgM1QAAEAAGyGAggAAGAzFEAAAACboQACAADYDAUQAADAZiiAAAAANvP/AaFiaqrJfHMyAAAAAElFTkSuQmCC", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "log_rang_log_freq('voy-log-log', get_words(voynich))" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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IsBCsfr166d+/fo5XYbrhYSE6O9//3uRUyjdiFrL3tlSp0St5eVsqfVsqVOi1vJwttQpUWt5OFvqlKi1vJwttZ4tdUrUCjiFuxACAAAAAADA1So5XQAAAAAAAABwMgRYAAAAAAAAcDUCLAAAAAAAALgaARYAAAAAAABcjQAL+K+jR4/qkUceUZ06dRQWFqaLLrpIo0ePVkFBQZG2U6dOVUBAgO69994i0xYuXCiPx6OoqCj99ttvftOWL18uj8cjj8dTqhp3796tvn37qmbNmgoJCVF8fLw6dOigL774wtdm9erVuummmxQXF6fQ0FBdcskluvvuu/Xdd9/52qxYsUJt27bVBRdcoKioKKWkpGjNmjV+y5oxY4Yuu+wyhYeHq1atWnr66adLVfPJ7NixQ3369FFCQoKCg4NVq1YtDRo0SL/88ouvTZs2bXzb7NihuG1/ugpfqxMN11xzja/tW2+9pTZt2sjr9apy5cpq3LixRo8erb179/ravPHGG2rSpInCw8NVvXp13XXXXX7rcuTIEY0ePVoXX3yxQkND1aRJE3300Uelrr8k74elS5fquuuuU1RUlEJDQ5WcnKxnn31W+fn5fvM60TaYPn36CZc/duxYeTwepaam+o1fv369evTooapVqyokJERJSUl69NFHdejQIb92tWvXLrK8GjVq+LVxw/u5JPuGn376SXfeeacSEhIUHh6ua6+9Vps3by7xMk6mIrZzSkqKAgICtGzZsiLLv/POO33PO7aGd955Rx6Pp0Jfa6l8P4tlfRwoHGJiYvTnP/9Zn3/+eZG2ZWnp0qUKCAjQtdde6zd+27Zt8ng8CgwM1K5du/ymZWZmKjAwUB6PR9u2bSuXusrq2PXJJ5+oZcuWioyMVPXq1fXQQw/p6NGj5VJzodM9TgUHB+viiy/WiBEjlJubW251ldf+v3LlymrSpInS09NPqx637KeK+zz269dPHo9Hd95552mtU6FTfa4KB6/XqxYtWui9994r1XJKqqy/u/zP//yPLr30UoWFhalevXp67bXXTlmDW47/ZbWOp7NNJ0+erD/+8Y+KiIhQZGSkrr76ar3//vslnl9WVtYpt29ZGDt2rK644gpFRkaqWrVquv7667Vp06YKWTZQrgyAmZn985//tJiYGHv//fctIyPDZs6caZUrV7bx48cXadu2bVsbPny4eb1eO3jwoN+0Tz/91CRZYmKiTZ061W9a3759rWbNmlbaj16rVq2sefPm9p///Me2bdtmX375pY0ZM8bef/99MzN77733LDg42Lp06WLz58+3rVu32rJly2zIkCHWo0cPMzPLycmxqKgou/POO+3bb7+1devW2Y033mjVqlWzvLw8MzObO3euBQYG2ksvvWRbtmyx999/3+Lj4+2FF14oVd3F2bJli1WrVs1atWplCxcutB9++MHmzp1rDRs2tKSkJPvll1/MzKx169Z29913W2Zmpt+QnZ19xjXk5uYWmW9mZqa9/PLL5vF4bMaMGWZm9vDDD1tAQIANHTrUPv/8c8vIyLB58+ZZ9+7dfe+PxYsXW6VKley5556zrVu32uLFi61hw4Z2/fXX+5Y3bNgwS0hIsA8++MC2bNliEyZMsNDQUFu1alWp6j/V++Htt9+2wMBAu/vuu2316tWWkZFhr7zyikVFRdlf/vIXKygo8M1Lkk2aNKnItjh8+HCxy16+fLnVrl3bGjdubIMGDfKN/+KLLywiIsK6detmX375pW3bts1mzJhhiYmJ1rJlS8vNzfW1rVWrlo0ePdpvebt37/ZNd8v7+VT7hoKCAmvRooX96U9/suXLl9u3335r99xzj9WsWdMOHDhQomWcSEVs5x9++MEqV65sAwcOtL/97W9FaujUqZN5PB6rVKmS9e3b1zf+ySefNEkV9lqblf9nsV+/fmV6HNi0aZNlZmba119/bT169DCv12s//fTTSV/zM9GnTx8bNGiQRURE2A8//OAbn5GR4TsujRkzxu85Y8eO9R2XMjIyyqWusjh2rV271oKDg+3xxx+3zZs328KFC61+/fo2ZMiQcqnZrHTHqR9++MFmzZplkZGRNnz48HKrrbz2/99//7098cQTJsk++uijEtXihv3UHXfcYYmJieb1eu3QoUO+8YcPH7YLLrjAatasaXfccUdJN6+fU32uFixYYJmZmbZx40YbMGCABQUF2TfffFOqZZVEWX53mTBhgkVGRtr06dNty5YtNm3aNKtcubLNmTPnhMt3y/G/LNexpNt0yJAhFhISYk8//bRt3rzZNmzYYA8//LBVqlTJ7zvF8ceAY4f8/PzSvOynrUOHDjZp0iRbt26drVmzxjp16lQm30sApxFgAf/VqVMn6927t9+47t2726233uo3LiMjw8LCwuzXX3+15s2b2+TJk/2mFx60HnnkEWvXrp1v/KFDh8zr9dqjjz5aqgBr3759JskWLlxY7PSDBw9abGys3x9pxz/fzGzFihUmybZv3+6b9vXXX5sk+/77783M7Oabb7a//OUvfs9PS0uzGjVq+H3pPRPXXnut1ahRw++LpplZZmamhYeH27333mtmv/9hcOwXpPK2YcMGq1Klio0cOdLMzL788kuTVOwfsGb/t12ffvppu+iii/ymPf/881ajRg3f4+rVq9uLL77o16Zbt27Wq1ev067zVO+HAwcOWExMjHXv3r3ItDlz5pgkmz59um+cJJs9e3aJlr1//35LSkqy+fPn+70+BQUF1qBBA2vWrFmRL2hr1qwxj8djTz75pG9crVq1LC0trdhluOn9fKp9w6ZNm0ySrVu3zjf96NGjFh0dba+88sop538iFbGdzcxGjRplf/3rX23jxo0WGRnp9+V2//79VqVKFWvevLmFhYVZ06ZNfTUkJiaapAp7rSvis5iQkFCmx4HCmsz+7315sj8Mz8SBAwcsMjLSvv32W+vZs6c9/vjjfvUWHpeSkpL8nlevXj3fcak8AqyyOnaNGDHCmjVr5jdt9uzZFhoaajk5OWVac6EzOU51797dLr/88nKpqyL2/9HR0TZ48OBT1uKG/ZTZ7wFWt27dLDk52V5//XXf+DfeeMOSk5OtW7dupQqwSvK5Wr16tW9cTk6OSbLnn3/+tJd1Jkr73eXKK6+0oUOH+k0bNGiQXXXVVcU+z03H//Jax0LHb9MvvvjihK/t4MGDLSgoyPddpLhjgNN2795tkmzRokVOlwKcEU4hBP6rVatW+uSTT3xdk9euXaslS5bouuuu82v3v//7v+rUqZO8Xq9uvfVWTZw4sdj53XbbbVq8eLG2b98u6fcuzrVr19bll19eqvoqV66sypUr65133in2tISPP/5YP//8s4YNG1bs8y+44AJJUr169RQbG6uJEycqLy9Phw8f1sSJE9WwYUPVqlVLkpSbm6vQ0FC/54eFhWnnzp364YcfSlX/sfbu3auPP/5Y/fr1U1hYmN+0+Ph49erVS2+++abM7IyXdTp+/fVXXX/99WrdurX+8Y9/SPr9VKTKlSurX79+xT6ncLu2bNlSO3fu1Ny5c2Vm+umnnzRr1ix16tTJ1/ZE23XJkiWnXeup3g/z5s3TL7/8oqFDhxaZ1qVLF11yySWaNm3aaS9Xku6//3516tRJ7dq18xu/Zs0abdiwQYMHD1alSv6HlyZNmqhdu3YlXqab3s+n2jcUbv9jlxEQEKDg4OBSvbaFKmI7m5kmTZqkW2+9VfXr19cll1yiGTNm+NVw4YUXKj4+XhdddJHWrFmjnTt3as2aNdqxY4ckVdhrXRGfxUOHDpXpcaDQoUOHNGnSJElSUFDQSduW1ptvvql69eqpXr16uvXWWzVp0qQi+9CuXbtq3759vvflkiVLtHfvXnXp0qVcapLK7th1otfst99+08qVK8u87jM5Tq1du1aff/55ub3W5bn/z8/P14wZM7R3794S1e+G/dSx7rrrLt9nTfr9s9q7d+8SLac4JflcFTpy5IheeeUVSeX3OS/OmXx3OdHnavny5Tpy5EiR57np+F9e6ygVv02nTZumypUrq2/fvkXaDxkyREeOHNFbb71VklV0RHZ2tiQpOjra4UqAM+Rcdga4S0FBgQ0fPtw8Ho8FBgaax+MpcqpFfn6+JSYm2jvvvGNmZnv27LGgoCDbvHmzr82xv7pcf/31vl/rrrnmGnvuueds9uzZpT6FcNasWRYVFWWhoaHWsmVLGzFihK1du9bMzP71r3+ZJNu7d+8p57Nu3Tq7+OKLrVKlSlapUiWrX7++X7f4l19+2cLDw23BggWWn59vmzZtsvr165skW7p0aalqP9ayZctO2uNn3LhxJsl++ukna926tQUFBVlERITfkJ6efsZ1HCs/P986duxol156qd/piR07drTGjRuXaB6FpxsFBgaaJOvatavvNDaz33sCNWjQwL777jvLz8+3efPmWVhYmAUHB5eq5pO9HwpP7zrRr39du3a1Sy+91PdYkoWGhhbZzlu2bPF73rRp06xRo0a+UwuP/QV2+vTpRX6NPtbAgQMtLCzM97hWrVoWHBzst7znnnvOzNz1fj7VviEvL89q1aplN910k+3du9dyc3Nt7NixJslSUlJOOf/iVNR2njdvnlWtWtWOHDliZr/3TCv8VbqwhltvvdW6detmrVu3tvj4eOvdu7evhhPty8rjta6Iz2JQUFCZHgcK19Xj8Zgka9q0qV8dZally5a+nghHjhyx2NhYmz9/vpn59xRJTU21u+66y8zM7rrrLnvggQds9erV5XoKYVkcuz7++GOrVKmSTZ061Y4ePWo7d+60Vq1amaQip+uXhdIep4KDg02SVapUyWbNmlXmdRUqr/1/QECASbLo6Gi/93Rx3LCfKlTYA2vPnj0WEhJiGRkZtm3bNgsNDbU9e/aUugdWST5XYWFhFhERYZUqVTJJVrt2bd/ppeXtTL+7jBgxwuLj4+2rr76ygoICW7FihVWrVs0k2Y8//ujX1m3H//JYR7MTb9Nrr73WmjRpcsLleL1eu++++8ys6DGgcLjkkktOWW95KCgosC5dulirVq0cWT5QluiBBfzXm2++qddff11Tp07VqlWrNHnyZD3zzDOaPHmyr828efN08OBBdezYUZIUGxurlJQU/e///m+x8+zdu7fS09O1detWffHFF+rVq9cZ1XjjjTfqxx9/1Jw5c9ShQwctXLhQl19+udLT00vcW+nw4cPq3bu3rrrqKi1btkyff/65GjZsqOuuu06HDx+WJN19993q37+/OnfurODgYLVo0UJ//etfJf3es6S8Fa5L4cXue/XqpTVr1vgNN9xwQ5ku8+GHH9YXX3yhd999V1WqVPGrpSQX3d+wYYMGDhyoxx57TCtXrtRHH32kjIwMvwvKPvfcc0pKSlL9+vUVHBys/v3766677ir1Nj3Z++HY+otT3HqlpaUV2c6JiYm+6Tt27NCgQYP0+uuvF/k1sySKW+aDDz7ot7zbb7/9pHUfryLez6faNwQFBemtt97Sd999p+joaIWHh2vhwoXq2LFjqV7bitzOEydOVM+ePRUYGChJuvnmm/Xll19q4cKFvhqOXYdWrVpp8uTJ2rlzZ5nVUNLXuiI+i5LK9DiwePFirVq1StOmTVOtWrWUnp5eLj0zNm3apOXLl/ve14GBgerZs2exNfXp00czZ85UVlaWZs6ceUa9U0qqLI5dKSkpevrpp3XvvfcqJCREl1xyia9XXUUcl453ouPUF198oR49eqh379668cYby2355bX/nz9/vi677DKlpaWpbt26J1y+G/ZTxV2QOjY2Vp06ddLkyZM1adIkderUSbGxsaddn1Tyz9Wbb76p1atXa86cOapbt65effXVCuvlcqbfXR599FF17NhRLVq0UFBQkLp16+a72P2xnys3Hv/Leh0LnWiblqaexYsX+63jxx9/XOL5laX+/fvr66+/LnXPe8BVKjQuA1ysRo0aRa6J8o9//MPq1avne3zTTTeZJAsICPAN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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "rang_freq_with_labels('voy-words-20', get_words(voynich), top=20)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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yszMNB0Jxxg9erTWrl2rVatWNbyGDBmi66+/XqtWraL8BYERI0Yct3XSpk2b1K1bN0OJcKyKigo5HI2rgdPpZBuYDogRwCCTk5OjG2+8UUOGDNGwYcM0ffp05efna9KkSaajQXWLC2bOnKl3331XsbGxDaO1brdbUVFRhtMhNjb2uPmYMTEx6ty5M/M0g8Tdd9+t4cOH65FHHtG1116rpUuXavr06Zo+fbrpaJB0xRVX6OGHH1ZGRob69u2rlStX6oknntBPf/pT09HQytgGJgg9++yzevTRR1VYWKh+/frpySefZIuRIHGyuZgvvviifvKTn7RvGDTJqFGj2AYmyLz33nuaOnWqNm/erMzMTOXk5OjWW281HQuSSktL9Zvf/EazZ89WUVGR0tLSNGHCBP32t79VRESE6XhoRRRAAAAAm2EOIAAAgM1QAAEAAGyGAggAAGAzFEAAAACboQACAADYDAUQAADAZiiAAAAANkMBBAAAsBkKIAAAgM1QAAEAAGyGAggAAGAzFEAAAACboQACAADYDAUQAADAZiiAAAAANkMBBAAAsBkKIAAAgM1QAAEAAGyGAggAAGAzFEAAAACboQACAADYDAUQAADAZiiAAAAANkMBBAAAsBkKIAAAgM1QAAEAAGyGAggAAGAzFEAAAACboQACAADYDAUQAADAZiiAAAAANvP/AaFiaqrJfHMyAAAAAElFTkSuQmCC", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "log_rang_log_freq('voy-words-log-log', get_words(voynich))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Język DNA\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Kod genetyczny przejawia własności zaskakująco podobne do języków naturalnych.\n", + "Przede wszystkim ma charakter dyskretny, genotyp to ciąg symboli ze skończonego alfabetu.\n", + "Podstawowe litery są tylko cztery, reprezentują one nukleotydy, z których zbudowana jest nić DNA:\n", + "a, g, c, t.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "TATAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTA" + ] + } + ], + "source": [ + "import requests\n", + "\n", + "dna_url = 'https://raw.githubusercontent.com/egreen18/NanO_GEM/master/rawGenome.txt'\n", + "dna = requests.get(dna_url).content.decode('utf-8')\n", + "\n", + "dna = ''.join(dna.split('\\n')[1:])\n", + "dna = dna.replace('N', 'A')\n", + "\n", + "dna[0:100]" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "rang_freq_with_labels('dna-chars', get_characters(dna))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Tryplety — znaczące cząstki genotypu\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Nukleotydy rzeczywiście są jak litery, same w sobie nie niosą\n", + "znaczenia. Dopiero ciągi trzech nukleotydów, *tryplety*, kodują jeden\n", + "z dwudziestu aminokwasów.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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X2658srqDh06pKysrHN+Xrz88sv/+FCXkEOHDunjjz9WcnKyUV6dFhwcrL59++rtt9/m82M9duedd+r666/Xe++9Z3YUSZKbm5vS09M1Y8YM7d271+w4hujoaK1Zs8a4v2bNGkVHRysqKsrYXllZqfXr15teYEnSQw89pK5du+rhhx9WRkaGtmzZotdee83sWIaHH35Yb7zxhnF/zpw5/MIBlzQKLMAFy5cvV+PGjeXl5aVrrrlGW7du1ZNPPml2LIO7u7syMzM1d+5cXX755ercubOeeuopffXVV2ZHuyTs2LFDDodDYWFhTtsDAgKMctBKf9+nbdiwQQsXLlTXrl3NjmKYPXu2HnjgAUm/nlJx7Ngxy10rx8oeeeQR7d69Wzk5Oca2OXPm6J577pGfn595wc7i9OfF396ee+45s2MZPvroI73wwgv64IMPznltMbOd+Rr+/e9/NzuS4fTnxeuuu87sKJek7777Tg6HQ23atDnr/jZt2qisrEwHDx78g5PVdLb/yz179jQ7Vr1w3XXXaffu3WbHMNx999264YYbnFb5mi06OlqfffaZTp48qaNHj2rz5s264447FBUVZXwtzM/P14kTJyxRYEnSa6+9pq1btyo1NVWvvvqqAgMDzY5kSEpKUm5urnbv3q3vv/9en332mfF9GXAp4hRCwAVdunTRyy+/rJ9//lmvv/66tm/frsGDB5sdy8m9996ruLg4rVu3TuvXr1dWVpYmTpyo119/3RLLmi8FZ66y2rBhg06dOqW+fftaZmXb6R80Tp48qaqqKvXu3VszZswwO5Ykadu2bdqwYYPx22Z3d3fdd999mjNnjmULBKu57rrrdNttt2nOnDnq0qWL/v3vf2vdunXKzs42O1oNpz8v/pa/v79JaWrq0KGDfvzxR40ZM0a33HKLfHx8zI5Uw5mv4blWgJrh9Mogq64+vdSdfn09PDxMTnL2/8uff/45P/TWAYfDYbn/Qy+88ILuvPNODRs2zOwokn7993f8+HFt3LhRZWVluvbaaxUYGKioqCglJSXp+PHjysnJUbNmzSxzGlxgYKAGDhyo999/X3fffbfZcZwEBAQoLi5Oc+fOlcPhUFxcnAICAsyOBbiMFViAC7y9vdWqVSt16NBBL730kioqKjR27FizY9XQsGFDde/eXWPGjFFeXp769etnqd+yWVWrVq1ks9n07bffOm2/+uqr1apVqxqnf5ipS5cuKiws1LZt2/TLL7/ovffes8xv/mbPnq2TJ0/qqquukru7u9zd3fXyyy/rvffes9RFY62uf//+WrJkiY4cOaI33nhDzZs3t9Qqu9NOf1787c1KBdZVV12ltWvXqqSkRD169NDRo0fNjlTDma/hlVdeaXYkQ+vWrWWz2VRUVGR2lEvS6a8rW7duPev+b7/9VldccYUlTsU82//lq666yuxY9UJRUZGl3phBku644w7FxsbqqaeeMjuKpF//rzRt2lRr1qzRmjVrjGu5BgcHq2XLlvrss8+0Zs0a3XnnnSYndXb6+xwreuSRR4wzMzh9EJc6CiygDjzzzDOaPHmyfvjhB7OjnFfbtm11/Phxs2NYXpMmTdS9e3dlZGRY/vU6/YNG8+bNLXUdtpMnT+rNN9/UlClTVFhYaNy+/PJLNW/eXAsWLDA74iWjT58+cnNz08KFCzV37lw9/PDDlvsN/qWiWbNmWrt2rQ4cOKCYmBgdOXLE7EiXDH9/f8XGxup///d/z/p58fDhw398qEvI6a8rM2fOdHpHMEkqLS3VggULWB1dz33yySf6+uuvLXn9vQkTJmjZsmXKy8szO4qkX385l5OTo5ycHEVHRxvbo6Ki9PHHHys/P98ypw9eCnr06KHKykpVVlYqNjbW7DjABaHAAupAdHS02rVrZ5l3Bfvpp5905513av78+frqq6+0a9cuLV68WBMnTlTv3r3NjmcoLy93KjcKCwu1Z88es2NJkmbOnKmTJ0/q5ptv1ttvv62ioiJt27ZN8+fP17fffis3NzezI1ra8uXLVVZWpv79+ys8PNzp9re//U2zZ882O+Ilo3Hjxrrvvvv01FNP6YcffrDsD7kVFRUqLS11uv34449mx6qhadOmysnJ0U8//aSYmBiVl5ebHemSMXPmTFVXV+vWW2/VkiVL9N1336moqEgvvfSSIiMjzY5neRkZGaqoqFBsbKw+/fRTFRcXKysrS927d9e1115rmXdoxYU7/flw37592rRpk9LT09W7d2/Fx8frwQcfNDteDe3bt1ffvn0tcwmCLl26KDc3V4WFhcYKLOnXAmvWrFn65ZdfKLBqwc3NTUVFRSoqKuL7V1zyKLCAOjJ06FDNmjVLxcXFZkdR48aN1bFjR02bNk133HGHwsPD9fTTT2vAgAHKyMgwO54hJydHN954o9PNKt/AX3PNNdq8ebO6deumUaNG6frrr9fNN9+sGTNmaPjw4Za6OLUVzZ49W926dZPdbq+x795771VhYaE2bdpkQrJLU//+/VVWVqZu3bqpWbNmZsc5q6ysLF155ZVOt9tvv93sWGd1+nTCw4cPq3v37qwe+p1atmypTZs2qUuXLho2bJjCw8PVvXt3rV69usY1k1BT69attXHjRl199dXq06ePmjdvrp49e+raa6/VZ599psaNG5sdEXXk9OfDFi1aqEePHlqzZo1eeuklffDBB5YtEJ577jnLvAtmly5ddOLECbVq1UpBQUHG9qioKB09elTXXHONQkNDTUx46fH19ZWvr6/ZMYALZnNY5TMVAAAA8CfyzDPPaOrUqcrOzmYVGwAA/wEFFgAAAGCSN954Q+Xl5UpJSdFll3FyxH+yZ88etW3b9pz7t27datmVqgCAC0OBBQAAAOCScPLkSe3evfuc+1u0aGHZd4MDAFwYCiwAAAAAAABYGuuUAQAAAAAAYGkUWAAAAAAAALA0CiwAAAAAAABYGgUWAAAAAAAALI0CCwAAAAAAAJZGgQUAAAAAAABLo8ACAAAAAACApVFgAQAAAAAAwNL+D1Zdk/6zbq58AAAAAElFTkSuQmCC", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "genetic_code = {\n", + " 'ATA':'I', 'ATC':'I', 'ATT':'I', 'ATG':'M',\n", + " 'ACA':'T', 'ACC':'T', 'ACG':'T', 'ACT':'T',\n", + " 'AAC':'N', 'AAT':'N', 'AAA':'K', 'AAG':'K',\n", + " 'AGC':'S', 'AGT':'S', 'AGA':'R', 'AGG':'R',\n", + " 'CTA':'L', 'CTC':'L', 'CTG':'L', 'CTT':'L',\n", + " 'CCA':'P', 'CCC':'P', 'CCG':'P', 'CCT':'P',\n", + " 'CAC':'H', 'CAT':'H', 'CAA':'Q', 'CAG':'Q',\n", + " 'CGA':'R', 'CGC':'R', 'CGG':'R', 'CGT':'R',\n", + " 'GTA':'V', 'GTC':'V', 'GTG':'V', 'GTT':'V',\n", + " 'GCA':'A', 'GCC':'A', 'GCG':'A', 'GCT':'A',\n", + " 'GAC':'D', 'GAT':'D', 'GAA':'E', 'GAG':'E',\n", + " 'GGA':'G', 'GGC':'G', 'GGG':'G', 'GGT':'G',\n", + " 'TCA':'S', 'TCC':'S', 'TCG':'S', 'TCT':'S',\n", + " 'TTC':'F', 'TTT':'F', 'TTA':'L', 'TTG':'L',\n", + " 'TAC':'Y', 'TAT':'Y', 'TAA':'_', 'TAG':'_',\n", + " 'TGC':'C', 'TGT':'C', 'TGA':'_', 'TGG':'W',\n", + " }\n", + "\n", + "def get_triplets(t):\n", + " for triplet in re.finditer(r'.{3}', t):\n", + " yield genetic_code[triplet.group(0)]\n", + "\n", + "rang_freq_with_labels('dna-aminos', get_triplets(dna))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### „Zdania” w języku DNA\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Z aminokwasów zakodowanych przez tryplet budowane są białka.\n", + "Maszyneria budująca białka czyta sekwencję aż do napotkania\n", + "trypletu STOP (\\_ powyżej). Taka sekwencja to *gen*.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAA9hAAAPYQGoP6dpAAA0B0lEQVR4nO3df3RU9Z3/8deU/DBkk1sCZIZZI6ZuSsFEV0M3JP0BKxBgjanHHsGGneKRAhaFzgrLj3W7RU+bAN2Cu83WokuFIm56vucYt6fQlLDVVDYE0mhaiEDpMfKjZBLqTiZB00kM9/uHh1smiYAKzEw+z8c59xzmc9/3zuc9dzAvP5k7uGzbtgUAAABjfCLaEwAAAMD1RQAEAAAwDAEQAADAMARAAAAAwxAAAQAADEMABAAAMAwBEAAAwDAEQAAAAMMQAAEAAAxDAAQAADAMARAAAMAwBEAAAADDEAABAAAMQwAEAAAwDAEQAADAMARAAAAAwxAAAQAADEMABAAAMAwBEAAAwDAEQAAAAMMQAAEAAAxDAAQAADAMARAAAMAwBEAAAADDEAABAAAMQwAEAAAwDAEQAADAMARAAAAAwxAAAQAADEMABAAAMAwBEAAAwDAEQAAAAMMQAAEAAAxDAAQAADAMARAAAMAwBEAAAADDEAABAAAMQwAEAAAwDAEQAADAMARAAAAAwxAAAQAADEMABAAAMAwBEAAAwDAEQAAAAMMQAAEAAAxDAAQAADAMARAAAMAwBEAAAADDEAABAAAMQwAEAAAwDAEQAADAMARAAAAAwxAAAQAADEMABAAAMAwBEAAAwDAEQAAAAMMkRHsC8ez8+fM6c+aM0tLS5HK5oj0dAABwBWzbVnd3t7xerz7xCTPXwgiAH8OZM2eUlZUV7WkAAICP4NSpU7rxxhujPY2oIAB+DGlpaZLefwOlp6dHeTYAAOBKdHV1KSsry/k5biIC4Mdw4de+6enpBEAAAOKMyR/fMvMX3wAAAAYjAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGEIgAAAAIYhAAIAABgmIdoTwAe7ec2uiMdvrb87SjMBAADDCSuAAAAAhom5APjee+/pn//5n5Wdna2UlBR96lOf0pNPPqnz5887NbZta926dfJ6vUpJSdG0adPU0tIScZ5wOKxly5ZpzJgxSk1NVWlpqU6fPh1REwwG5fP5ZFmWLMuSz+dTZ2fn9WgTAAAgamIuAG7YsEE//OEPVVlZqSNHjmjjxo367ne/q+9///tOzcaNG7Vp0yZVVlaqsbFRHo9HM2fOVHd3t1Pj9/tVXV2tqqoq7du3T+fOnVNJSYn6+/udmrKyMjU3N6umpkY1NTVqbm6Wz+e7rv0CAABcby7btu1oT+JiJSUlcrvd2rp1qzP25S9/WSNHjtSOHTtk27a8Xq/8fr9Wr14t6f3VPrfbrQ0bNmjJkiUKhUIaO3asduzYoXnz5kmSzpw5o6ysLO3evVuzZs3SkSNHNGnSJDU0NKigoECS1NDQoMLCQh09elQTJky47Fy7urpkWZZCoZDS09Ov+mvBZwABALj6rvXP73gQcyuAn//85/U///M/+t3vfidJ+s1vfqN9+/bp7/7u7yRJra2tCgQCKi4udo5JTk7W1KlTVV9fL0lqampSX19fRI3X61Vubq5Ts3//flmW5YQ/SZoyZYosy3JqBgqHw+rq6orYAAAA4k3M3QW8evVqhUIhfeYzn9GIESPU39+v73znO/rKV74iSQoEApIkt9sdcZzb7daJEyecmqSkJI0aNWpQzYXjA4GAMjMzBz1/ZmamUzNQRUWFnnjiiY/XIAAAQJTF3ArgT37yEz3//PN64YUX9Nprr2n79u3613/9V23fvj2izuVyRTy2bXvQ2EADa4aqv9R51q5dq1Ao5GynTp260rYAAABiRsytAP7jP/6j1qxZowceeECSlJeXpxMnTqiiokILFiyQx+OR9P4K3rhx45zjOjo6nFVBj8ej3t5eBYPBiFXAjo4OFRUVOTXt7e2Dnv/s2bODVhcvSE5OVnJy8tVpFAAAIEpibgXw3Xff1Sc+ETmtESNGOF8Dk52dLY/Ho9raWmd/b2+v6urqnHCXn5+vxMTEiJq2tjYdPnzYqSksLFQoFNLBgwedmgMHDigUCjk1AAAAw1HMrQDec889+s53vqObbrpJt956q15//XVt2rRJDz30kKT3f23r9/tVXl6unJwc5eTkqLy8XCNHjlRZWZkkybIsLVy4UCtWrNDo0aOVkZGhlStXKi8vTzNmzJAkTZw4UbNnz9aiRYu0ZcsWSdLixYtVUlJyRXcAAwAAxKuYC4Df//739c1vflNLly5VR0eHvF6vlixZon/5l39xalatWqWenh4tXbpUwWBQBQUF2rNnj9LS0pyazZs3KyEhQXPnzlVPT4+mT5+ubdu2acSIEU7Nzp07tXz5cudu4dLSUlVWVl6/ZgEAAKIg5r4HMJ7wPYAAAMQfvgcwBj8DCAAAgGuLAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGEIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGEIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhom5AHjzzTfL5XIN2h555BFJkm3bWrdunbxer1JSUjRt2jS1tLREnCMcDmvZsmUaM2aMUlNTVVpaqtOnT0fUBINB+Xw+WZYly7Lk8/nU2dl5vdoEAACImpgLgI2NjWpra3O22tpaSdL9998vSdq4caM2bdqkyspKNTY2yuPxaObMmeru7nbO4ff7VV1draqqKu3bt0/nzp1TSUmJ+vv7nZqysjI1NzerpqZGNTU1am5uls/nu77NAgAARIHLtm072pO4FL/fr5/97Gc6fvy4JMnr9crv92v16tWS3l/tc7vd2rBhg5YsWaJQKKSxY8dqx44dmjdvniTpzJkzysrK0u7duzVr1iwdOXJEkyZNUkNDgwoKCiRJDQ0NKiws1NGjRzVhwoQrmltXV5csy1IoFFJ6evpV7/3mNbsiHr+1/u6r/hwAAJjmWv/8jgcxtwJ4sd7eXj3//PN66KGH5HK51NraqkAgoOLiYqcmOTlZU6dOVX19vSSpqalJfX19ETVer1e5ublOzf79+2VZlhP+JGnKlCmyLMupGUo4HFZXV1fEBgAAEG9iOgC+9NJL6uzs1IMPPihJCgQCkiS32x1R53a7nX2BQEBJSUkaNWrUJWsyMzMHPV9mZqZTM5SKigrnM4OWZSkrK+sj9wYAABAtMR0At27dqjlz5sjr9UaMu1yuiMe2bQ8aG2hgzVD1lzvP2rVrFQqFnO3UqVNX0gYAAEBMidkAeOLECe3du1df+9rXnDGPxyNJg1bpOjo6nFVBj8ej3t5eBYPBS9a0t7cPes6zZ88OWl28WHJystLT0yM2AACAeBOzAfC5555TZmam7r77zzc+ZGdny+PxOHcGS+9/TrCurk5FRUWSpPz8fCUmJkbUtLW16fDhw05NYWGhQqGQDh486NQcOHBAoVDIqQEAABiuEqI9gaGcP39ezz33nBYsWKCEhD9P0eVyye/3q7y8XDk5OcrJyVF5eblGjhypsrIySZJlWVq4cKFWrFih0aNHKyMjQytXrlReXp5mzJghSZo4caJmz56tRYsWacuWLZKkxYsXq6Sk5IrvAAYAAIhXMRkA9+7dq5MnT+qhhx4atG/VqlXq6enR0qVLFQwGVVBQoD179igtLc2p2bx5sxISEjR37lz19PRo+vTp2rZtm0aMGOHU7Ny5U8uXL3fuFi4tLVVlZeW1bw4AACDKYv57AGMZ3wMIAED84XsAY/gzgAAAALg2CIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGEIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGEIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYJiYDIB/+MMf9Pd///caPXq0Ro4cqb/+679WU1OTs9+2ba1bt05er1cpKSmaNm2aWlpaIs4RDoe1bNkyjRkzRqmpqSotLdXp06cjaoLBoHw+nyzLkmVZ8vl86uzsvB4tAgAARE3MBcBgMKjPfe5zSkxM1M9//nO98cYb+t73vqdPfvKTTs3GjRu1adMmVVZWqrGxUR6PRzNnzlR3d7dT4/f7VV1draqqKu3bt0/nzp1TSUmJ+vv7nZqysjI1NzerpqZGNTU1am5uls/nu57tAgAAXHcu27btaE/iYmvWrNH//u//6tVXXx1yv23b8nq98vv9Wr16taT3V/vcbrc2bNigJUuWKBQKaezYsdqxY4fmzZsnSTpz5oyysrK0e/duzZo1S0eOHNGkSZPU0NCggoICSVJDQ4MKCwt19OhRTZgw4bJz7erqkmVZCoVCSk9Pv0qvwJ/dvGZXxOO31t991Z8DAADTXOuf3/Eg5lYAf/rTn2ry5Mm6//77lZmZqTvuuEPPPvuss7+1tVWBQEDFxcXOWHJysqZOnar6+npJUlNTk/r6+iJqvF6vcnNznZr9+/fLsiwn/EnSlClTZFmWUwMAADAcxVwAfPPNN/X0008rJydHv/jFL/Twww9r+fLl+vGPfyxJCgQCkiS32x1xnNvtdvYFAgElJSVp1KhRl6zJzMwc9PyZmZlOzUDhcFhdXV0RGwAAQLxJiPYEBjp//rwmT56s8vJySdIdd9yhlpYWPf300/rqV7/q1LlcrojjbNseNDbQwJqh6i91noqKCj3xxBNX3AsAAEAsirkVwHHjxmnSpEkRYxMnTtTJkyclSR6PR5IGrdJ1dHQ4q4Iej0e9vb0KBoOXrGlvbx/0/GfPnh20unjB2rVrFQqFnO3UqVMfoUMAAIDoirkA+LnPfU7Hjh2LGPvd736n8ePHS5Kys7Pl8XhUW1vr7O/t7VVdXZ2KiookSfn5+UpMTIyoaWtr0+HDh52awsJChUIhHTx40Kk5cOCAQqGQUzNQcnKy0tPTIzYAAIB4E3O/Av6Hf/gHFRUVqby8XHPnztXBgwf1zDPP6JlnnpH0/q9t/X6/ysvLlZOTo5ycHJWXl2vkyJEqKyuTJFmWpYULF2rFihUaPXq0MjIytHLlSuXl5WnGjBmS3l9VnD17thYtWqQtW7ZIkhYvXqySkpIrugMYAAAgXsVcAPzsZz+r6upqrV27Vk8++aSys7P11FNPaf78+U7NqlWr1NPTo6VLlyoYDKqgoEB79uxRWlqaU7N582YlJCRo7ty56unp0fTp07Vt2zaNGDHCqdm5c6eWL1/u3C1cWlqqysrK69csAABAFMTc9wDGE74HEACA+MP3AMbgZwABAABwbREAAQAADEMABAAAMAwBEAAAwDAEQAAAAMMQAAEAAAxDAAQAADAMARAAAMAwBEAAAADDEAABAAAMQwAEAAAwDAEQAADAMARAAAAAwxAAAQAADEMABAAAMAwBEAAAwDAEQAAAAMMQAAEAAAxDAAQAADAMARAAAMAwBEAAAADDEAABAAAMQwAEAAAwDAEQAADAMARAAAAAwxAAAQAADEMABAAAMAwBEAAAwDAEQAAAAMMQAAEAAAxDAAQAADAMARAAAMAwMRcA161bJ5fLFbF5PB5nv23bWrdunbxer1JSUjRt2jS1tLREnCMcDmvZsmUaM2aMUlNTVVpaqtOnT0fUBINB+Xw+WZYly7Lk8/nU2dl5PVoEAACIqpgLgJJ06623qq2tzdkOHTrk7Nu4caM2bdqkyspKNTY2yuPxaObMmeru7nZq/H6/qqurVVVVpX379uncuXMqKSlRf3+/U1NWVqbm5mbV1NSopqZGzc3N8vl817VPAACAaEiI9gSGkpCQELHqd4Ft23rqqaf0+OOP67777pMkbd++XW63Wy+88IKWLFmiUCikrVu3aseOHZoxY4Yk6fnnn1dWVpb27t2rWbNm6ciRI6qpqVFDQ4MKCgokSc8++6wKCwt17NgxTZgw4fo1CwAAcJ3F5Arg8ePH5fV6lZ2drQceeEBvvvmmJKm1tVWBQEDFxcVObXJysqZOnar6+npJUlNTk/r6+iJqvF6vcnNznZr9+/fLsiwn/EnSlClTZFmWUwMAADBcxdwKYEFBgX784x/r05/+tNrb2/Xtb39bRUVFamlpUSAQkCS53e6IY9xut06cOCFJCgQCSkpK0qhRowbVXDg+EAgoMzNz0HNnZmY6NUMJh8MKh8PO466uro/WJAAAQBTFXACcM2eO8+e8vDwVFhbqlltu0fbt2zVlyhRJksvlijjGtu1BYwMNrBmq/nLnqaio0BNPPHFFfQAAAMSqmPwV8MVSU1OVl5en48ePO58LHLhK19HR4awKejwe9fb2KhgMXrKmvb190HOdPXt20OrixdauXatQKORsp06d+li9AQAAREPMB8BwOKwjR45o3Lhxys7OlsfjUW1trbO/t7dXdXV1KioqkiTl5+crMTExoqatrU2HDx92agoLCxUKhXTw4EGn5sCBAwqFQk7NUJKTk5Wenh6xAQAAxJuY+xXwypUrdc899+imm25SR0eHvv3tb6urq0sLFiyQy+WS3+9XeXm5cnJylJOTo/Lyco0cOVJlZWWSJMuytHDhQq1YsUKjR49WRkaGVq5cqby8POeu4IkTJ2r27NlatGiRtmzZIklavHixSkpKuAMYAAAMezEXAE+fPq2vfOUr+uMf/6ixY8dqypQpamho0Pjx4yVJq1atUk9Pj5YuXapgMKiCggLt2bNHaWlpzjk2b96shIQEzZ07Vz09PZo+fbq2bdumESNGODU7d+7U8uXLnbuFS0tLVVlZeX2bBQAAiAKXbdt2tCcRr7q6umRZlkKh0DX5dfDNa3ZFPH5r/d1X/TkAADDNtf75HQ9i/jOAAAAAuLoIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGEIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGEIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYWI6AFZUVMjlcsnv9ztjtm1r3bp18nq9SklJ0bRp09TS0hJxXDgc1rJlyzRmzBilpqaqtLRUp0+fjqgJBoPy+XyyLEuWZcnn86mzs/M6dAUAABBdMRsAGxsb9cwzz+i2226LGN+4caM2bdqkyspKNTY2yuPxaObMmeru7nZq/H6/qqurVVVVpX379uncuXMqKSlRf3+/U1NWVqbm5mbV1NSopqZGzc3N8vl8160/AACAaInJAHju3DnNnz9fzz77rEaNGuWM27atp556So8//rjuu+8+5ebmavv27Xr33Xf1wgsvSJJCoZC2bt2q733ve5oxY4buuOMOPf/88zp06JD27t0rSTpy5Ihqamr0n//5nyosLFRhYaGeffZZ/exnP9OxY8ei0jMAAMD1EpMB8JFHHtHdd9+tGTNmRIy3trYqEAiouLjYGUtOTtbUqVNVX18vSWpqalJfX19EjdfrVW5urlOzf/9+WZalgoICp2bKlCmyLMupGUo4HFZXV1fEBgAAEG8Soj2BgaqqqvTaa6+psbFx0L5AICBJcrvdEeNut1snTpxwapKSkiJWDi/UXDg+EAgoMzNz0PkzMzOdmqFUVFToiSee+HANAQAAxJiYWgE8deqUvvGNb+j555/XDTfc8IF1Lpcr4rFt24PGBhpYM1T95c6zdu1ahUIhZzt16tQlnxMAACAWxVQAbGpqUkdHh/Lz85WQkKCEhATV1dXp3//935WQkOCs/A1cpevo6HD2eTwe9fb2KhgMXrKmvb190POfPXt20OrixZKTk5Wenh6xAQAAxJuYCoDTp0/XoUOH1Nzc7GyTJ0/W/Pnz1dzcrE996lPyeDyqra11junt7VVdXZ2KiookSfn5+UpMTIyoaWtr0+HDh52awsJChUIhHTx40Kk5cOCAQqGQUwMAADBcxdRnANPS0pSbmxsxlpqaqtGjRzvjfr9f5eXlysnJUU5OjsrLyzVy5EiVlZVJkizL0sKFC7VixQqNHj1aGRkZWrlypfLy8pybSiZOnKjZs2dr0aJF2rJliyRp8eLFKikp0YQJE65jxwAAANdfTAXAK7Fq1Sr19PRo6dKlCgaDKigo0J49e5SWlubUbN68WQkJCZo7d656eno0ffp0bdu2TSNGjHBqdu7cqeXLlzt3C5eWlqqysvK69wMAAHC9uWzbtqM9iXjV1dUly7IUCoWuyecBb16zK+LxW+vvvurPAQCAaa71z+94EFOfAQQAAMC1RwAEAAAwDAEQAADAMARAAAAAwxAAAQAADEMABAAAMAwBEAAAwDAEQAAAAMMQAAEAAAxDAAQAADAMARAAAMAwBEAAAADDEAABAAAMQwAEAAAwDAEQAADAMARAAAAAwyREewK4cjev2TVo7K31d0dhJgAAIJ6xAggAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGEIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGibkA+PTTT+u2225Tenq60tPTVVhYqJ///OfOftu2tW7dOnm9XqWkpGjatGlqaWmJOEc4HNayZcs0ZswYpaamqrS0VKdPn46oCQaD8vl8sixLlmXJ5/Ops7PzerQIAAAQVTEXAG+88UatX79ev/71r/XrX/9ad911l770pS85IW/jxo3atGmTKisr1djYKI/Ho5kzZ6q7u9s5h9/vV3V1taqqqrRv3z6dO3dOJSUl6u/vd2rKysrU3Nysmpoa1dTUqLm5WT6f77r3CwAAcL25bNu2oz2Jy8nIyNB3v/tdPfTQQ/J6vfL7/Vq9erWk91f73G63NmzYoCVLligUCmns2LHasWOH5s2bJ0k6c+aMsrKytHv3bs2aNUtHjhzRpEmT1NDQoIKCAklSQ0ODCgsLdfToUU2YMOGK5tXV1SXLshQKhZSenn7V+755za7L1ry1/u6r/rwAAAxn1/rndzyIuRXAi/X396uqqkrvvPOOCgsL1draqkAgoOLiYqcmOTlZU6dOVX19vSSpqalJfX19ETVer1e5ublOzf79+2VZlhP+JGnKlCmyLMupGUo4HFZXV1fEBgAAEG9iMgAeOnRIf/EXf6Hk5GQ9/PDDqq6u1qRJkxQIBCRJbrc7ot7tdjv7AoGAkpKSNGrUqEvWZGZmDnrezMxMp2YoFRUVzmcGLctSVlbWx+oTAAAgGmIyAE6YMEHNzc1qaGjQ17/+dS1YsEBvvPGGs9/lckXU27Y9aGyggTVD1V/uPGvXrlUoFHK2U6dOXWlLAAAAMSMmA2BSUpL+6q/+SpMnT1ZFRYVuv/12/du//Zs8Ho8kDVql6+jocFYFPR6Pent7FQwGL1nT3t4+6HnPnj07aHXxYsnJyc7dyRc2AACAeBOTAXAg27YVDoeVnZ0tj8ej2tpaZ19vb6/q6upUVFQkScrPz1diYmJETVtbmw4fPuzUFBYWKhQK6eDBg07NgQMHFAqFnBoAAIDhKiHaExjon/7pnzRnzhxlZWWpu7tbVVVVeuWVV1RTUyOXyyW/36/y8nLl5OQoJydH5eXlGjlypMrKyiRJlmVp4cKFWrFihUaPHq2MjAytXLlSeXl5mjFjhiRp4sSJmj17thYtWqQtW7ZIkhYvXqySkpIrvgMYAAAgXsVcAGxvb5fP51NbW5ssy9Jtt92mmpoazZw5U5K0atUq9fT0aOnSpQoGgyooKNCePXuUlpbmnGPz5s1KSEjQ3Llz1dPTo+nTp2vbtm0aMWKEU7Nz504tX77cuVu4tLRUlZWV17dZAACAKIiL7wGMVXwPIAAA8YfvAYyTzwACAADg6iEAAgAAGIYACAAAYBgCIAAAgGEIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGEIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGEIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhYi4AVlRU6LOf/azS0tKUmZmpe++9V8eOHYuosW1b69atk9frVUpKiqZNm6aWlpaImnA4rGXLlmnMmDFKTU1VaWmpTp8+HVETDAbl8/lkWZYsy5LP51NnZ+e1bhEAACCqYi4A1tXV6ZFHHlFDQ4Nqa2v13nvvqbi4WO+8845Ts3HjRm3atEmVlZVqbGyUx+PRzJkz1d3d7dT4/X5VV1erqqpK+/bt07lz51RSUqL+/n6npqysTM3NzaqpqVFNTY2am5vl8/mua78AAADXm8u2bTvak7iUs2fPKjMzU3V1dfriF78o27bl9Xrl9/u1evVqSe+v9rndbm3YsEFLlixRKBTS2LFjtWPHDs2bN0+SdObMGWVlZWn37t2aNWuWjhw5okmTJqmhoUEFBQWSpIaGBhUWFuro0aOaMGHCZefW1dUly7IUCoWUnp5+1Xu/ec2uy9a8tf7uq/68AAAMZ9f653c8iLkVwIFCoZAkKSMjQ5LU2tqqQCCg4uJipyY5OVlTp05VfX29JKmpqUl9fX0RNV6vV7m5uU7N/v37ZVmWE/4kacqUKbIsy6kBAAAYjhKiPYFLsW1bjz32mD7/+c8rNzdXkhQIBCRJbrc7otbtduvEiRNOTVJSkkaNGjWo5sLxgUBAmZmZg54zMzPTqRkoHA4rHA47j7u6uj5iZwAAANET0yuAjz76qH7729/qv/7rvwbtc7lcEY9t2x40NtDAmqHqL3WeiooK54YRy7KUlZV1JW0AAADElJgNgMuWLdNPf/pTvfzyy7rxxhudcY/HI0mDVuk6OjqcVUGPx6Pe3l4Fg8FL1rS3tw963rNnzw5aXbxg7dq1CoVCznbq1KmP3iAAAECUxFwAtG1bjz76qF588UX98pe/VHZ2dsT+7OxseTwe1dbWOmO9vb2qq6tTUVGRJCk/P1+JiYkRNW1tbTp8+LBTU1hYqFAopIMHDzo1Bw4cUCgUcmoGSk5OVnp6esQGAAAQb2LuM4CPPPKIXnjhBf33f/+30tLSnJU+y7KUkpIil8slv9+v8vJy5eTkKCcnR+Xl5Ro5cqTKysqc2oULF2rFihUaPXq0MjIytHLlSuXl5WnGjBmSpIkTJ2r27NlatGiRtmzZIklavHixSkpKrugOYAAAgHgVcwHw6aefliRNmzYtYvy5557Tgw8+KElatWqVenp6tHTpUgWDQRUUFGjPnj1KS0tz6jdv3qyEhATNnTtXPT09mj59urZt26YRI0Y4NTt37tTy5cudu4VLS0tVWVl5bRsEAACIspj/HsBYxvcAAgAQf/gewBj8DCAAAACurZj7FTA+nIGrhKwIAgCAy2EFEAAAwDAEQAAAAMMQAAEAAAxDAAQAADAMARAAAMAwBEAAAADDEAABAAAMQwAEAAAwDAEQAADAMARAAAAAwxAAAQAADEMABAAAMAwBEAAAwDAEQAAAAMMQAAEAAAxDAAQAADAMARAAAMAwBEAAAADDEAABAAAMQwAEAAAwDAEQAADAMARAAAAAwxAAAQAADEMABAAAMAwBEAAAwDAEQAAAAMMQAAEAAAxDAAQAADAMARAAAMAwBEAAAADDxFwA/NWvfqV77rlHXq9XLpdLL730UsR+27a1bt06eb1epaSkaNq0aWppaYmoCYfDWrZsmcaMGaPU1FSVlpbq9OnTETXBYFA+n0+WZcmyLPl8PnV2dl7j7gAAAKIv5gLgO++8o9tvv12VlZVD7t+4caM2bdqkyspKNTY2yuPxaObMmeru7nZq/H6/qqurVVVVpX379uncuXMqKSlRf3+/U1NWVqbm5mbV1NSopqZGzc3N8vl817w/AACAaHPZtm1HexIfxOVyqbq6Wvfee6+k91f/vF6v/H6/Vq9eLen91T63260NGzZoyZIlCoVCGjt2rHbs2KF58+ZJks6cOaOsrCzt3r1bs2bN0pEjRzRp0iQ1NDSooKBAktTQ0KDCwkIdPXpUEyZMuKL5dXV1ybIshUIhpaenX/X+b16z60Mf89b6u6/6PAAAGE6u9c/veJAQ7Ql8GK2trQoEAiouLnbGkpOTNXXqVNXX12vJkiVqampSX19fRI3X61Vubq7q6+s1a9Ys7d+/X5ZlOeFPkqZMmSLLslRfX3/FATAWDRUaCYUAAOBicRUAA4GAJMntdkeMu91unThxwqlJSkrSqFGjBtVcOD4QCCgzM3PQ+TMzM52aoYTDYYXDYedxV1fXR2sEAAAgimLuM4BXwuVyRTy2bXvQ2EADa4aqv9x5KioqnJtGLMtSVlbWh5w5AABA9MVVAPR4PJI0aJWuo6PDWRX0eDzq7e1VMBi8ZE17e/ug8589e3bQ6uLF1q5dq1Ao5GynTp36WP0AAABEQ1wFwOzsbHk8HtXW1jpjvb29qqurU1FRkSQpPz9fiYmJETVtbW06fPiwU1NYWKhQKKSDBw86NQcOHFAoFHJqhpKcnKz09PSIDQAAIN7E3GcAz507p9///vfO49bWVjU3NysjI0M33XST/H6/ysvLlZOTo5ycHJWXl2vkyJEqKyuTJFmWpYULF2rFihUaPXq0MjIytHLlSuXl5WnGjBmSpIkTJ2r27NlatGiRtmzZIklavHixSkpK4voGEAAAgCsRcwHw17/+tf72b//WefzYY49JkhYsWKBt27Zp1apV6unp0dKlSxUMBlVQUKA9e/YoLS3NOWbz5s1KSEjQ3Llz1dPTo+nTp2vbtm0aMWKEU7Nz504tX77cuVu4tLT0A797EAAAYDiJ6e8BjHWx+D2AQ+FrYAAA+DO+BzDOPgMIAACAj48ACAAAYBgCIAAAgGEIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhkmI9gRw7d28ZlfE47fW3x2lmQAAgFjACiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGH4l0AMNPBfBpH410EAADAJK4AAAACGIQACAAAYhgAIAABgGAIgAACAYbgJBJIG3xjCTSEAAAxfrAACAAAYhgAIAABgGH4FjCHxXYEAAAxfrAACAAAYhgAIAABgGOMD4A9+8ANlZ2frhhtuUH5+vl599dVoTylm3bxmV8QGAADik9EB8Cc/+Yn8fr8ef/xxvf766/rCF76gOXPm6OTJk9GeGgAAwDXjsm3bjvYkoqWgoEB33nmnnn76aWds4sSJuvfee1VRUXHZ47u6umRZlkKhkNLT06/6/OJxlY0bRQAAse5a//yOB8beBdzb26umpiatWbMmYry4uFj19fVDHhMOhxUOh53HoVBI0vtvpGvhfPjda3Lea+mmf/h/H/qYw0/MugYzAQBgaBd+bhu8BmZuAPzjH/+o/v5+ud3uiHG3261AIDDkMRUVFXriiScGjWdlZV2TOZrCeiraMwAAmKi7u1uWZUV7GlFhbAC8wOVyRTy2bXvQ2AVr167VY4895jw+f/68/u///k+jR4/+wGM+qq6uLmVlZenUqVNGLE/T7/BGv8Mb/Q5vw7Ff27bV3d0tr9cb7alEjbEBcMyYMRoxYsSg1b6Ojo5Bq4IXJCcnKzk5OWLsk5/85LWaoiQpPT192PyFuxL0O7zR7/BGv8PbcOvX1JW/C4y9CzgpKUn5+fmqra2NGK+trVVRUVGUZgUAAHDtGbsCKEmPPfaYfD6fJk+erMLCQj3zzDM6efKkHn744WhPDQAA4JoxOgDOmzdPb7/9tp588km1tbUpNzdXu3fv1vjx46M9NSUnJ+tb3/rWoF85D1f0O7zR7/BGv8Obaf2awujvAQQAADCRsZ8BBAAAMBUBEAAAwDAEQAAAAMMQAAEAAAxDAIxBP/jBD5Sdna0bbrhB+fn5evXVV6M9pQ+toqJCn/3sZ5WWlqbMzEzde++9OnbsWETNgw8+KJfLFbFNmTIloiYcDmvZsmUaM2aMUlNTVVpaqtOnT1/PVq7IunXrBvXi8Xic/bZta926dfJ6vUpJSdG0adPU0tIScY546fWCm2++eVDPLpdLjzzyiKT4v76/+tWvdM8998jr9crlcumll16K2H+1rmkwGJTP55NlWbIsSz6fT52dnde4u8Eu1W9fX59Wr16tvLw8paamyuv16qtf/arOnDkTcY5p06YNuuYPPPBARE089CtdvfdvvPQ71N9ll8ul7373u05NPF1fXB4BMMb85Cc/kd/v1+OPP67XX39dX/jCFzRnzhydPHky2lP7UOrq6vTII4+ooaFBtbW1eu+991RcXKx33nknom727Nlqa2tztt27d0fs9/v9qq6uVlVVlfbt26dz586ppKRE/f3917OdK3LrrbdG9HLo0CFn38aNG7Vp0yZVVlaqsbFRHo9HM2fOVHd3t1MTT71KUmNjY0S/F75U/f7773dq4vn6vvPOO7r99ttVWVk55P6rdU3LysrU3Nysmpoa1dTUqLm5WT6f75r3N9Cl+n333Xf12muv6Zvf/KZee+01vfjii/rd736n0tLSQbWLFi2KuOZbtmyJ2B8P/V5wNd6/8dLvxX22tbXpRz/6kVwul7785S9H1MXL9cUVsBFT/uZv/sZ++OGHI8Y+85nP2GvWrInSjK6Ojo4OW5JdV1fnjC1YsMD+0pe+9IHHdHZ22omJiXZVVZUz9oc//MH+xCc+YdfU1FzL6X5o3/rWt+zbb799yH3nz5+3PR6PvX79emfsT3/6k21Zlv3DH/7Qtu346vWDfOMb37BvueUW+/z587ZtD6/rK8murq52Hl+ta/rGG2/YkuyGhganZv/+/bYk++jRo9e4qw82sN+hHDx40JZknzhxwhmbOnWq/Y1vfOMDj4mnfq/G+zee+h3oS1/6kn3XXXdFjMXr9cXQWAGMIb29vWpqalJxcXHEeHFxserr66M0q6sjFApJkjIyMiLGX3nlFWVmZurTn/60Fi1apI6ODmdfU1OT+vr6Il4Pr9er3NzcmHw9jh8/Lq/Xq+zsbD3wwAN68803JUmtra0KBAIRfSQnJ2vq1KlOH/HW60C9vb16/vnn9dBDD8nlcjnjw+n6XuxqXdP9+/fLsiwVFBQ4NVOmTJFlWTH/GoRCIblcrkH/HvrOnTs1ZswY3XrrrVq5cmXEimi89ftx37/x1u8F7e3t2rVrlxYuXDho33C6vqYz+l8CiTV//OMf1d/fL7fbHTHudrsVCASiNKuPz7ZtPfbYY/r85z+v3NxcZ3zOnDm6//77NX78eLW2tuqb3/ym7rrrLjU1NSk5OVmBQEBJSUkaNWpUxPli8fUoKCjQj3/8Y336059We3u7vv3tb6uoqEgtLS3OXIe6ridOnJCkuOp1KC+99JI6Ozv14IMPOmPD6foOdLWuaSAQUGZm5qDzZ2ZmxvRr8Kc//Ulr1qxRWVmZ0tPTnfH58+crOztbHo9Hhw8f1tq1a/Wb3/zG+XhAPPV7Nd6/8dTvxbZv3660tDTdd999EePD6fqCABiTLl5Bkd4PUAPH4smjjz6q3/72t9q3b1/E+Lx585w/5+bmavLkyRo/frx27do16D88F4vF12POnDnOn/Py8lRYWKhbbrlF27dvdz44/lGuayz2OpStW7dqzpw58nq9zthwur4f5Gpc06HqY/k16Ovr0wMPPKDz58/rBz/4QcS+RYsWOX/Ozc1VTk6OJk+erNdee0133nmnpPjp92q9f+Ol34v96Ec/0vz583XDDTdEjA+n6wtuAokpY8aM0YgRIwb9n1JHR8eglYZ4sWzZMv30pz/Vyy+/rBtvvPGStePGjdP48eN1/PhxSZLH41Fvb6+CwWBEXTy8HqmpqcrLy9Px48edu4EvdV3judcTJ05o7969+trXvnbJuuF0fa/WNfV4PGpvbx90/rNnz8bka9DX16e5c+eqtbVVtbW1Eat/Q7nzzjuVmJgYcc3jqd+LfZT3bzz2++qrr+rYsWOX/fssDa/rayICYAxJSkpSfn6+s5x+QW1trYqKiqI0q4/Gtm09+uijevHFF/XLX/5S2dnZlz3m7bff1qlTpzRu3DhJUn5+vhITEyNej7a2Nh0+fDjmX49wOKwjR45o3Lhxzq9MLu6jt7dXdXV1Th/x3Otzzz2nzMxM3X333ZesG07X92pd08LCQoVCIR08eNCpOXDggEKhUMy9BhfC3/Hjx7V3716NHj36sse0tLSor6/Puebx1O9AH+X9G4/9bt26Vfn5+br99tsvWzucrq+RonHnCT5YVVWVnZiYaG/dutV+4403bL/fb6emptpvvfVWtKf2oXz961+3LcuyX3nlFbutrc3Z3n33Xdu2bbu7u9tesWKFXV9fb7e2ttovv/yyXVhYaP/lX/6l3dXV5Zzn4Ycftm+88UZ779699muvvWbfdddd9u23326/99570WptSCtWrLBfeeUV+80337QbGhrskpISOy0tzblu69evty3Lsl988UX70KFD9le+8hV73Lhxcdnrxfr7++2bbrrJXr16dcT4cLi+3d3d9uuvv26//vrrtiR706ZN9uuvv+7c9Xq1runs2bPt2267zd6/f7+9f/9+Oy8vzy4pKYmpfvv6+uzS0lL7xhtvtJubmyP+TofDYdu2bfv3v/+9/cQTT9iNjY12a2urvWvXLvszn/mMfccdd8Rdv1fz/RsP/V4QCoXskSNH2k8//fSg4+Pt+uLyCIAx6D/+4z/s8ePH20lJSfadd94Z8dUp8ULSkNtzzz1n27Ztv/vuu3ZxcbE9duxYOzEx0b7pppvsBQsW2CdPnow4T09Pj/3oo4/aGRkZdkpKil1SUjKoJhbMmzfPHjdunJ2YmGh7vV77vvvus1taWpz958+ft7/1rW/ZHo/HTk5Otr/4xS/ahw4dijhHvPR6sV/84he2JPvYsWMR48Ph+r788stDvocXLFhg2/bVu6Zvv/22PX/+fDstLc1OS0uz58+fbweDwevU5Z9dqt/W1tYP/Dv98ssv27Zt2ydPnrS/+MUv2hkZGXZSUpJ9yy232MuXL7fffvvtuOv3ar5/46HfC7Zs2WKnpKTYnZ2dg46Pt+uLy3PZtm1f0yVGAAAAxBQ+AwgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGEIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGEIgAAAAIYhAAIAABiGAAgAAGAYAiAAAIBhCIAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhvn/ohxy7uMGfzEAAAAASUVORK5CYII=", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "def get_genes(triplets):\n", + " gene = []\n", + " for ammino in triplets:\n", + " if ammino == '_':\n", + " yield gene\n", + " gene = []\n", + " else:\n", + " gene.append(ammino)\n", + "\n", + "plt.figure().clear()\n", + "plt.hist([len(g) for g in get_genes(get_triplets(dna))], bins=100)\n", + "\n", + "fname = '03_Ngramy/dna_length.png'\n", + "\n", + "plt.savefig(fname)\n", + "\n", + "fname" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + }, + "org": null + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/wyk/03_Ngramy.org b/wyk/03_Ngramy.org new file mode 100644 index 0000000..158581d --- /dev/null +++ b/wyk/03_Ngramy.org @@ -0,0 +1,225 @@ +* N-gramy + +W modelowaniu języka często rozpatruje się n-gramy, czyli podciągi o +rozmiarze $n$. + +Na przykład /digramy/ (/bigramy/) to zbitki dwóch jednostek, np. liter albo wyrazów. + +|$n$| $n$-gram| nazwa | +|---+---------+---------------| +| 1 | 1-gram | unigram | +| 2 | 2-gram | digram/bigram | +| 3 | 3-gram | trigram | +| 4 | 4-gram | tetragram | +| 5 | 5-gram | pentagram | + + +*Pytanie:* Jak nazywa się 6-gram? + +Jak widać, dla symetrii mówimy czasami o unigramach, jeśli operujemy +po prostu na jednostkach, nie na ich podciągach. + +*** N-gramy z Pana Tadeusza + +Statystyki, które policzyliśmy dla pojedynczych liter czy wyrazów, możemy powtórzyć dla n-gramów. + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer + def ngrams(iter, size): + ngram = [] + for item in iter: + ngram.append(item) + if len(ngram) == size: + yield tuple(ngram) + ngram = ngram[1:] + + list(ngrams("kotek", 3)) +#+END_SRC + +#+RESULTS: +:results: +[('k', 'o', 't'), ('o', 't', 'e'), ('t', 'e', 'k')] +:end: + +Zauważmy, że policzyliśmy wszystkie n-gramy, również częściowo się pokrywające. + +Zawsze powinniśmy się upewnić, czy jest jasne, czy chodzi o n-gramy znakowe czy wyrazowe + +*** 3-gramy znakowe + +#+BEGIN_SRC ipython :session mysession :results file + log_rang_log_freq('pt-3-char-ngrams-log-log', ngrams(get_characters(pan_tadeusz), 3)) +#+END_SRC + +#+RESULTS: +[[file:03_Ngramy/pt-3-char-ngrams-log-log.png]] + +*** 2-gramy wyrazowe + +#+BEGIN_SRC ipython :session mysession :results file + log_rang_log_freq('pt-2-word-ngrams-log-log', ngrams(get_words(pan_tadeusz), 2)) +#+END_SRC + +#+RESULTS: +[[file:03_Ngramy/pt-2-word-ngrams-log-log.png]] + +** Tajemniczy język Manuskryptu Wojnicza + +[[https://pl.wikipedia.org/wiki/Manuskrypt_Wojnicza][Manuskrypt Wojnicza]] to powstały w XV w. manuskrypt spisany w +tajemniczym alfabecie, do dzisiaj nieodszyfrowanym. Rękopis stanowi +jedną z największych zagadek historii (i lingwistyki). + +[[./02_Jezyki/voynich135.jpg][Źródło: https://commons.wikimedia.org/wiki/File:Voynich_Manuscript_(135).jpg]] + +Sami zbadajmy statystyczne własności tekstu manuskryptu. Użyjmy +transkrypcji Vnow, gdzie poszczególne znaki tajemniczego alfabetu +zamienione na litery alfabetu łacińskiego, cyfry i gwiazdkę. Jak +transkrybować manuskrypt, pozostaje sprawą dyskusyjną, natomiast wybór +takiego czy innego systemu transkrypcji nie powinien wpływać +dramatycznie na analizę statystyczną. + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer + import requests + + voynich_url = 'http://www.voynich.net/reeds/gillogly/voynich.now' + voynich = requests.get(voynich_url).content.decode('utf-8') + + voynich = re.sub(r'\{[^\}]+\}|^<[^>]+>|[-# ]+', '', voynich, flags=re.MULTILINE) + + voynich = voynich.replace('\n\n', '#') + voynich = voynich.replace('\n', ' ') + voynich = voynich.replace('#', '\n') + + voynich = voynich.replace('.', ' ') + + voynich[100:150] +#+END_SRC + +#+RESULTS: +:results: +9 OR 9FAM ZO8 QOAR9 Q*R 8ARAM 29 [O82*]OM OPCC9 OP +:end: + +#+BEGIN_SRC ipython :session mysession :results file + rang_freq_with_labels('voy-chars', get_characters(voynich)) +#+END_SRC + +#+RESULTS: +[[file:03_Ngramy/voy-chars.png]] + +#+BEGIN_SRC ipython :session mysession :results file + log_rang_log_freq('voy-log-log', get_words(voynich)) +#+END_SRC + +#+RESULTS: +[[file:03_Ngramy/voy-log-log.png]] + +#+BEGIN_SRC ipython :session mysession :results file + rang_freq_with_labels('voy-words-20', get_words(voynich), top=20) +#+END_SRC + +#+RESULTS: +[[file:03_Ngramy/voy-words-20.png]] + +#+BEGIN_SRC ipython :session mysession :results file + log_rang_log_freq('voy-words-log-log', get_words(voynich)) +#+END_SRC + +#+RESULTS: +[[file:03_Ngramy/voy-words-log-log.png]] + +** Język DNA + +Kod genetyczny przejawia własności zaskakująco podobne do języków naturalnych. +Przede wszystkim ma charakter dyskretny, genotyp to ciąg symboli ze skończonego alfabetu. +Podstawowe litery są tylko cztery, reprezentują one nukleotydy, z których zbudowana jest nić DNA: +a, g, c, t. + + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer + import requests + + dna_url = 'https://raw.githubusercontent.com/egreen18/NanO_GEM/master/rawGenome.txt' + dna = requests.get(dna_url).content.decode('utf-8') + + dna = ''.join(dna.split('\n')[1:]) + dna = dna.replace('N', 'A') + + dna[0:100] +#+END_SRC + +#+RESULTS: +:results: +TATAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTA +:end: + +#+BEGIN_SRC ipython :session mysession :results file + rang_freq_with_labels('dna-chars', get_characters(dna)) +#+END_SRC + +#+RESULTS: +[[file:03_Ngramy/dna-chars.png]] + +*** Tryplety — znaczące cząstki genotypu + +Nukleotydy rzeczywiście są jak litery, same w sobie nie niosą +znaczenia. Dopiero ciągi trzech nukleotydów, /tryplety/, kodują jeden +z dwudziestu aminokwasów. + +#+BEGIN_SRC ipython :session mysession :results file + genetic_code = { + 'ATA':'I', 'ATC':'I', 'ATT':'I', 'ATG':'M', + 'ACA':'T', 'ACC':'T', 'ACG':'T', 'ACT':'T', + 'AAC':'N', 'AAT':'N', 'AAA':'K', 'AAG':'K', + 'AGC':'S', 'AGT':'S', 'AGA':'R', 'AGG':'R', + 'CTA':'L', 'CTC':'L', 'CTG':'L', 'CTT':'L', + 'CCA':'P', 'CCC':'P', 'CCG':'P', 'CCT':'P', + 'CAC':'H', 'CAT':'H', 'CAA':'Q', 'CAG':'Q', + 'CGA':'R', 'CGC':'R', 'CGG':'R', 'CGT':'R', + 'GTA':'V', 'GTC':'V', 'GTG':'V', 'GTT':'V', + 'GCA':'A', 'GCC':'A', 'GCG':'A', 'GCT':'A', + 'GAC':'D', 'GAT':'D', 'GAA':'E', 'GAG':'E', + 'GGA':'G', 'GGC':'G', 'GGG':'G', 'GGT':'G', + 'TCA':'S', 'TCC':'S', 'TCG':'S', 'TCT':'S', + 'TTC':'F', 'TTT':'F', 'TTA':'L', 'TTG':'L', + 'TAC':'Y', 'TAT':'Y', 'TAA':'_', 'TAG':'_', + 'TGC':'C', 'TGT':'C', 'TGA':'_', 'TGG':'W', + } + + def get_triplets(t): + for triplet in re.finditer(r'.{3}', t): + yield genetic_code[triplet.group(0)] + + rang_freq_with_labels('dna-aminos', get_triplets(dna)) +#+END_SRC + +#+RESULTS: +[[file:03_Ngramy/dna-aminos.png]] + +*** „Zdania” w języku DNA + +Z aminokwasów zakodowanych przez tryplet budowane są białka. +Maszyneria budująca białka czyta sekwencję aż do napotkania +trypletu STOP (_ powyżej). Taka sekwencja to /gen/. + +#+BEGIN_SRC ipython :session mysession :results file + def get_genes(triplets): + gene = [] + for ammino in triplets: + if ammino == '_': + yield gene + gene = [] + else: + gene.append(ammino) + + plt.figure().clear() + plt.hist([len(g) for g in get_genes(get_triplets(dna))], bins=100) + + fname = '03_Ngramy/dna_length.png' + + plt.savefig(fname) + + fname +#+END_SRC + +#+RESULTS: +[[file:03_Ngramy/dna_length.png]] diff --git a/wyk/03_Ngramy/dna-aminos.png b/wyk/03_Ngramy/dna-aminos.png new file mode 100644 index 0000000..d1f36bd Binary files /dev/null and b/wyk/03_Ngramy/dna-aminos.png differ diff --git a/wyk/03_Ngramy/dna-chars.png b/wyk/03_Ngramy/dna-chars.png new file mode 100644 index 0000000..3a86ed0 Binary files /dev/null and b/wyk/03_Ngramy/dna-chars.png differ diff --git a/wyk/03_Ngramy/dna_length.png b/wyk/03_Ngramy/dna_length.png new file mode 100644 index 0000000..fd043ea Binary files /dev/null and b/wyk/03_Ngramy/dna_length.png differ diff --git a/wyk/03_Ngramy/pt-2-word-ngrams-log-log.png b/wyk/03_Ngramy/pt-2-word-ngrams-log-log.png new file mode 100644 index 0000000..25b8ec9 Binary files /dev/null and b/wyk/03_Ngramy/pt-2-word-ngrams-log-log.png differ diff --git a/wyk/03_Ngramy/pt-3-char-ngrams-log-log.png b/wyk/03_Ngramy/pt-3-char-ngrams-log-log.png new file mode 100644 index 0000000..608ef2a Binary files /dev/null and b/wyk/03_Ngramy/pt-3-char-ngrams-log-log.png differ diff --git a/wyk/03_Ngramy/voy-chars.png b/wyk/03_Ngramy/voy-chars.png new file mode 100644 index 0000000..e21ab90 Binary files /dev/null and b/wyk/03_Ngramy/voy-chars.png differ diff --git a/wyk/03_Ngramy/voy-log-log.png b/wyk/03_Ngramy/voy-log-log.png new file mode 100644 index 0000000..d0a7bee Binary files /dev/null and b/wyk/03_Ngramy/voy-log-log.png differ diff --git a/wyk/03_Ngramy/voy-words-20.png b/wyk/03_Ngramy/voy-words-20.png new file mode 100644 index 0000000..09a37e9 Binary files /dev/null and b/wyk/03_Ngramy/voy-words-20.png differ diff --git a/wyk/03_Ngramy/voy-words-log-log.png b/wyk/03_Ngramy/voy-words-log-log.png new file mode 100644 index 0000000..d0a7bee Binary files /dev/null and b/wyk/03_Ngramy/voy-words-log-log.png differ diff --git a/wyk/03_Ngramy/voynich135.jpg b/wyk/03_Ngramy/voynich135.jpg new file mode 100644 index 0000000..b8bd37a Binary files /dev/null and b/wyk/03_Ngramy/voynich135.jpg differ diff --git a/wyk/04_Entropia.ipynb b/wyk/04_Entropia.ipynb new file mode 100644 index 0000000..a99c70d --- /dev/null +++ b/wyk/04_Entropia.ipynb @@ -0,0 +1,19 @@ + +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n", + "
\n", + "

Modelowanie języka

\n", + "

04. Entropia [wykład]

\n", + "

Filip Graliński (2022)

\n", + "
\n", + "\n", + "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)\n", + "\n" + ] + }, +{"cell_type":"markdown","metadata":{},"source":["## Entropia\n\n"]},{"cell_type":"markdown","metadata":{},"source":["**Entropia** ($E$) to miara nieuporządkowania, niepewności, niewiedzy. Im\nwiększa entropia, tym mniej wiemy. Pojęcie to pierwotnie wywodzi się z\ntermodynamiki, później znaleziono wiele zaskakujących analogii i zastosowań w\ninnych dyscyplinach nauki.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Entropia w fizyce\n\n"]},{"cell_type":"markdown","metadata":{},"source":["W termodynamice entropia jest miarą nieuporządkowania układów\nfizycznych, na przykład pojemników z gazem. Przykładowo, wyobraźmy\nsobie dwa pojemniki z gazem, w którym panuje różne temperatury.\n\n![img](./04_Entropia/gas-low-entropy.drawio.png)\n\nJeśli usuniemy przegrodę między pojemnikami, temperatura się wyrówna,\na uporządkowanie się zmniejszy.\n\n![img](./04_Entropia/gas-high-entropy.drawio.png)\n\nInnymi słowy, zwiększy się stopień nieuporządkowania układu, czyli właśnie entropia.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### II prawo termodynamiki\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Jedno z najbardziej fundamentalnych praw fizyki, II prawo\ntermodynamiki głosi, że w układzie zamkniętym entropia nie spada.\n\n****Pytanie****: Czy to, że napisałem te materiały do wykładu i\n*uporządkowałem* wiedzę odnośnie do statystycznych własności języka, nie\njest sprzeczne z II prawem termodynamiki?\n\nKonsekwencją II prawa termodynamiki jest śmierć cieplna Wszechświata\n(zob. [wizualizacja przyszłości Wszechświata]([https://www.youtube.com/watch?v=uD4izuDMUQA](https://www.youtube.com/watch?v=uD4izuDMUQA))).\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Entropia w teorii informacji\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Pojęcie entropii zostało „odkryte” na nowo przez Claude'a Shannona,\ngdy wypracował ogólną teorię informacji.\n\nTeoria informacji zajmuje się między innymi zagadnieniem optymalnego kodowania komunikatów.\n\nWyobraźmy sobie pewne źródło (generator) losowych komunikatów z\nzamkniętego zbioru symboli ($\\Sigma$; nieprzypadkowo używamy oznaczeń\nz poprzedniego wykładu). Nadawca $N$ chce przesłać komunikat o wyniku\nlosowania do odbiorcy $O$ używając zer i jedynek (bitów).\nTeorioinformacyjną entropię można zdefiniować jako średnią liczbę\nbitów wymaganych do przesłania komunikatu.\n\n![img](./04_Entropia/communication.drawio.png)\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Obliczanie entropii — proste przykłady\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Załóżmy, że nadawca chce przekazać odbiorcy informację o wyniku rzutu monetą.\nEntropia wynosi wówczas rzecz jasna 1 — na jedno losowanie wystarczy jeden bit\n(informację o tym, że wypadł orzeł, możemy zakodować na przykład za pomocą zera,\nzaś to, że wypadła reszka — za pomocą jedynki).\n\nRozpatrzmy przypadek, gdy nadawca rzuca ośmiościenną kością. Aby przekazać\nwynik, potrzebuje wówczas 3 bity (a więc entropia ośmiościennej kości\nwynosi 3 bity). Przykładowe kodowanie może mieć następującą postać:\n\n| Wynik|Kodowanie|\n|---|---|\n| 1|001|\n| 2|010|\n| 3|011|\n| 4|100|\n| 5|101|\n| 6|110|\n| 7|111|\n| 8|000|\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Obliczenie entropii — trudniejszy przykład\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Załóżmy, że $\\Sigma = \\{A, B, C, D\\}$, natomiast poszczególne komunikaty\nsą losowane zgodnie z następującym rozkładem prawdopodobieństwa:\n$P(A)=1/2$, $P(B)=1/4$, $P(C)=1/8$, $P(D)=1/8$. Ile wynosi entropia w\ntakim przypadku? Można by sądzić, że 2, skoro wystarczą 2 bity do\nprzekazania wyniku losowania przy zastosowaniu następującego kodowania:\n\n| Wynik|Kodowanie|\n|---|---|\n| A|00|\n| B|01|\n| C|10|\n| D|11|\n\nProblem w tym, że w rzeczywistości nie jest to *optymalne* kodowanie.\nMożemy sprytnie zmniejszyć średnią liczbę bitów wymaganych do\nprzekazania losowego wyniku przypisując częstszym wynikom krótsze\nkody, rzadszym zaś — dłuższe. Oto takie optymalne kodowanie:\n\n| Wynik|Kodowanie|\n|---|---|\n| A|0|\n| B|10|\n| C|110|\n| D|111|\n\nUżywając takiego kodowanie średnio potrzebujemy:\n\n$$\\frac{1}{2}1 + \\frac{1}{4}2 + \\frac{1}{8}3 + \\frac{1}{8}3 = 1,75$$\n\nbita. Innymi słowy, entropia takiego źródła wynosi 1,75 bita.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Kodowanie musi być jednoznaczne!\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Można by sądzić, że da się stworzyć jeszcze krótsze kodowanie dla omawianego rozkładu nierównomiernego:\n\n| Wynik|Kodowanie|\n|---|---|\n| A|0|\n| B|1|\n| C|01|\n| D|11|\n\nNiestety, nie jest to właściwe rozwiązanie — kodowanie musi być\njednoznaczne nie tylko dla pojedynczego komunikatu, lecz dla całej sekwencji.\nNa przykład ciąg 0111 nie jest jednoznaczny przy tym kodowaniu (ABBB czy CD?).\nPodane wcześniej kodowanie spełnia warunek jednoznaczności, ciąg 0111 można odkodować tylko\njako AD.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Ogólny wzór na entropię.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Na podstawie poprzedniego przykładu można dojść do intuicyjnego wniosku, że\noptymalny kod dla wyniku o prawdopodobieństwie $p$ ma długość $-\\log_2(p)$, a zatem ogólnie\nentropia źródła o rozkładzie prawdopodobieństwa $\\{p_1,\\ldots,p_|\\Sigma|\\}$ wynosi:\n\n$$E = -\\sum_{i=1}^{|\\Sigma|} p_i\\log_2(p_i)$$.\n\nZauważmy, że jest to jeden z nielicznych przypadków, gdy w nauce naturalną\npodstawą logarytmu jest 2 zamiast… podstawy logarytmu naturalnego ($e$).\n\nTeoretycznie można mierzyć entropię używając logarytmu naturalnego\n($\\ln$), jednostką entropii będzie wówczas **nat** zamiast bita,\nniewiele to jednak zmienia i jest mniej poręczne i trudniejsze do interpretacji\n(przynajmniej w kontekście informatyki) niż operowanie na bitach.\n\n****Pytanie**** Ile wynosi entropia zwykłej sześciennej kostki? Jak wygląda\noptymalne kodowanie wyników rzutu taką kostką?\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Entropia dla próby Bernoulliego\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Wiemy już, że entropia dla rzutu monetą wynosi 1 bit. A jaki będzie wynik dla źle wyważonej monety?\n\n"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[{"data":{"image/png":"iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAA9hAAAPYQGoP6dpAABlTElEQVR4nO3deVhU9f4H8PcsDPsMsoMgi4qCKCi4YeSSS1ourVY3zbJuXvOaetvMe69l3euvW5l5S9tMr7lkVlaWlVqpKC6J4AIICCgiIIKy7zPf3x8DUwQqKnBm5rxfzzNPceYM85nDwfPmux2FEEKAiIiIiGRDKXUBRERERNS5GACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZIYBkIiIiEhmGACJiIiIZEYtdQGWzGAwIC8vD87OzlAoFFKXQ0RERG0ghEB5eTl8fX2hVMqzLYwB8Cbk5eXB399f6jKIiIjoBpw7dw5+fn5SlyEJBsCb4OzsDMB4Amm1WomrISIiorYoKyuDv7+/6TouRwyAN6Gp21er1TIAEhERWRg5D9+SZ8c3ERERkYwxABIRERHJDAMgERERkcwwABIRERHJDAMgERERkcwwABIRERHJDAMgERERkcwwABIRERHJDAMgERERkcxYTQDcu3cvJk6cCF9fXygUCnz11VfXfM2ePXsQFRUFOzs7BAcH47333uv4QomIiIgkZjUBsLKyEhEREXjnnXfatH92djYmTJiA2NhYJCYm4sUXX8TcuXPxxRdfdHClRERERNKymnsBjx8/HuPHj2/z/u+99x66deuG5cuXAwBCQ0Nx5MgRvPHGG7jnnns6qEoiIiIi6VlNALxeBw4cwNixY5ttGzduHFavXo36+nrY2Ni0eE1tbS1qa2tNX5eVlXV4nUTUfur1BhRV1KK4og6Xq+pwqdL4KK9pQE29HrUNBtQ26FFTb4DBIKBSKqBWKaBUKKBWKmBno4LW3gZaO3Xjf23g6qiBj84O7k62UCrle2N5IrIssg2ABQUF8PLyarbNy8sLDQ0NKCoqgo+PT4vXLF26FC+//HJnlUhEN6BBb0B2USVOFZQj62Ilzl2uwrlLVci9XI380moYRMe8r1qpgJfWDj46O/i7OqC7hyN6eDqhh6cTurk6QqO2mhE3RGQFZBsAAUChaP7XuhCi1e1NFi5ciAULFpi+Lisrg7+/f8cVSERXVa83ICWvDEdzLuNEbilOFZTj9MUK1DUYrvgatVIBV0eN6dHFUQOtnQ3sbJSws1HBVq2ErVoFlRLQGwC9wYAGg4DeIFBdp0dZTT3KqhtQVlOP0up6FFfUobC8Bg0GgfMl1ThfUo0jZy+3eM9gD0f083NBhJ8O/fxc0NvHGbZqVUcfIiKiVsk2AHp7e6OgoKDZtsLCQqjVari5ubX6GltbW9ja2nZGeUTUiqq6BhzKvoSDWcVIPFuCY7klqG0l7DloVAjxckZPTyd0c3WAv6sD/F3t4d/FoUO6auv1Blwsr0V+aQ3yS6txtrgKmYUVOH2xApmFFais0yP9QgXSL1Tg84RcAIBGpUSfrlrEdHfD0GB3RAV0gb2GgZCIOodsA+DQoUOxbdu2Ztt27NiB6OjoVsf/EVHnMxgEUvLLsDfjIvZlFOHImcuo0zcPfC4ONujv74JI/y4I9XFGb28t/LrYd+p4PBuVEr4u9vB1sQfQpdlzQgjkl9YgOa8Mx3NLcCy3FMdzS1BSVY/EnBIk5pTg3V8yoVEpEdnNBbE93DE6zAu9vZ2v2BtBRHSzFKKp39PCVVRU4PTp0wCA/v37Y9myZRg5ciRcXV3RrVs3LFy4EOfPn8e6desAGJeBCQ8Px5NPPoknnngCBw4cwKxZs7Bp06Y2zwIuKyuDTqdDaWkptFpth302Ijlp0BtwOPsSfkguwI/JBbhQVtvs+a4u9hjWww3Rga4Y0K0Lgt0dLW7yhRACOZeqcDj7Eg5kFuNAVjHyS2ua7dPVxR6jQz1xW6gXhgS7cQwhUTvi9duKAuDu3bsxcuTIFtsfeeQRrF27FjNmzMCZM2ewe/du03N79uzB/PnzkZycDF9fXzz//POYNWtWm9+TJxBR+9AbBOIzi7DtWB52plzA5ap603MOGhViurshtqcHYnu6I8jd0epaxoQQOFtchfjMYvx8qhD7Tl9ETf1vLZ06extM6OuNSRFdMTjI1eICL5G54fXbigKgFHgCEd2c04Xl+OLoeWw9eh4FZb+1gHVxsMGYMC/cHu6NmO7usLOR19i46jo94jOLsCv1AnalFuJi+W+toN5aO0yK9MXdA7qitzf/3SG6Ebx+MwDeFJ5ARNevqq4BXyfl4dPDOTiWW2rarrO3wZ39fHBHXx8MCnKFWsUuT8DYOnooqxhfJ+Vh+8l8lNc0mJ4b0M0FDw7qhjv7+XICCdF14PWbAfCm8AQiarvsokp8cuAstiScM4UYtVKBEb08cM8AP4wK9eSyKNdQ26DH7rSL2Hr0PHalXkBD46KGWjs17h7gh4eHdEMPT2eJqyQyf7x+MwDeFJ5ARFcnhEBcRhFW78vGnvSLpu3dXB0wbUgA7hrQFe5OXFrpRhSW12DLkVx8+msOzl2qNm0f1dsTT8QGY0iwq9WNlSRqL7x+MwDeFJ5ARK3TGwS+P5mPVbszkZxnvGWiQgGMCPHA9JhADO/pwYkM7cRgEIg7XYT1B89iV+oFNP2LHt5ViydigzGhrw9s2J1O1Ayv3wyAN4UnEFFztQ16fJFwHh/szcSZ4ioAgL2NCg8M8seMmEAEuDlKXKF1yy6qxOp9Wfg8Idc0i9jf1R5/HdkTdw3oyiBI1IjXbwbAm8ITiMioQW/AF0dzseKn0zhfYuyOdHGwwSNDA/FITCBcHTUSVygvlyrrsP7gWfwv/gyKK+sAGLvd54zqgbv6MwgS8frNAHhTeAKR3BkMAt+eyMdbO9ORXVQJAPB0tsWfbw3Gg4O6wdFWtjcbMgtVdQ3YcDAH7+/NRFGFMQgGuDng6dt6YkpkV3bDk2zx+s0AeFN4ApGc7U4rxP99fwqnCsoBAK6OGswe0R0PDwmQ3bp95q4pCL63J9PUItjHV4sXJ4RiWA93iasj6ny8fjMA3hSeQCRHpwvL8ep3qdidZpzV62yrxhO3BuOxW4LgxBY/s1ZV14C18Wew6pdMlNcal+IZ0csDC8eHopc3l48h+eD1mwHwpvAEIjm5XFmHt3/KwCcHz0JvELBRKfDI0EDMGdUDLg4c42dJLlXWYcVPGVh/8CwaDAJKBfDAoG54dmwvdOF4TZIBXr8ZAG8KTyCSA4NBYMPhHLzxYxpKq4336B0T5oUXJ4QiyJ2zei1ZdlEl/vPDKXx/sgCA8RZ8L4zvjfui/Dk+kKwar98MgDeFJxBZu9T8Mry49QQSc0oAAL29nfGPO8M4bszKHMoqxj++Pon0CxUAgP7dXPDK5HCEd9VJXBlRx+D1mwHwpvAEImtVVdeAt3dl4KN92dAbBJxs1XhmbAimDQ2Eii1DVqleb8D/4s/grZ3pqKzTQ6kAHokJxLPjesFBw7GdZF14/WYAvCk8gcga7Um/iBe/PGFaz29CX2/8884+8NbZSVwZdYYLZTV49btUbDuWB8C4kPRrd/dDDFt9yYrw+s0AeFN4ApE1qahtwL++S8Gmw+cAAF1d7PHKlD4Y1dtL4spICnvSL2LhF8eRV1oDAHhwUDcsnNAbWjsbiSsjunm8fjMA3hSeQGQt4k8X4dnPj5ta/WbEBOK529n1J3flNfV47YdTWH8wBwDgo7PD/93TD8NDPCSujOjm8PrNAHhTeAKRpauqa8D/fX8K6w6cBWDs7nv93ggMCXaTuDIyJwezivH8F8dxtvH+zjNiAvHC+N5c8JssFq/fDIA3hScQWbLkvFL8dVMisi4ab+H28JBuWDg+lLdvo1ZV1+nxf9+n4n+NfyyEeDnh7Qf6I9SH//aR5eH1mwHwpvAEIkskhMDa+DNYuv0U6vQGeGlt8cZ9EYjtyW49urZf0grx7JbjKKqohUalxHO398Jjw4K4biBZFF6/GQBvCk8gsjSXKuvw7JZj+OlUIQBgdKgn/nNvBFx59we6DkUVtXjhi+PYlWo8j4aHeOCtqZE8j8hi8PrNAHhTeAKRJTmUVYy/bkpEYXktNGolFk0IxfShAVAo2HJD108IgQ2HcvDKtymobTDAR2eHdx4agKiALlKXRnRNvH4DSqkLIKKOJYTAR3FZeOijQygsr0UPTyd8/dQwPBITyPBHN0yhUODhIQH46qlhCHZ3RH5pDaa+fwAfxWWB7QpE5o8BkMiKVdQ2YM7GRLz6XSr0BoEpkb74Zs4wDtyndhPqo8XXc4bhjn4+aDAIvPpdKv6y/ijKauqlLo2IroIBkMhKnS6swJR39+O7E/lQKxVYMrkP3poaybX9qN0529ngnQf74+VJfWCjUuCH5AJMeXc/Mi9WSF0aEV0BAyCRFdqRXIDJ7+zD6cIKeGltsfnJIZg+lF2+1HEUCgUeiQnEllkx8NHZIetiJaa8ux+/pBVKXRoRtYIBkMiKCCGwancmnlyfgMo6PQYHueLbv8YiKsBV6tJIJiL9XfDNnFsQHdAF5TUNeGztr3h/TybHBRKZGQZAIitR26DH37Ycw2s/nIIQwLQhAVj/+GB4ONtKXRrJjIezLTY8MRgPDPSHEMDS709h/uYk1NTrpS6NiBpxMBCRFSiqqMWsTxJw5OxlqJQKLJ4YhulDA6Uui2TMVq3C0rv7IsxXi5e3peCrpDycvVSFj6ZHw82Jf5QQSY0tgEQWLuNCOaa8ux9Hzl6Gs50aa2YMZPgjs6BQKDB9aCA+mTkIOnsbJOaU4O5V8cji5BAiyTEAElmww9mXcM+qeORerkaAmwO2zh6GW0N4SzcyLzHd3fHFX2Lg72qPs8VVuHtVPI6cuSR1WUSyxgBIZKG+P5GPh1cfQllNAwZ0c8FXs4ehh6eT1GURtaqHpxO+/MswRPjpUFJVj4c+OoTvjudLXRaRbDEAElmg/8WfweyNR1HXYMCYMC9sfGIIuvA+rGTmPJxtsenPQzAmzAt1DQY8tfEoPorLkrosIlliACSyIEIIvPbDKSz+JhlCAH8a3A3vPRwFOxuV1KURtYmDRo33Ho7CjJhAAMCr36XijR/TuEwMUSfjLGAiC6E3CLz45QlsPnIOAPDM2BA8NbIHF3cmi9M0U93D2Rav/5iGd345jZLqOiyZFA6lkuczUWdgACSyAPV6A+ZvTsK3x/OhVAD/d08/3B/tL3VZRDdMoVDgqZE9oLO3wT++Pon1B3NQWt2AN++LgEbNzimijsbfMiIzV1Ovx6xPEvDt8XzYqBR456EBDH9kNR4eEoAVD/SHWqnAtmN5+PMnR1BdxwWjiToaAyCRGausNd5K66dThbBVK/HB9GhM6OsjdVlE7WpihC8+eiQadjZK7E67iBlrDqOytkHqsoisGgMgkZkqra7Hw6sPIT6zGE62aqx7bBBG9vKUuiyiDjGilyfWzxwMZ1s1DmVfwow1h1HBEEjUYRgAicxQWU09pq8+hMScEujsbbDh8cEYHOwmdVlEHSo60BWfPD4YznZq/HrmMqavPoTymnqpyyKySgyARGamvKYe01cfxrHcUnRxsMGnfx6CCH8Xqcsi6hSR/i7Y8PhgaO3UOJpTgmmrD6O0miGQqL0xABKZkfKaejzy8WEknSuBi4MNNjw+BKE+WqnLIupU/fxcsPGJIXBxsEHSuRJMW30IpVUMgUTtiQGQyExU1DZgxppfcbSx23f9zMEI82X4I3kK76rDxseHoIuDDY7nlmL6msPsDiZqRwyARGagsrYBj645jISzl6G1U2PD44MR3lUndVlEkgrz1WLTn40tgcfOlWDmWi4RQ9ReGACJJFZTr8fM//2KX89chrOdGusZ/ohMentr8cljxtnBh89cwp8/OYLaBoZAopvFAEgkoXq9AXM2HsXBrEtwslVj/czB6OfnInVZRGalr58Oax8bCAeNCnEZRXhqQyLq9QapyyKyaAyARBIxGASe+/w4dqUaF3le/Ug0Z/sSXUFUgCs+mh4NjVqJXakXMH9zEvQGIXVZRBaLAZBIAkIIvLwtGVsTz0OtVGDVwwO4zh/RNcT0cMf7D0fBRqXAt8fz8fevTkAIhkCiG8EASCSBt3Zl4H8HzkKhAN68PwKjentJXRKRRRjZ2xMrHugPpQLYdPgc3tqVIXVJRBaJAZCok63el40VPxkvWksmh2NyZFeJKyKyLOP7+uCVKeEAgBU/ZeCTA2ekLYjIAjEAEnWir5PO45VvUwAAz4wNwbQhARJXRGSZ/jQ4APNG9wQA/PObZGw/kS9xRUSWhQGQqJMczCrGs1uOAwAeGxaEp0b2kLgiIsv29G098afB3SAEMO/TJBzILJa6JCKLwQBI1AkyLpTjz+uOoE5vwPhwb/z9jlAoFAqpyyKyaAqFAksmh+P2Pt6o0xvw53VHkJJXJnVZRBaBAZCogxWW1WDGml9RVtOAqIAueGtqJJRKhj+i9qBSKrD8gUgMDnJFeW0DZv7vV1woq5G6LCKzxwBI1IEqaxvw6Npfcb6kGkHujvhoejTsbFRSl0VkVexsVPhgejR6eDohv7QGj639FZW1DVKXRWTWGACJOkiD3oCnNh5Fcl4Z3Bw1WPvoQHRx1EhdFpFV0tnbYM2MgXBz1CA5rwxPf5rIhaKJroIBkKgDCCGw+Jtk7E67CDsbJVbPGIgAN0epyyKyav6uDvjwkWjYqpXYlVqIf32XKnVJRGaLAZCoA3xy8Cw2HMqBQgGseKA/InmLN6JOMaBbFyy7PxIA8PH+bPwv/oyk9RCZK6sKgCtXrkRQUBDs7OwQFRWFuLi4q+6/YcMGREREwMHBAT4+Pnj00UdRXMxlBOjm7D9dhJe3Gdf6e/723hjbx1viiojk5Y5+Pnju9l4AgJe3JeOXtEKJKyIyP1YTADdv3ox58+Zh0aJFSExMRGxsLMaPH4+cnJxW99+3bx+mT5+OmTNnIjk5GVu2bMGvv/6Kxx9/vJMrJ2uSXVSJ2RuOQm8QuLt/Vzx5a7DUJRHJ0l+Gd8fUaH8YBDB3UyIyL1ZIXRKRWbGaALhs2TLMnDkTjz/+OEJDQ7F8+XL4+/tj1apVre5/8OBBBAYGYu7cuQgKCsItt9yCJ598EkeOHOnkyslalNXU4/H//YrS6nr07+aCf9/dl2v9EUlEoVDglSnhiA7ogvKaBjyx7gjKauqlLovIbFhFAKyrq0NCQgLGjh3bbPvYsWMRHx/f6mtiYmKQm5uL7du3QwiBCxcu4PPPP8cdd9xxxfepra1FWVlZswcRAOgNAn/dmIjMi5Xw0dnh/WlRXO6FSGIatRKrHo6Cj84OWRcrMe/TJM4MJmpkFQGwqKgIer0eXl5ezbZ7eXmhoKCg1dfExMRgw4YNmDp1KjQaDby9veHi4oL//ve/V3yfpUuXQqfTmR7+/v7t+jnIci3dnoo96cYZvx9Oj4ans53UJRERAA9nW3wwzTgz+OdThXhzR5rUJRGZBasIgE3+2N0mhLhiF1xKSgrmzp2Lf/7zn0hISMAPP/yA7OxszJo164rff+HChSgtLTU9zp071671k2X6Ouk8PtqXDQB4875IhHfVSVwREf1eXz8d/nNvPwDAyt2Z2HYsT+KKiKSnlrqA9uDu7g6VStWita+wsLBFq2CTpUuXYtiwYXj22WcBAP369YOjoyNiY2Px6quvwsfHp8VrbG1tYWtr2/4fgCxWWkE5XvjiBADgqZHdcUe/lucNEUlvcmRXpOSX4f09WXj282MI9nBEH1/+sUbyZRUtgBqNBlFRUdi5c2ez7Tt37kRMTEyrr6mqqoJS2fzjq1TGMVtCcIwIXVtZTT1mrU9Adb0esT3dsWBML6lLIqKreG5cbwwP8UBNvQF/WX8UpdWcFELyZRUBEAAWLFiAjz76CB9//DFSU1Mxf/585OTkmLp0Fy5ciOnTp5v2nzhxIr788kusWrUKWVlZ2L9/P+bOnYtBgwbB19dXqo9BFsJgEPjbZ8eQXVSJri72ePuB/lApOeOXyJyplAq8/UAk/LrYI+dSFf722TEYOCmEZMoquoABYOrUqSguLsaSJUuQn5+P8PBwbN++HQEBAQCA/Pz8ZmsCzpgxA+Xl5XjnnXfwt7/9DS4uLhg1ahRee+01qT4CWZD39mZiZ8oFaFRKrPzTALjyHr9EFsHFQYNVf4rCPavisSv1At7fm4W/jOgudVlEnU4h2N95w8rKyqDT6VBaWgqtVit1OdRJ9p8uwrTVh2AQwNK7++LBQd2kLomIrtOmwzlY+OUJKBXA+scHI6a7u9QlUSfi9duKuoCJOkNeSTX+uikRBgHcH+2HBwZyKSAiS/TAQH/cM8DPdKeQC2U1UpdE1KkYAInaqEFvwNxNibhUWYfwrlosmRzOO30QWSiFQoFXp4Sjt7cziirq8NSGo6jXG6Qui6jTMAAStdFbu9Jx5OxlONuqsfIh3umDyNLZa1R47+EoONuqceTsZbzBRaJJRhgAidpgX0YRVu7OBAAsvacvurk5SFwREbWHQHdHvH6fcZHo9/dkYW/6RYkrIuocDIBE13CxvBbzNidBCODBQd1wZz8uE0RkTW4P98HDQ4yTuRZ8loTCco4HJOvHAEh0FQaDwILPklBUUYteXs5YPDFM6pKIqAP8/Y4w03jABZu5PiBZPwZAoqtYtScTcRlFsLNR4p2H+nPcH5GVsrNR4Z2H+sPeRoV9p4vw/t4sqUsi6lAMgERXcOTMJSzbmQ4AWDIpHD29nCWuiIg6Ug9PZ7w8qQ8A4I0daUg4e1niiog6DgMgUSvKaurx9KdJ0BsEJkf64r5oP6lLIqJOcF+0HyZG+EJvEJi7KZH3CyarxQBI1IrFXyfjfEk1urk64F939eV6f0QyoVAo8K+7wtHN1QHnS6qx+OuTUpdE1CEYAIn+4NvjediaeB5KBfDW1Ag42VrNLbOJqA20djZY/kAkVEoFvkrKw7ZjeVKXRNTuGACJfqegtAaLthr/4p89ogeiAlwlroiIpDCgWxc8NbIHAODvX51EQSmXhiHrwgBI1MhgEHj282Mora5H3646PD26p9QlEZGE/jqqB/r56VBaXY9nP+fSMGRdGACJGq07cMa05MtbUyNho+KvB5Gc2aiM/xbY2SgRl1GEdQfOSF0SUbvhFY4IQMaFciz9/hQA4MUJoejh6SRxRURkDrp7OOHFCaEAgKXfn0LGhXKJKyJqHwyAJHt1DQbM25yE2gYDbg3xwLQhAVKXRERmZNqQANwa4oHaxn8r6hoMUpdEdNMYAEn23v3lNJLzyuDiYIPX7+3HJV+IqBmFQoHX7+0HFwcbJOeVYeXu01KXRHTTGABJ1pLzSvHuL8Z/zF+ZHA4vrZ3EFRGROfLS2uGVyeEAgHd+Po2UvDKJKyK6OQyAJFv1egOe3XIcDQaB2/t4485+PlKXRERm7M5+Pri9jzcaDALPbDmGej27gslyMQCSbK3anYmUfGPX7ytTwtn1S0RXpVAo8MqUcLg42CAlvwyrdmdKXRLRDWMAJFk6VVCG//6cAQB4eVIfeDjbSlwREVkCD2dbvDypDwDgvz9n4FQBu4LJMjEAkuw0NHb91usFxoR5YVKEr9QlEZEFmRThizFhXqjXsyuYLBcDIMnO+3uzcOJ8KXT2NvgXu36J6DopFAr8a0o4dPY2OHm+DB/szZK6JKLrxgBIspJ+oRxv7zJ2/S6eGAZPzvolohvgqbXDS5PCAADLd6UjnQtEk4VhACTZMBgEnv/iOOr0Bozq7Ym7+neVuiQismBTIrvitt6eqNcLLPzyBO8VTBaFAZBkY8Ohs0jMKYGTrRr/vqsvu36J6KY0zQp21KiQcPYyNv2aI3VJRG3GAEiycKGsBv/5IQ0A8NztveCtY9cvEd08Xxd7PDOuFwDg/7afwoWyGokrImobBkCShZe+SUZ5bQMi/V3wp8G81y8RtZ/pQwMR4adDeW0DXt6WLHU5RG3CAEhWb1fKBXx/sgAqpQJL7+4LlZJdv0TUflRKBf7d+G/L9hMF2JVyQeqSiK6JAZCsWmVtA/759UkAwOOxQQj10UpcERFZoz6+Ojx+SxAA4J9fn0RFbYPEFRFdHQMgWbU3d6Qjr7QG/q72mHdbiNTlEJEVe3p0T/i72iOvtAZv7kiTuhyiq2IAJKt1IrcUa+OzAQCvTukLe41K4oqIyJo5aNR4dUpfAMD/4s/geG6JtAURXQUDIFklvUHgxa0nYBDG2zYND/GQuiQikoHhIR6YFOELgwD+8XUy1wYks8UASFbp019zcOJ8KZxt1fj7naFSl0NEMrLojlA42apx7FwJPjtyTupyiFrFAEhW53JlHV7/0Tj+Zv6YEHg6c80/Iuo8Xlo7zBvdEwDw2g+nUFJVJ3FFRC0xAJLV+c+PaSipqkdvb2dMH8o1/4io8z0SE4gQLydcrqo3/UFKZE4YAMmqHM8twaeNt2N6eVIfqFU8xYmo89molFgyORwAsPFwDieEkNnh1ZGshsEg8I+vkyEEMCXSF4OD3aQuiYhkbEiwG6ZE+kII4B9fneSEEDIrDIBkNT47cg7HzpXAyVaNFydw4gcRSe/FCY0TQnJLsZkTQsiMMACSVSipqsNrP5wCAMwb3ROeWk78ICLpeWrtMH+McRH6//xwCpcrOSGEzAMDIFmFN3ek43JVPUK8nPBITKDU5RARmTwyNAC9vJxxuaoeb/+UIXU5RAAYAMkKpBWUY8OhswCAlyb1gQ0nfhCRGVGrlFg8MQwA8MnBs8i4UC5xRUQMgGThhBB49bsUGARwex9vxHR3l7okIqIWYnq4Y0yYF/QGgVe/S5W6HCIGQLJsv6QVIi6jCBqVEgsn9Ja6HCKiK3pxQihsVArsSb+IX9IKpS6HZI4BkCxWvd6AV781/iX96C2BCHBzlLgiIqIrC3J3xKPDggAAr36bgnq9QeKKSM4YAMlifXLgLLKKKuHupMGckT2kLoeI6JrmjOoBN0cNMi9WYv3Bs1KXQzLGAEgW6XJlnWk23YIxveBsZyNxRURE16a1s8HfxvYCACzflcFlYUgyDIBkkd7+KQOl1cb7/U4d6C91OUREbTZ1oD96ezujtLoey3elS10OyRQDIFmc04Xl+KSx6+Sfd4ZBpVRIXBERUduplAr8807jsjDrD+XgdCGXhaHOxwBIFuff209BbxAYE+aFmB5c9oWILM/vl4V57Yc0qcshGWIAJItyMKsYP58qhEqpwMLxXPaFiCzX87f3glIB7Ey5gF/PXJK6HJIZBkCyGEIILP3eeL/fBwf5I9jDSeKKiIhuXA9PZ0wd2A0A8O/tqRBCSFwRyQkDIFmM708W4Ni5EjhoVJh7W0+pyyEiumnzR/eEvY0KiTkl+DG5QOpySEYYAMki1OsNeP1H4ziZx2OD4elsJ3FFREQ3z1NrhydijYtDv/ZDGheHpk7DAEgW4dPDOchuXPT5z7cGS10OEVG7+fPw7nBz1CC7qBKf/npO6nJIJhgAyexV1jaYFn2ee1tPONmqJa6IiKj9ONmq8fRo47CWt3elo6K2QeKKSA4YAMnsfRiXhaKKOgS4OeCBxgHTRETW5MFB3RDo5oCiijp8uDdL6nJIBqwqAK5cuRJBQUGws7NDVFQU4uLirrp/bW0tFi1ahICAANja2qJ79+74+OOPO6laaouL5bX4oPEfw2fH9YJGbVWnLBERAMBGpcSz44xLW30Yl4WL5bUSV0TWzmqupps3b8a8efOwaNEiJCYmIjY2FuPHj0dOTs4VX3P//ffjp59+wurVq5GWloZNmzahd2+uLWdO3vk5A1V1ekT46XBHXx+pyyEi6jAT+nojwt8FVXV6rNx9WupyyMophJUsPDR48GAMGDAAq1atMm0LDQ3FlClTsHTp0hb7//DDD3jggQeQlZUFV1fXG3rPsrIy6HQ6lJaWQqvV3nDt1Lrcy1UY+cZu1OsFNj4+mHf9ICKrF5dxEdNWH4ZGpcTuZ0fA18Ve6pKsEq/fVtICWFdXh4SEBIwdO7bZ9rFjxyI+Pr7V13zzzTeIjo7Gf/7zH3Tt2hUhISF45plnUF1dfcX3qa2tRVlZWbMHdZz//nQa9XqBmO5uDH9EJAu39HDH4CBX1OkN+O/PbAWkjmMVAbCoqAh6vR5eXl7Ntnt5eaGgoPWFNbOysrBv3z6cPHkSW7duxfLly/H555/jqaeeuuL7LF26FDqdzvTw9/dv189Bv8kuqsTnR3MBAH8bGyJxNUREnUOhUOCZcb0AAFuOnMPZ4kqJKyJrZRUBsIlCoWj2tRCixbYmBoMBCoUCGzZswKBBgzBhwgQsW7YMa9euvWIr4MKFC1FaWmp6nDvH9Zo6ytu70qE3CIzs5YGogBvroiciskQDA10xPMQDDQaB5bsypC6HrJRVBEB3d3eoVKoWrX2FhYUtWgWb+Pj4oGvXrtDpdKZtoaGhEEIgNze31dfY2tpCq9U2e1D7S79Qjq+P5QEAFozpJXE1RESd75mxxn/7vko6j4wL5RJXQ9bIKgKgRqNBVFQUdu7c2Wz7zp07ERMT0+prhg0bhry8PFRUVJi2paenQ6lUws/Pr0Prpat7a2c6hABu7+ONvn66a7+AiMjK9PXT4fY+3hACWLYzXepyyApZRQAEgAULFuCjjz7Cxx9/jNTUVMyfPx85OTmYNWsWAGP37fTp0037P/TQQ3Bzc8Ojjz6KlJQU7N27F88++ywee+wx2Ntz1pVUTp4vxfcnC6BQAPPHcOwfEcnXgrEhUCiA708W4OT5UqnLIStjNQFw6tSpWL58OZYsWYLIyEjs3bsX27dvR0BAAAAgPz+/2ZqATk5O2LlzJ0pKShAdHY0//elPmDhxIlasWCHVRyD89pfupAhf9PJ2lrgaIiLphHg5Y3KELwDgzR1pEldD1kbydQA///xzfPbZZ8jJyUFdXV2z544ePSpRVW3DdYTaV8LZy7hnVTxUSgV2zr8VwR5OUpdERCSpM0WVuG3ZHugNAl/OjsGAbl2kLskq8PotcQvgihUr8Oijj8LT0xOJiYkYNGgQ3NzckJWVhfHjx0tZGklg+S5j69/d/bsy/BERAQh0d8Q9A7oCAP77E2cEU/uRNACuXLkSH3zwAd555x1oNBo899xz2LlzJ+bOnYvSUo53kJPEnMuIyyiCSqnAX0f1lLocIiKz8dTIHlApFfgl7SKO55ZIXQ5ZCUkDYE5OjmmWrr29PcrLjVPdp02bhk2bNklZGnWyphXv7+rfFd3cHCSuhojIfAS4OWJypHEs4IqfeHcQah+SBkBvb28UFxcDAAICAnDw4EEAQHZ2NqzkFsXUBifPl+LnU4VQKox/6RIRUXNPjewBpQLYlXqBM4KpXUgaAEeNGoVt27YBAGbOnIn58+djzJgxmDp1Ku666y4pS6NOtKJxXMukCF8EuTtKXA0Rkfnp7uGEiY0zgt/hPYKpHailfPMPPvgABoMBADBr1iy4urpi3759mDhxomn9PrJuqfll2JFyAQoFMGcUW/+IiK5kzsge+OZYHn5ILsCpgjL09pbn7FVqH5IGQKVSCaXyt0bI+++/H/fff7+EFVFna/pLdkJfH/Tw5Lp/RERX0tPLGRP6+uC74/n478+n8e5DA6QuiSxYpwfA48ePIzw8HEqlEsePH7/qvv369eukqkgKGRfKsf1kPgDgr2z9IyK6pr+O6oHvjudj+4l8ZFwoR08v/uFMN6bTA2BkZCQKCgrg6emJyMhIKBSKVid8KBQK6PX6zi6POtE7v5yGEMC4Pl7syiAiaoPe3lqMD/fG9ycL8M4vp/H2A/2lLoksVKcHwOzsbHh4eJj+n+Qpu6gS247lAQDX/SMiug5zRvXA9ycLsO1YHuaNDuHkObohnR4Am+7N+8f/J3lZtfs0DAK4rbcnwrvqpC6HiMhi9PHV4bbenvjpVCE+2JuJpXdzuBRdP0mXgQGAtLQ0zJkzB7fddhtGjx6NOXPmIC2NN722Zvml1diaeB4A8BTH/hERXbe/jOgOAPgi4TwKy2okroYskaQB8PPPP0d4eDgSEhIQERGBfv364ejRowgPD8eWLVukLI060Mf7slGvFxgU5MobmxMR3YDoQFcMDOyCOr0Bq/dzOBVdP4WQ8JYbwcHBePjhh7FkyZJm2xcvXoxPPvkEWVlZElXWNmVlZdDpdCgtLYVWy0kMbVFaVY+Y//sJlXV6rJkxECN7e0pdEhGRRfr51AU8tvYInGzV2P/CKOjsbaQuyWLw+i1xC2BBQQGmT5/eYvvDDz+MgoICCSqijvbJwTOorNOjt7czRvTykLocIiKLNbKXJ3p5OaOitgHrD56VuhyyMJIGwBEjRiAuLq7F9n379iE2NlaCiqgj1dTrsWb/GQDArOHdoVAopC2IiMiCKRQKzBoRDABYsz8bNfVcOo3aTtI7gUyaNAnPP/88EhISMGTIEADAwYMHsWXLFrz88sv45ptvmu1Llm1LQi6KK+vQ1cUed/bzkbocIiKLd2c/X7zxYzrOl1RjS0Iupg3h6hrUNpKOAfz9beCuxlwXheYYgrZr0Bsw6s09yLlUhZcmhmHGsCCpSyIisgr/iz+Dxd8kw9/VHr/8bQTUKskX+DB7vH5L3AVsMBja9DDH8EfXZ/vJAuRcqoKrowZTB3aTuhwiIqtxf7Q/XB01OHepGttPcvw8tQ3/TKAOJ4TAe7szAQCPDA2EvUYlcUVERNbDXqPCozGBAIBVuzNbvb0q0R9JHgD37NmDiRMnokePHujZsycmTZrU6sQQslxxGUVIyS+DvY0K04dyfAoRUXubPjQQDhoVUvPLsP90sdTlkAWQNACuX78eo0ePhoODA+bOnYs5c+bA3t4et912GzZu3ChladSOPowzruf4wCB/dHHUSFwNEZH10TnY4P5ofwDAR/vMew1dMg+STgIJDQ3Fn//8Z8yfP7/Z9mXLluHDDz9EamqqRJW1DQeRXltaQTnGLd8LpQLY8+xI+Ls6SF0SEZFVyimuwvA3foEQwM75t6Knl7PUJZktXr8lbgHMysrCxIkTW2yfNGkSsrN5axtr8PE+489xXB9vhj8iog7Uzc0BY8O8AAAf8/ZwdA2SBkB/f3/89NNPLbb/9NNP8Pf3l6Aiak9FFbXYmnQeADDzFi77QkTU0R6PNS4M/cXR8yiuqJW4GjJnki4E/be//Q1z585FUlISYmJioFAosG/fPqxduxZvv/22lKVRO9hwMAd1DQZE+OkQFdBF6nKIiKxedEAXRPjpcCy3FOsP5uDp0T2lLonMlKQB8C9/+Qu8vb3x5ptv4rPPPgNgHBe4efNmTJ48WcrS6CbVNujxSeO9KR+7JYi3fSMi6gQKhQIzY4Mxd1MiPjl4Bk8OD4adDZfeopYkC4ANDQ3417/+hcceewz79u2TqgzqIN8k5aGoohY+OjtM6MvbvhERdZbx4d7w1dkhr7QG3yTl4f6BHFJFLUk2BlCtVuP111/nXT6skBACqxsnf0wfGggb3paIiKjT2KiUmDEsEIBxSRguDE2tkfTKPHr0aOzevVvKEqgDHMgsxqmCctjbqPDQIN72jYios00d2A0OGhXSL1QgLqNI6nLIDEk6BnD8+PFYuHAhTp48iaioKDg6OjZ7ftKkSRJVRjejqfXv3ig/6BxsJK6GiEh+dPbGhaHXxp/Bx/uzcWuIh9QlkZmRdCFopfLKDZAKhcLsu4e5kGRLWRcrMOrNPQCAn/82HMEeThJXREQkT2eKKjHijd1QKIBf/jYCge6O136RTPD6LXEXsMFguOLD3MMfte5/8WcAALf19mT4IyKSUKC7I0b08oAQMK3KQNRE0gC4bt061Na2XKiyrq4O69atk6AiuhkVtQ344qhx4eemAchERCSdR4YGAgA+O3IOlbUN0hZDZkXSAPjoo4+itLS0xfby8nI8+uijElREN2Pr0VxU1DYg2MMRw7q7S10OEZHsDQ/xQICbA8prGvBV452ZiACJA6AQotUFgnNzc6HT6SSoiG6UEALrDhi7GKYNCYBSyYWfiYikplQqMG1IAABgXfxZLglDJpLMAu7fvz8UCgUUCgVuu+02qNW/laHX65GdnY3bb79ditLoBh3IKkZGYQUcNCrcE+UndTlERNTovmh/vLkjHWkXynEw6xKGdneTuiQyA5IEwClTpgAAkpKSMG7cODg5/TZZQKPRIDAwEPfcc48UpdEN+qSx9e+u/l2htePSL0RE5kJnb4O7BnTFxkM5WHfgDAMgAZAoAC5evBgAEBgYiKlTp8LOzk6KMqid5JdWY0fKBQDGO38QEZF5eWRoIDYeysGOlAvIK6mGr4u91CWRxCQdA/jII4/Azs4OdXV1yM3NRU5OTrMHWYaNh3KgNwgMCnJFL29nqcshIqI/6OXtjCHBrtAbBDYc4pIwJHEAzMjIQGxsLOzt7REQEICgoCAEBQUhMDAQQUFBUpZGbVTXYMCmw+cA/LbcABERmZ+mf6M3HT6HmnqutSt3kt4KbsaMGVCr1fj222/h4+PT6oxgMm/fn8xHUUUtvLS2GNvHS+pyiIjoCsaEecFHZ4f80hr8mFyAyZFdpS6JJCRpAExKSkJCQgJ69+4tZRl0E5qWfnlwUDfYqCRtUCYioqtQq5SYOtAfy3dlYMOhHAZAmZP0ih0WFoaioiIpS6CbkJpfhoSzl6FWKvDQoG5Sl0NERNcwdaA/lArgcPYlnC4sl7ockpCkAfC1117Dc889h927d6O4uBhlZWXNHmTePj1snKgzJswLnlrO5CYiMnc+OnuM6m0crrPx0DmJqyEpSdoFPHr0aADAqFGjmo3/a7pDiF7PQarmqrpOjy8TjbcVepCtf0REFuNPg7thV+oFfHE0F8/d3gt2NiqpSyIJSBoAf/nlFynfnm7C9hP5KK9pgF8Xe9zSg/f9JSKyFLeGeKCriz3Ol1Rj+4l83D2Ad2+SI0m7gIcPHw6lUokPP/wQL7zwAnr06IHhw4cjJycHKhX/IjFnmxq7fx8c1I33/SUisiAqpQIPDPQHYFzHleRJ0gD4xRdfYNy4cbC3t0diYiJqa2sBAOXl5fj3v/8tZWl0FekXynHk7GWolArcx/v+EhFZnPsH+kOlVODI2ctIv8DJIHIkaQB89dVX8d577+HDDz+Ejc1v94+NiYnB0aNHJayMrqap9W90qCcnfxARWSAvrR1Gh3oCYCugXEkaANPS0nDrrbe22K7ValFSUtL5BdE11dTr8eVRTv4gIrJ0Dw0OAAB8cTQX1XWcdCk3kgZAHx8fnD59usX2ffv2ITg4WIKK6Fq+P5mP0up6dHWxR2xPD6nLISKiGxTbwx3+rvYor2nAtuN5UpdDnUzSAPjkk0/i6aefxqFDh6BQKJCXl4cNGzbgmWeewezZs6Usja5gU+O6UQ80jh8hIiLLpFQq8MBAY0/OZ79yTUC5kXQZmOeeew6lpaUYOXIkampqcOutt8LW1hbPPPMM5syZI2Vp1IrTheU4fOaScfJHtL/U5RAR0U26N8oPb+5Iw5Gzl5F5sQLdPZykLok6ieQ3b/3Xv/6FoqIiHD58GAcPHsTFixfxyiuvSF0WtWJz41+Io3p7wlvHyR9ERJbOS2uHEb2Mk0G2HMmVuBrqTJIHQABwcHBAdHQ0Bg0aBCcn/vVhjur1BmxtvPPHVLb+ERFZjfujjct5fXk0Fw16g8TVUGcxiwBI5m932kUUVdTB3ckWw3tx8gcRkbUY1dsLro4aFJbXYm/GRanLoU5iVQFw5cqVCAoKgp2dHaKiohAXF9em1+3fvx9qtRqRkZEdW6AF23LE2P17V39f2Kis6rQhIpI1jVqJKZFdAbAbWE6s5kq+efNmzJs3D4sWLUJiYiJiY2Mxfvx45ORcfYHL0tJSTJ8+HbfddlsnVWp5iitq8fOpQgDAvVHs/iUisjb3DzR2A+9KvYBLlXUSV0OdwWoC4LJlyzBz5kw8/vjjCA0NxfLly+Hv749Vq1Zd9XVPPvkkHnroIQwdOrSTKrU8XyXlocEg0M9Ph17ezlKXQ0RE7ay3txZ9u+pQrxf4qnG8N1k3qwiAdXV1SEhIwNixY5ttHzt2LOLj46/4ujVr1iAzMxOLFy9u0/vU1tairKys2UMOPk8wdgnwvr9ERNaraTLIZ0fOQQghcTXU0awiABYVFUGv18PLy6vZdi8vLxQUFLT6moyMDLzwwgvYsGED1Oq2LYe4dOlS6HQ608Pf3/q7Q0+eL0Vqfhk0KiUmRXSVuhwiIuogkyK6QqNW4lRBOU6el0cDh5xZRQBsolA0vzOFEKLFNgDQ6/V46KGH8PLLLyMkJKTN33/hwoUoLS01Pc6ds/6V05ta/8b08YLOwUbiaoiIqKPoHGwwro83AGBLgvVf3+TOKgKgu7s7VCpVi9a+wsLCFq2CAFBeXo4jR45gzpw5UKvVUKvVWLJkCY4dOwa1Wo2ff/651fextbWFVqtt9rBmtQ16fJVkHAvC7l8iIuvX1A38VeJ51NTrJa6GOpJVBECNRoOoqCjs3Lmz2fadO3ciJiamxf5arRYnTpxAUlKS6TFr1iz06tULSUlJGDx4cGeVbtZ+Ti1ESVU9vLS2iO3Jtf+IiKxdTHd3+OrsUFbTYFr9gayTpPcCbk8LFizAtGnTEB0djaFDh+KDDz5ATk4OZs2aBcDYfXv+/HmsW7cOSqUS4eHhzV7v6ekJOzu7FtvlrKn79+4BflApW3alExGRdVEpFZjcvytW7c7El0fPY0JfH6lLog5iNQFw6tSpKC4uxpIlS5Cfn4/w8HBs374dAQEBAID8/PxrrglIv7lYXovd6cYV4e9l9y8RkWzc3RgAd6cV4lJlHVwdNVKXRB1AITjX+4aVlZVBp9OhtLTU6sYDrtmfjZe3pSDC3wVfPzVM6nKIiKgT3bEiDsl5ZXhlch9MGxoodTntzpqv321lFWMAqf01LQR6V6SvxJUQEVFnu6u/cdmvrVwU2moxAFILWRcrcCy3FCqlAndGMAASEcnNpAhfKBXA0ZwSnCmqlLoc6gAMgNTCV0l5AIDYnu5wd7KVuBoiIupsnlo73NK4+kPTcmBkXRgAqRkhBL5u/GWfEsk7fxARydVd/Y09QFsTz/PWcFaIAZCaSTpXgrPFVbC3UWFMWMtFtImISB7G9fGGg0aFs8VVSDxXInU51M4YAKmZpskf4/p4wdHWalYJIiKi6+SgUZtuDbf1KLuBrQ0DIJnU6w349ng+AGByf3b/EhHJXdNs4G+P56GuwSBxNdSeGADJZF9GEYor6+DmqEFsD3epyyEiIonFdHeDh7MtLlfVIy7jotTlUDtiACSTppleEyN8oVbx1CAikju1Sok7Gm8H19RDRNaBV3kCAFTWNmBH8gUAwGQu/kxERI0mNq4HuyO5ADX1eomrofbCAEgAgJ9OFaK6Xo8ANwdE+rtIXQ4REZmJAd1c0NXFHpV1evxyqlDqcqidMAASAODbY8bFn+/s5wOFQiFxNUREZC4UCgXu7MduYGvDAEgor6nH7nTj4N47+rL7l4iImmvqBv7p1AVU1DZIXA21BwZAwq7UC6hrMCDYwxGhPs5Sl0NERGamj68WQe6OqKk34KfUC1KXQ+2AAZDwXWOT/p192f1LREQt/b4beNsxdgNbAwZAmSutrseexu7fOyPY/UtERK1r6gbek16I0up6iauhm8UAKHM7Uy6gXi8Q4uWEEC92/xIRUetCvJzRy8sZ9XqBHckFUpdDN4kBUOa+PW6c/cvJH0REdC2mbmDOBrZ4DIAyVlJVh30ZRQCAOxp/qYmIiK6kaajQ/tNFKK6olbgauhkMgDL2Y3IBGgwCvb2d0cPTSepyiIjIzAW5OyK8qxZ6g8CPyZwNbMkYAGWsaUHPiZz8QUREbTQ+3Nhj9APHAVo0BkCZulRZh/jMYgAw3eibiIjoWm4P9wYAxJ8u4mxgC8YAKFM7UwqgNwj08dUi0N1R6nKIiMhCdPdwQoiXExoMgotCWzAGQJlqGrtxex9viSshIiJLc3tjN/D3J9kNbKkYAGWovKbeNPt3XDgDIBERXZ+mxoO96RdRyXsDWyQGQBnanXYRdXoDgt0d0ZOzf4mI6DqF+jgjwM0BtQ0G7E67KHU5dAMYAGWoaebW2D7evPcvERFdN4VCYWoF5Gxgy8QAKDM19XrsPlUI4LeZXERERNer6Rryc+oF1NTrJa6GrhcDoMzsP12Eyjo9vLV26NdVJ3U5RERkoSL8XOCjs0Nlnd40rpwsBwOgzPzY2FQ/ro8XlEp2/xIR0Y1RKhUYx25gi8UAKCMNegN2phiXfxnH5V+IiOgmNXUD70y5gHq9QeJq6HowAMrIr2cu43JVPVwcbDAoyFXqcoiIyMINDHSFm6MGpdX1OJhVLHU5dB0YAGWkqft3dKgX1Cr+6ImI6OaolAqMCfMCAOxK4V1BLAlTgEwIIUwBkHf/ICKi9jI6tDEAphZCCCFxNdRWDIAyceJ8KfJLa+CgUeGWnu5Sl0NERFZiWA932KqVOF9SjVMF5VKXQ23EACgTu1KNa//d2tMDdjYqiashIiJrYa9RIbaxYYHdwJaDAVAmfko1/lLeFuopcSVERGRtfusGZgC0FAyAMpBfWo3kvDIoFMDI3gyARETUvkY1Ni4cyy3FhbIaiauhtmAAlIGfG2/91t/fBe5OthJXQ0RE1sbT2Q6R/i4AfrvmkHljAJSBnxrH/93W2ERPRETU3kY3tgJyHKBlYAC0ctV1euw/bbxHI8f/ERFRRxnduB7gvtNFqKprkLgauhYGQCu3/3QRahsM6Opij15ezlKXQ0REVqqXlzP8utijtsGAfRlFUpdD18AAaOV+OvXb7F+FQiFxNUREZK0UCoVpNnDT0CMyXwyAVkwIYfolHMXZv0RE1MFMAfDUBRgMvCuIOWMAtGInz5ehsLwWDhoVhgS7SV0OERFZuUFBrnCyVaOoog4n80qlLoeuggHQijUtyBnb0513/yAiog6nUSsR093Y4LA77aLE1dDVMABasaa1mG7rzeVfiIioc4zoZRxytDuN4wDNGQOglbpYXosT543N7yN6e0hcDRERycWIXsZrTtK5EpRU1UlcDV0JA6CV2nfa2PQe5qOFp7OdxNUQEZFc+LrYI8TLCQYB7OVyMGaLAdBK7WkcezG8F1v/iIioc7Eb2PwxAFohg0GY/uoaHsIASEREnWtE47Vnb/pFLgdjphgArVByXhkuVdbBUaPCgG5dpC6HiIhkJjrQFY4aFYoq6pCcVyZ1OdQKBkArtCfd2OQe08MdGjV/xERE1Lk0aiViergDYDewuWI6sEJ70hvH/7H7l4iIJNI0G3h3OtcDNEcMgFamrKYeR3NKADAAEhGRdJquQYk5l7kcjBliALQy8aeLoDcIBLs7wt/VQepyiIhIpvy6OKCHp3E5mDguB2N2GACtzJ504y/ZrWz9IyIiiTXNBt7DbmCzY1UBcOXKlQgKCoKdnR2ioqIQFxd3xX2//PJLjBkzBh4eHtBqtRg6dCh+/PHHTqy2/QkhsDed6/8REZF5iG0MgPGniyAEl4MxJ1YTADdv3ox58+Zh0aJFSExMRGxsLMaPH4+cnJxW99+7dy/GjBmD7du3IyEhASNHjsTEiRORmJjYyZW3n8yLFThfUg2NWokhQW5Sl0NERDI3KNAVGpUSeaU1yC6qlLoc+h2rCYDLli3DzJkz8fjjjyM0NBTLly+Hv78/Vq1a1er+y5cvx3PPPYeBAweiZ8+e+Pe//42ePXti27ZtnVx5+2nq/h0c5Ap7jUriaoiISO7sNSpEBRjXo91/muMAzYlVBMC6ujokJCRg7NixzbaPHTsW8fHxbfoeBoMB5eXlcHV1veI+tbW1KCsra/YwJ02/XLc0rr1EREQktVt6Gq9J+xgAzYpVBMCioiLo9Xp4eXk12+7l5YWCgoI2fY8333wTlZWVuP/++6+4z9KlS6HT6UwPf3//m6q7PdXrDTiUVQwAGMYASEREZqLpmhSfWQw9bwtnNqwiADZRKBTNvhZCtNjWmk2bNuGll17C5s2b4enpecX9Fi5ciNLSUtPj3LlzN11zezmeW4rKOj1cHGwQ5qOVuhwiIiIAQN+uOmjt1CivacDx3BKpy6FGVhEA3d3doVKpWrT2FRYWtmgV/KPNmzdj5syZ+OyzzzB69Oir7mtrawutVtvsYS7iG5vWhwa7Qam8duglIiLqDCqlAjHdja2AHAdoPqwiAGo0GkRFRWHnzp3Ntu/cuRMxMTFXfN2mTZswY8YMbNy4EXfccUdHl9mh9mcaf6li2P1LRERmZhjHAZodtdQFtJcFCxZg2rRpiI6OxtChQ/HBBx8gJycHs2bNAmDsvj1//jzWrVsHwBj+pk+fjrfffhtDhgwxtR7a29tDp9NJ9jluRHWdHkfPlgAAhnXn8i9ERGRemiYnHj1bgqq6BjhorCZ+WCyraAEEgKlTp2L58uVYsmQJIiMjsXfvXmzfvh0BAQEAgPz8/GZrAr7//vtoaGjAU089BR8fH9Pj6aefluoj3LAjZy+hTm+Aj84OQe6OUpdDRETUTKCbA7q62KNOb8CvZy5LXQ7BiloAAWD27NmYPXt2q8+tXbu22de7d+/u+II6SXymcfbv0O5ubZr0QkRE1JkUCgWG9XDDZ0dysf90EYbzdqWSs5oWQDlrmgAyrDvH/xERkXlqWg6GE0HMAwOghSutrseJ86UAuP4fERGZr6HBxjHqKfllKK2ul7gaYgC0cAezimEQQLCHI7x1dlKXQ0RE1CpPrXGcuhDAkTOXpC5H9hgALdyBxvF/7P4lIiJzNyTYeLvVQ9kMgFJjALRwB7N+mwBCRERkzgYHGa9VTdcukg4DoAUrqapD2oVyAMCgIFeJqyEiIrq6wY0tgCfPl6K8huMApcQAaMGOnLkMIYDuHo5wd7KVuhwiIqKr8tHZo5urAwwCOHKW6wFKiQHQgh3KNjahDwpi9y8REVmGwY09VoeyOA5QSgyAFuxw4yDawez+JSIiCzEkmOMAzQEDoIWqqG3AybwyABz/R0RElqNpHOCJ86WorG2QuBr5YgC0UEfPXobeIODXxR6+LvZSl0NERNQmfl2M9wXWGwQSOA5QMgyAFqqp+5etf0REZGkGm9YDZDewVBgALVRTABzCCSBERGRhhpjWA+REEKkwAFqgmno9ks6VAGALIBERWZ6mFsDjuSWoqddLXI08MQBaoGPnSlCnN8DT2RYBbg5Sl0NERHRdurk6wN3JFvV6gZPnS6UuR5YYAC1Q0+KZAwNdoVAoJK6GiIjo+igUCkQFuAAAJ4JIhAHQAh1t/GUZENBF4kqIiIhuTFTjNYwBUBoMgBZGCIHExvF/A7q5SFoLERHRjWoKgEdzLkMIIXE18sMAaGHOFFfhUmUdNGol+vjqpC6HiIjohvTx1UGjUqKoog45l6qkLkd2GAAtTFNTeb+uOmjU/PEREZFlsrNRIbyrFgC7gaXABGFhjuZw/B8REVkHjgOUDgOghTFNAOH4PyIisnAMgNJhALQgFbUNSL9QDgAY0I0tgEREZNmarmVpF8pRXlMvcTXywgBoQY6dK4FBAH5d7OGptZO6HCIiopviqbWDv6s9hIDpDlfUORgALchv3b9s/SMiIusQ1XhNO3KG3cCdiQHQgiTkcPwfERFZl6ZJjWwB7FwMgBbCYBBIzCkBwBnARERkPfr5uQAAjueWcEHoTsQAaCHOXqpCaXU9bNVKhPpopS6HiIioXYT6OMNGpcDlqnrkXq6WuhzZYAC0EMdzSwAAYb5a2Kj4YyMiIutgq1aht7exYeNY47WOOh6ThIU4kVsKwHgHECIiImvSz894bWu61lHHYwC0EMfPG38p+jaOlSAiIrIWEY3XNrYAdh4GQAtgMAgkNwbApr+SiIiIrEU/f+O17eT5MhgMnAjSGRgALUBWUSUq6/Swt1Ghu4eT1OUQERG1qx4eTrCzUaKitgFZRRVSlyMLDIAW4MT5EgBAH18tVEqFtMUQERG1M7VKiXBfYyvgsXMcB9gZGAAtwPHcpvF/7P4lIiLr9Pv1AKnjMQBaANMMYAZAIiKyUhGN4wCPcSZwp2AANHMNegOS88oAAH25BAwREVmppmtcan4ZGvQGiauxfgyAZi7zYiWq6/Vw1KgQ5M4JIEREZJ0C3Bxhb6NCbYMBZ4orpS7H6jEAmrmTjcu/9PHVcQIIERFZLZVSgd4+zgCAlPxyiauxfgyAZu5UgbH7N8yX9/8lIiLr1nSv+5TGoU/UcRgAzdypAuNfQb29nSWuhIiIqGOFNQbA1HwGwI7GAGjmTAHQhy2ARERk3Zp6uxgAOx4DoBkrqqjFxfJaKBRAiBcngBARkXXr7e0MhQIoLK9FUUWt1OVYNQZAM5bW2PoX4OoAB41a4mqIiIg6loNGjSA3RwBsBexoDIBmrOnk7+3N7l8iIpIHTgTpHAyAZuy38X+cAEJERPLAcYCdgwHQjDUtAcMWQCIikosQL2OjR0ZhhcSVWDcGQDPVoDcg/YLx5A9lCyAREclET0/jpMfMixUwGITE1VgvBkAzdfZSFeoaDHDQqODfxUHqcoiIiDqFv6sDNGolauoNOF9SLXU5VosB0ExlNjZ9B3s4QslbwBERkUyolAoEuxtnAmcU8pZwHYUB0ExlFRlvhB3szvX/iIhIXno0dgNnXOA4wI7CAGimsi7+1gJIREQkJz09jWPfT3MiSIdhADRTWRcbWwA92AJIRETyYmoBZADsMAyAZuq3LmC2ABIRkbz0bLz9aWZhBYTgTOCOwABohkqq6nCpsg4Au4CJiEh+At0coVQA5bUNuFjOewJ3BAZAM5TZ2P3ro7PjPYCJiEh2NGolunaxB2BcFo3aHwOgGeIEECIikrtAN+M1MLtxSBS1L6sKgCtXrkRQUBDs7OwQFRWFuLi4q+6/Z88eREVFwc7ODsHBwXjvvfc6qdKr4xIwREQkdwFuxpsgnC1mAOwIVtO/uHnzZsybNw8rV67EsGHD8P7772P8+PFISUlBt27dWuyfnZ2NCRMm4IknnsD69euxf/9+zJ49Gx4eHrjnnnsk+AS/GR/uDTdHDcJ8eA9gIiKSp/HhPgh0c8SgIFepS7FKCmEl02sGDx6MAQMGYNWqVaZtoaGhmDJlCpYuXdpi/+effx7ffPMNUlNTTdtmzZqFY8eO4cCBA216z7KyMuh0OpSWlkKrZVgjIiKyBLx+W0kXcF1dHRISEjB27Nhm28eOHYv4+PhWX3PgwIEW+48bNw5HjhxBfX19q6+pra1FWVlZswcRERGRpbGKAFhUVAS9Xg8vL69m2728vFBQUNDqawoKClrdv6GhAUVFRa2+ZunSpdDpdKaHv79/+3wAIiIiok5kFQGwiUKhaPa1EKLFtmvt39r2JgsXLkRpaanpce7cuZusmIiIiKjzWcUkEHd3d6hUqhatfYWFhS1a+Zp4e3u3ur9arYabm1urr7G1tYWtrW37FE1EREQkEatoAdRoNIiKisLOnTubbd+5cydiYmJafc3QoUNb7L9jxw5ER0fDxsamw2olIiIikppVBEAAWLBgAT766CN8/PHHSE1Nxfz585GTk4NZs2YBMHbfTp8+3bT/rFmzcPbsWSxYsACpqan4+OOPsXr1ajzzzDNSfQQiIiKiTmEVXcAAMHXqVBQXF2PJkiXIz89HeHg4tm/fjoCAAABAfn4+cnJyTPsHBQVh+/btmD9/Pt599134+vpixYoVkq8BSERERNTRrGYdQClwHSEiIiLLw+u3FXUBExEREVHbMAASERERyQwDIBEREZHMMAASERERyQwDIBEREZHMWM0yMFJomkBdVlYmcSVERETUVk3XbTkvhMIAeBPKy8sBAP7+/hJXQkRERNervLwcOp1O6jIkwXUAb4LBYEBeXh6cnZ2hUCja7fuWlZXB398f586dk+36RJ2Bx7nz8Fh3Dh7nzsNj3Tk66jgLIVBeXg5fX18olfIcDccWwJugVCrh5+fXYd9fq9XyH5ZOwOPceXisOwePc+fhse4cHXGc5dry10SesZeIiIhIxhgAiYiIiGSGAdAM2draYvHixbC1tZW6FKvG49x5eKw7B49z5+Gx7hw8zh2Hk0CIiIiIZIYtgEREREQywwBIREREJDMMgEREREQywwBIREREJDMMgBJZuXIlgoKCYGdnh6ioKMTFxV11/z179iAqKgp2dnYIDg7Ge++910mVWrbrOc5ffvklxowZAw8PD2i1WgwdOhQ//vhjJ1Zr2a73nG6yf/9+qNVqREZGdmyBVuJ6j3NtbS0WLVqEgIAA2Nraonv37vj44487qVrLdb3HecOGDYiIiICDgwN8fHzw6KOPori4uJOqtUx79+7FxIkT4evrC4VCga+++uqar+G1sB0J6nSffvqpsLGxER9++KFISUkRTz/9tHB0dBRnz55tdf+srCzh4OAgnn76aZGSkiI+/PBDYWNjIz7//PNOrtyyXO9xfvrpp8Vrr70mDh8+LNLT08XChQuFjY2NOHr0aCdXbnmu91g3KSkpEcHBwWLs2LEiIiKic4q1YDdynCdNmiQGDx4sdu7cKbKzs8WhQ4fE/v37O7Fqy3O9xzkuLk4olUrx9ttvi6ysLBEXFyf69OkjpkyZ0smVW5bt27eLRYsWiS+++EIAEFu3br3q/rwWti8GQAkMGjRIzJo1q9m23r17ixdeeKHV/Z977jnRu3fvZtuefPJJMWTIkA6r0Rpc73FuTVhYmHj55ZfbuzSrc6PHeurUqeLvf/+7WLx4MQNgG1zvcf7++++FTqcTxcXFnVGe1bje4/z666+L4ODgZttWrFgh/Pz8OqxGa9OWAMhrYftiF3Anq6urQ0JCAsaOHdts+9ixYxEfH9/qaw4cONBi/3HjxuHIkSOor6/vsFot2Y0c5z8yGAwoLy+Hq6trR5RoNW70WK9ZswaZmZlYvHhxR5doFW7kOH/zzTeIjo7Gf/7zH3Tt2hUhISF45plnUF1d3RklW6QbOc4xMTHIzc3F9u3bIYTAhQsX8Pnnn+OOO+7ojJJlg9fC9qWWugC5KSoqgl6vh5eXV7PtXl5eKCgoaPU1BQUFre7f0NCAoqIi+Pj4dFi9lupGjvMfvfnmm6isrMT999/fESVajRs51hkZGXjhhRcQFxcHtZr/DLXFjRznrKws7Nu3D3Z2dti6dSuKioowe/ZsXLp0ieMAr+BGjnNMTAw2bNiAqVOnoqamBg0NDZg0aRL++9//dkbJssFrYftiC6BEFApFs6+FEC22XWv/1rZTc9d7nJts2rQJL730EjZv3gxPT8+OKs+qtPVY6/V6PPTQQ3j55ZcREhLSWeVZjes5pw0GAxQKBTZs2IBBgwZhwoQJWLZsGdauXctWwGu4nuOckpKCuXPn4p///CcSEhLwww8/IDs7G7NmzeqMUmWF18L2wz+9O5m7uztUKlWLvyQLCwtb/GXTxNvbu9X91Wo13NzcOqxWS3Yjx7nJ5s2bMXPmTGzZsgWjR4/uyDKtwvUe6/Lychw5cgSJiYmYM2cOAGNQEUJArVZjx44dGDVqVKfUbklu5Jz28fFB165dodPpTNtCQ0MhhEBubi569uzZoTVbohs5zkuXLsWwYcPw7LPPAgD69esHR0dHxMbG4tVXX2XLVDvhtbB9sQWwk2k0GkRFRWHnzp3Ntu/cuRMxMTGtvmbo0KEt9t+xYweio6NhY2PTYbVashs5zoCx5W/GjBnYuHEjx++00fUea61WixMnTiApKcn0mDVrFnr16oWkpCQMHjy4s0q3KDdyTg8bNgx5eXmoqKgwbUtPT4dSqYSfn1+H1mupbuQ4V1VVQalsfjlVqVQAfmuhopvHa2E7k2jyiaw1LTGwevVqkZKSIubNmyccHR3FmTNnhBBCvPDCC2LatGmm/Zumvs+fP1+kpKSI1atXc+p7G1zvcd64caNQq9Xi3XffFfn5+aZHSUmJVB/BYlzvsf4jzgJum+s9zuXl5cLPz0/ce++9Ijk5WezZs0f07NlTPP7441J9BItwvcd5zZo1Qq1Wi5UrV4rMzEyxb98+ER0dLQYNGiTVR7AI5eXlIjExUSQmJgoAYtmyZSIxMdG03A6vhR2LAVAi7777rggICBAajUYMGDBA7Nmzx/TcI488IoYPH95s/927d4v+/fsLjUYjAgMDxapVqzq5Yst0Pcd5+PDhAkCLxyOPPNL5hVug6z2nf48BsO2u9zinpqaK0aNHC3t7e+Hn5ycWLFggqqqqOrlqy3O9x3nFihUiLCxM2NvbCx8fH/GnP/1J5ObmdnLVluWXX3656r+5vBZ2LIUQbJ8mIiIikhOOASQiIiKSGQZAIiIiIplhACQiIiKSGQZAIiIiIplhACQiIiKSGQZAIiIiIplhACQiIiKSGQZAIrJIycnJeOONN6DX66UuhYjI4jAAEpmpM2fOQKFQICkpSepSsHbtWri4uFzXaxQKBb766qsrPn8zn6+iogL33XcfQkJCTPdclYuXXnoJkZGRUpfRoUaMGIF58+ZJ8t5yOL5EAKCWugAikid/f3/k5+fD3d39ul87e/ZszJo1C5MmTbqu1wUGBmLevHmShQtqmy+//BI2NjZSl0Fk1RgAia5TXV0dNBqN1GVYPJVKBW9v7xt67bp169q5GjInrq6unf6eer0eCoWi09+XSCrsAiZZGzFiBObMmYM5c+bAxcUFbm5u+Pvf/47f3yI7MDAQr776KmbMmAGdTocnnngCAPD8888jJCQEDg4OCA4Oxj/+8Q/U19cDAEpLS6FSqZCQkAAAEELA1dUVAwcONH3fTZs2wcfHx/T14cOH0b9/f9jZ2SE6OhqJiYkt6t2zZw8GDRoEW1tb+Pj44IUXXkBDQ8N1fZ7Lly9j+vTp6NKlCxwcHDB+/HhkZGQ0e5+1a9eiW7ducHBwwF133YXi4uIWtaxatQrdu3eHRqNBr1698Mknn7TYJz8/H+PHj4e9vT2CgoKwZcsW03OtdQGnpKRgwoQJcHJygpeXF6ZNm4aioqJmn2/u3Ll47rnn4OrqCm9vb7z00kvN3vOll15Ct27dYGtrC19fX8ydO9f02rNnz2L+/PlQKBRQKBQQQsDDwwNffPGF6fWRkZHw9PQ0fX3gwAHY2NigoqICAJCTk4PJkyfDyckJWq0W999/Py5cuNDisze555578Ne//tX09bx586BQKJCcnAwAaGhogLOzM3788UesW7cObm5uqK2tbfE9pk+f3ur3NxgMWLJkCfz8/GBra4vIyEj88MMPpufr6uowZ84c+Pj4wM7ODoGBgVi6dKnp+at9nhs5j6/2e9H084mMjMQnn3yCwMBA6HQ6PPDAAygvLzft88cu4PXr1yM6OhrOzs7w9vbGQw89hMLCwisec+Da53nTsIZvv/0WYWFhsLW1xdmzZ03PN+3766+/YsyYMXB3d4dOp8Pw4cNx9OjRq743kUUQRDI2fPhw4eTkJJ5++mlx6tQpsX79euHg4CA++OAD0z4BAQFCq9WK119/XWRkZIiMjAwhhBCvvPKK2L9/v8jOzhbffPON8PLyEq+99prpdQMGDBBvvPGGEEKIpKQk0aVLF6HRaERpaakQQog///nPYurUqUIIISoqKoSHh4eYOnWqOHnypNi2bZsIDg4WAERiYqIQQojc3Fzh4OAgZs+eLVJTU8XWrVuFu7u7WLx48XV9nkmTJonQ0FCxd+9ekZSUJMaNGyd69Ogh6urqhBBCHDx4UCgUCrF06VKRlpYm3n77beHi4iJ0Op3pe3z55ZfCxsZGvPvuuyItLU28+eabQqVSiZ9//tm0DwDh5uYmPvzwQ5GWlib+/ve/C5VKJVJSUoQQQmRnZzf7fHl5ecLd3V0sXLhQpKamiqNHj4oxY8aIkSNHNvt8Wq1WvPTSSyI9PV3873//EwqFQuzYsUMIIcSWLVuEVqsV27dvF2fPnhWHDh0yffbi4mLh5+cnlixZIvLz80V+fr4QQoi7775bzJkzRwghxKVLl4SNjY1wcXERycnJQggh/v3vf4vBgwcLIYQwGAyif//+4pZbbhFHjhwRBw8eFAMGDBDDhw+/4jm2YsUKER4ebvo6MjJSuLu7i3fffVcIIUR8fLxQq9WivLxcVFVVCZ1OJz777DPT/hcvXhQajcZ0bBcvXiwiIiJMzy9btkxotVqxadMmcerUKfHcc88JGxsbkZ6eLoQQ4vXXXxf+/v5i79694syZMyIuLk5s3LixzZ/nes5jIa79e7F48WLh5OQk7r77bnHixAmxd+9e4e3tLV588cVmP+enn37a9PXq1avF9u3bRWZmpjhw4IAYMmSIGD9+/BWPuRDXPs/XrFkjbGxsRExMjNi/f784deqUqKioEIsXLxZ2dnaiX79+oqqqSvz000/ik08+ESkpKSIlJUXMnDlTeHl5ibKysqu+P5G5YwAkWRs+fLgIDQ0VBoPBtO35558XoaGhpq8DAgLElClTrvm9/vOf/4ioqCjT1wsWLBB33nmnEEKI5cuXi3vvvVcMGDBAfPfdd0IIIUJCQsSqVauEEEK8//77wtXVVVRWVppev2rVqmYB6cUXXxS9evVqVuu7774rnJychF6vb9PnSU9PFwDE/v37Tc8XFRUJe3t7U+h48MEHxe23397ss02dOrVZAIyJiRFPPPFEs33uu+8+MWHCBNPXAMSsWbOa7TN48GDxl7/8RQjRMgD+4x//EGPHjm22/7lz5wQAkZaWZvp8t9xyS7N9Bg4cKJ5//nkhhBBvvvmmCAkJMV3k/yggIEC89dZbzbb9PqB99dVXIjo6Wtx9992mgDZ27FjT99+xY4dQqVQiJyfH9Prk5GQBQBw+fLjV9zx+/LhQKBTi4sWLpoD56quvivvuu08I0TxgCiHEX/7yl2bhZvny5SI4ONj0M/1jAPT19RX/+te/WhyT2bNnCyGE+Otf/ypGjRrV7Jxo0pbPcz3ncWv++HuxePFi4eDg0CxAPfvss82OwR8D4B8dPnxYABDl5eWtPt+W83zNmjUCgEhKSjLtk5mZKfr16yeCgoJEVVVVq9+7oaFBODs7i23btl2xPiJLwC5gkr0hQ4Y0G/szdOhQZGRkNFteJDo6usXrPv/8c9xyyy3w9vaGk5MT/vGPfyAnJ8f0/IgRIxAXFweDwYA9e/ZgxIgRGDFiBPbs2YOCggKkp6dj+PDhAIDU1FRERETAwcGhWR2/l5qaiqFDhzarddiwYaioqEBubm6bPk9qairUajUGDx5set7NzQ29evVCampqs/f5vdZqGTZsWLNtw4YNM32PK71u6NChLfZpkpCQgF9++QVOTk6mR+/evQEAmZmZpv369evX7HU+Pj6m7sD77rsP1dXVCA4OxhNPPIGtW7c26yJvzYgRI5CcnIyioqIWP6eGhgbEx8c3+zn5+/vD39/f9PqwsDC4uLhc8XOFh4fDzc0Ne/bsQVxcHCIiIjBp0iTs2bMHALB7927T9weAJ554Ajt27MD58+cBAGvWrMGMGTNaHZ9WVlaGvLy8q/4sZsyYgaSkJPTq1Qtz587Fjh07TPu15fNcz3kMXPv3AjAOq3B2djZ9/fufYWsSExMxefJkBAQEwNnZGSNGjACAFt/395/rWuc5AGg0mmbn09q1a+Hu7g6tVgt7e3sAQGFhIWbNmoWQkBDodDrodDpUVFRc8b2JLAUDIFEbODo6Nvv64MGDeOCBBzB+/Hh8++23SExMxKJFi1BXV2fa59Zbb0V5eTmOHj2KuLg4jBgxAsOHD8eePXvwyy+/wNPTE6GhoQDQbIzelQghWoSApte1dfD6ld7n99+7LbW09p6t1deW1zUxGAyYOHEikpKSmj0yMjJw6623mvb74+xQhUIBg8EAwDizOC0tDe+++y7s7e0xe/Zs3Hrrrc3GoP3R7wNaU8Bp+jn9+uuvqK6uxi233HLVz3i1z65QKHDrrbdi9+7dpu8fHh4OvV6PEydOID4+3hRoAKB///6IiIjAunXrcPToUZw4cQIzZsy4Yv1N73GlegYMGIDs7Gy88sorqK6uxv3334977723zZ/nes7jtvxeAFf/Gf5RZWUlxo4dCycnJ6xfvx6//vortm7dCgAtvu/v67/S9t9/Xnt7+2ZfL1myBLGxsc1eM2PGDCQkJGD58uWIj49HUlIS3NzcrvjeRJaCAZBk7+DBgy2+7tmz51XXl9u/fz8CAgKwaNEiREdHo2fPns0GkAOATqdDZGQk3nnnHSgUCoSFhSE2NhaJiYn49ttvm7WahIWF4dixY6iurr5iXWFhYYiPj292cYuPj4ezszO6du3aps8TFhaGhoYGHDp0yPR8cXEx0tPTTRfxsLCwVr/H74WGhmLfvn3NtsXHx5u+x9VqaWrV+6MBAwYgOTkZgYGB6NGjR7PHHwP41djb22PSpElYsWIFdu/ejQMHDuDEiRMAjC0+f1w4uimgff311zh58iRiY2PRt29f1NfX47333sOAAQNMrVVhYWHIycnBuXPnTK9PSUlBaWlpi8/+eyNGjMDu3buxe/dujBgxAgqFArGxsXjjjTdQXV3dogXv8ccfx5o1a/Dxxx9j9OjRzVrofk+r1cLX1/eaPwutVoupU6fiww8/xObNm/HFF1/g0qVLbfo813Met+X34nqdOnUKRUVF+L//+z/Exsaid+/e15wA0pbzvK3i4uIwd+5cTJgwAX369IGtrW2ziUlEFkuCbmcis9E0aWL+/Pni1KlTYuPGjcLR0VG89957pn1aGzf21VdfCbVaLTZt2iROnz4t3n77beHq6tpsnJwQxvFTKpVK3HvvvaZtkZGRQqVSmcaYCSFEeXm5cHd3Fw8++KBITk4W3333nejRo0erk0CeeuopkZqaKr766qsrTgK52ueZPHmyCAsLE3FxcSIpKUncfvvtzQbHHzhwQCgUCvHaa6+JtLQ08d///rfFJJCtW7cKGxsbsWrVKpGenm6aBPLLL7+Y9gEg3N3dxerVq0VaWpr45z//KZRKpWlyxR/HAJ4/f154eHiIe++9Vxw6dEhkZmaKH3/8UTz66KOioaHB9Pn+ODZs8uTJ4pFHHhFCGMd1ffTRR+LEiRMiMzNTLFq0SNjb24uioiIhhBBjxowRkyZNErm5ueLixYum77FixQqhUqlEdHS0aduUKVOESqUSzz77rGlb06SJ2NhYkZCQIA4dOiSioqKuOglEiN/GAdrY2JgmTyxfvlyoVCoxcODAFvuXlpYKBwcHodFoxKefftrsuT+OAXzrrbeEVqsVn376qTh16pR4/vnnm00CWbZsmdi0aZNITU0VaWlpYubMmcLb21vo9fo2f562nsdt+b34Y/1NnyEgIMD09e9/zoWFhUKj0Yhnn31WZGZmiq+//lqEhIQ0O3dac63zfM2aNS1+X1urLzIyUowZM0akpKSIgwcPitjYWGFvb9/i3wQiS8MASLI2fPhwMXv2bDFr1iyh1WpFly5dxAsvvNBswHxrAVAI48B1Nzc34eTkJKZOnSreeuutFheUbdu2CQDinXfeMW17+umnBQBx8uTJZvseOHBARERECI1GIyIjI8UXX3zR4iK3e/duMXDgQKHRaIS3t7d4/vnnRX19/XV9nkuXLolp06YJnU4n7O3txbhx40xhocnq1auFn5+fsLe3FxMnThRvvPFGi8+2cuVKERwcLGxsbERISIhYt25ds+cBiHfffVeMGTNG2NraioCAALFp0ybT838MgEIYB+/fddddwsXFRdjb24vevXuLefPmmeq/VgDcunWrGDx4sNBqtcLR0VEMGTJE7Nq1q9kx7tevn7C1tRW///v3xIkTAoB45plnTNveeustAUB8++23zd7v7NmzYtKkScLR0VE4OzuL++67TxQUFIirMRgMwsPDo1nATExMbPGevzdt2jTh6uoqampqmm3/Y0DR6/Xi5ZdfFl27dhU2NjYiIiJCfP/996bnP/jgAxEZGSkcHR2FVqsVt912mzh69Oh1fZ7rOY+v9XtxvQFQCCE2btwoAgMDha2trRg6dKj45ptvrhkAr3WetzUAHj16VERHRwtbW1vRs2dPsWXLliv+m0BkSRRCtHHAD5EVGjFiBCIjI7F8+XKpS2kX1vZ55GzMmDEIDQ3FihUrpC6FiKwQ7wRCRGRGLl26hB07duDnn3/GO++8I3U5RGSlGACJiMzIgAEDcPnyZbz22mvo1auX1OUQkZViFzARERGRzHAZGCIiIiKZYQAkIiIikhkGQCIiIiKZYQAkIiIikhkGQCIiIiKZYQAkIiIikhkGQCIiIiKZYQAkIiIikpn/ByHvkDd/JMknAAAAAElFTkSuQmCC","text/plain":""},"metadata":{},"output_type":"display_data"}],"source":["import matplotlib.pyplot as plt\nfrom math import log\nimport numpy as np\n\ndef binomial_entropy(p):\n return -(p * log(p, 2) + (1-p) * log(1-p, 2))\n\nx = list(np.arange(0.001,1,0.001))\ny = [binomial_entropy(x) for x in x]\nplt.figure().clear()\nplt.xlabel('prawdopodobieństwo wylosowania orła')\nplt.ylabel('entropia')\nplt.plot(x, y)\n\nfname = f'04_Entropia/binomial-entropy.png'\n\nplt.savefig(fname)\n\nfname"]},{"cell_type":"markdown","metadata":{},"source":["**Pytanie** Dla oszukańczej monety (np. dla której wypada zawsze orzeł) entropia\nwynosi 0, czy to wynik zgodny z intuicją?\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### Entropia a język\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Tekst w danym języku możemy traktować jako ciąg symboli (komunikatów) losowanych według jakiegoś\nrozkładu prawdopodobieństwa. W tym sensie możemy mówić o entropii języka.\n\nOczywiście, jak zawsze, musimy jasno stwierdzić, czym są symbole\njęzyka: literami, wyrazami czy jeszcze jakimiś innymi jednostkami.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Pomiar entropii języka — pierwsze przybliżenie\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Załóżmy, że chcemy zmierzyć entropię języka polskiego na przykładzie\n„Pana Tadeusza” — na poziomie znaków. W pierwszym przybliżeniu można\nby policzyć liczbę wszystkich znaków…\n\n"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"['K', 's', 'i', 'ę', 'g', 'a', ' ', 'p', 'i', 'e', 'r', 'w', 's', 'z', 'a', '\\r', '\\n', '\\r', '\\n', '\\r', '\\n', '\\r', '\\n', 'G', 'o', 's', 'p', 'o', 'd', 'a', 'r', 's', 't', 'w', 'o', '\\r', '\\n', '\\r', '\\n', 'P', 'o', 'w', 'r', 'ó', 't', ' ', 'p', 'a', 'n', 'i']"}],"source":["import requests\nfrom itertools import islice\n\nurl = 'https://wolnelektury.pl/media/book/txt/pan-tadeusz.txt'\npan_tadeusz = requests.get(url).content.decode('utf-8')\n\ndef get_characters(t):\n yield from t\n\nlist(islice(get_characters(pan_tadeusz), 100, 150))"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"95"}],"source":["chars_in_pan_tadeusz = len(set(get_characters(pan_tadeusz)))\nchars_in_pan_tadeusz"]},{"cell_type":"markdown","metadata":{},"source":["… założyć jednostajny rozkład prawdopodobieństwa i w ten sposób policzyć entropię:\n\n"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"6.569855608330948"}],"source":["from math import log\n\n95 * (1/95) * log(95, 2)"]},{"cell_type":"markdown","metadata":{},"source":["#### Mniej rozrzutne kodowanie\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Przypomnijmy sobie jednak, że rozkład jednostek języka jest zawsze\nskrajnie nierównomierny! Jeśli uwzględnić ten nierównomierny rozkład\nznaków, można opracować o wiele efektywniejszy sposób zakodowania znaków składających się na „Pana Tadeusza”\n(częste litery, np. „a” i „e” powinny mieć krótkie kody, a rzadkie, np. „ź” — dłuższe).\n\nPoliczmy entropię przy takim założeniu:\n\n"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"4.938605272823633"}],"source":["from collections import Counter\nfrom math import log\n\ndef unigram_entropy(t):\n counter = Counter(t)\n\n total = counter.total()\n return -sum((p := count / total) * log(p, 2) for count in counter.values())\n\nunigram_entropy(get_characters(pan_tadeusz))"]},{"cell_type":"markdown","metadata":{},"source":["(Jak dowiemy się na kolejnym wykładzie, zastosowaliśmy tutaj **unigramowy model języka**).\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Ile wynosi entropia rękopisu Wojnicza?\n\n"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"9 OR 9FAM ZO8 QOAR9 Q*R 8ARAM 29 [O82*]OM OPCC9 OP"}],"source":["import requests\nimport re\n\nvoynich_url = 'http://www.voynich.net/reeds/gillogly/voynich.now'\nvoynich = requests.get(voynich_url).content.decode('utf-8')\n\nvoynich = re.sub(r'\\{[^\\}]+\\}|^<[^>]+>|[-# ]+', '', voynich, flags=re.MULTILINE)\n\nvoynich = voynich.replace('\\n\\n', '#')\nvoynich = voynich.replace('\\n', ' ')\nvoynich = voynich.replace('#', '\\n')\n\nvoynich = voynich.replace('.', ' ')\n\nvoynich[100:150]"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"3.902708104423842"}],"source":["unigram_entropy(get_characters(voynich))"]},{"cell_type":"markdown","metadata":{},"source":["#### Rzeczywista entropia?\n\n"]},{"cell_type":"markdown","metadata":{},"source":["W rzeczywistości entropia jest jeszcze mniejsza, tekst nie jest\ngenerowany przecież według rozkładu wielomianowego. Istnieją rzecz\njasna pewne zależności między znakami, np. niemożliwe, żeby po „ń”\nwystąpiły litera „a” czy „e”. Na poziomie wyrazów zależności mogę mieć\njeszcze bardziej skrajny charakter, np. po wyrazie „przede” prawie na\npewno wystąpi „wszystkim”, co oznacza, że w takiej sytuacji słowo\n„wszystkim” może zostać zakodowane za pomocą 0 (!) bitów.\n\nMożna uwzględnić takie zależności i uzyskać jeszcze lepsze kodowanie,\na co za tym idzie lepsze oszacowanie entropii. (Jak wkrótce się\ndowiemy, oznacza to użycie digramowego, trigramowego, etc. modelu języka).\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Rozmiar skompresowanego pliku jako przybliżenie entropii\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Celem algorytmów kompresji jest właściwie wyznaczanie efektywnych\nsposobów kodowania danych. Możemy więc użyć rozmiaru skompresowanego pliku w bitach\n(po podzieleniu przez oryginalną długość) jako dobrego przybliżenia entropii.\n\n"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"3.673019884633768"}],"source":["import zlib\n\ndef entropy_by_compression(t):\n compressed = zlib.compress(t.encode('utf-8'))\n return 8 * len(compressed) / len(t)\n\nentropy_by_compression(pan_tadeusz)"]},{"cell_type":"markdown","metadata":{},"source":["Dla porównania wynik dla rękopisu Wojnicza:\n\n"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"2.942372881355932"}],"source":["entropy_by_compression(voynich)"]},{"cell_type":"markdown","metadata":{},"source":["#### Gra Shannona\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Innym sposobem oszacowania entropii tekstu jest użycie… ludzi. Można poprosić rodzimych użytkowników\ndanego języka o przewidywanie kolejnych liter (bądź wyrazów) i w ten sposób oszacować entropię.\n\n**Projekt** Zaimplementuj aplikację webową, która umożliwi „rozegranie” gry Shannona.\n\n"]}],"metadata":{"org":null,"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.5.2"}},"nbformat":4,"nbformat_minor":0} \ No newline at end of file diff --git a/wyk/04_Entropia.org b/wyk/04_Entropia.org new file mode 100644 index 0000000..a578ae4 --- /dev/null +++ b/wyk/04_Entropia.org @@ -0,0 +1,347 @@ +* Entropia + +*Entropia* ($E$) to miara nieuporządkowania, niepewności, niewiedzy. Im +większa entropia, tym mniej wiemy. Pojęcie to pierwotnie wywodzi się z +termodynamiki, później znaleziono wiele zaskakujących analogii i zastosowań w +innych dyscyplinach nauki. + +*** Entropia w fizyce + +W termodynamice entropia jest miarą nieuporządkowania układów +fizycznych, na przykład pojemników z gazem. Przykładowo, wyobraźmy +sobie dwa pojemniki z gazem, w którym panuje różne temperatury. + +[[./04_Entropia/gas-low-entropy.drawio.png]] + +Jeśli usuniemy przegrodę między pojemnikami, temperatura się wyrówna, +a uporządkowanie się zmniejszy. + +[[./04_Entropia/gas-high-entropy.drawio.png]] + +Innymi słowy, zwiększy się stopień nieuporządkowania układu, czyli właśnie entropia. + +*** II prawo termodynamiki + +Jedno z najbardziej fundamentalnych praw fizyki, II prawo +termodynamiki głosi, że w układzie zamkniętym entropia nie spada. + +**Pytanie**: Czy to, że napisałem te materiały do wykładu i +/uporządkowałem/ wiedzę odnośnie do statystycznych własności języka, nie +jest sprzeczne z II prawem termodynamiki? + +Konsekwencją II prawa termodynamiki jest śmierć cieplna Wszechświata +(zob. [wizualizacja przyszłości Wszechświata](https://www.youtube.com/watch?v=uD4izuDMUQA)). + +*** Entropia w teorii informacji + +Pojęcie entropii zostało „odkryte” na nowo przez Claude'a Shannona, +gdy wypracował ogólną teorię informacji. + +Teoria informacji zajmuje się między innymi zagadnieniem optymalnego kodowania komunikatów. + +Wyobraźmy sobie pewne źródło (generator) losowych komunikatów z +zamkniętego zbioru symboli ($\Sigma$; nieprzypadkowo używamy oznaczeń +z poprzedniego wykładu). Nadawca $N$ chce przesłać komunikat o wyniku +losowania do odbiorcy $O$ używając zer i jedynek (bitów). +Teorioinformacyjną entropię można zdefiniować jako średnią liczbę +bitów wymaganych do przesłania komunikatu. + +[[./04_Entropia/communication.drawio.png]] + +*** Obliczanie entropii — proste przykłady + +Załóżmy, że nadawca chce przekazać odbiorcy informację o wyniku rzutu monetą. +Entropia wynosi wówczas rzecz jasna 1 — na jedno losowanie wystarczy jeden bit +(informację o tym, że wypadł orzeł, możemy zakodować na przykład za pomocą zera, +zaś to, że wypadła reszka — za pomocą jedynki). + +Rozpatrzmy przypadek, gdy nadawca rzuca ośmiościenną kością. Aby przekazać +wynik, potrzebuje wówczas 3 bity (a więc entropia ośmiościennej kości +wynosi 3 bity). Przykładowe kodowanie może mieć następującą postać: + +| Wynik | Kodowanie | +|-------+-----------| +| 1 | 001 | +| 2 | 010 | +| 3 | 011 | +| 4 | 100 | +| 5 | 101 | +| 6 | 110 | +| 7 | 111 | +| 8 | 000 | + +*** Obliczenie entropii — trudniejszy przykład + +Załóżmy, że $\Sigma = \{A, B, C, D\}$, natomiast poszczególne komunikaty +są losowane zgodnie z następującym rozkładem prawdopodobieństwa: +$P(A)=1/2$, $P(B)=1/4$, $P(C)=1/8$, $P(D)=1/8$. Ile wynosi entropia w +takim przypadku? Można by sądzić, że 2, skoro wystarczą 2 bity do +przekazania wyniku losowania przy zastosowaniu następującego kodowania: + +| Wynik | Kodowanie | +|-------+-----------| +| A | 00 | +| B | 01 | +| C | 10 | +| D | 11 | + +Problem w tym, że w rzeczywistości nie jest to /optymalne/ kodowanie. +Możemy sprytnie zmniejszyć średnią liczbę bitów wymaganych do +przekazania losowego wyniku przypisując częstszym wynikom krótsze +kody, rzadszym zaś — dłuższe. Oto takie optymalne kodowanie: + +| Wynik | Kodowanie | +|-------+-----------| +| A | 0 | +| B | 10 | +| C | 110 | +| D | 111 | + + +Używając takiego kodowanie średnio potrzebujemy: + +$$\frac{1}{2}1 + \frac{1}{4}2 + \frac{1}{8}3 + \frac{1}{8}3 = 1,75$$ + +bita. Innymi słowy, entropia takiego źródła wynosi 1,75 bita. + +*** Kodowanie musi być jednoznaczne! + +Można by sądzić, że da się stworzyć jeszcze krótsze kodowanie dla omawianego rozkładu nierównomiernego: + +| Wynik | Kodowanie | +|-------+-----------| +| A | 0 | +| B | 1 | +| C | 01 | +| D | 11 | + +Niestety, nie jest to właściwe rozwiązanie — kodowanie musi być +jednoznaczne nie tylko dla pojedynczego komunikatu, lecz dla całej sekwencji. +Na przykład ciąg 0111 nie jest jednoznaczny przy tym kodowaniu (ABBB czy CD?). +Podane wcześniej kodowanie spełnia warunek jednoznaczności, ciąg 0111 można odkodować tylko +jako AD. + + +*** Ogólny wzór na entropię. + +Na podstawie poprzedniego przykładu można dojść do intuicyjnego wniosku, że +optymalny kod dla wyniku o prawdopodobieństwie $p$ ma długość $-\log_2(p)$, a zatem ogólnie +entropia źródła o rozkładzie prawdopodobieństwa $\{p_1,\ldots,p_|\Sigma|\}$ wynosi: + +$$E = -\sum_{i=1}^{|\Sigma|} p_i\log_2(p_i)$$. + +Zauważmy, że jest to jeden z nielicznych przypadków, gdy w nauce naturalną +podstawą logarytmu jest 2 zamiast… podstawy logarytmu naturalnego ($e$). + +Teoretycznie można mierzyć entropię używając logarytmu naturalnego +($\ln$), jednostką entropii będzie wówczas *nat* zamiast bita, +niewiele to jednak zmienia i jest mniej poręczne i trudniejsze do interpretacji +(przynajmniej w kontekście informatyki) niż operowanie na bitach. + +**Pytanie** Ile wynosi entropia zwykłej sześciennej kostki? Jak wygląda +optymalne kodowanie wyników rzutu taką kostką? + +*** Entropia dla próby Bernoulliego + +Wiemy już, że entropia dla rzutu monetą wynosi 1 bit. A jaki będzie wynik dla źle wyważonej monety? + +#+BEGIN_SRC ipython :session mysession :results file + import matplotlib.pyplot as plt + from math import log + import numpy as np + + def binomial_entropy(p): + return -(p * log(p, 2) + (1-p) * log(1-p, 2)) + + x = list(np.arange(0.001,1,0.001)) + y = [binomial_entropy(x) for x in x] + plt.figure().clear() + plt.xlabel('prawdopodobieństwo wylosowania orła') + plt.ylabel('entropia') + plt.plot(x, y) + + fname = f'04_Entropia/binomial-entropy.png' + + plt.savefig(fname) + + fname +#+END_SRC + +#+RESULTS: +[[file:04_Entropia/binomial-entropy.png]] + +*Pytanie* Dla oszukańczej monety (np. dla której wypada zawsze orzeł) entropia +wynosi 0, czy to wynik zgodny z intuicją? + +** Entropia a język + +Tekst w danym języku możemy traktować jako ciąg symboli (komunikatów) losowanych według jakiegoś +rozkładu prawdopodobieństwa. W tym sensie możemy mówić o entropii języka. + +Oczywiście, jak zawsze, musimy jasno stwierdzić, czym są symbole +języka: literami, wyrazami czy jeszcze jakimiś innymi jednostkami. + +*** Pomiar entropii języka — pierwsze przybliżenie + +Załóżmy, że chcemy zmierzyć entropię języka polskiego na przykładzie +„Pana Tadeusza” — na poziomie znaków. W pierwszym przybliżeniu można +by policzyć liczbę wszystkich znaków… + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer + import requests + from itertools import islice + + url = 'https://wolnelektury.pl/media/book/txt/pan-tadeusz.txt' + pan_tadeusz = requests.get(url).content.decode('utf-8') + + def get_characters(t): + yield from t + + list(islice(get_characters(pan_tadeusz), 100, 150)) +#+END_SRC + +#+RESULTS: +:results: +['K', 's', 'i', 'ę', 'g', 'a', ' ', 'p', 'i', 'e', 'r', 'w', 's', 'z', 'a', '\r', '\n', '\r', '\n', '\r', '\n', '\r', '\n', 'G', 'o', 's', 'p', 'o', 'd', 'a', 'r', 's', 't', 'w', 'o', '\r', '\n', '\r', '\n', 'P', 'o', 'w', 'r', 'ó', 't', ' ', 'p', 'a', 'n', 'i'] +:end: + + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer + chars_in_pan_tadeusz = len(set(get_characters(pan_tadeusz))) + chars_in_pan_tadeusz +#+END_SRC + +#+RESULTS: +:results: +95 +:end: + +… założyć jednostajny rozkład prawdopodobieństwa i w ten sposób policzyć entropię: + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer + from math import log + + 95 * (1/95) * log(95, 2) +#+END_SRC + +#+RESULTS: +:results: +6.569855608330948 +:end: + +*** Mniej rozrzutne kodowanie + +Przypomnijmy sobie jednak, że rozkład jednostek języka jest zawsze +skrajnie nierównomierny! Jeśli uwzględnić ten nierównomierny rozkład +znaków, można opracować o wiele efektywniejszy sposób zakodowania znaków składających się na „Pana Tadeusza” +(częste litery, np. „a” i „e” powinny mieć krótkie kody, a rzadkie, np. „ź” — dłuższe). + +Policzmy entropię przy takim założeniu: + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer + from collections import Counter + from math import log + + def unigram_entropy(t): + counter = Counter(t) + + total = counter.total() + return -sum((p := count / total) * log(p, 2) for count in counter.values()) + + unigram_entropy(get_characters(pan_tadeusz)) +#+END_SRC + +#+RESULTS: +:results: +4.938605272823633 +:end: + +(Jak dowiemy się na kolejnym wykładzie, zastosowaliśmy tutaj *unigramowy model języka*). + +*** Ile wynosi entropia rękopisu Wojnicza? + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer + import requests + import re + + voynich_url = 'http://www.voynich.net/reeds/gillogly/voynich.now' + voynich = requests.get(voynich_url).content.decode('utf-8') + + voynich = re.sub(r'\{[^\}]+\}|^<[^>]+>|[-# ]+', '', voynich, flags=re.MULTILINE) + + voynich = voynich.replace('\n\n', '#') + voynich = voynich.replace('\n', ' ') + voynich = voynich.replace('#', '\n') + + voynich = voynich.replace('.', ' ') + + voynich[100:150] +#+END_SRC + +#+RESULTS: +:results: +9 OR 9FAM ZO8 QOAR9 Q*R 8ARAM 29 [O82*]OM OPCC9 OP +:end: + + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer + unigram_entropy(get_characters(voynich)) +#+END_SRC + +#+RESULTS: +:results: +3.902708104423842 +:end: + +*** Rzeczywista entropia? + +W rzeczywistości entropia jest jeszcze mniejsza, tekst nie jest +generowany przecież według rozkładu wielomianowego. Istnieją rzecz +jasna pewne zależności między znakami, np. niemożliwe, żeby po „ń” +wystąpiły litera „a” czy „e”. Na poziomie wyrazów zależności mogę mieć +jeszcze bardziej skrajny charakter, np. po wyrazie „przede” prawie na +pewno wystąpi „wszystkim”, co oznacza, że w takiej sytuacji słowo +„wszystkim” może zostać zakodowane za pomocą 0 (!) bitów. + +Można uwzględnić takie zależności i uzyskać jeszcze lepsze kodowanie, +a co za tym idzie lepsze oszacowanie entropii. (Jak wkrótce się +dowiemy, oznacza to użycie digramowego, trigramowego, etc. modelu języka). + +*** Rozmiar skompresowanego pliku jako przybliżenie entropii + +Celem algorytmów kompresji jest właściwie wyznaczanie efektywnych +sposobów kodowania danych. Możemy więc użyć rozmiaru skompresowanego pliku w bitach +(po podzieleniu przez oryginalną długość) jako dobrego przybliżenia entropii. + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer + import zlib + + def entropy_by_compression(t): + compressed = zlib.compress(t.encode('utf-8')) + return 8 * len(compressed) / len(t) + + entropy_by_compression(pan_tadeusz) +#+END_SRC + +#+RESULTS: +:results: +3.673019884633768 +:end: + +Dla porównania wynik dla rękopisu Wojnicza: + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer + entropy_by_compression(voynich) +#+END_SRC + +#+RESULTS: +:results: +2.942372881355932 +:end: + +*** Gra Shannona + +Innym sposobem oszacowania entropii tekstu jest użycie… ludzi. Można poprosić rodzimych użytkowników +danego języka o przewidywanie kolejnych liter (bądź wyrazów) i w ten sposób oszacować entropię. + +*Projekt* Zaimplementuj aplikację webową, która umożliwi „rozegranie” gry Shannona. diff --git a/wyk/04_Entropia/binomial-entropy.png b/wyk/04_Entropia/binomial-entropy.png new file mode 100644 index 0000000..e16dd0f Binary files /dev/null and b/wyk/04_Entropia/binomial-entropy.png differ diff --git a/wyk/04_Entropia/communication.drawio b/wyk/04_Entropia/communication.drawio new file mode 100644 index 0000000..13aa4d0 --- /dev/null +++ b/wyk/04_Entropia/communication.drawio @@ -0,0 +1 @@ +1VbbcpswEP0aHpMxEGznMbFzmTZtPc1Dk0cZrUGJ0LpC2JCvrwTC3OzcO9P6waM9klbsObtaOf4sya8kWcffkAJ3vBHNHX/ueN7piav/DVBUQOAFFRBJRivIbYBb9gQWHFk0YxTSzkKFyBVbd8EQhYBQdTAiJW67y1bIu6euSQQD4DYkfIj+YlTFFTr1Jg1+DSyK65Pd8Wk1k5B6sY0kjQnFbQvyLxx/JhFVNUryGXDDXc1Lte/ywOzuwyQI9ZoNX6X3O78fXS/phv3kIss2X7wj62VDeGYD/k4o2YbEfrMqaiL056/NMEv4WahQOv75BqRimqobsgS+wJQphkIvWaJSmLQWnHEWmQmFa43GKuHacPUQM8WZgNlOvJEG7SfpvZAfjNXdMagzDzABJQu9xG7wTizpRc/eNhr6Fopb8o0tRmzWRDvPDbF6YLl9A88nA55/0CVD+b8THfj/GNHBgOiDBK845GfmitBUgKB2OA85SVMWdvmTmAkKtEMc0MHV8SJtLVqCPbTUmAROFNt03e/jyp6wQKYPbtJ/2lNl0qM7xUyGYHe174yeo8B7wZEiMgI1cFRKtwv7/WqOB2o+EkGcWeBMDf6ISSbYIwkf2EBlo05ZL10hia2QUCsFck/pJIxS4+NcQsqeyLL0Z0RfmyDLsINzJ5g/Vz+2GdnNTQtoJ8jh7D1YbEejY7dun+/NkHoJrlYp/BXNpnuluLUmShVjhILwiwbtlVez5gbNRVYK9wBKFfZ9QDKFXVkhZ+rObD8OrHXfmpnn1nNpFLUhdKB3beO+9OD3fvVs46W0Om4WIJkmzmTUm24IzVNZis/waV8aVaW91MqHufPqRPnQtTsZFOoVCJDE9C8dY5EskQ9r9ON9rb7LdTov9FPM9reyaXZzKq0yp8qPT2h8bu+F4U6GjW/8OY1Pm80rsarS5qntX/wB \ No newline at end of file diff --git a/wyk/04_Entropia/communication.drawio.png b/wyk/04_Entropia/communication.drawio.png new file mode 100644 index 0000000..3338d9e Binary files /dev/null and b/wyk/04_Entropia/communication.drawio.png differ diff --git a/wyk/04_Entropia/gas-high-entropy.drawio b/wyk/04_Entropia/gas-high-entropy.drawio new file mode 100644 index 0000000..667bb82 --- /dev/null +++ b/wyk/04_Entropia/gas-high-entropy.drawio @@ -0,0 +1 @@ +jZPfb4MgEMf/Gh+bKFS3vs513bLsqUv2TIQKLXiO0mr31w/l/JVmydAofO444HtHRHPT7iyr5QdwoSMS8zaizxEhm3Xivx24BZCSNIDSKh5QMoG9+hEIY6QXxcV54egAtFP1EhZQVaJwC8ashWbpdgC9XLVmpbgD+4Lpe/qluJOBPpKHib8KVcph5STbBIthgzOGOEvGoQmoPxzdRjS3AC70TJsL3Wk36BIUePnDOm7Misr9Z8LpuNrG5ppe31ylDf1+P+6yFR7jyvQFDxyRtX8/ww937m6DHBYuFRddxDiiT41UTuxrVnTWxuffM+mM9qPEd8/OwmmUjXpyUFrnoMH20egh7Z6OQ+VmPLQxwsyS9c1bcN/COtH+KUgyyuzLU4ARzt68C04gFGsMS5OmOG6mRJM1MjlLcoaMYW2VY+hJft/BDAzDKdO9bXZd6PYX \ No newline at end of file diff --git a/wyk/04_Entropia/gas-high-entropy.drawio.png b/wyk/04_Entropia/gas-high-entropy.drawio.png new file mode 100644 index 0000000..69022e4 Binary files /dev/null and b/wyk/04_Entropia/gas-high-entropy.drawio.png differ diff --git a/wyk/04_Entropia/gas-low-entropy.drawio b/wyk/04_Entropia/gas-low-entropy.drawio new file mode 100644 index 0000000..5ab76e1 --- /dev/null +++ b/wyk/04_Entropia/gas-low-entropy.drawio @@ -0,0 +1 @@ +5ZVRT8IwEMc/zR5NtpUVeBRENMYnTHw0db1t1W7FUhj46b3RbmMwEk3UmJgQcv3f7a79/QvzyDTfzjVbZveKg/RCn289cuWF4XgQ4Hcl7KwQhZEVUi24lYJWWIh3cKLv1LXgsOoUGqWkEcuuGKuigNh0NKa1KrtliZLdqUuWwomwiJk8VR8FN5lVR+Gw1W9ApFk9OaBjm8lZXexarDLGVWml/eHIzCNTrZSxUb6dgqzY1Vwsgesz2WZjGgrzmQdeXy5mfr6JNremkDl5u3uZ04vQdtkwuXYHdps1u5qAVuuCQ9XE98ikzISBxZLFVbZEy1HLTC5xFWC4Mlq9NqQIKomQcqqk0vtuJEmAxnFTeZDhw/GzX41wWwJtYHv2rEFDEG8eqByM3mGJeyAk7vrsjtZl62HgePnZgX/Uacxdm7Rp3ZLFwMH9Amjy26A5g1HSC5rGI3hOvgc0if4a6KgHNJU4dcLFBsPU7E8+wM/DU2CDugIHdoqODEJMps+Fmm2hCjgywklMirTAZYxYAfVJBV3gv8ylS+SC82pMr+3di/EdPw965NogOnGN9phGfso0+hXTwv9pGhn9mmm4bN9L+9zBy53MPgA= \ No newline at end of file diff --git a/wyk/04_Entropia/gas-low-entropy.drawio.png b/wyk/04_Entropia/gas-low-entropy.drawio.png new file mode 100644 index 0000000..0217e1c Binary files /dev/null and b/wyk/04_Entropia/gas-low-entropy.drawio.png differ diff --git a/wyk/05_Ngramowy_model.ipynb b/wyk/05_Ngramowy_model.ipynb new file mode 100644 index 0000000..2eb2875 --- /dev/null +++ b/wyk/05_Ngramowy_model.ipynb @@ -0,0 +1,19 @@ + +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n", + "
\n", + "

Modelowanie języka

\n", + "

05. N-gramowe modele języka i ich zastosowania [wykład]

\n", + "

Filip Graliński (2022)

\n", + "
\n", + "\n", + "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)\n", + "\n" + ] + }, +{"cell_type":"markdown","metadata":{},"source":["## N-gramowe modele języka i ich zastosowania\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Przypomnienie\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Przypomnijmy, że model języka zwraca prawdopodobieństwo dla danego\nciągu symboli (tokenów, wyrazów itp.) $w_1\\ldots w_N$ (o długości $N$):\n\n$$P_M(w_1\\ldots w_N) = ?$$\n\nW dalszym ciągu będziemy zakładali, że będziemy operować na wyrazach.\nZbiór wszystkich wyrazów nazywa się **słownikiem** (ang. *vocabulary*,\nnie *dictionary!*), w literaturze dotyczącej modelowania języka\nzazwyczaj oznacza się go literą $V$ (częściej niż $\\Sigma$).\nDale zakładamy, że słownik jest skończony.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Co jeszcze potrafi model języka?\n\n"]},{"cell_type":"markdown","metadata":{},"source":["##### Przewidywanie kolejnego słowa\n\n"]},{"cell_type":"markdown","metadata":{},"source":["$$P_M(w_N|w_1\\ldots w_{N-1}) = \\frac{P_M(w_1\\dots w_{N-1}w_N*)}{P_M(w_1\\dots w_{n-1}*)} = \\frac{\\sum_{\\alpha \\in\n \\Sigma^*}P_M(w_1\\dots w_N\\alpha)}{\\sum_{\\alpha\\in\\Sigma^*}P(w_1\\dots w_{n-1}\\alpha)}$$\n\n$P_M(w_N|w_1\\ldots w_{N-1})$ to właściwie skrót notacyjny, pełny zapis powinien mieć następujący kształt:\n\n$$P_M(X_N=w_N|X_1=w_1,\\ldots,X_{N-1}=w_{N-1}),$$\n\ngdzie $P_M(X_i=w)$ oznacza prawdopodobieństwo, że na $i$-tej pozycji wystąpi słowo $w$.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["##### Odgadywanie słowa w luce\n\n"]},{"cell_type":"markdown","metadata":{},"source":["$$P_M(w_1\\dots w_{i-1}?w_{i+1}\\dots w_N) = \\operatorname{argmax}_w P_M(w_1\\ldots w_{i-1}ww_{i+1}\\dots w_N)$$\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Przykład dla autentycznego modelu języku\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Zobaczmy przykładowe zastosowania i wyniki dla modelu języku\nwyuczonego na tekstach z II poł. XX w.\n\n![img](./05_Ngramowy_model/tabelka.png)\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Do czego stosujemy model języka?\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Model języka sam w sobie nie jest zbyt użyteczny. To raczej środek do celu\nniż cel sam w sobie.\n\nModel języka:\n\n- ma zastosowanie w kryptoanalizie\n - Oxmynsxq mkx lo kmrsofon li cdenisxq sdc kvzrklodsm mrkbkmdobc kxn bozvkmsxq okmr yxo li dro 13dr voddob zvkmon pebdrob kvyxq sx dro kvzrklod.\n- pomaga(ł) wybrać właściwe tłumaczenie w tłumaczeniu maszynowym\n czy transkrypcję w systemach rozpoznawania mowy (ASR)\n (zanim zaczęto używać do tego sieci neuronowych, gdzie nie\n ma już wyraźnego rozróżnienia między modelem tłumaczenia\n czy modelem akustycznym a modelem języka),\n- pomaga znaleźć „podejrzane” miejsca w tekście\n (korekta pisowni/gramatyki),\n- może być stosowany jako klasyfikator (potrzeba wtedy więcej niż jednego modelu,\n np. model języka spamów kontra model języka niespamów),\n- może być stosowany w kompresji danych,\n- bardzo dobry model języka **musi** mieć **w środku** bardzo dobrą **wiedzę**\n o języku i o świecie, można wziąć **„wnętrzności”** modelu, nie dbając o prawdopodobieństwa\n i użyć modelu w zupełnie innym celu.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### N-gramowy model języka\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Zawsze prawdziwe:\n\n$$P_M(w_1\\dots w_N) = P_M(w_1)P_M(w_2|w_1)\\dots P_M(w_N|w_1\\dots w_{N-1}).$$\n\nMożna aproksymować prawdopodobieństwa używając $n$-gramów:\n\n$$P_M(w_1\\dots w_N) \\approx P_M(w_1)\\dots P_M(w_i|w_{i-n+1}\\dots w_{i-1})\\dots P_M(w_N|w_{N-n+1}\\dots w_{N-1}).$$\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Model trigramowy\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Dla $n=3$:\n\n$$P_M(w_1\\dots w_N) = P_M(w_1)P_M(w_2|w_1)P_M(w_3|w_1w_2)\\dots P_M(w_i|w_{i-2}w_{i-1})\\dots P_M(w_N|w_{N-2}w_{N-1}).$$\n\nZauważmy, że model trigramowy oznacza modelowanie kolejnego wyrazu przy znajomości\n2 (nie 3!) poprzedzających wyrazów (**razem** mamy 3 wyrazy).\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Model digramowy/bigramowy\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Dla $n=2$:\n\n$$P_M(w_1\\dots w_N) = P_M(w_1)P_M(w_2|w_1)P_M(w_3|w_2)\\dots P_M(w_i|w_{i-1})\\dots P_M(w_N|w_{N-1})$$\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Model unigramowy\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Dla $n=1$ uzyskujemy przypadek szczególny:\n\n$$P_M(w_1\\dots w_N) = P_M(w_1)P_M(w_2)P_M(w_3)\\dots P_M(w_N) = \\prod_{i=1}^N P_M(w_i)$$\n\nZauważmy, że w modelu unigramowym w ogóle nie bierzemy pod uwagę kolejności wyrazów.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Estymacja prawdopodobieństw\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Dla $n$-gramowego modelu potrzebujmy estymować wartości:\n\n$$P_M(w_i|w_{i-n+1}\\dots w_{i-1}).$$\n\nPrawdopodobieństwa te estymujemy na podstawie jakiegoś **korpusu tekstów**\n(możemy nazywać go również **zbiorem uczącym**).\n\nNajprostszy sposób:\n\n$$P_M(w_i|w_{i-n+1}\\dots w_{i-1}) = \\frac{\\# w_{i-n+1}\\dots w_{i-1}w_i}{\\# w_{i-n+1}\\dots w_{i-1}},$$\n\ngdzie $\\# w_1\\dots w_k$ oznacza liczbę wystąpień w korpusie.\n\nNa przykład, jeśli model $M$ zostanie wyuczony na tekście *do be do be do do*, wówczas\n$P_M(\\mathit{be}|\\mathit{do})=\\frac{2}{3}$.\n\n"]}],"metadata":{"org":null,"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.5.2"}},"nbformat":4,"nbformat_minor":0} \ No newline at end of file diff --git a/wyk/05_Ngramowy_model.org b/wyk/05_Ngramowy_model.org new file mode 100644 index 0000000..8f637c8 --- /dev/null +++ b/wyk/05_Ngramowy_model.org @@ -0,0 +1,112 @@ + +* N-gramowe modele języka i ich zastosowania + +*** Przypomnienie + +Przypomnijmy, że model języka zwraca prawdopodobieństwo dla danego +ciągu symboli (tokenów, wyrazów itp.) $w_1\ldots w_N$ (o długości $N$): + +$$P_M(w_1\ldots w_N) = ?$$ + +W dalszym ciągu będziemy zakładali, że będziemy operować na wyrazach. +Zbiór wszystkich wyrazów nazywa się *słownikiem* (ang. /vocabulary/, +nie /dictionary!/), w literaturze dotyczącej modelowania języka +zazwyczaj oznacza się go literą $V$ (częściej niż $\Sigma$). +Dale zakładamy, że słownik jest skończony. + +*** Co jeszcze potrafi model języka? + +**** Przewidywanie kolejnego słowa + +$$P_M(w_N|w_1\ldots w_{N-1}) = \frac{P_M(w_1\dots w_{N-1}w_N*)}{P_M(w_1\dots w_{n-1}*)} = \frac{\sum_{\alpha \in + \Sigma^*}P_M(w_1\dots w_N\alpha)}{\sum_{\alpha\in\Sigma^*}P(w_1\dots w_{n-1}\alpha)}$$ + +$P_M(w_N|w_1\ldots w_{N-1})$ to właściwie skrót notacyjny, pełny zapis powinien mieć następujący kształt: + +$$P_M(X_N=w_N|X_1=w_1,\ldots,X_{N-1}=w_{N-1}),$$ + +gdzie $P_M(X_i=w)$ oznacza prawdopodobieństwo, że na $i$-tej pozycji wystąpi słowo $w$. + +**** Odgadywanie słowa w luce + +$$P_M(w_1\dots w_{i-1}?w_{i+1}\dots w_N) = \operatorname{argmax}_w P_M(w_1\ldots w_{i-1}ww_{i+1}\dots w_N)$$ + +*** Przykład dla autentycznego modelu języku + +Zobaczmy przykładowe zastosowania i wyniki dla modelu języku +wyuczonego na tekstach z II poł. XX w. + +[[./05_Ngramowy_model/tabelka.png]] + +*** Do czego stosujemy model języka? + +Model języka sam w sobie nie jest zbyt użyteczny. To raczej środek do celu +niż cel sam w sobie. + +Model języka: +- ma zastosowanie w kryptoanalizie + - Oxmynsxq mkx lo kmrsofon li cdenisxq sdc kvzrklodsm mrkbkmdobc kxn bozvkmsxq okmr yxo li dro 13dr voddob zvkmon pebdrob kvyxq sx dro kvzrklod. +- pomaga(ł) wybrać właściwe tłumaczenie w tłumaczeniu maszynowym + czy transkrypcję w systemach rozpoznawania mowy (ASR) + (zanim zaczęto używać do tego sieci neuronowych, gdzie nie + ma już wyraźnego rozróżnienia między modelem tłumaczenia + czy modelem akustycznym a modelem języka), +- pomaga znaleźć „podejrzane” miejsca w tekście + (korekta pisowni/gramatyki), +- może być stosowany jako klasyfikator (potrzeba wtedy więcej niż jednego modelu, + np. model języka spamów kontra model języka niespamów), +- może być stosowany w kompresji danych, +- bardzo dobry model języka *musi* mieć *w środku* bardzo dobrą *wiedzę* + o języku i o świecie, można wziąć *„wnętrzności”* modelu, nie dbając o prawdopodobieństwa + i użyć modelu w zupełnie innym celu. + +** N-gramowy model języka + +Zawsze prawdziwe: + +$$P_M(w_1\dots w_N) = P_M(w_1)P_M(w_2|w_1)\dots P_M(w_N|w_1\dots w_{N-1}).$$ + +Można aproksymować prawdopodobieństwa używając $n$-gramów: + +$$P_M(w_1\dots w_N) \approx P_M(w_1)\dots P_M(w_i|w_{i-n+1}\dots w_{i-1})\dots P_M(w_N|w_{N-n+1}\dots w_{N-1}).$$ + +*** Model trigramowy + +Dla $n=3$: + +$$P_M(w_1\dots w_N) = P_M(w_1)P_M(w_2|w_1)P_M(w_3|w_1w_2)\dots P_M(w_i|w_{i-2}w_{i-1})\dots P_M(w_N|w_{N-2}w_{N-1}).$$ + +Zauważmy, że model trigramowy oznacza modelowanie kolejnego wyrazu przy znajomości +2 (nie 3!) poprzedzających wyrazów (*razem* mamy 3 wyrazy). + +*** Model digramowy/bigramowy + +Dla $n=2$: + +$$P_M(w_1\dots w_N) = P_M(w_1)P_M(w_2|w_1)P_M(w_3|w_2)\dots P_M(w_i|w_{i-1})\dots P_M(w_N|w_{N-1})$$ + +*** Model unigramowy + +Dla $n=1$ uzyskujemy przypadek szczególny: + +$$P_M(w_1\dots w_N) = P_M(w_1)P_M(w_2)P_M(w_3)\dots P_M(w_N) = \prod_{i=1}^N P_M(w_i)$$ + +Zauważmy, że w modelu unigramowym w ogóle nie bierzemy pod uwagę kolejności wyrazów. + +*** Estymacja prawdopodobieństw + +Dla $n$-gramowego modelu potrzebujmy estymować wartości: + +$$P_M(w_i|w_{i-n+1}\dots w_{i-1}).$$ + +Prawdopodobieństwa te estymujemy na podstawie jakiegoś *korpusu tekstów* +(możemy nazywać go również *zbiorem uczącym*). + +Najprostszy sposób: + +$$P_M(w_i|w_{i-n+1}\dots w_{i-1}) = \frac{\# w_{i-n+1}\dots w_{i-1}w_i}{\# w_{i-n+1}\dots w_{i-1}},$$ + +gdzie $\# w_1\dots w_k$ oznacza liczbę wystąpień w korpusie. + +Na przykład, jeśli model $M$ zostanie wyuczony na tekście /do be do be do do/, wówczas +$P_M(\mathit{be}|\mathit{do})=\frac{2}{3}$. diff --git a/wyk/05_Ngramowy_model/tabelka.pdf b/wyk/05_Ngramowy_model/tabelka.pdf new file mode 100644 index 0000000..c44d268 Binary files /dev/null and b/wyk/05_Ngramowy_model/tabelka.pdf differ diff --git a/wyk/05_Ngramowy_model/tabelka.png b/wyk/05_Ngramowy_model/tabelka.png new file mode 100644 index 0000000..5f29011 Binary files /dev/null and b/wyk/05_Ngramowy_model/tabelka.png differ diff --git a/wyk/06_Ewaluacja.ipynb b/wyk/06_Ewaluacja.ipynb new file mode 100644 index 0000000..a82eabf --- /dev/null +++ b/wyk/06_Ewaluacja.ipynb @@ -0,0 +1,19 @@ + +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n", + "
\n", + "

Modelowanie języka

\n", + "

06. Ewaluacja modeli języka [wykład]

\n", + "

Filip Graliński (2022)

\n", + "
\n", + "\n", + "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)\n", + "\n" + ] + }, +{"cell_type":"markdown","metadata":{},"source":["## Ewaluacja modeli języka\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Jak już widzimy, możemy mieć różne modele języka. Nawet jeśli\npozostajemy tylko na gruncie najprostszych, $n$-gramowych modeli\njęzyka, inne prawdopodobieństwa uzyskamy dla modelu digramowego, a\ninny dla trigramowego. Jedne modele będą lepsze, inne — gorsze. Jak\nobiektywnie odróżnić dobry model od złego? Innymi słowy, jak ewaluować\nmodele języka?\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### Ewaluacja zewnętrzna i wewnętrzna\n\n"]},{"cell_type":"markdown","metadata":{},"source":["W ewaluacji zewnętrznej (ang. *extrinsic*) ewaluację modelu języka sprowadzamy\ndo ewaluacji większego systemu, którego częścią jest model języka, na przykład\nsystemu tłumaczenia maszynowego albo systemu ASR.\n\nEwaluacja wewnętrzna (ang. *intrinsic*) polega na ewaluacji modelu języka jako takiego.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### Podział zbioru\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Po pierwsze, jak zazwyczaj bywa w uczeniu maszynowym, powinniśmy\npodzielić nasz zbiór danych. W modelowaniu języka zbiorem danych jest\nzbiór tekstów w danym języku, czyli korpus języka.\nPowinniśmy podzielić nasz korpus na część uczącą (*training set*) $C = \\{w_1\\ldots w_N\\}$ i testową\n(*test set*) $C' = \\{w_1'\\ldots w_{N'}'\\}$.\n\nWarto też wydzielić osobny „deweloperski” zbiór testowy (*dev set*) —\ndo testowania na bieżąco, optymalizacji hiperparametrów itd. Zbiory\ntestowe nie muszą być bardzo duże, np. kilka tysięcy zdań może w zupełności wystarczyć.\n\nTak podzielony korpus możemy traktować jako **wyzwanie modelowania języka**.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Przykład wyzwania modelowania języka\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Wyzwanie\n[https://gonito.net/challenge/challenging-america-word-gap-prediction|Challenging America word-gap prediction](https://gonito.net/challenge/challenging-america-word-gap-prediction|Challenging America word-gap prediction)\nto wyzwanie modelowania amerykańskiej odmiany języka angielskiego, używanej w gazetach w XIX w. i I poł. XX w.\n\n $ git clone git://gonito.net/challenging-america-word-gap-prediction\n $ cd challenging-america-word-gap-prediction\n $ xzcat train/in.tsv.xz | wc\n 432022 123677147 836787912\n $ xzcat dev-0/in.tsv.xz | wc\n 10519 3076536 20650825\n $ xzcat test-A/in.tsv.xz | wc\n 7414 2105734 14268877\n\nDodajmy, że poszczególne zbiory zawierają teksty z różnych gazet. Jest\nto właściwe podejście, jeśli chcemy mierzyć rzeczywistą skuteczność modeli języka.\n(Teksty z jednej gazety mogłyby być zbyt proste).\n\nOto przykład tekstu z wyzwania:\n\n $ xzcat train/in.tsv.xz | head -n 1 | fold\n 4e04702da929c78c52baf09c1851d3ff\tST\tChronAm\t1919.6041095573314\n 30.47547\t-90.100911\tcame fiom the last place to this\\nplace, and thi\n s place is Where We\\nWere, this is the first road I ever\\nwas on where you can r\n ide elsewhere\\nfrom anywhere and be nowhere.\\nHe says, while this train stops ev\n ery-\\nwhere, it never stops anywhere un-\\nless its somewhere. Well, I says,\\nI'm\n glad to hear that, but, accord-\\ning to your figures, I left myself\\nwhere 1 wa\n s, which is five miles near-\\ner to myself than I was when we\\nwere where we are\n now.\\nWe have now reached Slidell.\\nThat's a fine place. The people\\ndown there\n remind me of bananas-\\nthey come and go in bunches. 811-\\ndell used to be noted\n for her tough\\npeople. Now she is noted for be,\\ntough steaks. Well, I certainl\n y got\\none there. When the waiter brought\\nit in it was so small I thought. It\\n\n was a crack in the plate. I skid,\\nwaiter what else have you got? +He\\nbrought m\n e in two codfish and one\\nsmelt. I said, waiter have you got\\npigs feet? He said\n no, rheumatism\\nmakes me walk that way. I sald,\\nhow is the pumpkin pie?\n said\\nit's all squash. The best I could get\\nin that hotel was a soup sandwich.\\\n nAfter the table battle the waiter and\\nI signed an armistice. I then went\\nover\n to the hotel clerk and asked for\\na room. He said with or without a\\nbed? I sai\n d, with a bed. He said,\\nI don't think I 'have' a bed long\\nenough for you. I sa\n id, well, I'll\\naddtwo feettoitwhenIgetinit.\\nHe gave me a lovely room on the\\nt\n op floor. It was one of those rooms\\nthat stands on each side. If you\\nhappen to\n get up in the middle of\\nthe night you want to be sure and\\nget up in the middl\n e of the room.\\nThat night I dreamt I was eating\\nflannel cakes. When I woke up\n half\\nof the blanket was gone. I must\\nhave got up on the wrong side of the\\nbed\n , for next morning I had an awful\\nheadache. I told the manager about\\nit. He sa\n id, you have rheumatic\\npains. I said, no, I think it is on,\\nof those attic roo\n m pains. I nad to\\ngetupat5a.m.inthemorningso\\nthey could use the sheet to set t\n he\\nbreakfast table.\n\nZauważmy, że mamy nie tylko tekst, lecz również metadane (czas i\nwspółrzędne geograficzne). W modelowaniu języka można uwzględnić\nrównież takie dodatkowe parametry (np. prawdopodobieństwa wystąpienia\nsłowa *koronawirus* wzrasta po roku 2019).\n\nZauważmy również, że tekst zawiera błędy OCR-owe (np. *nad* zamiast\n*had*). Czy w takim razie jest to sensowne wyzwanie modelowania\njęzyka? Tak, w niektórych przypadkach możemy chcieć modelować tekst z\nuwzględnieniem „zaszumień” wprowadzanych przez ludzi bądź komputery\n(czy II prawo termodynamiki!).\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### Co podlega ocenie?\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Ogólnie ocenie powinno podlegać prawdopodobieństwo $P_M(C')$, czyli\nprawdopodobieństwo przypisane zbiorowi testowemu $C'$ przez model\n(wyuczony na zbiorze $C$).\n\nJeśli oceniamy przewidywania, które człowiek lub komputer czynią, to\nim większe prawdopodobieństwo przypisane do tego, co miało miejsce,\ntym lepiej. Zatem im wyższe $P_M(C')$, tym lepiej.\n\nZazwyczaj będziemy rozbijali $P_M(C')$ na prawdopodobieństwa\nprzypisane do poszczególnych słów:\n\n$$P_M(w_1'\\dots w_{N'}') = P_M(w'_1)P_M(w'_2|w'_1)\\dots P_M(w'_{N'}|w'_1\\dots w'_{N'-1}) = \\prod_{i=1}^{N'} P_M(w'_i|w'_1\\ldots w'_{i-1}).$$\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### Entropia krzyżowa\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Można powiedzieć, że dobry model języka „wnosi” informację o języku. Jeśli zarówno\nnadawca i odbiorca tekstu mają do dyspozycji ten sam model języka…\n\n![img](./06_Ewaluacja/lm-communication.drawio.png)\n\n… powinni być w stanie zaoszczędzić na długości komunikatu.\n\nW skrajnym przypadku, jeśli model jest pewny kolejnego słowa, tj.\n$P_M(w'_i|w'_1\\ldots w'_{i-1}) = 1$, wówczas w $i$-tym kroku w ogóle\nnic nie trzeba przesyłać przez kanał komunikacji. Taka sytuacja może\nrealnie wystąpić, na przykład: z prawdopodobieństwem zbliżonym do 1 po wyrazie\n*Hong* wystąpi słowo *Kong*, a po wyrazie *przede* — wyraz *wszystkim*.\n\nModel języka może pomóc również w mniej skrajnym przypadkach, np.\njeżeli na danej pozycji w tekście model redukuje cały słownik do dwóch\nwyrazów z prawdopodobieństwem 1/2, wówczas nadawca może zakodować tę\npozycję za pomocą jednego bitu.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Wzór na entropię krzyżową\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Przypomnijmy, że symbol o prawdopodobieństwie $p$ można zakodować za\npomocą (średnio) $-\\log_2(p)$ bitów, tak więc jeśli nadawca i odbiorca dysponują\nmodelem $M$, wówczas można przesłać cały zbiór testowy $C$ za pomocą następującej liczby bitów:\n\n$$-\\sum_{i=1}^{N'} log P_M(w'_i|w'_1\\ldots w'_{i-1}).$$\n\nAby móc porównywać wyniki dla korpusów dla różnej długości, warto znormalizować\ntę wartość, tzn. podzielić przez długość tekstu:\n\n$$H(M) = -\\frac{\\sum_{i=1}^{N'} log P_M(w'_i|w'_1\\ldots w'_{i-1})}{N'}.$$\n\nTę wartość nazywamy **entropią krzyżową** modelu $M$. Entropia krzyżowa\nmierzy naszą niewiedzę przy założeniu, że dysponujemy modelem $M$. Im niższa wartość\nentropii krzyżowej, tym lepiej, im bowiem mniejsza nasza niewiedza,\ntym lepiej.\n\nEntropią krzyżową jest często nazywaną funkcją **log loss**, zwłaszcza w\nkontekście jej użycia jako funkcji straty przy uczeniu neuronowych modeli języka\n(o których dowiemy się później).\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### Wiarygodność\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Innym sposobem mierzenia jakości modelu języka jest odwołanie się do\n**wiarygodności** (ang. *likelihood*). Wiarygodność to\nprawdopodobieństwo przypisane zdarzeniom niejako „po fakcie”. Jak już\nwspomnieliśmy, im wyższe prawdopodobieństwo (wiarygodność) przypisane\ntestowej części korpusu, tym lepiej. Innymi słowy, jako metrykę ewaluacji\nużywać będziemy prawdopodobieństwa:\n\n$$P_M(w_1'\\dots w_{N'}') = P_M(w'_1)P_M(w'_2|w'_1)\\dots P_M(w'_{N'}|w'_1\\dots w'_{N'-1}) = \\prod_{i=1}^{N'} P_M(w'_i|w'_1\\ldots w'_{i-1}),$$\n\nz tym, że znowu warto znormalizować to prawdopodobieństwo względem rozmiaru korpusu.\nZe względu na to, że prawdopodobieństwa przemnażamy, zamiast średniej arytmetycznej\nlepiej użyć **średniej geometrycznej**:\n\n$$\\sqrt[N']{P_M(w_1'\\dots w_{N'}')} = \\sqrt[N']{\\prod_{i=1}^{N'} P_M(w'_i|w'_1\\ldots w'_{i-1})}.$$\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Interpretacja wiarygodności\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Co ciekawe, wiarygodność jest używana jako metryka ewaluacji modeli\njęzyka rzadziej niż entropia krzyżowa (log loss), mimo tego, że wydaje\nsię nieco łatwiejsza do interpretacji dla człowieka. Otóż wiarygodność\nto **średnia geometryczna prawdopodobieństw przypisanych przez model języka do słów, które rzeczywiście wystąpiły**.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Związek między wiarygodnością a entropią krzyżową\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Istnieje bardzo prosty związek między entropią krzyżową a wiarygodnością.\nOtóż entropia krzyżowa to po prostu logarytm wiarygodności (z minusem):\n\n-$$\\log_2\\sqrt[N']{P_M(w_1'\\dots w_N')} = -\\frac{\\log_2\\prod_{i=1}^{N'} P_M(w'_i|w'_1\\ldots w'_{i-1})}{N'} = -\\frac{\\sum_{i=1}^{N'} \\log_2 P_M(w'_i|w'_1\\ldots w'_{i-1})}{N'}.$$\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### „log-proby”\n\n"]},{"cell_type":"markdown","metadata":{},"source":["W modelowaniu języka bardzo często używa się logarytmów prawdopodobieństw (z angielskiego skrótowo *log probs*),\nzamiast wprost operować na prawdopodobieństwach:\n\n- dodawanie log probów jest tańsze obliczeniowo niż mnożenie prawdopodobieństw,\n- bardzo małe prawdopodobieństwa znajdują się na granicy dokładności reprezentacji\n liczb zmiennopozycyjnych, log proby są liczbami ujemnymi o „poręczniejszych”\n rzędach wielkości.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### Perplexity\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Tak naprawdę w literaturze przedmiotu na ogół używa się jeszcze innej metryki ewaluacji —\n**perplexity**. Perplexity jest definiowane jako:\n\n$$\\operatorname{PP}(M) = 2^{H(M)}.$$\n\nIntuicyjnie można sobie wyobrazić, że perplexity to liczba możliwości\nprognozowanych przez model z równym prawdopodobieństwem. Na przykład,\njeśli model przewiduje, że w danym miejscu tekstu może wystąpić z\nrównym prawdopodobieństwem jedno z 32 słów, wówczas (jeśli\nrzeczywiście któreś z tych słów wystąpiło) entropia wynosi 5 bitów, a\nperplexity — 32.\n\nInaczej: perplexity to po prostu odwrotność wiarygodności:\n\n$$\\operatorname{PP}(M) = \\sqrt[N']{P_M(w_1'\\dots w_N')}.$$\n\nPerplexity zależy oczywiście od języka i modelu, ale typowe wartości\nzazwyczaj zawierają się w przedziale 20-400.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Perplexity — przykład\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Wyuczmy model języka przy użyciu gotowego narzędzia [https://github.com/kpu/kenlm|KenLM](https://github.com/kpu/kenlm|KenLM).\nKenLM to zaawansowane narzędzie do tworzenia n-gramowych modeli języka\n(zaimplementowano w nim techniki wygładzania, które omówimy na kolejnym wykładzie).\n\nWyuczmy na zbiorze uczącym wspomnianego wyzwania *Challenging America word-gap prediction*\ndwa modele, jeden 3-gramowy, drugi 4-gramowy.\n\nZ powodu, który za chwilę stanie się jasny, teksty w zbiorze uczącym musimy sobie „poskładać” z kilku „kawałków”.\n\n $ cd train\n $ xzcat in.tsv.xz | paste expected.tsv - | perl -ne 'chomp;s/\\\\n/ /g;s// /g;@f=split/\\t/;print \"$f[7] $f[0] $f[8]\\n\"' | lmplz -o 3 --skip-symbols > model3.arpa\n $ xzcat in.tsv.xz | paste expected.tsv - | perl -ne 'chomp;s/\\\\n/ /g;s// /g;@f=split/\\t/;print \"$f[7] $f[0] $f[8]\\n\"' | lmplz -o 4 --skip-symbols > model4.arpa\n $ cd ../dev-0\n $ xzcat in.tsv.xz | paste expected.tsv - | perl -ne 'chomp;s/\\\\n/ /g;s// /g;@f=split/\\t/;print \"$f[7] $f[0] $f[8]\\n\"' | query ../train/model3.arpa\n Perplexity including OOVs:\t976.9905056314793\n Perplexity excluding OOVs:\t616.5864921901557\n OOVs:\t125276\n Tokens:\t3452929\n $ xzcat in.tsv.xz | paste expected.tsv - | perl -ne 'chomp;s/\\\\n/ /g;s// /g;@f=split/\\t/;print \"$f[7] $f[0] $f[8]\\n\"' | query ../train/model4.arpa\n Perplexity including OOVs:\t888.698932611321\n Perplexity excluding OOVs:\t559.1231510292068\n OOVs:\t125276\n Tokens:\t3452929\n\nJak widać model 4-gramowy jest lepszy (ma niższe perplexity) niż model 3-gramowy, przynajmniej\njeśli wierzyć raportowi programu KenLM.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### Entropia krzyżowa, wiarygodność i perplexity — podsumowanie\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Trzy omawiane metryki ewaluacji modeli języka (entropia krzyżowa,\nwiarygodność i perplexity) są ze sobą ściśle związane, w gruncie\nrzeczy to po prostu jedna miara.\n\n| Metryka|Kierunek|Najlepsza wartość|Najgorsza wartość|\n|---|---|---|---|\n| entropia krzyżowa|im mniej, tym lepiej|0|$\\infty$|\n| wiarygodność|im więcej, tym lepiej|1|0|\n| perplexity|im mniej, tym lepiej|1|$\\infty$|\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Uwaga na zerowe prawdopodobieństwa\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Entropia krzyżowa, wiarygodność czy perplexity są bardzo czułe na zbyt\ndużą pewność siebie. Wystarczy, że dla **jednej** pozycji w zbiorze\nprzypiszemy zerowe prawdopodobieństwo, wówczas wszystko „eksploduje”.\nPerplexity i entropia krzyżowa „wybuchają” do nieskończoności,\nwiarygodność spada do zera — bez względu na to, jak dobre są\nprzewidywania dotyczące innych pozycji w tekście!\n\nW przypadku wiarygodności wiąże się to z tym, że wiarygodność\ndefiniujemy jako iloczyn prawdopodobieństwa, oczywiście wystarczy, że\njedna liczba w iloczynie była zerem, żeby iloczyn przyjął wartość\nzero. Co więcej, nawet jeśli pominiemy taki skrajny przypadek, to\nśrednia geometryczna „ciągnie” w dół, bardzo niska wartość\nprawdopodobieństwa przypisana do rzeczywistego słowa może drastycznie obniżyć\nwartość wiarygodności (i podwyższyć perplexity).\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Słowa spoza słownika\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Prostym sposobem przeciwdziałania zerowaniu/wybuchaniu metryk jest\nprzypisywanie każdemu możliwemu słowu przynajmniej niskiego\nprawdopodobieństwa $\\epsilon$. Niestety, zawsze może pojawić się\nsłowa, którego nie było w zbiorze uczącym — **słowo spoza słownika**\n(*out-of-vocabulary word*, *OOV*). W takim przypadku znowu może\npojawić się zerowy/nieskończony wynik.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### Ewaluacja modeli języka w warunkach konkursu\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Jeśli używać tradycyjnych metryk ewaluacji modeli języka (perplexity\nczy wiarygodność), bardzo łatwo można „oszukać” — wystarczy\nzaraportować prawdopodobieństwo 1! Oczywiście to absurd, bo albo\nwszystkim innym tekstom przypisujemy prawdopodobieństwo 0, albo —\njeśli „oszukańczy” system każdemu innemu tekstowi przypisze\nprawdopodobieństwo 1 — nie mamy do czynienia z poprawnym rozkładem\nprawdopodobieństwa.\n\nCo gorsza, nawet jeśli wykluczymy scenariusz świadomego oszustwa,\nłatwo *samego siebie* wprowadzić w błąd. Na przykład przez pomyłkę\nmożna zwracać zawyżone prawdopodobieństwo (powiedzmy przemnożone przez 2).\n\nTe problemy stają się szczególnie dokuczliwe, jeśli organizujemy\nwyzwanie, *konkurs* modelowania języka, gdzie chcemy w sposób\nobiektywny porównywać różne modele języka, tak aby uniknąć celowego\nbądź nieświadomego zawyżania wyników.\n\nPrzedstawimy teraz, w jaki sposób poradzono sobie z tym problemem\nw wyzwaniu *Challenging America word-gap prediction*\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Odgadywanie słowa w luce\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Po pierwsze, jaka sama nazwa wskazuje, w wyzwaniu *Challenging America\nword-gap prediction* zamiast zwracania prawdopodobieństwa dla całego\ntekstu oczekuje się podania rozkładu prawdopodobieństwa dla brakującego słowa.\n\nMianowicie, w każdym wierszu wejściu (plik `in.tsv.xz`) w 7. i 8. polu\npodany jest, odpowiednio, lewy i prawy kontekst słowa do odgadnięcia.\n(W pozostałych polach znajdują się metadane, o których już wspomnieliśmy,\nna razie nie będziemy ich wykorzystywać).\nW pliku z oczekiwanym wyjściem (`expected.tsv`), w odpowiadającym\nwierszu, podawane jest brakujące słowo. Oczywiście w ostatecznym\nteście `test-A` plik `expected.tsv` jest niedostępny, ukryty przed uczestnikami konkursu.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Zapis rozkładu prawdopodobieństwa\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Dla każdego wiersza wejścia podajemy rozkład prawdopodobieństwa dla\nsłowa w luce w formacie:\n\n wyraz1:prob1 wyraz2:prob2 ... wyrazN:probN :prob0\n\ngdzie wyraz1, …, wyrazN to konkretne wyrazy, prob1, …, probN ich prawdopodobieństwa.\nMożna podać dowolną liczbę wyrazów.\nZ kolei prob0 to „resztowe” prawdopodobieństwo przypisane do wszystkich pozostałych wyrazów,\nprawdopodobieństwo to pozwala uniknąć problemów związanych ze słowami OOV, trzeba jeszcze tylko dokonać\nmodyfikacji metryki\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Metryka LikelihoodHashed\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Metryka LikelihoodHashed jest wariantem metryki Likelihood\n(wiarygodności) opracowanym z myślą o wyzwaniach czy konkursach\nmodelowania języka. W tej metryce każde słowo wpada pseudolosowo do\njednego z $2^{10}=1024$ „kubełków”. Numer kubełka jest wyznaczony na\npodstawie funkcji haszującej MurmurHash.\n\nPrawdopodobieństwa zwrócone przez ewaluowany model są sumowane w\nkażdym kubełku, następnie ewaluator zagląda do pliku \\`expected.tsv\\` i\nuwzględnia prawdopodobieństwo z kubełka, do którego „wpada” oczekiwane\nsłowo. Oczywiście czasami więcej niż jedno słowo może wpaść do\nkubełka, model mógł też „wrzucić” do kubełka tak naprawdę inne słowo\nniż oczekiwane (przypadkiem oba słowa wpadają do jednego kubełka).\nTak więc LikelihoodHashed będzie nieco zawyżone w stosunku do Likelihood.\n\nDlaczego więc taka komplikacja? Otóż LikelihoodHashed nie zakłada\nżadnego słownika, znika problem słów OOV — prawdopodobieństwa resztowe prob0\nsą rozkładane równomiernie między wszystkie 1024 kubełki.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Alternatywne metryki\n\n"]},{"cell_type":"markdown","metadata":{},"source":["LikelihoodHashed została zaimplementowana w narzędziu ewaluacyjnym\n[https://gitlab.com/filipg/geval|GEval](https://gitlab.com/filipg/geval|GEval). Są tam również dostępne\nanalogiczne warianty entropii krzyżowej (log loss) i perplexity\n(LogLossHashed i PerplexityHashed).\n\n"]}],"metadata":{"org":null,"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.5.2"}},"nbformat":4,"nbformat_minor":0} \ No newline at end of file diff --git a/wyk/06_Ewaluacja.org b/wyk/06_Ewaluacja.org new file mode 100644 index 0000000..651ca18 --- /dev/null +++ b/wyk/06_Ewaluacja.org @@ -0,0 +1,363 @@ +* Ewaluacja modeli języka + +Jak już widzimy, możemy mieć różne modele języka. Nawet jeśli +pozostajemy tylko na gruncie najprostszych, $n$-gramowych modeli +języka, inne prawdopodobieństwa uzyskamy dla modelu digramowego, a +inny dla trigramowego. Jedne modele będą lepsze, inne — gorsze. Jak +obiektywnie odróżnić dobry model od złego? Innymi słowy, jak ewaluować +modele języka? + +** Ewaluacja zewnętrzna i wewnętrzna + +W ewaluacji zewnętrznej (ang. /extrinsic/) ewaluację modelu języka sprowadzamy +do ewaluacji większego systemu, którego częścią jest model języka, na przykład +systemu tłumaczenia maszynowego albo systemu ASR. + +Ewaluacja wewnętrzna (ang. /intrinsic/) polega na ewaluacji modelu języka jako takiego. + +** Podział zbioru + +Po pierwsze, jak zazwyczaj bywa w uczeniu maszynowym, powinniśmy +podzielić nasz zbiór danych. W modelowaniu języka zbiorem danych jest +zbiór tekstów w danym języku, czyli korpus języka. +Powinniśmy podzielić nasz korpus na część uczącą (/training set/) $C = \{w_1\ldots w_N\}$ i testową +(/test set/) $C' = \{w_1'\ldots w_{N'}'\}$. + +Warto też wydzielić osobny „deweloperski” zbiór testowy (/dev set/) — +do testowania na bieżąco, optymalizacji hiperparametrów itd. Zbiory +testowe nie muszą być bardzo duże, np. kilka tysięcy zdań może w zupełności wystarczyć. + +Tak podzielony korpus możemy traktować jako *wyzwanie modelowania języka*. + +*** Przykład wyzwania modelowania języka + +Wyzwanie +[[https://gonito.net/challenge/challenging-america-word-gap-prediction|Challenging America word-gap prediction]] +to wyzwanie modelowania amerykańskiej odmiany języka angielskiego, używanej w gazetach w XIX w. i I poł. XX w. + +#+BEGIN_SRC +$ git clone git://gonito.net/challenging-america-word-gap-prediction +$ cd challenging-america-word-gap-prediction +$ xzcat train/in.tsv.xz | wc +432022 123677147 836787912 +$ xzcat dev-0/in.tsv.xz | wc +10519 3076536 20650825 +$ xzcat test-A/in.tsv.xz | wc +7414 2105734 14268877 +#+END_SRC + +Dodajmy, że poszczególne zbiory zawierają teksty z różnych gazet. Jest +to właściwe podejście, jeśli chcemy mierzyć rzeczywistą skuteczność modeli języka. +(Teksty z jednej gazety mogłyby być zbyt proste). + +Oto przykład tekstu z wyzwania: + +#+BEGIN_SRC +$ xzcat train/in.tsv.xz | head -n 1 | fold +4e04702da929c78c52baf09c1851d3ff ST ChronAm 1919.6041095573314 +30.47547 -90.100911 came fiom the last place to this\nplace, and thi +s place is Where We\nWere, this is the first road I ever\nwas on where you can r +ide elsewhere\nfrom anywhere and be nowhere.\nHe says, while this train stops ev +ery-\nwhere, it never stops anywhere un-\nless its somewhere. Well, I says,\nI'm + glad to hear that, but, accord-\ning to your figures, I left myself\nwhere 1 wa +s, which is five miles near-\ner to myself than I was when we\nwere where we are + now.\nWe have now reached Slidell.\nThat's a fine place. The people\ndown there + remind me of bananas-\nthey come and go in bunches. 811-\ndell used to be noted + for her tough\npeople. Now she is noted for be,\ntough steaks. Well, I certainl +y got\none there. When the waiter brought\nit in it was so small I thought. It\n +was a crack in the plate. I skid,\nwaiter what else have you got? +He\nbrought m +e in two codfish and one\nsmelt. I said, waiter have you got\npigs feet? He said + no, rheumatism\nmakes me walk that way. I sald,\nhow is the pumpkin pie? +said\nit's all squash. The best I could get\nin that hotel was a soup sandwich.\ +nAfter the table battle the waiter and\nI signed an armistice. I then went\nover + to the hotel clerk and asked for\na room. He said with or without a\nbed? I sai +d, with a bed. He said,\nI don't think I 'have' a bed long\nenough for you. I sa +id, well, I'll\naddtwo feettoitwhenIgetinit.\nHe gave me a lovely room on the\nt +op floor. It was one of those rooms\nthat stands on each side. If you\nhappen to + get up in the middle of\nthe night you want to be sure and\nget up in the middl +e of the room.\nThat night I dreamt I was eating\nflannel cakes. When I woke up +half\nof the blanket was gone. I must\nhave got up on the wrong side of the\nbed +, for next morning I had an awful\nheadache. I told the manager about\nit. He sa +id, you have rheumatic\npains. I said, no, I think it is on,\nof those attic roo +m pains. I nad to\ngetupat5a.m.inthemorningso\nthey could use the sheet to set t +he\nbreakfast table. +#+END_SRC + +Zauważmy, że mamy nie tylko tekst, lecz również metadane (czas i +współrzędne geograficzne). W modelowaniu języka można uwzględnić +również takie dodatkowe parametry (np. prawdopodobieństwa wystąpienia +słowa /koronawirus/ wzrasta po roku 2019). + +Zauważmy również, że tekst zawiera błędy OCR-owe (np. /nad/ zamiast +/had/). Czy w takim razie jest to sensowne wyzwanie modelowania +języka? Tak, w niektórych przypadkach możemy chcieć modelować tekst z +uwzględnieniem „zaszumień” wprowadzanych przez ludzi bądź komputery +(czy II prawo termodynamiki!). + +** Co podlega ocenie? + +Ogólnie ocenie powinno podlegać prawdopodobieństwo $P_M(C')$, czyli +prawdopodobieństwo przypisane zbiorowi testowemu $C'$ przez model +(wyuczony na zbiorze $C$). + +Jeśli oceniamy przewidywania, które człowiek lub komputer czynią, to +im większe prawdopodobieństwo przypisane do tego, co miało miejsce, +tym lepiej. Zatem im wyższe $P_M(C')$, tym lepiej. + +Zazwyczaj będziemy rozbijali $P_M(C')$ na prawdopodobieństwa +przypisane do poszczególnych słów: + +$$P_M(w_1'\dots w_{N'}') = P_M(w'_1)P_M(w'_2|w'_1)\dots P_M(w'_{N'}|w'_1\dots w'_{N'-1}) = \prod_{i=1}^{N'} P_M(w'_i|w'_1\ldots w'_{i-1}).$$ + +** Entropia krzyżowa + +Można powiedzieć, że dobry model języka „wnosi” informację o języku. Jeśli zarówno +nadawca i odbiorca tekstu mają do dyspozycji ten sam model języka… + +[[./06_Ewaluacja/lm-communication.drawio.png]] + +… powinni być w stanie zaoszczędzić na długości komunikatu. + +W skrajnym przypadku, jeśli model jest pewny kolejnego słowa, tj. +$P_M(w'_i|w'_1\ldots w'_{i-1}) = 1$, wówczas w $i$-tym kroku w ogóle +nic nie trzeba przesyłać przez kanał komunikacji. Taka sytuacja może +realnie wystąpić, na przykład: z prawdopodobieństwem zbliżonym do 1 po wyrazie +/Hong/ wystąpi słowo /Kong/, a po wyrazie /przede/ — wyraz /wszystkim/. + +Model języka może pomóc również w mniej skrajnym przypadkach, np. +jeżeli na danej pozycji w tekście model redukuje cały słownik do dwóch +wyrazów z prawdopodobieństwem 1/2, wówczas nadawca może zakodować tę +pozycję za pomocą jednego bitu. + +*** Wzór na entropię krzyżową + +Przypomnijmy, że symbol o prawdopodobieństwie $p$ można zakodować za +pomocą (średnio) $-\log_2(p)$ bitów, tak więc jeśli nadawca i odbiorca dysponują +modelem $M$, wówczas można przesłać cały zbiór testowy $C$ za pomocą następującej liczby bitów: + +$$-\sum_{i=1}^{N'} log P_M(w'_i|w'_1\ldots w'_{i-1}).$$ + +Aby móc porównywać wyniki dla korpusów dla różnej długości, warto znormalizować +tę wartość, tzn. podzielić przez długość tekstu: + +$$H(M) = -\frac{\sum_{i=1}^{N'} log P_M(w'_i|w'_1\ldots w'_{i-1})}{N'}.$$ + +Tę wartość nazywamy *entropią krzyżową* modelu $M$. Entropia krzyżowa +mierzy naszą niewiedzę przy założeniu, że dysponujemy modelem $M$. Im niższa wartość +entropii krzyżowej, tym lepiej, im bowiem mniejsza nasza niewiedza, +tym lepiej. + +Entropią krzyżową jest często nazywaną funkcją *log loss*, zwłaszcza w +kontekście jej użycia jako funkcji straty przy uczeniu neuronowych modeli języka +(o których dowiemy się później). + +** Wiarygodność + +Innym sposobem mierzenia jakości modelu języka jest odwołanie się do +*wiarygodności* (ang. /likelihood/). Wiarygodność to +prawdopodobieństwo przypisane zdarzeniom niejako „po fakcie”. Jak już +wspomnieliśmy, im wyższe prawdopodobieństwo (wiarygodność) przypisane +testowej części korpusu, tym lepiej. Innymi słowy, jako metrykę ewaluacji +używać będziemy prawdopodobieństwa: + +$$P_M(w_1'\dots w_{N'}') = P_M(w'_1)P_M(w'_2|w'_1)\dots P_M(w'_{N'}|w'_1\dots w'_{N'-1}) = \prod_{i=1}^{N'} P_M(w'_i|w'_1\ldots w'_{i-1}),$$ + +z tym, że znowu warto znormalizować to prawdopodobieństwo względem rozmiaru korpusu. +Ze względu na to, że prawdopodobieństwa przemnażamy, zamiast średniej arytmetycznej +lepiej użyć *średniej geometrycznej*: + +$$\sqrt[N']{P_M(w_1'\dots w_{N'}')} = \sqrt[N']{\prod_{i=1}^{N'} P_M(w'_i|w'_1\ldots w'_{i-1})}.$$ + +*** Interpretacja wiarygodności + +Co ciekawe, wiarygodność jest używana jako metryka ewaluacji modeli +języka rzadziej niż entropia krzyżowa (log loss), mimo tego, że wydaje +się nieco łatwiejsza do interpretacji dla człowieka. Otóż wiarygodność +to *średnia geometryczna prawdopodobieństw przypisanych przez model języka do słów, które rzeczywiście wystąpiły*. + +*** Związek między wiarygodnością a entropią krzyżową + +Istnieje bardzo prosty związek między entropią krzyżową a wiarygodnością. +Otóż entropia krzyżowa to po prostu logarytm wiarygodności (z minusem): + +-$$\log_2\sqrt[N']{P_M(w_1'\dots w_N')} = -\frac{\log_2\prod_{i=1}^{N'} P_M(w'_i|w'_1\ldots w'_{i-1})}{N'} = -\frac{\sum_{i=1}^{N'} \log_2 P_M(w'_i|w'_1\ldots w'_{i-1})}{N'}.$$ + +*** „log-proby” + +W modelowaniu języka bardzo często używa się logarytmów prawdopodobieństw (z angielskiego skrótowo /log probs/), +zamiast wprost operować na prawdopodobieństwach: + +- dodawanie log probów jest tańsze obliczeniowo niż mnożenie prawdopodobieństw, +- bardzo małe prawdopodobieństwa znajdują się na granicy dokładności reprezentacji + liczb zmiennopozycyjnych, log proby są liczbami ujemnymi o „poręczniejszych” + rzędach wielkości. + +** Perplexity + +Tak naprawdę w literaturze przedmiotu na ogół używa się jeszcze innej metryki ewaluacji — +*perplexity*. Perplexity jest definiowane jako: + +$$\operatorname{PP}(M) = 2^{H(M)}.$$ + +Intuicyjnie można sobie wyobrazić, że perplexity to liczba możliwości +prognozowanych przez model z równym prawdopodobieństwem. Na przykład, +jeśli model przewiduje, że w danym miejscu tekstu może wystąpić z +równym prawdopodobieństwem jedno z 32 słów, wówczas (jeśli +rzeczywiście któreś z tych słów wystąpiło) entropia wynosi 5 bitów, a +perplexity — 32. + +Inaczej: perplexity to po prostu odwrotność wiarygodności: + +$$\operatorname{PP}(M) = \sqrt[N']{P_M(w_1'\dots w_N')}.$$ + +Perplexity zależy oczywiście od języka i modelu, ale typowe wartości +zazwyczaj zawierają się w przedziale 20-400. + +*** Perplexity — przykład + +Wyuczmy model języka przy użyciu gotowego narzędzia [[https://github.com/kpu/kenlm|KenLM]]. +KenLM to zaawansowane narzędzie do tworzenia n-gramowych modeli języka +(zaimplementowano w nim techniki wygładzania, które omówimy na kolejnym wykładzie). + +Wyuczmy na zbiorze uczącym wspomnianego wyzwania /Challenging America word-gap prediction/ +dwa modele, jeden 3-gramowy, drugi 4-gramowy. + +Z powodu, który za chwilę stanie się jasny, teksty w zbiorze uczącym musimy sobie „poskładać” z kilku „kawałków”. + +#+BEGIN_SRC +$ cd train +$ xzcat in.tsv.xz | paste expected.tsv - | perl -ne 'chomp;s/\\n/ /g;s// /g;@f=split/\t/;print "$f[7] $f[0] $f[8]\n"' | lmplz -o 3 --skip-symbols > model3.arpa +$ xzcat in.tsv.xz | paste expected.tsv - | perl -ne 'chomp;s/\\n/ /g;s// /g;@f=split/\t/;print "$f[7] $f[0] $f[8]\n"' | lmplz -o 4 --skip-symbols > model4.arpa +$ cd ../dev-0 +$ xzcat in.tsv.xz | paste expected.tsv - | perl -ne 'chomp;s/\\n/ /g;s// /g;@f=split/\t/;print "$f[7] $f[0] $f[8]\n"' | query ../train/model3.arpa +Perplexity including OOVs: 976.9905056314793 +Perplexity excluding OOVs: 616.5864921901557 +OOVs: 125276 +Tokens: 3452929 +$ xzcat in.tsv.xz | paste expected.tsv - | perl -ne 'chomp;s/\\n/ /g;s// /g;@f=split/\t/;print "$f[7] $f[0] $f[8]\n"' | query ../train/model4.arpa +Perplexity including OOVs: 888.698932611321 +Perplexity excluding OOVs: 559.1231510292068 +OOVs: 125276 +Tokens: 3452929 +#+END_SRC + +Jak widać model 4-gramowy jest lepszy (ma niższe perplexity) niż model 3-gramowy, przynajmniej +jeśli wierzyć raportowi programu KenLM. + +** Entropia krzyżowa, wiarygodność i perplexity — podsumowanie + +Trzy omawiane metryki ewaluacji modeli języka (entropia krzyżowa, +wiarygodność i perplexity) są ze sobą ściśle związane, w gruncie +rzeczy to po prostu jedna miara. + +|Metryka | Kierunek |Najlepsza wartość | Najgorsza wartość | +|------------------+----------------------+------------------+-------------------| +|entropia krzyżowa | im mniej, tym lepiej | 0 | $\infty$ | +|wiarygodność | im więcej, tym lepiej| 1 | 0 | +|perplexity | im mniej, tym lepiej | 1 | $\infty$ | + +*** Uwaga na zerowe prawdopodobieństwa + +Entropia krzyżowa, wiarygodność czy perplexity są bardzo czułe na zbyt +dużą pewność siebie. Wystarczy, że dla *jednej* pozycji w zbiorze +przypiszemy zerowe prawdopodobieństwo, wówczas wszystko „eksploduje”. +Perplexity i entropia krzyżowa „wybuchają” do nieskończoności, +wiarygodność spada do zera — bez względu na to, jak dobre są +przewidywania dotyczące innych pozycji w tekście! + +W przypadku wiarygodności wiąże się to z tym, że wiarygodność +definiujemy jako iloczyn prawdopodobieństwa, oczywiście wystarczy, że +jedna liczba w iloczynie była zerem, żeby iloczyn przyjął wartość +zero. Co więcej, nawet jeśli pominiemy taki skrajny przypadek, to +średnia geometryczna „ciągnie” w dół, bardzo niska wartość +prawdopodobieństwa przypisana do rzeczywistego słowa może drastycznie obniżyć +wartość wiarygodności (i podwyższyć perplexity). + + +*** Słowa spoza słownika + +Prostym sposobem przeciwdziałania zerowaniu/wybuchaniu metryk jest +przypisywanie każdemu możliwemu słowu przynajmniej niskiego +prawdopodobieństwa $\epsilon$. Niestety, zawsze może pojawić się +słowa, którego nie było w zbiorze uczącym — *słowo spoza słownika* +(/out-of-vocabulary word/, /OOV/). W takim przypadku znowu może +pojawić się zerowy/nieskończony wynik. + + +** Ewaluacja modeli języka w warunkach konkursu + +Jeśli używać tradycyjnych metryk ewaluacji modeli języka (perplexity +czy wiarygodność), bardzo łatwo można „oszukać” — wystarczy +zaraportować prawdopodobieństwo 1! Oczywiście to absurd, bo albo +wszystkim innym tekstom przypisujemy prawdopodobieństwo 0, albo — +jeśli „oszukańczy” system każdemu innemu tekstowi przypisze +prawdopodobieństwo 1 — nie mamy do czynienia z poprawnym rozkładem +prawdopodobieństwa. + +Co gorsza, nawet jeśli wykluczymy scenariusz świadomego oszustwa, +łatwo /samego siebie/ wprowadzić w błąd. Na przykład przez pomyłkę +można zwracać zawyżone prawdopodobieństwo (powiedzmy przemnożone przez 2). + +Te problemy stają się szczególnie dokuczliwe, jeśli organizujemy +wyzwanie, /konkurs/ modelowania języka, gdzie chcemy w sposób +obiektywny porównywać różne modele języka, tak aby uniknąć celowego +bądź nieświadomego zawyżania wyników. + +Przedstawimy teraz, w jaki sposób poradzono sobie z tym problemem +w wyzwaniu /Challenging America word-gap prediction/ + +*** Odgadywanie słowa w luce + +Po pierwsze, jaka sama nazwa wskazuje, w wyzwaniu /Challenging America +word-gap prediction/ zamiast zwracania prawdopodobieństwa dla całego +tekstu oczekuje się podania rozkładu prawdopodobieństwa dla brakującego słowa. + +Mianowicie, w każdym wierszu wejściu (plik ~in.tsv.xz~) w 7. i 8. polu +podany jest, odpowiednio, lewy i prawy kontekst słowa do odgadnięcia. +(W pozostałych polach znajdują się metadane, o których już wspomnieliśmy, +na razie nie będziemy ich wykorzystywać). +W pliku z oczekiwanym wyjściem (~expected.tsv~), w odpowiadającym +wierszu, podawane jest brakujące słowo. Oczywiście w ostatecznym +teście ~test-A~ plik ~expected.tsv~ jest niedostępny, ukryty przed uczestnikami konkursu. + +*** Zapis rozkładu prawdopodobieństwa + +Dla każdego wiersza wejścia podajemy rozkład prawdopodobieństwa dla +słowa w luce w formacie: + +#+BEGIN_SRC +wyraz1:prob1 wyraz2:prob2 ... wyrazN:probN :prob0 +#+END_SRC + +gdzie wyraz1, …, wyrazN to konkretne wyrazy, prob1, …, probN ich prawdopodobieństwa. +Można podać dowolną liczbę wyrazów. +Z kolei prob0 to „resztowe” prawdopodobieństwo przypisane do wszystkich pozostałych wyrazów, +prawdopodobieństwo to pozwala uniknąć problemów związanych ze słowami OOV, trzeba jeszcze tylko dokonać +modyfikacji metryki + +*** Metryka LikelihoodHashed + +Metryka LikelihoodHashed jest wariantem metryki Likelihood +(wiarygodności) opracowanym z myślą o wyzwaniach czy konkursach +modelowania języka. W tej metryce każde słowo wpada pseudolosowo do +jednego z $2^{10}=1024$ „kubełków”. Numer kubełka jest wyznaczony na +podstawie funkcji haszującej MurmurHash. + +Prawdopodobieństwa zwrócone przez ewaluowany model są sumowane w +każdym kubełku, następnie ewaluator zagląda do pliku `expected.tsv` i +uwzględnia prawdopodobieństwo z kubełka, do którego „wpada” oczekiwane +słowo. Oczywiście czasami więcej niż jedno słowo może wpaść do +kubełka, model mógł też „wrzucić” do kubełka tak naprawdę inne słowo +niż oczekiwane (przypadkiem oba słowa wpadają do jednego kubełka). +Tak więc LikelihoodHashed będzie nieco zawyżone w stosunku do Likelihood. + +Dlaczego więc taka komplikacja? Otóż LikelihoodHashed nie zakłada +żadnego słownika, znika problem słów OOV — prawdopodobieństwa resztowe prob0 +są rozkładane równomiernie między wszystkie 1024 kubełki. + +*** Alternatywne metryki + +LikelihoodHashed została zaimplementowana w narzędziu ewaluacyjnym +[[https://gitlab.com/filipg/geval|GEval]]. Są tam również dostępne +analogiczne warianty entropii krzyżowej (log loss) i perplexity +(LogLossHashed i PerplexityHashed). diff --git a/wyk/06_Ewaluacja/lm-communication.drawio b/wyk/06_Ewaluacja/lm-communication.drawio new file mode 100644 index 0000000..36a18c8 --- /dev/null +++ b/wyk/06_Ewaluacja/lm-communication.drawio @@ -0,0 +1 @@ +7VjbUtswEP0aP4bxJU7IIyQUhkJhYIbCEyPbii0iW0GWE4evr2TJVzmBcm1n4CFoj+S1tGePdhPDmcb5MQXL6JwEEBu2GeSGMzNsezK0+KcANhJwbVcCIUWBhKwauEZPUIGmQjMUwLS1kBGCGVq2QZ8kCfRZCwOUknV72Zzg9luXIIQacO0DrKO/UcAiie7b4xo/gSiMyjdbo4mciUG5WJ0kjUBA1g3IOTKcKSWEyVGcTyEWsSvjIp/7sWW22hiFCXvJA3R1NohuBmByf3NxZV/f0+Or04Gj9sY25YFhwM+vTEJZREKSAHxUo4eUZEkAhVeTW/WaM0KWHLQ4+AAZ2ygyQcYIhyIWYzULc8RuxeN7rrLulDMxnuVNY9MwLiFFMWSQlljC6Oa2adw1jcKR61amcDWuZrvO5iRhasf2kNsyMCIaW+OtoJRk1FerflL7Mb8zT7xgha5wkmWrU3tQ5i2gIWQ7yLCqrOBqgoTvjm74cxRiwNCqvQ+g8jqs1tXU84Fivz8Tdm1yBXCm3vQLBGDtAy1DeCIvxTCL8YHPCA/g4QpShrhozoAH8SVJEUMk4Us8whiJGwsOMArFBBOp0swJkjGMEjitZGxWHPSEXLiDeQPSo6Zm7aGS36Zjr2s1OwqKGkIemW+Pcy/J7rfiPl5xwxcqbviVihtqirsIPETo/y451/k6yfUG2tUCvTXAcwzzA9E2FEkbqOHMxyBNkd+OX1uVWwPXSWg9bI2wuD1hKbEXJ6V6wyVBfCf1RbjfYWXcCbcUlXqq2Ud0HLn2M46k6jRHBXXVsV/P5khjcwESYExdY1/gCxJnCVoA/wH13rSFXtpEAqUQn1MHaY90YhQE8iKGKXoCXuFPkL4UhyyO7R4a7qw3DXamZFdUVSOrXtLqFfvENjD3rLKlfm2GlEvIfJ7CD+Fs/98petbuotdf4Paczl+r4pmtgre13r2+nI31crarh3v2xvmc+jbWhHoME0iBqF/80JvYI1jX6NvrWnmX83S+5F/PVH0rimY7p1KZOTI/3qHwWWb7ZrRGeuEbfWavqff0hj3CTPVerbiPHjNSTgxkYA74Anu4zOtJPgrF//PSDd+V9CTxrWXVzzwh6XWEGLxegiLZ1xR0iPMkO2deBQB/ERacXcheReEBoIsL7gaxQnB7ptsG7QK1qh31XLMa0du/QXRZdXRWJz2sdsviu7Gq943frP41q8PJp7HKzfpXHllR65/KnKM/ \ No newline at end of file diff --git a/wyk/06_Ewaluacja/lm-communication.drawio.png b/wyk/06_Ewaluacja/lm-communication.drawio.png new file mode 100644 index 0000000..6b9a8d4 Binary files /dev/null and b/wyk/06_Ewaluacja/lm-communication.drawio.png differ