aitech-moj-2023/wyk/03_Entropia.ipynb

658 lines
52 KiB
Plaintext
Raw Normal View History

2022-03-20 20:40:49 +01:00
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Entropia\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Entropia** ($E$) to miara nieuporządkowania, niepewności, niewiedzy. Im\n",
"większa entropia, tym mniej wiemy. Pojęcie to pierwotnie wywodzi się z\n",
"termodynamiki, później znaleziono wiele zaskakujących analogii i zastosowań w\n",
"innych 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\n",
"fizycznych, na przykład pojemników z gazem. Przykładowo, wyobraźmy\n",
"sobie dwa pojemniki z gazem, w którym panuje różne temperatury.\n",
"\n",
"![img](./03_Entropia/gas-low-entropy.drawio.png)\n",
"\n",
"Jeśli usuniemy przegrodę między pojemnikami, temperatura się wyrówna,\n",
"a uporządkowanie się zmniejszy.\n",
"\n",
"![img](./03_Entropia/gas-high-entropy.drawio.png)\n",
"\n",
"Innymi 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\n",
"termodynamiki 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\n",
"jest sprzeczne z II prawem termodynamiki?\n",
"\n",
"Konsekwencją 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,\n",
"gdy wypracował ogólną teorię informacji.\n",
"\n",
"Teoria informacji zajmuje się między innymi zagadnieniem optymalnego kodowania komunikatów.\n",
"\n",
"Wyobraźmy sobie pewne źródło (generator) losowych komunikatów z\n",
"zamkniętego zbioru symboli ($\\Sigma$; nieprzypadkowo używamy oznaczeń\n",
"z poprzedniego wykładu). Nadawca $N$ chce przesłać komunikat o wyniku\n",
"losowania do odbiorcy $O$ używając zer i jedynek (bitów).\n",
"Teorioinformacyjną entropię można zdefiniować jako średnią liczbę\n",
"bitów wymaganych do przesłania komunikatu.\n",
"\n",
"![img](./03_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ą.\n",
"Entropia 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,\n",
"zaś to, że wypadła reszka — za pomocą jedynki).\n",
"\n",
"Rozpatrzmy przypadek, gdy nadawca rzuca ośmiościenną kością. Aby przekazać\n",
"wynik, potrzebuje wówczas 3 bity (a więc entropia ośmiościennej kości\n",
"wynosi 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\n",
"są 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\n",
"takim przypadku? Można by sądzić, że 2, skoro wystarczą 2 bity do\n",
"przekazania 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",
"\n",
"Problem w tym, że w rzeczywistości nie jest to *optymalne* kodowanie.\n",
"Możemy sprytnie zmniejszyć średnią liczbę bitów wymaganych do\n",
"przekazania losowego wyniku przypisując częstszym wynikom krótsze\n",
"kody, 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",
"\n",
"Uż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",
"\n",
"bita. 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",
"\n",
"Niestety, nie jest to właściwe rozwiązanie — kodowanie musi być\n",
"jednoznaczne nie tylko dla pojedynczego komunikatu, lecz dla całej sekwencji.\n",
"Na przykład ciąg 0111 nie jest jednoznaczny przy tym kodowaniu (ABBB czy CD?).\n",
"Podane wcześniej kodowanie spełnia warunek jednoznaczności, ciąg 0111 można odkodować tylko\n",
"jako 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\n",
"optymalny kod dla wyniku o prawdopodobieństwie $p$ ma długość $-\\log_2(p)$, a zatem ogólnie\n",
"entropia ź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",
"\n",
"Zauważmy, że jest to jeden z nielicznych przypadków, gdy w nauce naturalną\n",
"podstawą logarytmu jest 2 zamiast… podstawy logarytmu naturalnego ($e$).\n",
"\n",
"Teoretycznie można mierzyć entropię używając logarytmu naturalnego\n",
"($\\ln$), jednostką entropii będzie wówczas **nat** zamiast bita,\n",
"niewiele 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\n",
"optymalne 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
"text/plain": [
"<matplotlib.figure.Figure>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"from math import log\n",
"import numpy as np\n",
"\n",
"def binomial_entropy(p):\n",
" return -(p * log(p, 2) + (1-p) * log(1-p, 2))\n",
"\n",
"x = list(np.arange(0.001,1,0.001))\n",
"y = [binomial_entropy(x) for x in x]\n",
"plt.figure().clear()\n",
"plt.xlabel('prawdopodobieństwo wylosowania orła')\n",
"plt.ylabel('entropia')\n",
"plt.plot(x, y)\n",
"\n",
"fname = f'03_Entropia/binomial-entropy.png'\n",
"\n",
"plt.savefig(fname)\n",
"\n",
"fname"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Pytanie** Dla oszukańczej monety (np. dla której wypada zawsze orzeł) entropia\n",
"wynosi 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ś\n",
"rozkładu prawdopodobieństwa. W tym sensie możemy mówić o entropii języka.\n",
"\n",
"Oczywiście, jak zawsze, musimy jasno stwierdzić, czym są symbole\n",
"ję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\n",
"by 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\n",
"from itertools import islice\n",
"\n",
"url = 'https://wolnelektury.pl/media/book/txt/pan-tadeusz.txt'\n",
"pan_tadeusz = requests.get(url).content.decode('utf-8')\n",
"\n",
"def get_characters(t):\n",
" yield from t\n",
"\n",
"list(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)))\n",
"chars_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",
"\n",
"95 * (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\n",
"skrajnie nierównomierny! Jeśli uwzględnić ten nierównomierny rozkład\n",
"znakó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",
"\n",
"Policzmy 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\n",
"from math import log\n",
"\n",
"def 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",
"\n",
"unigram_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\n",
"import re\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": [
{
"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\n",
"generowany przecież według rozkładu wielomianowego. Istnieją rzecz\n",
"jasna pewne zależności między znakami, np. niemożliwe, żeby po „ń”\n",
"wystąpiły litera „a” czy „e”. Na poziomie wyrazów zależności mogę mieć\n",
"jeszcze bardziej skrajny charakter, np. po wyrazie „przede” prawie na\n",
"pewno wystąpi „wszystkim”, co oznacza, że w takiej sytuacji słowo\n",
"„wszystkim” może zostać zakodowane za pomocą 0 (!) bitów.\n",
"\n",
"Można uwzględnić takie zależności i uzyskać jeszcze lepsze kodowanie,\n",
"a co za tym idzie lepsze oszacowanie entropii. (Jak wkrótce się\n",
"dowiemy, 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\n",
"sposobó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",
"\n",
"def entropy_by_compression(t):\n",
" compressed = zlib.compress(t.encode('utf-8'))\n",
" return 8 * len(compressed) / len(t)\n",
"\n",
"entropy_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\n",
"danego 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": {
"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.2"
},
"org": null
},
"nbformat": 4,
"nbformat_minor": 1
}