Beim Versuch, die Beziehungen zwischen Huffman-Codierung, arithmetischer Codierung und Bereichscodierung zu verstehen, begann ich über die Mängel der Huffman-Codierung nachzudenken, die mit dem Problem der fraktionierten Bitpackung zusammenhängen .
Angenommen, Sie haben 240 mögliche Werte für ein Symbol und müssen diese in Bits codieren. Sie würden also mit 8 Bits pro Symbol stecken bleiben, obwohl Sie keine "volle" 8 benötigen, da 8 256 mögliche Werte ausdrücken kann pro Symbol. Eine Lösung für dieses Problem ist etwas, das ich als "fraktionierte Bitpackung" bezeichnet habe, bei der Sie durch Multiplikation eine "Bitverschiebung" durch eine Nicht-Zweierpotenz erzielen können. So wie sich die Multiplikation von Zweierpotenzen verschiebt x * 2 == x << 1
und x * 4 == x << 2
so weiter für alle Zweierpotenzen, können Sie auch mit einer Nicht-Zweierpotenz "verschieben", indem Sie stattdessen multiplizieren und Symbole in Bruchbitgröße einpacken .
Das Problem ist bei der Huffman-Codierung ähnlich: Sie erhalten Codes, deren Länge nicht fraktionell bitgroß sein muss, und daher weist sie diese Ineffizienz beim Packen auf. Sie können jedoch nicht einfach die Lösung der Fracitonal-Bit-Packung verwenden, da diese Lösung Symbole mit fester Größe voraussetzt.
Die Frage ist, gibt es irgendwelche Papiere oder Lösungen, um die Huffman-Codierung mit einer ähnlichen Idee wie die fraktionierte Bitpackung zu verbessern, um etwas Ähnliches wie die arithmetische Codierung zu erreichen? (oder gegenteilige Ergebnisse).
Antworten:
Schauen wir uns eine etwas andere Sichtweise der Huffman-Codierung an.
Angenommen, Sie haben ein Alphabet mit drei Symbolen, A, B und C, mit Wahrscheinlichkeiten von 0,5, 0,25 und 0,25. Da die Wahrscheinlichkeiten alle inverse Zweierpotenzen sind, hat dies einen optimalen Huffman-Code (dh er ist identisch mit der arithmetischen Codierung). Wir werden für dieses Beispiel den kanonischen Code 0, 10, 11 verwenden.
Beginnen wir also mit dem Zustand 11 (der binär 1011 ist) und codieren Sie das Symbol B. Der neue Zustand ist 46, der binär 101110 ist. Wie Sie sehen können, ist dies der "alte" Zustand mit der am Ende hinzugefügten Sequenz 10. Wir haben im Wesentlichen die Bitfolge 10 "ausgegeben".
So weit, ist es gut.
Grundsätzlich multiplizieren wir hier alles mit dem gemeinsamen Nenner. Stellen Sie sich vor, der Zustand befand sich tatsächlich in Basis 4. Das Codieren eines Symbols B gibt tatsächlich die Ziffer 2 in dieser Basis aus, und das Codieren eines Symbols C gibt die Ziffer 3 in dieser Basis aus.
Symbol A ist jedoch etwas anders, da es in Basis 4 keine ganze Ziffer ist.
Stattdessen können wir uns das Alphabet als die Menge der Symbole A_0, A_1, B, C mit gleicher Wahrscheinlichkeit vorstellen. Dies hat wiederum einen optimalen Huffman-Code 00, 01, 10, 11. Oder wir können uns dies in Basis 4 vorstellen. Um ein Symbol zu codieren, tun wir einfach:
und dann .encode(s′,Ai)
Anhand unseres vorherigen Beispiels, , stellen wir fest, dass und und dann . Der neue Status ist 10101 in binär.s=11 s′=5 i=1 encode(5,A1)=4×5+1=21
Dies erzeugt nicht genau die gleiche Bitausgabe wie die Huffman-Codierung, sondern eine Ausgabe mit der gleichen Länge. Und ich hoffe, Sie können sehen, dass dies auch einzigartig dekodierbar ist. Um ein Symbol zu dekodieren, nehmen wir den Rest, wenn er durch 4 geteilt wird. Wenn der Wert 2 oder 3 ist, ist das Symbol B bzw. C. Wenn es 0 oder 1 ist, ist das Symbol A, und dann können wir das Informationsbit zurücksetzen, indem wir den Zustand mit 2 multiplizieren und entweder 0 oder 1 addieren.
Das Schöne an diesem Ansatz ist, dass er sich natürlich auf die Bruchbitcodierung erstreckt, wenn der Zähler und / oder der Nenner der Wahrscheinlichkeiten keine Zweierpotenzen sind. Angenommen, wir haben zwei Symbole, A und B, wobei die Wahrscheinlichkeit von A und die Wahrscheinlichkeit von B . Dann können wir ein Symbol codieren mit:35 25
Um das Symbol A zu codieren, nehmen wir und und dann .i=smod3codieren(s',Ai)s′=⌊s3⌋ i=smod3 encode(s′,Ai)
Dies entspricht einer arithmetischen Codierung. Es ist eigentlich eine Familie von Methoden, die als asymmetrische Zahlensysteme bekannt sind und in den letzten Jahren von Jarek Duda entwickelt wurden. Die Bedeutung des Namens sollte offensichtlich sein: Um ein Symbol mit der Wahrscheinlichkeit zu codieren , stehlen Sie konzeptionell eine Basis-p-Ziffer aus dem Status und fügen dann eine Basis-q-Ziffer hinzu. Die Asymmetrie ergibt sich aus der Interpretation des Zustands als Zahl in zwei verschiedenen Grundlagen.pq
Der Grund, warum es sich um eine Familie von Codierungsmethoden handelt, ist, dass das, was wir hier gesehen haben, für sich genommen unpraktisch ist. Es sind einige Änderungen erforderlich, um die Tatsache zu berücksichtigen, dass Sie wahrscheinlich keine Ganzzahlen mit unendlicher Genauigkeit haben, um die Statusvariable effizient zu manipulieren, und es gibt verschiedene Möglichkeiten, wie Sie dies erreichen können. Die arithmetische Codierung hat natürlich ein ähnliches Problem mit der Genauigkeit ihres Zustands.
Praktische Varianten sind rANS ("r" bedeutet "Verhältnis") und tANS ("tabellengesteuert").
ANS hat einige interessante Vorteile gegenüber der arithmetischen Codierung, sowohl in der Praxis als auch in der Theorie:
Ich glaube nicht, dass ich jemals wieder arithmetisch codieren werde.
quelle
Wenn Sie beispielsweise drei Symbole mit einer Wahrscheinlichkeit von jeweils 1/3 hätten, würde Ihre optimale Huffman-Codierung die drei Symbole 0, 10 und 11 mit einem Durchschnitt von 5/3-Bits verwenden.
Es gibt 243 Symbole, die durch Verketten von 5 der ursprünglichen Symbole mit einer Wahrscheinlichkeit von jeweils 1/243 erstellt wurden. Welches ist viel näher an 1/256. Die optimale Huffman-Codierung codiert 13 dieser Gruppen in 7 Bit und 230 Gruppen in 8 Bit für durchschnittlich 7,9465 Bit pro Gruppe oder 1,5893 Bit pro Originalsymbol, verglichen mit 1,6667 Bit für die ursprüngliche Huffman-Codierung, wobei die arithmetische Codierung 1,5850 beträgt Bits.
Theoretisch könnten Sie also einfach zwei Symbole zu einem größeren Symbol oder drei Symbole zu einem größeren Symbol kombinieren und die Hufman-Codierung für die Kombinationen verwenden.
quelle