[英]What is the difference between numpy.fft.fft and numpy.fft.rfft?
[英]skcuda.fft not the same as numpy.fft.rfft?
我試圖將ftf的輸出與numpy的ftf進行測試以進行單元測試,但我意識到在失敗后不久,這並不是因為我做錯了什么,但是skcuda實際上並不會產生相同的答案。 我知道它們會有所不同,但是至少其中一個數字與numpy產生的結果allclose
幾個數量級,並且allclose
和almost_equal
返回大量錯誤( rtol=1e-6
為33%和25% ,對於atol=1e-6
則為16%)。 我在這里做錯了什么? 我可以解決這個問題嗎?
測試文件:
import pycuda.autoinit
from skcuda import fft
from pycuda import gpuarray
import numpy as np
def test_skcuda():
array_0 = np.array([[1, 2, 3, 4, 5, 4, 3, 2, 1, 0]], dtype=np.float32)
array_1 = array_0 * 10
time_domain_signal = np.array([array_0[0], array_1[0]], dtype=np.float32)
fft_point_count = 10
fft_plan = fft.Plan(fft_point_count, np.float32, np.complex64,
batch=2)
fft_reserved = gpuarray.empty((2, fft_point_count // 2 + 1), dtype=np.complex64)
fft.fft(gpuarray.to_gpu(time_domain_signal), fft_reserved, fft_plan)
np.testing.assert_array_almost_equal(
np.fft.rfft(time_domain_signal, fft_point_count), fft_reserved.get())
test_skcuda()
斷言失敗:
AssertionError:
Arrays are not almost equal to 6 decimals
(mismatch 25.0%)
x: array([[ 2.500000e+01+0.000000e+00j, -8.472136e+00-6.155367e+00j,
-1.193490e-15+2.331468e-15j, 4.721360e-01-1.453085e+00j,
2.664535e-15+0.000000e+00j, 1.000000e+00+0.000000e+00j],...
y: array([[ 2.500000e+01+0.000000e+00j, -8.472136e+00-6.155367e+00j,
8.940697e-08+5.960464e-08j, 4.721359e-01-1.453085e+00j,
0.000000e+00+0.000000e+00j, 1.000000e+00+0.000000e+00j],...
打印輸出:
#numpy
[[ 2.50000000e+01+0.00000000e+00j -8.47213595e+00-6.15536707e+00j
-1.19348975e-15+2.33146835e-15j 4.72135955e-01-1.45308506e+00j
2.66453526e-15+0.00000000e+00j 1.00000000e+00+0.00000000e+00j]
[ 2.50000000e+02+0.00000000e+00j -8.47213595e+01-6.15536707e+01j
-1.11022302e-14+2.39808173e-14j 4.72135955e+00-1.45308506e+01j
3.55271368e-14+7.10542736e-15j 1.00000000e+01+0.00000000e+00j]]
#skcuda
[[ 2.5000000e+01+0.0000000e+00j -8.4721355e+00-6.1553669e+00j
8.9406967e-08+5.9604645e-08j 4.7213593e-01-1.4530852e+00j
0.0000000e+00+0.0000000e+00j 1.0000000e+00+0.0000000e+00j]
[ 2.5000000e+02+0.0000000e+00j -8.4721359e+01-6.1553673e+01j
1.4305115e-06-4.7683716e-07j 4.7213597e+00-1.4530851e+01j
0.0000000e+00+1.9073486e-06j 1.0000000e+01+0.0000000e+00j]]
FFT的輸出具有相對於輸入值大小的誤差。 每個輸出元素都是通過組合所有輸入元素來計算的,因此,決定其結果精度的是它們的大小。
您正在同一陣列中計算兩個1D FFT。 它們各自具有不同的幅度輸入,因此應具有不同的幅度容差。
以下快速代碼演示了如何實現此目的。 我不知道如何調整numpy.testing
任何功能來做到這一點。
import numpy as np
array_0 = np.array([[1, 2, 3, 4, 5, 4, 3, 2, 1, 0]], dtype=np.float32)
array_1 = array_0 * 10
time_domain_signal = np.array([array_0[0], array_1[0]], dtype=np.float32)
# numpy result
a=np.array([[ 2.50000000e+01+0.00000000e+00j, -8.47213595e+00-6.15536707e+00j,
-1.19348975e-15+2.33146835e-15j, 4.72135955e-01-1.45308506e+00j,
2.66453526e-15+0.00000000e+00j, 1.00000000e+00+0.00000000e+00j],
[ 2.50000000e+02+0.00000000e+00j, -8.47213595e+01-6.15536707e+01j,
-1.11022302e-14+2.39808173e-14j, 4.72135955e+00-1.45308506e+01j,
3.55271368e-14+7.10542736e-15j, 1.00000000e+01+0.00000000e+00j]])
# skcuda result
b=np.array([[ 2.5000000e+01+0.0000000e+00j, -8.4721355e+00-6.1553669e+00j,
8.9406967e-08+5.9604645e-08j, 4.7213593e-01-1.4530852e+00j,
0.0000000e+00+0.0000000e+00j, 1.0000000e+00+0.0000000e+00j],
[ 2.5000000e+02+0.0000000e+00j, -8.4721359e+01-6.1553673e+01j,
1.4305115e-06-4.7683716e-07j, 4.7213597e+00-1.4530851e+01j,
0.0000000e+00+1.9073486e-06j, 1.0000000e+01+0.0000000e+00j]])
# Tolerance for result array row relative to the mean absolute input values
# 1e-6 because we're using single-precision floats
tol = np.mean(np.abs(time_domain_signal), axis=1) * 1e-6
# Compute absolute difference and compare that to our tolearances
diff = np.abs(a-b)
if np.any(diff > tol[:,None]):
print('ERROR!!!')
這看起來很像舍入錯誤,單精度浮點數的精度為〜8個十進制數字(雙精度數為〜16)
代替使用numpy.fft
,替代方法是使用fftpack
的fftpack ,它直接支持單精度浮點數,例如:
from scipy import fftpack
x = np.array([1, 2, 3, 4, 5, 4, 3, 2, 1, 0])
y = fftpack.fft(
np.array([x, x * 10], dtype=np.float32)
)
print(y[:,:6])
輸出:
[[ 2.5000000e+01+0.0000000e+00j -8.4721355e+00-6.1553669e+00j
8.9406967e-08+5.9604645e-08j 4.7213593e-01-1.4530852e+00j
0.0000000e+00+0.0000000e+00j 1.0000000e+00+0.0000000e+00j]
[ 2.5000000e+02+0.0000000e+00j -8.4721359e+01-6.1553673e+01j
1.1920929e-06+1.9073486e-06j 4.7213583e+00-1.4530851e+01j
0.0000000e+00+1.9073486e-06j 1.0000000e+01+0.0000000e+00j]]
看起來更近了
來自FFT的e-8(浮點)和e-15(雙)的微小結果值(給定的滿量程輸入或輸出接近1.0)基本上等於零(加上四舍五入的噪聲)。
和
零+噪音==零+噪音
因此您的結果可能實際上是相同的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.