ハイダイナミックレンジ用の高速かつ正確な畳み込みアルゴリズム(FFTなど)


8

FFTベースのたたみ込みでは、1の根の周りのすべてを評価するため、浮動小数点の解像度が制限されているようです。 1014このPythonコードの-factorエラー:

from scipy.signal import convolve, fftconvolve
a = [1.0, 1E-15]
b = [1.0, 1E-15]
convolve(a, b)     # [  1.00000000e+00,   2.00000000e-15,   1.00000000e-30]
fftconvolve(a, b)  # [  1.00000000e+00,   2.11022302e-15,   1.10223025e-16]

この問題の影響を受けない高速畳み込みアルゴリズムはありますか?
または、直接(2次時間)畳み込みが正確な解を得る唯一の方法ですか?

(そのような小さい数が切り落とさないように十分重要であるかどうかは私のポイントの外です。)


入力サイズが大きい場合は、今convolve()すぐ呼び出すことに注意してくださいfftconvolve()method='direct'直接するかどうかを指定します。
内部石2017年

@endolith:良い点!私は最近それを学びましたが、ここでそれを忘れていました。
user541686 2017年

回答:


5

免責事項:私はこのトピックが古いことを知っていますが、「高速で正確な畳み込みハイダイナミックレンジ」または類似のものを探している場合、これは数少ないまともな結果の最初の1つです。このトピックについて得た洞察を共有したいので、将来誰かを助けるかもしれません。回答で間違った用語を使用した場合はお詫びしますが、このトピックで見つけたものはすべて漠然としており、このスレッドでも混乱を招きます。とにかく読者に理解してもらいたい。

直接畳み込みは、ほとんどの場合、各ポイントの機械精度に対して正確です。つまり、相対誤差は通常、結果の各ポイントの倍精度の場合、おおよそ1.e-16に近いです。ポイントには16桁の正しい数字があります。丸め誤差は、通常は大きくない畳み込みの場合に重大になる可能性があります。厳密に言えば、キャンセルには注意し、Kahan加算や十分に高い精度のデータ型などを使用する必要がありますが、実際にはほとんど常に最適な誤差です。

誤差FFT畳み込みは離れ丸め誤差からの各点の誤差を意味する「グローバル相対」誤差は、機械精度及び結果のピーク値に依存しています。たとえば、結果のピーク値がの場合、2.e9各ポイントの絶対誤差は21091016=2107。結果の値が非常に小さいと思われる場合は、109、その時点での相対誤差は非常に大きくなる可能性があります。FFT畳み込みは、結果の末尾に小さな相対誤差が必要な場合、たとえばデータの指数関数的減衰があり、末尾に正確な値が必要な場合、基本的に役に立ちません。興味深いことに、FFTたたみ込みがその誤差によって制限されない場合、加算/乗算が明らかに少ないため、直接たたみ込みに比べて丸め誤差がはるかに小さくなります。これが実際に人々がFFT畳み込みがより正確であるとしばしば主張する理由であり、彼らはほとんどある意味で正しいので、それらは非常に厳格である可能性があります。

残念ながら、高速で正確な畳み込みを行うための簡単なユニバーサルフィックスはありませんが、問題によっては1つある場合があります... 2つ見つかりました。

尾部の多項式で近似できる滑らかなカーネルがある場合は、チェビシェフ補間によるブラックボックス高速多重極法が興味深いかもしれません。カーネルが「良い」場合、これは実際には完全に機能します。線形(!)の計算の複雑さとマシンの精度の精度の両方が得られます。これが問題に適合する場合は、それを使用する必要があります。ただし、実装は簡単ではありません。

一部の特定のカーネル(通常は確率密度に基づくと考えられる凸関数)では、「指数シフト」を使用して、結果のテールの一部で最適なエラーを取得できます。ある博士論文およびPython実装とgithubのそれは体系的にそれを使用するには、著者CALの正確なFFT畳み込み。ただし、直接畳み込みに逆戻りするか、FFT畳み込みを使用できるため、ほとんどの場合、これはあまり役に立ちません。コードはそれを自動的に行いますが、もちろんこれは素晴らしいことです。

-------------------- EDIT:--------------------

私は唐津原アルゴリズムを少し見ました(実際には小さな実装を行いました)。私には、FFT畳み込みのような通常のエラー動作があるように見えます。つまり、結果のピーク値に対してエラーが発生します。アルゴリズムの分割統治の性質により、結果の末尾の一部の値には実際にはより良いエラーがありますが、どの値をどのように使用するか、またはどのようにしてこの観測を使用するかを簡単に体系的に示す方法はわかりません。残念ながら、最初は、唐津波が直接とFFTの畳み込みの間に役立つものだと思いました。しかし、一般的な2つの畳み込みアルゴリズムよりもKaratsubaを優先すべき一般的な使用例は見当たりません。

そして、上記の指数シフトに加えて、畳み込みの結果を改善するためにそれを使用できる多くの場合がありますが、これも普遍的な修正ではありません。これをFFT畳み込みと実際に使用してかなり良い結果を得ます(すべての入力の一般的な場合:通常のFFT畳み込みと同じ最悪のエラー、各ポイントでのマシンの精度に対する相対誤差が最高)。しかし、繰り返しますが、これは実際には特定のカーネルとデータに対してのみうまく機能しますが、私にとってはカーネルとデータの両方、または減衰がいくらか指数関数的です。


