1 / 65

Algorytmy kodowania Shannona-Fano i Huffmana

Algorytmy kodowania Shannona-Fano i Huffmana. Algorytmy Kompresji Danych wykład 3 Roman Starosolski. Plan wykładu. Algorytm kompresji statystycznej Algorytm Shannona-Fano Algorytm Huffmana Rozszerzone kody Huffmana Dynamiczne kodowanie Huffmana

kerem
Download Presentation

Algorytmy kodowania Shannona-Fano i Huffmana

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Algorytmy kodowania Shannona-Fano i Huffmana Algorytmy Kompresji Danychwykład 3Roman Starosolski

  2. Plan wykładu • Algorytm kompresji statystycznej • Algorytm Shannona-Fano • Algorytm Huffmana • Rozszerzone kody Huffmana • Dynamiczne kodowanie Huffmana • Adaptacyjny algorytm kompresji z wykorzystaniem rodziny kodów (Golomb, Golomb-Rice)

  3. Algorytm kompresji statystycznej Algorytm kompresji statystycznej = = probabilistyczny model danych + + koder entropijny (+ dodatkowe przetwarzanie) (+ dekoder)

  4. Koder entropijny • Koder entropijny to algorytm, którego zadaniem jest, na podstawie znajomości prawdopodobieństw występowania symboli, binarne zakodowanie ciągu symboli tak, aby zminimalizować średnią długość ciągu po zakodowaniu. Z podstawowego twierdzenia Shannona o kodowaniu bezszumowym: LŚr ≥ H(S) gdzie LŚr to średnia długość słowa kodowego kodu przedrostkowego. Zatem dążymy do uzyskania średniej długości słowa kodowego możliwie bliskiej entropii (stąd nazwa „koder entropijny”). • Budowa kodera entropijnego jest banalnie prosta, gdy dysponujemy kodem optymalnym dla rozkładu prawdopodobieństwa symboli źródła

  5. Algorytmy adaptacyjne i inne • algorytm (semi-)statyczny • stosowany w algorytmach dwuprzebiegowych • przebieg 1: analiza stałego ciągu, budowa modelu • przebieg 2: kodowanie • problemy: • dwuprzebiegowy • wymaga transmisji i modelu i zakodowanego ciągu • algorytm adaptacyjny • algorytm jednoprzebiegowy, on-line • aktualizacja modelu każdorazowo po zakodowaniu symbolu (taki model nazywamy adaptacyjnym modelem danych) • problemy • przyrostowa aktualizacja modelu nie może być złożona • Zero Frequency Problem

  6. Algorytmy adaptacyjne i inne • algorytm stały • budowa dla całej klasy danych • kodowanie przy założeniu, że dane należą do tej klasy • problemy • dane „nie pasujące” do założeń • inne • kilka (stałych) modeli przełączanych adaptacyjnie podczas kodowania • podział ciągu na podciągi i zastosowanie algorytmu statycznego do każdego podciągu z osobna • ...

  7. „Podstawowe twierdzenie Shannona o kodowaniu bezszumowym” (jedna z postaci twierdzenia, wg.: Drozdek: „Wprowadzenie do kompresji danych”) Dla bezpamięciowego źródła S o entropii H(S) możliwe jest przypisanie ciągom k symboli źródła, słów kodu przedrostkowego tak, że spełnione jest H(S) ≤ Lk / k < H(S) + 1/k • asymptotycznie, możliwe jest uzyskanie średniej długości kodu (w przeliczeniu na pojedynczy symbol) równej entropii źródła • optymalna długość słowa kodowego dla symbolu o prawdopodobieństwie p równa jest –log(p) (czyli autoinformacji dla tego symbolu) • można zbudować koder entropijny o efektywności bliskiej 100%

  8. Jak wygenerować kod przedrostkowy? • Problem: • Mamy wyznaczony przez model rozkład prawdopodobieństwa symboli źródła p1, p2, p3, p4 ... pN, :∑pi = 1 • Znamy optymalne długości słów kodowych (tj. przybliżone długości słów optymalnego kodu przedrostkowego) l1, l2, l3, l4 ... lN: li = –log(pi) • Wiemy jaki warunek muszą spełniać długości słów kodowych aby istniał kod jednoznacznie dekodowalny (nierówność Krafta) ∑2-li ≤ 1 • Chcemy wyznaczyć • Kod przedrostkowy o minimalnej średniej długości kodu • szukamy: dokładnych długości słów • szukamy: postaci (kolejnych bitów) słów

  9. Algorytm Shannona-Fano • Algorytm Shannona-Fano generuje kod przedrostkowy dla zadanego rozkładu prawdopodobieństwa symboli alfabetu.

  10. (na podstawie: A. Drozdek, Wprowadzenie do kompresji danych, WNT, Warszawa, 1999) Krok 1: Ustaw symbole alfabetu źródła w ciąg s uporządkowane zgodnie z prawdopodobieństwem ich użycia; Krok 2: AlgorytmShannonaFano(ciąg s) if s zawiera dwa symbole dołącz 0 do słowa kodowego jednego z symboli, 1 do słowa drugiego symbolu; elseif s zawiera więcej niż dwa symbole podziel s na dwa podciągi s1 i s2 tak, by różnica między sumą prawdopodobieństw symboli w podciągach była najmniejsza; dołącz 0 do słów kodowych symboli w s1 i 1 do słów symboli w s2; AlgorytmShannonaFano(s1); AlgorytmShannonaFano(s2); endif;

  11. Przykład: kodujemy ciąg abracadabra w tabeli mamy ciąg symboli alfabetu źródła i kolejne kroki budowania słów kodowych

  12. Przykład: kodujemy ciąg abracadabra można wygenerować kod o innych długościach słów

  13. Algorytm Huffmana • Algorytm Huffmana generuje kod przedrostkowy dla zadanego rozkładu prawdopodobieństwa symboli alfabetu.

  14. W algorytmie Huffmana buduje się drzewo binarne, zwane drzewem Huffmana. • Każdemu z liści odpowiada pojedynczy symbol alfabetu źródła. • Z każdym węzłem skojarzona jest waga równa łącznemu prawdopodobieństwu liści w poddrzewie dla którego ten węzeł jest korzeniem • Utwórz n drzew, gdzie n jest rozmiarem alfabetu źródła. Każdemu z symboli alfabetu źródła odpowiada pojedyncze drzewo składające się wyłącznie z korzenia i mające wagę równą prawdopodobieństwu wystąpienia danego symbolu. • Wyznacz dwa drzewa o najmniejszych wagach i utwórz z nich nowe drzewo, w którym dwa właśnie wyznaczone drzewa te są synami korzenia o wadze równej sumie ich wag. Powtarzaj krok 2 aż pozostanie tylko jedno drzewo (n – 1 razy). • Słowo kodowe kodu Huffmana dla danego symbolu znajduje się przechodząc ścieżką od korzenia drzewa Huffmana do liścia odpowiadającego temu symbolowi (i-ty bit słowa kodowego ma wartość 0, jeżeli i-ta krawędź ścieżki prowadzi do lewego syna i-tego węzła, a 1 — jeżeli do prawego).

  15. a r d c b 2/11 1/11 1/11 5/11 2/11 Przykład: kodujemy ciąg abracadabra • Utwórz n drzew, gdzie n jest rozmiarem alfabetu źródła. Każdemu z symboli alfabetu źródła odpowiada pojedyncze drzewo składające się wyłącznie z korzenia i mające wagę równą prawdopodobieństwu wystąpienia danego symbolu.

  16. a r d c b 2/11 1/11 1/11 5/11 2/11 2/11 Przykład: kodujemy ciąg abracadabra • Wyznacz dwa drzewa o najmniejszych wagach i utwórz z nich nowe drzewo, w którym dwa właśnie wyznaczone drzewa te są synami korzenia o wadze równej sumie ich wag. Powtarzaj krok 2 aż pozostanie tylko jedno drzewo (n – 1 razy). 0 1

  17. a r d c b 2/11 2/11 4/11 1/11 1/11 2/11 5/11 Przykład: kodujemy ciąg abracadabra • Wyznacz dwa drzewa o najmniejszych wagach i utwórz z nich nowe drzewo, w którym dwa właśnie wyznaczone drzewa te są synami korzenia o wadze równej sumie ich wag. Powtarzaj krok 2 aż pozostanie tylko jedno drzewo (n – 1 razy). 0 1 0 1

  18. a b r d c 4/11 2/11 2/11 6/11 1/11 1/11 2/11 5/11 Przykład: kodujemy ciąg abracadabra • Wyznacz dwa drzewa o najmniejszych wagach i utwórz z nich nowe drzewo, w którym dwa właśnie wyznaczone drzewa te są synami korzenia o wadze równej sumie ich wag. Powtarzaj krok 2 aż pozostanie tylko jedno drzewo (n – 1 razy). 0 1 0 1 0 1

  19. a r d c b 6/11 4/11 2/11 5/11 1 1/11 2/11 2/11 1/11 Przykład: kodujemy ciąg abracadabra 0 1 0 1 0 1 0 1

  20. 0 1 0 1 0 1 0 1 a b c r d 1 2/11 4/11 5/11 1/11 1/11 2/11 6/11 2/11 Przykład: kodujemy ciąg abracadabra • Słowo kodowe kodu Huffmana dla danego symbolu znajduje się przechodząc ścieżką od korzenia drzewa Huffmana do liścia odpowiadającego temu symbolowi (i-ty bit słowa kodowego ma wartość 0, jeżeli i-ta krawędź ścieżki prowadzi do lewego syna i-tego węzła, a 1 — jeżeli do prawego).

  21. Własności kodów Huffmana • Podobnie, jak algorytm Shannona-Fano, przedstawiony algorytm jest niedeterministyczny • niedeterminizm można łatwo usunąć –kanoniczne kodowanie Huffmana • Efektywnośc kodów Huffmana jest typowo nieznacznie większa niż Shannona-Fano • (dla przykładu „abracadabra” jest taka sama) • algorytm Huffmana jest prostszy

  22. Własności kodów Huffmana • Kod wygenerowany algorytmem Huffmana jest optymalny w klasie kodów przedrostkowych (gdy prawdopodobieństwa symboli są 2 -N, gdzie N jest nieujemną liczbą całkowitą, to kod jest optymalny, gdyż dla symbolu o prawdopodobieństwie p optymalna długość słowa kodowego to –log(p) bitów) • Nieefektywność kodu Huffmana • Jednocześnie nieefektywność kodów przedrostkowych pmaxto prawdopodobieństwo najbardziej prawdopodobnego symbolu.

  23. Rozszerzone kody Huffmana • Kod Huffmana jest nieefektywny, gdy prawdopodobieństwo wystąpienia jednego z symboli jest duże, najbardziej gdy bliskie 1. • długość słowa kodowego tego symbolu wynosi 1 bit • optymalna długość słowa kodowego jest bliska 0 • zatem średnia długość kodu jest wielokrotnie większa od entropii rozkładu prawdopodobieństwa symboli.

  24. „Podstawowe twierdzenie Shannona o kodowaniu bezszumowym” (jedna z postaci twierdzenia, wg.: Drozdek: „Wprowadzenie do kompresji danych”) Dla bezpamięciowego źródła S o entropii H(S) możliwe jest przypisanie ciągom k symboli źródła, słów kodu przedrostkowego tak, że spełnione jest H(S) ≤ Lk / k < H(S) + 1/k • asymptotycznie, możliwe jest uzyskanie średniej długości kodu (w przeliczeniu na pojedynczy symbol) równej entropii źródła • optymalna długość słowa kodowego dla symbolu o prawdopodobieństwie p równa jest –log(p) (czyli autoinformacji dla tego symbolu) • można zbudować koder entropijny o efektywności bliskiej 100%

  25. Rozszerzone kody Huffmana • Kod Huffmana jest nieefektywny, gdy prawdopodobieństwo wystąpienia jednego z symboli jest duże, najbardziej gdy bliskie 1. • długość słowa kodowego tego symbolu wynosi 1 bit • optymalna długość słowa kodowego jest bliska 0 • zatem średnia długość kodu jest wielokrotnie większa od entropii rozkładu prawdopodobieństwa symboli. • Zamiast konstruować kod dla symboli alfabetu źródła możemy zinterpretować kodowany ciąg jako ciąg nad rozszerzonym alfabetem zawierającym ciągi symboli alfabetu źródła

  26. Przykład: Rozszerzone kody Huffmana Kodujemy ciąg binarny (alfabet źródła to {0, 1}) Prawdopodobieństwo wygenerowania zera przez źródło wynosi 0.9 Entropia rozkładu prawdopodobieństwa H(S) wynosi 0.467. Efektywność kodu Huffmana dla tego źródła wynosi EHuffBin=( H(S)/LHuffBin )•100%=47% Jeżeli kodować będziemy pary symboli ... ... to średnia długość słowa kodowego (w przeliczeniu na symbol alfabetu źródła) wyniesie 0.649, czyli efektywność kodu wzrośnie do około 72 %.

  27. Algorytm kompresji z kodowaniem Huffmana • Typowe zastosowanie algorytmu Huffmana (i Shannona-Fano) to statyczny algorytm kompresji. • zbudowanie modelu wymaga znajomości rozkładu prawdopodobieństwa symboli źródła, praktycznie przesyła się tablicę częstości wystąpień symboli • koszt transmisji modelu np. dla alfabetu źródła ASCII jest niewielki • kodowanie jest bardzo szybkie • po zbudowaniu modelu wyliczamy słowa kodowe wszystkich symboli alfabetu źródła • kodowanie polega na wyprowadzeniu już wyliczonych słów kodowych dla kolejnych symboli kodowanego ciąg

  28. Algorytm kompresji z kodowaniem Huffmana • Zalety • prosty • szybki • wady • nieefektywny gdy prawdopodobieństwo wystąpienia jednego z symboli alfabetu źródła jest duże (ale można kodować ciągi symboli) • dwuprzebiegowy • koszt transmisji modelu może być duży • nie do zastosowania wprost do kodowania on-line

  29. Dynamiczne kodowanie Huffmana • Użycie algorytmu Huffmana w adaptacyjnym modelu jest możliwe Metoda brute-force – każdorazowo po zakodowniu symbolu buduj od nowa drzewo Huffmana ( Uwaga na Zero Frequency Problem ) ... ale w praktyce zbyt kosztowne

  30. Dynamiczne kodowanie Huffmana • Algorytmy Dynamicznego kodowania Huffmana • (Adaptacyjne kodowanie Huffmana) • To algorytm generujący kod zbliżony do kodu Huffmana, nadający się do zastosowania w algorytmie adaptacyjnym • Drzewo Huffmana budowane jest przyrostowo – możliwa jest „aktualizacja modelu” • Ww. algorytm został wynaleziony niezależnie przez Fallera i Gallagera • ... udoskonalony przez Cormacka i Horspoola oraz (niezależnie) przez Knutha • ... następnie udoskonalony przez Vittera

  31. Algorytm Fallera-Gallagera • Budujemy przyrostowo drzewo binarne, którego węzły zawierają liczniki częstości, a liście są dodatkowo skojarzone z symbolami alfabetu źródła • Drzewo ma własność rodzeństwa gdy: • każdy węzeł nie będący liściem ma 2 potomków • przechodząc węzły w kolejności z góry do dołu, a na danym poziomie od prawej do lewej, otrzymamy ciąg węzłów o nierosnących licznikach • Drzewo mające własność rodzeństwa jest drzewem Huffmana (tw. Fallera-Gallagera)

  32. a r d c b 2 1 1 5 2 2 4 6 11 Przykład: drzewo mające własność rodzeństwa (wygląda znajomo?)

  33. Algorytm Fallera-Gallagera • Budowane drzewo zawiera liść (0-węzeł) reprezentujący wszystkie symbole, które jeszcze nie wystąpiły w kodowanym ciągu • Kodowanie rozpoczynamy od drzewa składającego się wyłącznie z 0-węzła • Używamy pomocniczej struktury węzły, listy dwukierunkowej zawierającej węzły drzewa uporządkowane w kolejności przeglądania drzewa z góry do dołu, a na danym poziomie od prawej do lewej • Podlistę listy węzły składającą się z wszystkich węzłów o wartości licznika i nazywamy blokiem-i , a pierwszy węzeł takiego bloku liderem

  34. (na podstawie: A. Drozdek, Wprowadzenie do kompresji danych, WNT, Warszawa, 1999) DynamiczneKodowanieHuffmanaFGK(symbol s) p = liść zawierający symbol s; wyprowadź słowo kodowe dla s (*); if p jest 0-węzłem utwórz nowy węzeł q dla symolu s; q.licznik = 1; p = nowy węzeł w miejscu 0-węzła będący rodzicem 0-węzła i węzła q; p.licznik = 1; else p.licznik++; endif while p nie jest korzeniem if p narusza własność rodzeństwa if liderbloku-i zawierającego p nie jest rodzicem p zamień p z liderem; endif endif p = rodzic(p); p.licznik++; endwhile

  35. a q p a 0 1 1 0 Przykład: kodujemy ciąg abrr, inicjalizacja i wstawienie pierwszego symbolu ( a )

  36. a b q q p p b a a 0 1 0 1 1 1 1 0 1 Przykład: kodujemy ciąg abrr, wstawienie symbolu b

  37. r a b q q p p a b a a b 1 0 1 1 0 1 1 0 1 1 1 2 0 1 Przykład: kodujemy ciąg abrr, wstawienie symbolu b

  38. r a b 2 1 1 1 0 wstawienie symbolu r

  39. r p a a b b r 2 1 1 1 0 1 0 2 1 2 1 1 wstawienie symbolu r

  40. r p p b a a b r r b a 0 2 1 1 1 0 1 1 2 1 1 2 1 2 1 0 1 2 1 wstawienie symbolu r (przywróć własność rodzeństwa)

  41. p r a b 1 1 0 2 1 2 1 wstawienie symbolu r (przywróć własność rodzeństwa)

  42. p p b r a r b a 1 1 0 2 1 2 1 1 1 2 1 0 2 1 wstawienie symbolu r (przywróć własność rodzeństwa)

  43. r p p r r b a a a r b b 2 1 2 1 1 1 1 0 2 1 1 3 1 1 1 2 0 2 1 1 0 wstawienie symbolu r

  44. r a r b 3 1 1 1 0 2 1 ponowne wstawienie symbolu r (ciąg abrr)

  45. r p a b r b r a 1 1 1 0 2 1 0 1 2 1 2 1 3 3 ponowne wstawienie symbolu r (ciąg abrr)

  46. r p p a r b b b a r r a 1 1 1 1 0 2 1 3 1 0 1 2 3 2 3 1 1 1 2 0 2 ponowne wstawienie symbolu r (przywróć własność rodzeństwa)

  47. p a r b 3 1 1 2 0 2 1 ponowne wstawienie symbolu r (przywróć własność rodzeństwa)

  48. p p a b r b a r 1 1 2 0 2 1 0 1 1 2 2 1 3 4 ponowne wstawienie symbolu r (przywróć własność rodzeństwa)

  49. r a b 4 2 1 1 0 2 1 postać drzewa po przetworzeniu ciągu abrr

  50. Algorytm Vittera • Dodatkowe założenie: w bloku-i węzłów najpierw znajdują się węzły wewnętrzne, później liście • minimalizujemy głębokość drzewa • bardziej złożone staje się przywracanie własności rodzeństwa • ciąg o długości s zakodujemy na nie więcej niż h+s bitach, gdzie h to liczba bitów dla kodowania statycznego Huffmana • ten algorytm radzi sobie z ZFP lepiej, niż algorytm Fallera-Gallagera • (dla niektórych ciągów wynik dynamicznego kodowania Huffmana może by lepszy, niż w statycznym algorytmie, bo tu nie przesyłamy modelu)

More Related