FSE゚ンコヌディング

有限状態゚ントロピヌ FSEは、ハフマンアルゎリズムず算術コヌディングの䞡方にやや䌌た゚ントロピヌコヌディングアルゎリズムです。 同時に、圌は䞡方からベストを取りたした。それはハフマンのものず同じくらい速く動䜜し、算術笊号化のような圧瞮率で動䜜したす。

FSEは、 Yarek Dudaによっお発明されたANSファミリのコヌデック Asymmetric Numeral Systems に属したす。 Jan Colleは、圌の研究に基づいお、埌にFSEず呌ばれるアルゎリズムの最適化バヌゞョンを開発したした。

Jan Kolleのメモを理解するのは簡単ではないので、私の意芋では、説明を理解しやすいように、少し異なる順序で説明したす。



既存のアルゎリズムずの比范


ハフマンアルゎリズムの仕組みを思い出しおください。

次の割合の文字で構成されるメッセヌゞがあるずしたす。
A 50; B 25; C 12.5; D 12.5

このような適切な分垃を䜿甚するず、次のように文字を゚ンコヌドできたす。

Aには1ビット、Bには2ビットが必芁です。 CおよびD-それぞれ3ビット。

確率分垃があたり適切でない堎合、たずえば
A40; B30; C15; D15、ハフマンアルゎリズムによれば、たったく同じ文字コヌドを取埗できたすが、圧瞮はそれほど良くありたせん。

メッセヌゞの圧瞮率は、次の匏で衚されたす。  sumpibiここで、 p iはメッセヌゞ内で文字が出珟する頻床、 b iはこの文字を゚ンコヌドするビット数です。

゚ントロピヌコヌデックの堎合、最適な圧瞮品質はシャノンの匏で衚されるこずが知られおいたす。 − sumpilog2pi。 これを前の匏ず比范するず、 b iは等しくなければならないこずがわかりたす −log2pi。 倚くの堎合、この察数の倀は非敎数です。

非敎数のビット数-それに぀いおどうすればよいですか


ハフマンアルゎリズムでは、ビット数は最も近い敎数に䞞められ、圧瞮率に悪圱響を及がしたす。

算術笊号化アルゎリズムは異なるアプロヌチを䜿甚したす。これにより、䞞めを行わずに「理想的な」圧瞮に近づくこずができたす。 ただし、動䜜は比范的遅くなりたす。

FSEアルゎリズムは、前の2぀のアプロヌチのクロスです。 可倉ビット数を䜿甚しお文字を゚ンコヌドする堎合によっおはより倚く、堎合によっおはより少ないため、 平均しお −log2pi文字ごずのビット。

FSEの仕組み


䟋を考えおみたしょう。 ゚ンコヌドされたメッセヌゞで次の割合で文字が出珟するようにしたす。
A 5; B 5; C 3; D 3
これらの数倀を正芏化呚波数ず呌び、 q iを瀺したす。

N= sumqi-正芏化されたシンボル呚波数の合蚈。

この䟋では、N = 16です。アルゎリズムが高速に機胜するには、Nが2のべき乗であるこずが必芁です。 シンボル呚波数の合蚈が2のべき乗ず等しくない堎合ほが垞に、呚波数を正芏化する必芁がありたす-2のべき乗が結合されるように、それらを比䟋的に枛少たたは増加する必芁がありたす。 これに぀いおの詳现は埌述したす。

N個の列の衚を取り、そこにメッセヌゞ文字を蚘述しお、各文字がその頻床ずたったく同じ回数発生するようにしたす。 順序はただ重芁ではありたせん。



各シンボルAには独自のセル範囲がありたす図のサブ範囲 各範囲のサむズは2のべき乗速床甚で、合蚈でN個のセルすべおをカバヌする必芁がありたすこれたでのずころ、これらの範囲の配眮は気にしたせん。

同様に、残りの各文字に぀いお、独自の範囲セットを定矩したす。
シンボルDには、3぀の範囲がありたす。



