離散畳み込み (Discrete Convolution) の精度保証

$\newcommand{\im}{\mathrm{i}}$

離散フーリエ変換 (DFT)

離散畳み込みを理解するために、離散フーリエ変換を以下で定義する。

定義 $b = (b_0, \dots , b_{2M-2}) \in \mathbb{C}^{2M-1} $ に対して、$a = \mathcal{F}(b) \in \mathbb{C}^{2M-1}$ を

$$ a_k = \mathcal{F}_k(b) := \sum_{j=0}^{2M-2} b_j e^{-2\pi \im \left(\frac{jk}{2M-1}\right) },\quad |k|<M $$

とし、これを 離散フーリエ変換(DFT) と呼ぶ。

逆離散フーリエ変換 (IDFT)

定義 $a = (a_k)_{|k| < M} = (a_{-M+1}, \dots , a_{M-1}) \in \mathbb{C}^{2M-1}$ に対して、$b = \mathcal{F}^{-1} (a) \in \mathbb{C}^{2M-1}$を

$$ b_j = \mathcal{F}^{-1}_j (a) := \sum_{k = -M+1}^{M-1} a_k e^{2 \pi \im \left(\frac{jk}{2M-1}\right)} \quad j=0, \dots , 2M-2 $$

とし、逆離散フーリエ変換(IDFT) と呼ぶ。

注意 一般的なDFT/IDFTはスケーリング係数をつけた形で定義されることが多い。この点で上の定義は一般的な定義と違う。

離散畳み込みのアルゴリズム

$u_1, u_2$を周期 $L$ の周期関数とし、周波数を $\omega = \frac{2\pi}{L}$ とする。このとき、$u_1, u_2$をフーリエ級数展開すると、

$$ u_1(t) = \sum_{k \in \mathbb{Z}} a_{k}^{(1)} e^{\im k\omega t} , \quad a^{(1)} = (a_{k}^{(1)})_{k \in \mathbb{Z}} \\ u_2(t) = \sum_{k \in \mathbb{Z}} a_{k}^{(2)} e^{\im k\omega t} , \quad a^{(2)} = (a_{k}^{(2)})_{k \in \mathbb{Z}}. $$

そして、これらの周期関数の積は、

$$ u_1(t)u_2(t) = \sum_{k \in \mathbb{Z}} (a^{(1)}*a^{(2)})_{k} e^{\im k\omega t} $$

と表される。ここで $ (a^{(1)}*a^{(2)})_k$ を 離散畳み込み といい、

$$ (a^{(1)}*a^{(2)})_k = \sum_{k_1 + k_2 = k \\ k_1 , k_2 \in \mathbb{Z}} a_{k_1}^{(1)} a_{k_2}^{(2)} , \quad k \in \mathbb{Z} $$

と表される。

数値計算への応用を意識すると、$u_1, u_2$ のような有限次元のフーリエ級数で表される周期関数が $p$ 個 ($p \in \mathbb{N}$) あったとき、関数 $u_i(t)$ が

$$ u_i(t) = \sum_{|k| < M} a_{k}^{(i)} e^{\im k\omega t} , \quad a^{(i)} = (a_{k}^{(i)})_{|k| < M} \quad i = 1 , \cdots ,p \quad M \in \mathbb{Z} $$

と表されたとすると、離散畳み込みはこれらの周期関数の積

$$ u_1(t)\cdots u_p(t) = \sum_{|k| \leq p(M-1)}(a^{(1)}* \cdots *a^{(p)})_k e^{\im k\omega t} $$

を表す事になる。ここで

$$ (a^{(1)}* \cdots *a^{(p)})_k = \sum_{k_1 + \cdots + k_p = k,\\ |k| \leq p(M-1), \\ |k_1| , \cdots ,|k_p|<M} a_{k_1}^{(1)} \cdots a_{k_p}^{(p)} $$

と表される。

畳み込み定理

畳み込みを離散フーリエ変換したものは、それぞれのフーリエ係数の離散フーリエ変換の積になる。

$$ \begin{aligned} \mathcal{F}(a^{(1)}* \cdots *a^{(p)}) &= \mathcal{F}(a^{(1)})\hat{\ast} \cdots \hat{\ast}\mathcal{F}(a^{(p)}) \\ &= b^{(1)}\hat{\ast}\cdots \hat{\ast}b^{(p)} \end{aligned} $$

