ざっとググったところ出てこなかったこともあり、メモ。
離散コサイン変換(Discrete Cosine Transform, DCT)をchainer.links.Linearクラスを使って作成してみました。
離散コサイン変換とは、高速フーリエ変換(Fast Fourier Transform, FFT)の親戚で、FFTの実数部を引き出すのと同じ意味合いになります。(詳しい解説は他の方の説明に頼ります)
以下の関数DCT(wave)を使うと、scipy.fftpack.dct(wave)と同じ結果が返ってくることを確認しました。
モジュールのimportは、Chainerのチュートリアルに準じて行っています。
def DCT(wave):
num_base = np.size(wave.data[0,:])
lDCT = L.Linear(num_base,num_base)
for n in range(num_base):
for k in range(num_base):
lDCT.W.data[k,n] = 2*np.cos(np.pi*k*(2*n+1)/(2*num_base))
lDCT.b.data[:] = 0.0
return lDCT(wave)
私がはまった点は、
・Linearに渡すのはVariable形式
・np.array([[入力ベクトル]])のように、次元を2次元にして渡す
という点です。
これを使うとDCTを使ったChainや誤差関数を作れる(はず)です。(まだ未使用です)
(追記:2016年2月4日)
逆離散コサイン変換(Inverse DCT, IDCT)も作ってみました。
Scipyのドキュメントより、scipy.fftpack.dct(wave)はデフォルトでType2を返します。
この場合逆変換はType3を使用すればよいので、実装は以下の通りとしました。
def IDCT(wave):
num_base = np.size(wave.data[0,:])
lIDCT = L.Linear(num_base,num_base)
for n in range(num_base):
for k in range(num_base):
if(n==0):
lIDCT.W.data[k,n] = 0.0
else:
lIDCT.W.data[k,n] = 2*np.cos(np.pi*(k+0.5)*n/num_base)
lIDCT.b.data[:] = wave.data[0,0]
return lIDCT(wave)
このIDCTの注意点は、バッチ処理には使えない(!)ということです。
よりよい実装があればよいのですが。。