Esiste una generalizzazione della codifica di Huffman in codifica aritmetica?


11

Nel tentativo di comprendere le relazioni tra Huffman Coding, Arithmetic Coding e Range Coding, ho iniziato a pensare alle carenze della codifica Huffman legate al problema del bit packing frazionario .

Cioè, supponiamo che tu abbia 240 possibili valori per un simbolo e che sia necessario codificarlo in bit, rimarrai bloccato con 8 bit per simbolo, anche se non hai bisogno di un "pieno" 8, in quanto 8 può esprimere 256 possibili valori per simbolo. Una soluzione a questo problema è qualcosa che ho visto indicato come "impacchettamento di bit frazionario", in cui si è in grado di "cambiare bit" da una non-potenza di due usando la moltiplicazione. Proprio come la moltiplicazione dei poteri di due si sta spostando x * 2 == x << 1e x * 4 == x << 2così via per tutti i poteri di due, così anche tu puoi "spostare" con un non-potere di 2 moltiplicando invece e racchiudendo simboli frazionari .

Il problema è simile con la codifica Huffman: si finisce con codici che devono essere di lunghezza non frazionaria, e quindi ha questa inefficienza di impacchettamento. Tuttavia, non puoi semplicemente usare la soluzione di fracitonal-bit-packing, poiché questa soluzione assume simboli di dimensioni fisse.

La domanda è: ci sono documenti o soluzioni per migliorare la codifica di Huffman con un'idea simile a quella del bit-packing frazionario per ottenere qualcosa di simile alla codifica aritmetica? (o qualsiasi risultato contrario).


1
La codifica aritmetica è già ottimale. Non è necessario migliorarlo.
Yuval Filmus,

@YuvalFilmus sì, intendevo come migliorare la codifica huffman per portarla alla pari con la codifica aritmetica.
Realz Slaw,

1
Proprio come un suggerimento, potresti trovare la codifica del sistema numerico asimmetrico (ANS) più facile da comprendere della codifica aritmetica. In particolare, è un po 'più facile vedere quella particolare formulazione come "impaccamento di bit frazionario".
Pseudonimo del

@Pseudonimo Ho trovato questa pagina che sembra rendere questa connessione tra rANS e Huffman Coding. Non posso dire di averlo ancora capito, ma penso che sia sufficiente. Se fai una risposta al commento, accetto.
Realz Slaw,

@YuvalFilmus Spero di aver sostenuto che la codifica aritmetica necessitava di un miglioramento e ANS è un miglioramento.
Pseudonimo,

Risposte:


12

Diamo un'occhiata a un modo leggermente diverso di pensare alla codifica di Huffman.

Supponiamo di avere un alfabeto di tre simboli, A, B e C, con probabilità 0,5, 0,25 e 0,25. Poiché le probabilità sono tutte potenze inverse di due, questo ha un codice Huffman che è ottimale (cioè è identico alla codifica aritmetica). Useremo il codice canonico 0, 10, 11 per questo esempio.

Supponiamo che il nostro stato sia un intero di grandi dimensioni, che chiameremo . Puoi pensare alla codifica come una funzione che accetta lo stato corrente e un simbolo per codificare e restituisce il nuovo stato:S

codificare(S,UN)=2Scodificare(S,B)=4S+2codificare(S,C)=4S+3

Quindi cominciamo con lo stato 11 (che è 1011 in binario), codificate il simbolo B. Il nuovo stato è 46, che è 101110 in binario. Come puoi vedere, questo è lo stato "vecchio" con la sequenza 10 aggiunta alla fine. Abbiamo essenzialmente "emesso" la sequenza di bit 10.

Fin qui tutto bene.