ここで $ b^{(1)}\hat{\ast} \cdots \hat{\ast}b^{(p)}$ におけるベクトル同士の積は、要素毎の積を表す。

離散フーリエ変換を使った畳み込みの計算方法(FFTアルゴリズム)

実際の畳み込みの計算方法について説明する。

周期$L$、変数$t$の周期関数 $u_i(t)$ が有限項のフーリエ級数

$$ u_i(t) = \sum_{|k|<M} a_{k}^{(i)} e^{\im k\omega t} , \quad a^{(i)} = (a_{k}^{(i)})_{|k|<M} $$

で表されているとする。このとき、$p$ 個の関数の積

$$ u_1(t)\cdots u_p(t) = \sum_{|k| \leq p(M-1)}c_k e^{\im k\omega t} $$

を表現するフーリエ係数 $(c_k)_{|k| \leq p(M-1)}$ を以下の計算方法により求める。


FFTアルゴリズム

入力: $a^{(i)} = (a^{(i)}_k)_{|k|<M}\in\mathbb{C}^{2M-1} \quad (i = 1, \cdots , p)$

step1: エイリアシングエラーを防ぐために、入力された値 $a^{(i)}$ の両脇に $(p-1)M$ 個の $0$ を付け加える。これを $\tilde{a}^{(i)}$ と書く。

$$ \tilde{a}^{(i)} = (\underbrace{0, \cdots , 0}_{(p-1)M\text{個}}, \underbrace{a^{(i)}_{-M+1}, \cdots , a^{(i)}_{M-1}}_{2M-1\text{個}},\underbrace{0, \cdots , 0}_{(p-1)M\text{個}}) \in \mathbb{C}^{2pM-1}. $$

step2: step1で得た値 $\tilde{a}^{(i)}$ に対して逆離散フーリエ変換を行う。変換した後の値を $\tilde{b}^{(i)}$ と置く。

$$ \tilde{b}^{(i)} = \mathcal{F}^{-1}(\tilde{a}^{(i)}) \in \mathbb{C}^{2pM-1}. $$

step3: $ (\tilde{b}^{(1)} \hat{*} \cdots \hat{*} \tilde{b}^{(p)}) $を計算する。上記の畳み込みの定理と同じく、このベクトル同士の積は、要素毎の積を表す。

$$ (\tilde{b}^{(1)} \hat{*} \cdots \hat{*} \tilde{b}^{(p)} )_{j} = \tilde{b}^{(1)}_j \cdots \tilde{b}^{(p)}_j , \quad j = 0, \cdots , 2pM-2. $$

step4: step3で求めた$ (\tilde{b}^{(1)} \hat{*} \cdots \hat{*} \tilde{b}^{(p)}) $に対して、離散フーリエ変換を行い、得た値を $2pM-1$ で割る。

$$ \tilde{c} = \frac{1}{2pM-1} \mathcal{F} (\tilde{b}^{(1)} \tilde{*} \cdots \tilde{*} \tilde{b}^{(p)}). %\quad |k| \leq p(M-1) $$

求めた $\tilde{c}=(\tilde{c}_k)_{|k|<pM}$ のうち、実際に必要なのは両脇の $p-1$ 個を取り除いた $|k| \leq p(M-1)$ の範囲である。

$$ \tilde{c} = (\underbrace{\tilde{c}_{-pM+1}, \cdots}_{p-1 \text{個いらない}}, \underbrace{\tilde{c}_{-p(M-1)}, \cdots , \tilde{c}_{p(M-1)}}_{=:c},\underbrace{\cdots ,\tilde{c}_{pM-1}}_{p-1 \text{個いらない}}) \in \mathbb{C}^{2pM-1}. $$

出力: $c = (c_k)_{|k|\le p(M-1)}\in\mathbb{C}^{2p(M-1)+1}$.


具体例

適当に周期関数を決めて、離散畳み込みを行ってみる。はじめに、以前のフーリエ級数のページで作った関数をFourierChebyshev.jlとして読み込む。

具体的に周期関数を $f(x)=\frac{\exp(\sin(5x))}{1+\sin(\cos(x))}$ とし、フーリエ係数について畳み込みを行う。

JuliaのパッケージApproxFun.jlで $f(x)$ を近似してみると、グラフは下のようになる。

フーリエ係数を比較すると一致することが確認できる。

この周期関数の2乗をする場合の畳み込みについて考えてみよう。2乗した関数の概形は、