+1ようこそ、これを投稿していただき、ありがとうございます。:)
user541686 2018年

1
うわー!私はまた何かを学びました、そしてそれは私が1993年以来やってきた何かの新しい用語です。このKahan総和アルゴリズムは、ノイズから出力への伝達関数でゼロでノイズシェーピングと呼んでいたものとまったく同じようです DCの右側に配置されるか、ゼロがz=1z飛行機。ランディ・イェーツはそれを「分数節約」と呼びました。これは簡潔な総称です。私はmr / ms Kahanが誰で、いつこれがクレジットされるか知りたいです。
robert bristow-johnson

2
カハンの最初の出版物は1964
。– oli

今日は驚きです。実際、しばらくの間、@ DanBoschenは、浮動小数点数のダイナミックレンジを考慮してdspパズルを求めていました。これは、非常に小さい数を非常に大きい数に追加するという同じ概念についてでした...
Fat32

3

候補の1つは、カラツバアルゴリズムですONログ2ON1.5849625時間。変換ベースではありません。同様のアルゴリズムの独立した発見のように見える、Music-DSPソースコードアーカイブに説明付きのコードもあります。

KaratsubaアルゴリズムのPython実装のテスト(sudo pip install karatsuba質問の数値を使用し)のと、64ビットの浮動小数点数を使用しても、出力値の1つで相対エラーが大きくなることがわかります。

import numpy as np
from karatsuba import *
k = make_plan(range(2), range(2))
l = [np.float64(1), np.float64(1E-15)]
np.set_printoptions(formatter={'float': lambda x: format(x, '.17E')})
print "Karatsuba:"
print(k(l, l)[0:3])
print "Direct:"
print(np.convolve(l, l)[0:3])

印刷する:

Karatsuba:
[1.0, 1.9984014443252818e-15, 1.0000000000000001e-30]
Direct:
[1.00000000000000000E+00 2.00000000000000016E-15 1.00000000000000008E-30]


+1は素晴らしいですし、唐津波が畳み込みアルゴリズムであるとは思いもしなかったので、なぜこの問題を解決する必要があるのか​​を説明できればすばらしいと思います。2x2の場合は簡単に確認できますが、一般的な再帰的な設定では、この問題を修正する必要がある理由がわかりません。それは一般に修正可能ではないかもしれないことは私にはもっともらしく思えるかもしれませんが、私は知りません。
user541686 2017年

1
@OlliNiemitalo:それを説明する簡単な方法は、直接誤差に比べて相対誤差を低くしたいということです O2畳み込み。(「低」の合理的な定義はすべてここで機能します... FFTで得られる相対エラーは次のようなものです1014これはどの定義からも低くはありません。)
user541686

1
IEEEのdoubleの精度は、一般的な場合、15桁から16桁までです。したがって、1e-14は、いくつかの算術演算のシーケンスにとって妥当なサイズエラーです(いくつかの魔法の値を選択しない限り)。
hotpaw2 2017年

1
浮動小数点加算器を設計したことがある場合は、正規化時の仮数の結果によって指数が決定されることがわかります。幅の狭い仮数を生成する数値を選択しました。
hotpaw2 2017年

3

高速たたみ込みアルゴリズムを破棄するのではなく、より高いダイナミックレンジのFFTを使用してみませんか?

この質問への回答は、ブースト多重精度でEigen FFTライブラリを使用する方法を示しています。


2

Cordicアルゴリズムの精度は、必要に応じて拡張できます。問題がある場合は、整数DFTと語長を使用してください。

同じことが直接畳み込みにも当てはまります。非常に長い整数を使用してください。


1

同じ演算タイプと演算ユニットを使用する場合、DFT結果を取得するための2次時間たたみ込みは、通常のFFTアルゴリズムよりも精度が低くなります(算術ステップの階層が深いため、有限の量子化数値ノイズが発生する可能性があります)。

より高精度のデータ型(4倍精度またはbignum算術)を試してみてください。


えっと、これ同じ算術型と演算ユニットを使っているのでは?明らかにそれはより正確です。あなたが話しているノイズの種類は、私が話している種類のノイズと同じではないと思います。単一性の根の大きさは1です。つまり、非常に小さな値を表すことはできません。これは、ノイズがシステム全体にどのように伝播するかという問題とは完全には関係がないようです。
user541686 2017年

丸めがうまく機能する長さと値を選択したため、この例ではより正確に見えるだけです。広範囲の大きさを含む分布を持つ、より多くの非ゼロ係数を使用して、はるかに長い畳み込みの範囲を試してください。
hotpaw2 2017年

私が解決しようとしている問題は、丸めとは関係ありません。それは私が解決しようとしていない別の問題です。私が持っていた元の例は、あなたが言ったとおりで、直接畳み込みでうまく機能しましたが、FFTによって破壊されました。
user541686 2017年

丸め(または他の量子化方法)は、すべての有限精度演算に含まれます。いくつかの計算結果は丸められたときに変化しますが、他の変化は変化しないか、あまり変化しません。
hotpaw2 2017年

私は他に主張したことはありません。先ほどお話ししたとおり、私が解決しようとしている問題は丸めとは関係ありません。それは別の問題です。丸めを回避することは気にしませんが、この問題を回避することは気にします。
user541686 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.