この質問は、範囲を格納するために必要なビット数についてです。または別の言い方をすると、与えられたビット数に対して、保存できる最大範囲はどのくらいですか?
0-255の範囲内のサブ範囲を格納したいとします。
たとえば、45-74です。
上記の例は2つの符号なしバイトとして格納できますが、そこには情報の冗長性が必要だと思います。 2番目の値が最初の値よりも大きいことがわかっているため、最初の値が大きい場合は2番目の値に必要なビットが少なくなり、2番目の値が大きい場合は最初の値に必要なビットが少なくなります。 。
どんな圧縮手法でも限界的な結果がもたらされるのではないかと思うので、「1バイトに格納できる最大範囲はいくつですか?」これは、2つの数値を別々に格納することで得られる値よりも大きくする必要があります。
この種のことを行うための標準的なアルゴリズムはありますか?
可能な範囲の数を数えるだけです。下限0(0-0、0-1、... 0-254、0-255)の256の範囲、下限1の255の範囲、そして最後に下限255(255- 255)。したがって、合計数は(256 + 255 + ... + 1)= 257 * 128 = 32,896になります。これは2より少し高いので15 = 32,768。この情報を保存するには、少なくとも16ビット(2バイト)が必要です。
一般に、0からn-1までの数値の場合、可能な範囲の数はn *(n + 1)/ 2です。 nが22以下の場合、これは256未満です。n= 22は22 * 23/2 = 253の可能性を与えます。つまり1バイト-21のサブ範囲には十分です。
問題を調べる別の方法は次のとおりです。0からn-1の範囲の整数のペアを格納することは、0n-1)にサブレンジを追加して格納することとほぼ同じです---(単一ビット =最初の数値が2番目の数値より小さいか大きいかを決定します。 (違いは両方の整数が等しい場合から来ますが、nが大きくなるにつれてこの可能性はますます小さくなります。)このため、この手法では1ビット程度しか節約できず、おそらくそれがほとんど使用されない主な理由です。
そのようなビット数が少ない場合、 Glorfindelが指摘した のように多くのビットを保存することは不可能です。ただし、使用しているドメインのビット数がさらに多い場合は、範囲を開始値とデルタでエンコードすることにより、平均的なケースで大幅な節約を実現できます。
ドメインが整数、つまり32ビットであると仮定しましょう。単純なアプローチでは、範囲を格納するために64ビット(開始、終了)が必要です。
(start、delta)のエンコーディングに切り替えると、それから範囲の終わりを構築できます。最悪の場合、開始は0で、デルタは32ビットです。
2 ^ 5は32であるため、デルタの長さを5ビットでエンコードし(ゼロ長なし、常に1を追加)、エンコーディングは(開始、長さ、デルタ)になります。最悪の場合、これは32 * 2 + 5ビットなので、69ビットになります。したがって、最悪の場合、すべての範囲が長いと、これは単純なエンコーディングよりも悪くなります。
最良のケースでは、32 + 5 + 1 = 38ビットです。
つまり、多くの範囲をエンコードする必要があり、それらの範囲がそれぞれドメインのごく一部しかカバーしていない場合、平均してより少ないスペースを使用することになりますこのエンコーディングを使用します。開始は常に32ビットを取るため、開始がどのように分散されるかは関係ありませんが、範囲の長さがどのように分散されるかは重要です。長さが短いほど、圧縮率が高くなり、ドメインの全長をカバーする範囲が増えるほど、このエンコーディングは悪化します。
ただし、(たとえば、センサーから値を取得するため)同様の開始点の周りにグループ化された範囲のロットがある場合、さらに大きな節約を達成できます。同じ手法を開始値に適用し、バイアスを使用して開始値をオフセットすることができます。
10000個の範囲があるとします。範囲は特定の値を中心にグループ化されます。バイアスを32ビットでエンコードします。
単純なアプローチを使用すると、これらのすべての範囲を格納するために32 * 2 * 10 000 = 640 000ビットが必要になります。
バイアスのエンコードには32ビットが必要で、各範囲のエンコードには5 + 1 + 5 + 1 = 12ビットが最適で、合計で120 000 + 32 = 120 032ビットになります。最悪の場合、5 + 32 + 5 + 32ビット、つまり74ビットが必要になり、合計で740 032ビットになります。
つまり、エンコードに32ビットを必要とするドメインの10 000個の値に対して、
ナイーブエンコーディングをベースラインとする場合、最大81.25%または最大15.625%のコスト削減を意味します。
値がどのように配分されるかに応じて、これらの節約は重要です。あなたのビジネスドメインを知ってください!何をエンコードしたいかを知ってください。
拡張機能として、バイアスを変更することもできます。データを分析して値のグループを識別する場合、データをバケットに分類し、それらのバケットをそれぞれ独自のバイアスで個別にエンコードできます。つまり、この手法は、1つの開始値を中心にグループ化されている範囲だけでなく、複数の値を中心にグループ化されている範囲にも適用できます。
開始点が均等に分散されている場合、このエンコーディングは実際にはうまく機能しません。
このエンコーディングは明らかにインデックス化に非常に悪いです。単にx番目の値を読み取ることはできません。それはほとんど順番に読むことができるだけです。これは、状況によっては適切です。ネットワークまたはバルクストレージ(テープやHDDなど)を介したストリーミング。
データの評価、グループ化、正しいバイアスの選択は、かなりの作業になる可能性があり、最適な結果を得るために微調整が必要になる場合があります。
この種の問題は、Claude Shannonの独創的な論文 Aの数学的理論 の主題であり、Wordの「ビット」を導入し、多かれ少なかれデータ圧縮を発明しました。
一般的な考え方は、範囲のエンコードに使用されるビット数は、その範囲が発生する確率に反比例するということです。たとえば、45〜74の範囲が時間の約1/4であるとします。シーケンス00は45-74に対応すると言えます。 45〜74の範囲をエンコードするには、「00」を出力してそこで停止します。
また、99〜100と140〜155の範囲がそれぞれ約1/8の時間で表示されるとします。それぞれを3ビットシーケンスでエンコードできます。 45〜74の範囲ですでに予約されている「00」で始まらない限り、どの3ビットでも機能します。
00: 45-74
010: 99-100
101: 140-155
すべての可能な範囲がエンコードされるまで、この方法で続行できます。確率が最も低い範囲では、100ビット以上が必要になる場合があります。しかし、ほとんど表示されないので問題ありません。
最適なコーディングを見つけるためのアルゴリズムareがあります。ここでは説明しませんが、詳細は上記のリンクにアクセスするか、「情報理論」、「シャノンファーノコーディング」、または「ハフマンコーディング」を検索してください。
他の人が指摘したように、開始番号と開始番号と終了番号の差を保存しておく方が良いでしょう。確率分布が異なるため、最初のコーディングと差異のコーディングを使用する必要があります(後者の方が冗長であると思います)。 polygnomeが示唆しているように、最適なアルゴリズムはドメインによって異なります。
@Glorfindelからの答えを拡張するには:
N→∞として、(n-1)→n。したがって、Ω(範囲)→n²/ 2およびlog(Ω(範囲))→(2n-1)。単純なエンコードでは2nビットを使用するため、漸近最大圧縮では1ビットしか節約できません。
同様の答えがありますが、最適な圧縮を実現するには、次のものが必要です。
重要なのは、2番は、最も有益な値(ビットごとのエンコード)が最初になるようにエンコードすることを意味します。たとえば、並べ替えられたリストを「そのまま」エンコードすることを提案しましたが、通常、「バイナリツリー」としてエンコードする方が賢明です。つまり、幅で並べ替えられており、len
要素、要素len/2
をエンコードすることから始めます。幅wあるとしましょう。これで、[0、w]のどこかに幅がある前のすべての要素と、[w、max val受け入れる]のどこかに幅がある後のすべての要素がわかりました。 len
要素をカバーするまで、再帰的に繰り返します(各半分のリストを半分に分割するなど)(修正されていない限り、最初にlen
をエンコードする必要があるため、終了トークンに煩わされる)。 「max val you accept」が本当に開かれている場合、最初に実際にデータに表示される最大値、つまり最後の要素をエンコードし、、次にバイナリパーティショニングを行います。繰り返しますが、最初にビットごとに最も有益なものは何でもです。
また、間隔の幅を最初にエンコードしていて、処理している可能な最大値がわかっている場合は、明らかに、オーバーフローするすべての開始値を除外することができます...デコード時に残りのデータについて可能な限り推測できるようにデータを変換および順序付けします。最適なエントロピーエンコードアルゴリズムにより、「既知の」ビットエンコード情報を無駄にしないようにします。 。