Ora pensa per un momento a come funziona la codifica aritmetica. Se metti le probabilità su un comune denominatore, il simbolo A rappresenta effettivamente l'intervallo , il simbolo B rappresenta l'intervallo[2[04,24)e il simbolo C rappresenta l'intervallo[3[24,34).[34,44)

Fondamentalmente quello che stiamo facendo qui è moltiplicare tutto per il comune denominatore. Immagina che lo stato fosse effettivamente nella base 4. La codifica di un simbolo B sta davvero emettendo la cifra 2 in quella base, e la codifica di un simbolo C sta emettendo la cifra 3 in quella base.

Tuttavia, il simbolo A è leggermente diverso, poiché non è una cifra intera nella base 4.

Invece, possiamo pensare all'alfabeto come l'insieme dei simboli A_0, A_1, B, C, con uguale probabilità. Questo, ancora una volta, ha un codice Huffman ottimale 00, 01, 10, 11. O, ancora, possiamo pensarlo in base 4. Per codificare un simbolo, facciamo semplicemente:

codificare(S,UN0)=4S+0codificare(S,UN1)=4S+1codificare(S,B)=4S+2codificare(S,C)=4S+3

UN0UN1

S

S'=S2
io=Smod2

encode(s,Ai)

s=11s=5io=1codificare(5,UN1)=4×5+1=21

Questo non produce esattamente lo stesso bit output della codifica Huffman, ma genera un output che ha la stessa lunghezza. E quello che spero che possiate vedere è che anche questo è unicamente decodificabile. Per decodificare un simbolo, prendiamo il resto quando diviso per 4. Se il valore è 2 o 3, allora il simbolo è rispettivamente B o C. Se è 0 o 1, il simbolo è A, quindi possiamo riportare il bit di informazione moltiplicando lo stato per 2 e aggiungendo 0 o 1.

3525

codificare(S,UN0)=5S+0codificare(S,UN1)=5S+1codificare(S,UN2)=5S+2codificare(S,B0)=5S+3codificare(S,B1)=5S+4

S'=S3io=Smod3codificare(S',UNio)

pq

Il motivo per cui è una famiglia di metodi di codifica è che ciò che abbiamo visto qui non è pratico da solo; ha bisogno di alcune modifiche per far fronte al fatto che probabilmente non hai numeri interi a precisione infinita per manipolare la variabile di stato in modo efficiente e ci sono vari modi per raggiungere questo obiettivo. La codifica aritmetica, ovviamente, ha un problema simile con precisione per il suo stato.

Le varianti pratiche includono rANS ("r" significa "rapporto") e tANS ("guidato dalla tabella").

ANS presenta alcuni vantaggi interessanti rispetto alla codifica aritmetica, sia pratica che teorica:

  • A differenza della codifica aritmetica, lo "stato" è una singola parola, piuttosto che una coppia di parole.
  • Non solo, ma un codificatore ANS e il relativo decodificatore hanno stati identici e le loro operazioni sono completamente simmetriche. Ciò solleva alcune possibilità interessanti, come ad esempio che puoi intercalare diversi flussi di simboli codificati e tutto si sincronizza perfettamente.
  • Le implementazioni pratiche devono, ovviamente, "produrre" informazioni man mano che procedi, e non solo raccoglierle in un intero grande da scrivere alla fine. Tuttavia, la dimensione dell '"output" può essere configurata in cambio di una perdita di compressione (generalmente modesta). Pertanto, laddove i programmatori aritmetici devono emettere un po 'alla volta, ANS può emettere un byte o un nybble alla volta. Questo ti dà un compromesso diretto tra velocità e compressione.
  • Sembra essere veloce tanto quanto l'hardware di generazione attuale quanto la codifica aritmetica binaria, e quindi competitivo con la codifica Huffman. Ciò lo rende molto più veloce della codifica aritmetica a caratteri alfabetici di grandi dimensioni e delle sue varianti (ad es. Codifica di intervallo).
  • Sembra essere privo di brevetti.

Non credo che farò mai più codifica aritmetica.


3
Questa è la spiegazione più chiara sulla codifica ANS che io abbia mai visto.
Michael Deardeuff,

2

Ad esempio, se avessi tre simboli con probabilità 1/3 ciascuno, la tua codifica Huffman ottimale userebbe i tre simboli 0, 10 e 11 con una media di 5/3 bit.

Ci sono 243 simboli creati concatenando 5 dei simboli originali, ognuno con probabilità 1/243. Che è molto più vicino a 1/256. La codifica Huffman ottimale codificherà 13 di questi gruppi in 7 bit e 230 gruppi in 8 bit, per una media di 7,9465 bit per gruppo o 1,5893 bit per simbolo originale, in calo da 1,66667 bit per la codifica Huffman originale, con una codifica aritmetica di 1,5850 bit.

Quindi in teoria potresti semplicemente combinare due simboli ciascuno in un simbolo più grande, o tre simboli ciascuno in un simbolo più grande, e usare la codifica Hufman per le combinazioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.