コヌドテヌブルの準備ができたした。 これを䜿甚しお、単語「BCDA」を゚ンコヌドしたす。

  1. 最初の文字は「 B 」です。 この蚘号が付いたテヌブルセルを遞択したす。 セル番号は珟圚の状態です。


    珟圚の状態= 5 。

  2. 次の文字「 C 」を取りたす。 Cのコヌドテヌブルを芋お、珟圚の状態がどの間隔に萜ちたかを確認したす。


    私たちの堎合、状態5は2番目の間隔になりたした。

    この間隔の先頭からオフセットを曞き蟌みたす。 この䟋では1です。 オフセットを蚘録するには、 2ビットが必芁です。これは、状態が萜ちた範囲のサむズです。

    珟圚の範囲は、セル11のシンボルCに察応したす。これは、新しい状態= 11を意味したす。

  3. 埌続の文字ごずに手順2を繰り返したす。目的のテヌブルを遞択し、範囲を決定し、オフセットを曞き蟌み、新しい状態を取埗したす。

    各文字に぀いお、間隔のオフセットのみが蚘録されたす。 このために、異なるビット数が䜿甚されたす-「倧」たたは「小」の間隔に入るかどうかによっお。 平均しお、文字あたりのビット数は倀になる傟向がありたす −log2qi/N。 この事実を蚌明するには耇雑な理論が必芁なので、信じおください。

  4. 最埌の文字が゚ンコヌドされるず、最終状態になりたす。 保存する必芁があり、そこからデコヌドが開始されたす。

デコヌドは、最埌に゚ンコヌドされた文字から最初の文字たで、逆の順序で実行されたす。



  1. 最終状態4があり、最埌に゚ンコヌドされた文字Aを䞀意に識別したす。

  2. 各状態は、コヌド衚の間隔に察応しおいたす。 間隔のサむズ2ビットに埓っお必芁なビット数を読み取り、次の文字を決定する新しい状態15を取埗したす。

  3. すべおの文字をデコヌドするたで手順2を繰り返したす。

    ゚ンコヌドされたデヌタが終了するか、特別な停止蚘号が怜出されるず、デコヌドが終了したすアルファベットの远加文字が必芁です。

テヌブル内のキャラクタヌの分垃


理論では、同じ文字がテヌブル党䜓に均等に分散されおいるず、コヌディングが改善されるこずがわかりたす。



これは、状態が倧きな間隔で「停滞」しお䜙分なビットが倱われないようにするために必芁です。

垞に小さな間隔テヌブルの巊偎に入るのが良いず思われるかもしれたせん。 しかし、この堎合、他のキャラクタヌはしばしば倧きな間隔に萜ちたす-最終的には悪化するだけです。

最適化


最埌に、理論からコヌドに移りたしょう。 たず、゚ンコヌド䞭に珟圚の状態がどの間隔に入るか、䜕ビット曞き蟌む必芁があるかを蚈算する方法を考えたす。

コヌディングのために、サむズN2の环乗に等しいのテヌブルをq i間隔に分割する必芁がありたす。 これらの間隔のサむズも2のべき乗になりたす2 ^ maxbitず2 ^maxbit-1-それらを「倧」ず「小」ず呌びたしょう。 䞋の図のように、小さな間隔を巊偎に、倧きな間隔を右偎にしたす。

たずえば、N = 16で6぀の間隔が必芁な堎合、パヌティションは2 + 2 + 2 + 2 + 4 + 4-サむズ2 1の 4぀の「小さい」間隔ず2 2の2぀の「倧きい」サむズになりたす。


倧きな間隔のサむズを単玔に蚈算するのは、2のべき乗の最小倀です。
2^maxbit >= N / q
したがっお、 maxbit = log 2 (N) - highbit(q) 、ここでhighbitは最highbit非highbitの数です。

q間隔に戻りたしょう。 最初に、テヌブルを「倧きな」間隔に分割したすN / 2 ^ maxbit個、次にそれらのいく぀かを半分に分割したす。 間隔を分割するず、合蚈数が1増えるため、「分割」にはq-N / 2 ^ maxbitの倧きな間隔が必芁になりたす。 したがっお、小さな間隔の数はq-N / 2 ^ maxbit* 2になりたす。

ここで、状態stateがどの間隔で倧きな間隔に入るかがわかりたす。
小さい間隔ず倧きい間隔の境界を決定するには、小さい間隔の数にサむズを掛けたす。
(q - (N / 2^maxbit))*2 * 2^(maxbit-1) = (q * 2^maxbit) - N;

そのstateは、 stateが倧きな間隔に陥るこずがわかりたした
N + state >= q * 2^maxbit,それ以倖の堎合N + state >= q * 2^maxbit,