一方、FFTアルゴリズムを用いて2乗した関数のフーリエ係数を求め、得たフーリエ級数の概形をプロットすると次のようになる。

二つの概形が一致しているのが分かる(水色と赤の曲線がほぼ一致している)。

次に別の周期関数を $f(x)= \mathop{\mathrm{erf}}(\sin(3x)+\cos(2x))^4$ とする。

関数が与えられたら、そのフーリエ係数を計算するfouriercoeffsを使って得たフーリエ係数の離散畳み込み(powerconvfourier)をFFTアルゴリズムにより計算し、関数の冪乗を計算できる。解の概形を重ねてプロットするとほぼ一致している様子がわかる。

離散畳み込みの精度保証付き数値計算

離散畳み込みの精度保証を行う。離散畳み込みのアルゴリズムには、FFTが含まれるため、まず、FFTの精度保証を行うための関数 verifyfft(FFTの精度保証はverifyfft.ipynbを参照)を用意する。

verifyfftは、要素数が2のべき乗の場合しか実行できないので、step1のpaddingの部分で要素数を調整する。

$$ \tilde{a}=(\underbrace{0, \cdots , 0}_{L\text{個}},\underbrace{0, \cdots , 0}_{N=(p-1)M\text{個}}, \underbrace{a_{-M+1}, \cdots , a_{M-1}}_{2M-1\text{個}},\underbrace{0, \cdots , 0}_{N\text{個}},\underbrace{0, \cdots , 0}_{L-1\text{個}}) \in \mathbb{C}^{2pM-2+2L} $$$$ c=(\underbrace{0, \cdots , 0}_{L\text{個}},\underbrace{0, \cdots , 0}_{(p-1)\text{個}}, \underbrace{a_{-p(M-1)}, \cdots , a_{p(M-1)}}_{2p(M-1)+1\text{個}},\underbrace{0, \cdots , 0}_{(p-1)\text{個}},\underbrace{0, \cdots , 0}_{L-1\text{個}}) \in \mathbb{C}^{2pM-2+2L}. $$

このとき $2pM-2+2L$ の要素数をJuliaの nextpow 関数で取得して $L$ を決定する。

step1のia_extが上の $\tilde{a}$ を指し、ic_extが $c$ である。2のべき乗になるようにpaddingした分、関数の最後に取り出す値の範囲に注意が必要。また、区間演算とベクトル、両方の型に対応できるように、多重ディスパッチを利用する関数を用意。

区間演算は、数値計算で得た値の範囲全体を含むため、ic_full $\in$ c_fullが成り立つ。

また、下の図から精度保証をした場合は、係数の両端に$10^{-14}$ほどの誤差が含まれることがわかる。

チェビシェフ級数の冪乗を計算する

離散畳み込みのもう一つの応用例として、関数 $f(x) = \exp(-100(x-1/2)^2)$ をチェビシェフ級数で近似し、その係数の畳み込み計算を使って関数の冪乗を計算する方法を紹介する。チェビシェフ級数の取り扱い方は別記事で紹介予定。

本資料は以下のような文献・Web ページ等を参考にこの文章を書いています。

参考文献

  1. Jan Bouwe van den Berg, Jean-Philippe Lessard, Proceedings of Symposia in Applied Mathematics 74, American Mathematical Society, 2018.
    (力学系におけるNewton-Kantorovich型定理を使った精度保証付き数値計算の教科書、フーリエ級数・チェビシェフ級数の畳み込みを使った実践例をいくつか紹介している)
  2. Jean-Philippe Lessard, Computing discrete convolutions with verified accuracy via Banach algebras and the FFT, Applications of Mathematics, 63(3):219–235, Jun 2018.
    (離散畳み込みのFFTアルゴリズムの分かりやすい紹介と、Banach環の性質を使った精度保証方法の提案をしている)
  3. 井藤佳奈子, 高安亮紀, Juliaで精度保証付き高速フーリエ変換, 2021.
    (区間演算を利用したFFTの精度保証方法をJuliaで実装する例を紹介している)
  4. S. Rump. INTLAB - INTerval LABoratory. In T. Csendes, editor, Developments in Reliable Computing, pages 77–104. Kluwer Academic Publishers, Dordrecht, 1999. http://www.ti3.tuharburg.de/rump/.
    (MATLABの区間演算ツールボックスINTLABの紹介記事、本記事のverifyfftはINTLABに実装されている方法のコピー)
高橋和暉, 高安亮紀,2022年2月28日