浮動小数点時系列データに適用できるロスレス圧縮方法はありますか。たとえば、データをバイナリとしてファイルに書き込んでgzipで実行すると、パフォーマンスが大幅に向上しますか?
精度の低下は許容できるかもしれませんが、制御された方法で発生する必要があります(つまり、保持する必要がある桁数に限界を設定できる必要があります)
時間の関数を記述する一連の相関double
sであるいくつかの大きなデータファイルで作業しています(つまり、値は相関しています)。通常、完全なdouble
精度は必要ありませんが、float
より多くの精度が必要になる場合があります。
画像/音声にはロスレスの特殊な方法があるため、この状況に特化したものが存在するのではないかと思っていました。
説明:このようなものを実装する方法を説明する論文ではなく、既存の実用的なツールを探しています。速度のgzipに匹敵するものは素晴らしいでしょう。
以下のリソースをご覧ください。
また、 Logluv-compressed TIFF を試してみることもできます。自分で使ったことはないと思います。
独自の単純なアルゴリズムを作成する場合のアイデアをいくつか次に示します。
「float」と「double」の間のどこかに精度が必要であると述べたので、単精度および倍精度の浮動小数点の最下位ビットをいくつでもゼロにできます。 IEEE-754浮動小数点数は、おおよそseeefffffffff
のようにバイナリで表され、値を表します
sign * 1.fffffff * 2 ^(eee)。
最下位(f)ビットをゼロにできます。単精度(32ビット)浮動小数点数の場合、23の小数ビットがあり、最大で22までゼロ化できます。倍精度(64ビット)の場合は、52から最大51です。(すべてのビットをゼロ化する場合、その後、特別な値NaNおよび+/- infは失われます)。
特に、データが1.2345などの10進数値を表す場合、これはデータ圧縮に役立ちます。これは、1.2345を2進浮動小数点値として正確に表すことができないため、データ圧縮に適さない0x3ff3c083126e978d
として表すことができるためです。最下位の24ビットを切り落とすと、0x3ff3c08312000000
が生成されますが、これは10桁の約9桁まで正確です(この例では、差は1.6e-9です)。
これを生データで実行し、その後の連続番号の違いを保存すると、生データの変化が遅い場合に、(gzipを使用して)圧縮しやすくなります。
Cの例を次に示します。
#include <inttypes.h>
double double_trunc(double x, int zerobits)
{
// mask is e.g. 0xffffffffffff0000 for zerobits==16
uint64_t mask = -(1LL << zerobits);
uint64_t floatbits = (*((uint64_t*)(&x)));
floatbits &= mask;
x = * ((double*) (&floatbits));
return x;
}
そして、python/numpyの1つ:
import numpy as np
def float_trunc(a, zerobits):
"""Set the least significant <zerobits> bits to zero in a numpy float32 or float64 array.
Do this in-place. Also return the updated array.
Maximum values of 'nzero': 51 for float64; 22 for float32.
"""
at = a.dtype
assert at == np.float64 or at == np.float32 or at == np.complex128 or at == np.complex64
if at == np.float64 or at == np.complex128:
assert nzero <= 51
mask = 0xffffffffffffffff - (1 << nzero) + 1
bits = a.view(np.uint64)
bits &= mask
Elif at == np.float32 or at == np.complex64:
assert nzero <= 22
mask = 0xffffffff - (1 << nzero) + 1
bits = a.view(np.uint32)
bits &= mask
return a
既存のツールを求めているので、多分 zfp でうまくいくでしょう。
浮動小数点圧縮に使用できる可能な方法:
Floatの場合は4xN、double + lz77の場合は8xNを転置します
実装: TurboTransposeでの浮動小数点圧縮
エラー制限付き不可逆圧縮も参照
予測子(例:有限コンテキストメソッド)+エンコード(例: "整数圧縮")。
実装: TurboPForの浮動小数点圧縮
可能であれば、すべての浮動小数点数を整数に変換します(例:1.63-> 163)、
その後、整数圧縮を使用します
実装: 整数圧縮
LinuxおよびWindows用の icapp ツールを使用して、これらのすべてのメソッドをデータでテストできます。
HDF5の人々が使用する1つの手法は「シャッフル」で、N個の浮動小数点値の各バイトをグループ化します。これは、gzipでよりよく圧縮される反復的なバイトシーケンスを提供する可能性が高くなります たとえば 。
圧縮されたgzip圧縮されたデータのサイズを大幅に削減する2つ目の方法は、最初にデータを float16(半精度)形式 に変換し、再びfloat32に戻すことです。これにより、出力ストリームに多くのゼロが生成され、圧縮後にファイルサイズを約40〜60%縮小できます。微妙な点の1つは、float16の最大値がかなり低いことです。そのため、最初にデータをスケーリングすることをお勧めします。 Pythonで
import numpy as np
import math
input = np.array(...)
# format can only hold 65504 maximum, so we scale input data
log2max = int(math.log(np.nanmax(input), 2))
scale = 2**(log2max - 14)
scaled = input * (1./scale)
# do the conversion to float16
temp_float16 = np.array(scaled, dtype=np.float16)
# convert back again and rescale
output = np.array(temp_float16, dtype=np.float32) * scale
一部のテストでは、一部のデータの入力と出力の間の平均絶対フラクショナル差が約0.00019で最大が0.00048であることが示唆されています。これは、仮数の2 ** 11精度と一致しています。
Holtの指数平滑化アルゴリズム(予測ベースの圧縮アルゴリズム)を使用できます。最初にデータにいくつかの重みを割り当て、次の値を予測します。両方のデータが同じ場合、XOR演算を実行することにより、MSBに多くのゼロが生成されます