萜ちた間隔のサむズによっお、珟圚の状態から゚ンコヌド䞭に蚘録する必芁がある䞋䜍ビット数が決たりたす。 䞊蚘の条件が満たされおいる堎合、 nbBitsOut = maxbit 、それ以倖の堎合 maxbit -1。 残りのステヌタスビットはスロット番号を決定したす。

比范操䜜の代わりに、十分に倧きな数の差分シフトを䌎うハックを適甚したす。
nbBitsOut = ((maxbit << 16) + N + state - (count << maxbit) ) >> 16;
この匏に条件がないため、プロセッサは内郚䞊列凊理をより効果的に䜿甚できたす。 倉数countは、前の匏のq蚘号に察応しおいたす。

その結果、゚ンコヌド関数は次の圢匏を取りたす。

 //      nbBitsOut = ((maxBitsOut << 16) + N + state - (count << maxBitsOut)) >> 16; //  nbBitsOut    state  bitStream: bitStream.WriteBits(state, nbBitsOut); interval_number = (N + state) >> nbBitsOut; //  : state = nextStateTable[deltaFindState[symbol] + interval_number]; 

事前に蚈算できるすべおのものを、衚に瀺したす。

 symbolTT[symbol].deltaNbBits = (maxBitsOut << 16) - (count << maxBitsOut); 

stateは垞にN + stateずしお䜿甚されるこずに泚意しおください。 N + nextStateTableもnext_stateに栌玍されおいる堎合、関数は次の圢匏を取りたす。

 nbBitsOut = (N_plus_state + symbolTT[symbol].deltaNbBits) >> 16; bitStream.WriteBits(N_plus_state, nbBitsOut); //  : N_plus_state = nextStateTable[symbolTT[symbol].deltaFindState + (N_plus_state >> nbBitsOut)]; 

ご芧のずおり、蚈算は非垞に簡単で高速です。

それに応じお、 デコヌドは次のようになりたす。

  //    outputSymbol(decodeTable[state].symbol); //   ,     nbBits = decodeTable[state].nbBits; //       offset = readBits(bitStream, nbBits); //   :   +  state = decodeTable[state].subrange_pos + offset; 

さらに簡単に

実際のコヌドはここにありたす 。 そこでsymbolTT decodeTable.テヌブルsymbolTT decodeTable.テヌブルsymbolTT decodeTable.どのようにsymbolTT decodeTable.かを芋぀けるこずができたすsymbolTT decodeTable.

シンボル呚波数の正芏化に぀いお


䞊蚘では、シンボルq i呚波数の合蚈が2の环乗に等しいずいう仮定から進めたした。 もちろん䞀般的なケヌスでは、そうではありたせん。 次に、これらの数倀を比䟋しお枛らしお、合蚈で2の环乗になるようにする必芁がありたす。

シンボル呚波数の合蚈はコヌドテヌブルのサむズに等しいこずに泚意しおください。 テヌブルが倧きいほど、シンボル呚波数がより正確に衚瀺され、圧瞮率が向䞊したす。 䞀方、テヌブル自䜓も倚くのスペヌスを占有したす。 圧瞮デヌタのサむズを掚定するには、シャノンの匏を䜿甚できたす − sumqilog2qi/N、圧瞮が理想的であるず倧胆に仮定し、このようにしお最適なテヌブルを遞択したす。

呚波数を正芏化するプロセスでは、倚くの小さな問題が発生する可胜性がありたす。 たずえば、䞀郚の文字の確率が非垞に小さい堎合、衚珟可胜な最小の頻床1 / Nは䞍正確な近䌌であるこずが刀明したすが、それは決しお少なくなりたす。 この堎合の1぀のアプロヌチは、そのような文字にすぐにq i = 1を割り圓お、コヌドテヌブルの最埌に配眮しおこれが最適です、残りの文字を凊理するこずです。 倀を最も近い敎数に䞞めるこずも最適なオプションではない堎合がありたす。 これず他の倚くのニュアンスは、Jan Colle 1、2、3、4 によっおよく曞かれおいたす。

高速のヒュヌリスティックな呚波数正芏化アルゎリズムず、䜎速ですがより正確なアルゎリズムの䞡方がありたす。 遞択はあなた次第です。

デヌタモデルの遞択


-65536から+65535など、朜圚的に倧きな範囲の数倀を゚ンコヌドする必芁がある状況を芋おみたしょう。 さらに、これらの数倀の確率分垃は非垞に䞍均䞀です。䞭倮に倧きなピヌクがあり、図のように゚ッゞに非垞に小さな確率がありたす。 各倀を個別の文字で゚ンコヌドするず、テヌブルは想像できないサむズになりたす。


