wyk 03
@ -9,7 +9,7 @@ Używać będziemy generatorów.
|
|||||||
|
|
||||||
*Pytanie* Dlaczego generatory zamiast list?
|
*Pytanie* Dlaczego generatory zamiast list?
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
url = 'https://wolnelektury.pl/media/book/txt/pan-tadeusz.txt'
|
url = 'https://wolnelektury.pl/media/book/txt/pan-tadeusz.txt'
|
||||||
@ -31,7 +31,7 @@ Powrót pani
|
|||||||
|
|
||||||
*** Znaki
|
*** Znaki
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||||
from itertools import islice
|
from itertools import islice
|
||||||
|
|
||||||
def get_characters(t):
|
def get_characters(t):
|
||||||
@ -45,7 +45,7 @@ Powrót pani
|
|||||||
['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']
|
['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:
|
:end:
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
|
|
||||||
c = Counter(get_characters(pan_tadeusz))
|
c = Counter(get_characters(pan_tadeusz))
|
||||||
@ -65,7 +65,7 @@ Napiszmy pomocniczą funkcję, która zwraca *listę frekwencyjną*.
|
|||||||
Counter({' ': 63444, 'a': 30979, 'i': 29353, 'e': 25343, 'o': 23050, 'z': 22741, 'n': 15505, 'r': 15328, 's': 15255, 'w': 14625, 'c': 14153, 'y': 13732, 'k': 12362, 'd': 11465, '\r': 10851, '\n': 10851, 't': 10757, 'm': 10269, 'ł': 10059, ',': 9130, 'p': 8031, 'u': 7699, 'l': 6677, 'j': 6586, 'b': 5753, 'ę': 5534, 'ą': 4794, 'g': 4775, 'h': 3915, 'ż': 3334, 'ó': 3097, 'ś': 2524, '.': 2380, 'ć': 1956, ';': 1445, 'P': 1265, 'W': 1258, ':': 1152, '!': 1083, 'S': 1045, 'T': 971, 'I': 795, 'N': 793, 'Z': 785, 'J': 729, '—': 720, 'A': 698, 'K': 683, 'ń': 651, 'M': 585, 'B': 567, 'O': 567, 'C': 556, 'D': 552, '«': 540, '»': 538, 'R': 489, '?': 441, 'ź': 414, 'f': 386, 'G': 358, 'L': 316, 'H': 309, 'Ż': 219, 'U': 184, '…': 157, '*': 150, '(': 76, ')': 76, 'Ś': 71, 'F': 47, 'é': 43, '-': 33, 'Ł': 24, 'E': 23, '/': 19, 'Ó': 13, '8': 10, '9': 8, '2': 6, 'v': 5, 'Ź': 4, '1': 4, '3': 3, 'x': 3, 'V': 3, '7': 2, '4': 2, '5': 2, 'q': 2, 'æ': 2, 'à': 1, 'Ć': 1, '6': 1, '0': 1})
|
Counter({' ': 63444, 'a': 30979, 'i': 29353, 'e': 25343, 'o': 23050, 'z': 22741, 'n': 15505, 'r': 15328, 's': 15255, 'w': 14625, 'c': 14153, 'y': 13732, 'k': 12362, 'd': 11465, '\r': 10851, '\n': 10851, 't': 10757, 'm': 10269, 'ł': 10059, ',': 9130, 'p': 8031, 'u': 7699, 'l': 6677, 'j': 6586, 'b': 5753, 'ę': 5534, 'ą': 4794, 'g': 4775, 'h': 3915, 'ż': 3334, 'ó': 3097, 'ś': 2524, '.': 2380, 'ć': 1956, ';': 1445, 'P': 1265, 'W': 1258, ':': 1152, '!': 1083, 'S': 1045, 'T': 971, 'I': 795, 'N': 793, 'Z': 785, 'J': 729, '—': 720, 'A': 698, 'K': 683, 'ń': 651, 'M': 585, 'B': 567, 'O': 567, 'C': 556, 'D': 552, '«': 540, '»': 538, 'R': 489, '?': 441, 'ź': 414, 'f': 386, 'G': 358, 'L': 316, 'H': 309, 'Ż': 219, 'U': 184, '…': 157, '*': 150, '(': 76, ')': 76, 'Ś': 71, 'F': 47, 'é': 43, '-': 33, 'Ł': 24, 'E': 23, '/': 19, 'Ó': 13, '8': 10, '9': 8, '2': 6, 'v': 5, 'Ź': 4, '1': 4, '3': 3, 'x': 3, 'V': 3, '7': 2, '4': 2, '5': 2, 'q': 2, 'æ': 2, 'à': 1, 'Ć': 1, '6': 1, '0': 1})
|
||||||
:end:
|
:end:
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ OrderedDict([(' ', 63444), ('a', 30979), ('i', 29353), ('e', 25343), ('o', 23050
|
|||||||
:end:
|
:end:
|
||||||
|
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ Co rozumiemy pod pojęciem słowa czy wyrazu, nie jest oczywiste. W praktyce zal
|
|||||||
Załóżmy, że przez wyraz rozumieć będziemy nieprzerwany ciąg liter bądź cyfr (oraz gwiazdek
|
Załóżmy, że przez wyraz rozumieć będziemy nieprzerwany ciąg liter bądź cyfr (oraz gwiazdek
|
||||||
— to za chwilę ułatwi nam analizę pewnego tekstu…).
|
— to za chwilę ułatwi nam analizę pewnego tekstu…).
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||||
from itertools import islice
|
from itertools import islice
|
||||||
import regex as re
|
import regex as re
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ Załóżmy, że przez wyraz rozumieć będziemy nieprzerwany ciąg liter bądź
|
|||||||
Zobaczmy 20 najczęstszych wyrazów.
|
Zobaczmy 20 najczęstszych wyrazów.
|
||||||
|
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
rang_freq_with_labels('pt-words-20', get_words(pan_tadeusz), top=20)
|
rang_freq_with_labels('pt-words-20', get_words(pan_tadeusz), top=20)
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ Zobaczmy 20 najczęstszych wyrazów.
|
|||||||
|
|
||||||
Zobaczmy pełny obraz, już bez etykiet.
|
Zobaczmy pełny obraz, już bez etykiet.
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from math import log
|
from math import log
|
||||||
|
|
||||||
@ -169,10 +169,10 @@ Zobaczmy pełny obraz, już bez etykiet.
|
|||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
[[file:02_Jezyki/pt-words.png]]
|
[[file:02_Jezyki/pt-words.png]]
|
||||||
|
|
||||||
Widać, jak różne skale obejmuje ten wykres. Zastosujemy logartm,
|
Widać, jak różne skale obejmuje ten wykres. Zastosujemy logarytm,
|
||||||
najpierw tylko do współrzędnej y.
|
najpierw tylko do współrzędnej $y$.
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from math import log
|
from math import log
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ logarytmicznej dla **obu** osi, otrzymamy kształt zbliżony do linii prostej.
|
|||||||
|
|
||||||
Tę własność tekstów nazywamy **prawem Zipfa**.
|
Tę własność tekstów nazywamy **prawem Zipfa**.
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from math import log
|
from math import log
|
||||||
|
|
||||||
@ -249,7 +249,7 @@ Tę własność tekstów nazywamy **prawem Zipfa**.
|
|||||||
Powiązane z prawem Zipfa prawo językowe opisuje zależność między
|
Powiązane z prawem Zipfa prawo językowe opisuje zależność między
|
||||||
częstością użycia słowa a jego długością. Generalnie im krótsze słowo, tym częstsze.
|
częstością użycia słowa a jego długością. Generalnie im krótsze słowo, tym częstsze.
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
def freq_vs_length(name, g, top=None):
|
def freq_vs_length(name, g, top=None):
|
||||||
freq = freq_list(g)
|
freq = freq_list(g)
|
||||||
|
|
||||||
@ -292,9 +292,9 @@ po prostu na jednostkach, nie na ich podciągach.
|
|||||||
|
|
||||||
*** N-gramy z Pana Tadeusza
|
*** N-gramy z Pana Tadeusza
|
||||||
|
|
||||||
Statystyki, które policzyliśmy dla pojedynczych liter czy wyrazów możemy powtórzyć dla n-gramów.
|
Statystyki, które policzyliśmy dla pojedynczych liter czy wyrazów, możemy powtórzyć dla n-gramów.
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||||
def ngrams(iter, size):
|
def ngrams(iter, size):
|
||||||
ngram = []
|
ngram = []
|
||||||
for item in iter:
|
for item in iter:
|
||||||
@ -317,7 +317,7 @@ Zawsze powinniśmy się upewnić, czy jest jasne, czy chodzi o n-gramy znakowe c
|
|||||||
|
|
||||||
*** 3-gramy znakowe
|
*** 3-gramy znakowe
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
log_rang_log_freq('pt-3-char-ngrams-log-log', ngrams(get_characters(pan_tadeusz), 3))
|
log_rang_log_freq('pt-3-char-ngrams-log-log', ngrams(get_characters(pan_tadeusz), 3))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
@ -326,8 +326,8 @@ Zawsze powinniśmy się upewnić, czy jest jasne, czy chodzi o n-gramy znakowe c
|
|||||||
|
|
||||||
*** 2-gramy wyrazowe
|
*** 2-gramy wyrazowe
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
log_rang_log_freq('pt-2-word-ngrams-log-log', ngrams(get_words(pan_tadeusz), 3))
|
log_rang_log_freq('pt-2-word-ngrams-log-log', ngrams(get_words(pan_tadeusz), 2))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
@ -348,7 +348,7 @@ transkrybować manuskrypt, pozostaje sprawą dyskusyjną, natomiast wybór
|
|||||||
takiego czy innego systemu transkrypcji nie powinien wpływać
|
takiego czy innego systemu transkrypcji nie powinien wpływać
|
||||||
dramatycznie na analizę statystyczną.
|
dramatycznie na analizę statystyczną.
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
voynich_url = 'http://www.voynich.net/reeds/gillogly/voynich.now'
|
voynich_url = 'http://www.voynich.net/reeds/gillogly/voynich.now'
|
||||||
@ -370,28 +370,28 @@ dramatycznie na analizę statystyczną.
|
|||||||
9 OR 9FAM ZO8 QOAR9 Q*R 8ARAM 29 [O82*]OM OPCC9 OP
|
9 OR 9FAM ZO8 QOAR9 Q*R 8ARAM 29 [O82*]OM OPCC9 OP
|
||||||
:end:
|
:end:
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
rang_freq_with_labels('voy-chars', get_characters(voynich))
|
rang_freq_with_labels('voy-chars', get_characters(voynich))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
[[file:02_Jezyki/voy-chars.png]]
|
[[file:02_Jezyki/voy-chars.png]]
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
log_rang_log_freq('voy-log-log', get_words(voynich))
|
log_rang_log_freq('voy-log-log', get_words(voynich))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
[[file:02_Jezyki/voy-log-log.png]]
|
[[file:02_Jezyki/voy-log-log.png]]
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
rang_freq_with_labels('voy-words-20', get_words(voynich), top=20)
|
rang_freq_with_labels('voy-words-20', get_words(voynich), top=20)
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
[[file:02_Jezyki/voy-words-20.png]]
|
[[file:02_Jezyki/voy-words-20.png]]
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
log_rang_log_freq('voy-words-log-log', get_words(voynich))
|
log_rang_log_freq('voy-words-log-log', get_words(voynich))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
@ -406,7 +406,7 @@ Podstawowe litery są tylko cztery, reprezentują one nukleotydy, z których zbu
|
|||||||
a, g, c, t.
|
a, g, c, t.
|
||||||
|
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
dna_url = 'https://raw.githubusercontent.com/egreen18/NanO_GEM/master/rawGenome.txt'
|
dna_url = 'https://raw.githubusercontent.com/egreen18/NanO_GEM/master/rawGenome.txt'
|
||||||
@ -423,7 +423,7 @@ a, g, c, t.
|
|||||||
TATAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTA
|
TATAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTA
|
||||||
:end:
|
:end:
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
rang_freq_with_labels('dna-chars', get_characters(dna))
|
rang_freq_with_labels('dna-chars', get_characters(dna))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
@ -436,7 +436,7 @@ Nukleotydy rzeczywiście są jak litery, same w sobie nie niosą
|
|||||||
znaczenia. Dopiero ciągi trzech nukleotydów, /tryplety/, kodują jeden
|
znaczenia. Dopiero ciągi trzech nukleotydów, /tryplety/, kodują jeden
|
||||||
z dwudziestu aminokwasów.
|
z dwudziestu aminokwasów.
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
genetic_code = {
|
genetic_code = {
|
||||||
'ATA':'I', 'ATC':'I', 'ATT':'I', 'ATG':'M',
|
'ATA':'I', 'ATC':'I', 'ATT':'I', 'ATG':'M',
|
||||||
'ACA':'T', 'ACC':'T', 'ACG':'T', 'ACT':'T',
|
'ACA':'T', 'ACC':'T', 'ACG':'T', 'ACT':'T',
|
||||||
@ -472,7 +472,7 @@ Z aminokwasów zakodowanych przez tryplet budowane są białka.
|
|||||||
Maszyneria budująca białka czyta sekwencję aż do napotkania
|
Maszyneria budująca białka czyta sekwencję aż do napotkania
|
||||||
trypletu STOP (_ powyżej). Taka sekwencja to /gen/.
|
trypletu STOP (_ powyżej). Taka sekwencja to /gen/.
|
||||||
|
|
||||||
#+BEGIN_SRC python :session mysession :results file
|
#+BEGIN_SRC ipython :session mysession :results file
|
||||||
def get_genes(triplets):
|
def get_genes(triplets):
|
||||||
gene = []
|
gene = []
|
||||||
for ammino in triplets:
|
for ammino in triplets:
|
||||||
@ -494,308 +494,3 @@ trypletu STOP (_ powyżej). Taka sekwencja to /gen/.
|
|||||||
|
|
||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
[[file:02_Jezyki/dna_length.png]]
|
[[file:02_Jezyki/dna_length.png]]
|
||||||
|
|
||||||
** 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.
|
|
||||||
|
|
||||||
[[./02_Jezyki/gas-low-entropy.drawio.png]]
|
|
||||||
|
|
||||||
Jeśli usuniemy przegrodę między pojemnikami, temperatura się wyrówna,
|
|
||||||
a uporządkowanie się zmniejszy.
|
|
||||||
|
|
||||||
[[./02_Jezyki/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.
|
|
||||||
|
|
||||||
[[./02_Jezyki/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 python :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'02_Jezyki/binomial-entropy.png'
|
|
||||||
|
|
||||||
plt.savefig(fname)
|
|
||||||
|
|
||||||
fname
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
#+RESULTS:
|
|
||||||
[[file:02_Jezyki/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 python :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 python :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 python :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 python :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 python :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 python :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.
|
|
||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 7.8 KiB |
304
wyk/03_Entropia.org
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
** 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.
|
||||||
|
|
||||||
|
[[./03_Jezyki/gas-low-entropy.drawio.png]]
|
||||||
|
|
||||||
|
Jeśli usuniemy przegrodę między pojemnikami, temperatura się wyrówna,
|
||||||
|
a uporządkowanie się zmniejszy.
|
||||||
|
|
||||||
|
[[./03_Jezyki/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.
|
||||||
|
|
||||||
|
[[./03_Jezyki/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 python :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'03_Entropia/binomial-entropy.png'
|
||||||
|
|
||||||
|
plt.savefig(fname)
|
||||||
|
|
||||||
|
fname
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
[[file:03_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 python :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 python :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 python :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 python :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 python :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 python :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.
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |