3

これは、numpyで実装するのが非常に簡単な特定の種類の不可逆圧縮です。

原則として、元の(float64)と再構築された(float64(float32(original))を直接比較して、最大誤差などを知ることができます。

私の実際のデータの最大誤差を見る以外に、たとえば元の値の大きさの関数として、これがどのような種類の歪みを作成するかについて誰かが良い考えを持っていますか?

すべての値(64ビット)を最初に[-1,1]にマッピングして(64ビットで保持できる極値の一部として)、ゼロに近いフロートの密度を高める方がよいでしょうか。 ?

私が念頭に置いている特定のケースを追加しています。-20から20の範囲の500kから1e6の値があり、それらはおよそIID〜Normal(mu = 0、sigma = 4)であるため、すでにゼロ近くにかなり集中しており、「20」は約5シグマのレアです。 。それらが科学的な測定値であり、真の精度が64ビットフロートよりもはるかに低いとしましょう。ただし、正確に知ることは困難です。私はたくさんの個別のインスタンス(潜在的にTBの価値)を持っているので、圧縮には多くの実用的な価値があり、float32は50%を取得するための迅速な方法です(そして、どちらかといえば、gzipのようなロスレス圧縮の追加ラウンドでよりうまく機能します)。したがって、「-20から20」は、非常に大きな値に関する多くの懸念を排除します。

4

3 に答える 3

7

以下は、通常の最も近い丸めモードで一般的な(一部の例外を除いて)標準のIEEE-754浮動小数点演算を使用していることを前提としています。

double値がfloat値の通常の範囲内にある場合、doubleがfloatに丸められるときに発生する唯一の変更は、仮数(値の小数部分)が53ビットから24ビットに丸められることです。これにより、最大で1/2 ULP(最小精度の単位)のエラーが発生します。フロートのULPは、フロートより大きくない2の最大累乗の2〜23倍です。たとえば、フロートが7.25の場合、2の最大の累乗は4以下であるため、そのULPは4 * 2 -23 = 2 -21、約4.77e-7です。したがって、区間[4、8)のdoubleがfloatに変換されるときの誤差は、最大で2 -22、約2.38e-7です。別の例として、フロートが約.03の場合、2の最大の累乗は2-6以下です、したがって、ULPは2 -29であり、doubleに変換するときの最大エラーは2-30です。

これらは絶対的なエラーです。相対誤差は2-24未満です。これは、1/2 ULPを可能な最小値で割ったものです(特定のULPの間隔内の最小値、つまり2の累乗で境界を定めます)。たとえば、[4、8)の各数値xについて、数値は少なくとも4であり、誤差は最大で2 -22であることがわかっているため、相対誤差は最大で2 -22/4 = 2-24です。(2の正確な累乗をfloatからdoubleに変換するときにエラーがないため、エラーを正確に2〜24にすることはできません。したがって、xが4より大きい場合にのみエラーが発生し、相対エラーは以下になります。 、2 -24。)変換される値について詳しく知っている場合、たとえば、値が4よりも8に近い場合は、エラーをより厳密に制限できます。

数値がフロートの通常の範囲外である場合、エラーが大きくなる可能性があります。最大の有限浮動小数点値は2128-2 104、約3.40e38です1/2 ULP(floatの; doublesはより細かいULP)であるdoubleをfloatに変換すると、無限大が返されます。これは、もちろん、無限の絶対誤差と無限の相対誤差です。(最大有限フロートよりも大きいが、1/2 ULP未満のdoubleは、最大有限フロートに変換され、前の段落で説明したのと同じエラーが発生します。)

最小の正の通常のフロートは2-126、約1.18e-38です。これ(両端を含む)の1/2 ULP以内の数値はそれに変換されますが、それ未満の数値は、ULPが2-149に固定されている特別な非正規化形式に変換されます。絶対誤差は最大で1/2ULP、2-150になります。相対誤差は、変換される値に大きく依存します。

上記は正の数について説明しています。負の数の誤差は対称的です。

doubleの値をfloatとして正確に表すことができれば、変換にエラーはありません。

入力番号を新しい間隔にマッピングすると、特定の状況でのエラーを減らすことができます。不自然な例として、すべての数値が区間[ 2 48、2 48 +2 24 の整数であると仮定します。次に、それらをfloatに変換すると、値を区別するすべての情報が失われます。それらはすべて248に変換されます。ただし、それらを[0、2 24)にマッピングすると、すべての情報が保持されます。それぞれの異なる入力は、異なる結果に変換されます。

どのマップが目的に最も適しているかは、特定の状況によって異なります。

于 2012-06-13T17:06:23.847 に答える
5

分布はゼロを中心としているため、単純な変換によってエラーが大幅に減少する可能性はほとんどありません。

スケーリングは、2つの方法でのみ効果があります。1つは、単精度値の非正規化区間から値を移動します(-2 -126、2 -126 。(たとえば、[2 -249、2 -126)にあった2 123の値を乗算すると、[ 2 -126、2 -3)にマップされます。これ正規化数の間隔の外にあります。)2つ目は変化します。ここで、値は各「binade」にあります(2の累乗から次の累乗への間隔)。たとえば、最大値は20で、相対誤差は1/2 ULP / 20であり、そのビネードのULPは16 * 2 -23 = 2 -19であるため、相対誤差は1/2*2-である可能性があります。 19/ 20、約4.77e-8。32/20でスケーリングすると、20未満の値は32未満の値になります。次に、floatに変換すると、相対誤差は最大で1/2 * 2 -19 / 32(または32未満)になります。 2.98e-8。したがって、エラーをわずかに減らすことができます。

前者に関しては、値がほぼ正規分布している場合、その間隔が非常に小さいという理由だけで、(- 2 -126、2 -126 )に含まれるものはほとんどありません。(正規分布の1兆サンプルは、ほぼ確実にその間隔に値がありません。)これらは科学的な測定値であると言うので、おそらく何らかの機器で生成されます。マシンが2-126から20の範囲の値を返すのに十分なほど細かく測定または計算していない可能性があるため、非正規化数の間隔に値がまったくない場合でも、私は驚かないでしょう。単精度の非正規化数の範囲に値がない場合、その範囲を回避するためのスケーリングは役に立ちません。

後者に関しては、範囲の最後でわずかな改善が利用可能であることがわかります。ただし、範囲内の他の場所では、一部の値もビネードの上限に移動されますが、一部の値はビネード境界を越えて新しいビネードの下限に移動されるため、相対誤差が増加します。大幅な純改善はありそうにありません。

一方、アプリケーションにとって何が重要かはわかりません。アプリケーションはどのくらいのエラーを許容できますか?各数値に1%のランダムノイズを加えると、最終的な結果の変化は目立たなくなりますか?または、いくつかの数値が2〜200だけ変化した場合、結果は完全に受け入れられませんか?

これらの数字を生成する機械について何を知っていますか?単精度浮動小数点数よりも正確な数値を生成するのでしょうか。おそらく、64ビット浮動小数点値を生成しますが、実際の値は32ビット浮動小数点で表現可能な母集団に制限されます。ダブルからフロートへの変換を実行し、エラーを測定しましたか?

これらの可能性や他の可能性を排除するにはまだ十分な情報がありませんが、私の推測では、変換によって得られるものはほとんどないでしょう。floatに変換すると、エラーが多すぎるか、発生しないかのどちらかであり、最初に数値を変換しても、それが変わる可能性はほとんどありません。

于 2012-06-14T05:34:12.840 に答える
2

float32の指数はかなり小さいですが(負の指数の場合は大きくなります)、すべての数値がそれよりも小さいと仮定すると、精度の低下を心配するだけで済みます。float32は、有効な10進数の約7桁または8桁までしか有効ではありません。

于 2012-06-13T01:56:02.747 に答える