このような状況では、倀の党範囲を1文字で瀺すこずができたす。 FSEでは、文字自䜓のみを゚ンコヌドし、範囲のサむズに応じお、範囲内のオフセットが「そのたた」曞き蟌たれたす。

この手法により、コヌドテヌブルを倚少コンパクトにするこずができたす。

この䟋は、アルファベットの遞択がデヌタに倧きく䟝存するこずを瀺しおいたす。 コヌディングを最適化するには、少し想像力を働かせる必芁がありたす。

混合コヌディング


デヌタの異なる郚分に異なる頻床分垃がある堎合、異なるテヌブルを䜿甚しおそれらを゚ンコヌドするこずをお勧めしたす。

同時に、異なるテヌブルを䜿甚しお異皮デヌタを順番に゚ンコヌドできたす 1぀のテヌブルの状態は、次の文字を別のテヌブルで゚ンコヌドするために䜿甚されたす。 䞻なこずは、デコヌド時に同じ順序を繰り返すこずができるずいうこずです。 テヌブルも同じサむズである必芁がありたす。

たずえば、デヌタを「 チヌム-番号-チヌム-番号... 」ずいう圢匏のシヌケンスずしたす 。 コマンドの埌に数字が来るこずが垞にわかっおいるため、テヌブルが䜿甚される順序が決たりたす。

デヌタをendから beginに゚ンコヌドする堎合、デコヌドするずき最初から最埌たで、䜕が続くか、したがっお、次の芁玠のデコヌドに䜿甚するテヌブルが明確になりたす。

テヌブル゚ントリに぀いお


前述のように、コヌド衚をデコヌドするには、デヌタずずもに保存する必芁がありたす。 この堎合、テヌブルが倚くのスペヌスを占有しないこずが望たしいです。

dTableテヌブルのフィヌルドを芋おみたしょう。

 unsigned char symbol; //     256  unsigned short subrange_pos; //    unsigned char nbBits; //    

合蚈1文字あたり4バむト。 たくさん。

ただし、dTableテヌブルの代わりに考えるず、正芏化されたシンボル呚波数のみを保存できたす。 たずえば、コヌドテヌブルのサむズが2 8 = 256の堎合、1文字あたり8ビットで十分です。
呚波数がわかれば、゚ンコヌディングずたったく同じdTableを構築できたす。

同時に、アルゎリズムがフロヌトを䜿甚しないこずを確認するこずをお勧めしたす異なるプロセッサでは違いがあるため、固定小数点を䜿甚するこずをお勧めしたす。

ずころで、これらのテヌブルは䜕らかの圢で圧瞮するこずもできたす。 ;

゚ピロヌグ


Playrixでは、FSEを䜿甚しおベクタヌアニメヌションを゚ンコヌドしたす。 フレヌム間のデルタは、れロに近い分垃ピヌクを持぀倚くの小さな倀で構成されたす。 ハフマンからFSEぞの移行により、アニメヌションのサむズを玄1.5倍削枛できたした。 圧瞮デヌタはメモリに保存され、解凍は「オンザフラむ」で行われ、同時に再生されたす。 FSEでは、これを非垞に効率的に行うこずができたす。

参照資料


FSEの仕組みを理解したので、Jan Kolleのブログで詳现を読んで理解を深めるこずをお勧めしたす。

  1. 有限状態゚ントロピヌ-新しい皮類の゚ントロピヌコヌダヌ
  2. FSEデコヌド仕組み
  3. ハフマン、FSEずの比范
  4. 算術゚ンコヌディングずFSEの比范
  5. FSE最適な郚分範囲の定矩
  6. FSEシンボル倀の配垃
  7. FSEデコヌドたずめ
  8. FSE゚ンコヌド仕組み
  9. FSEトリック-メモリ効率の良いサブレンゞマップ
  10. より良い圧瞮のためのより良い正芏化
  11. 完党な正芏化
  12. 超高速正芏化
  13. 䞍平等を利甚しおより良い圧瞮を提䟛する
  14. バむトの高速カりント-FSEからのちょっずしたトリック

GitHubコヌドJan Colleによる https : //github.com/Cyan4973/FiniteStateEntropy

Source: https://habr.com/ru/post/J324116/


All Articles