傅立葉三角函數基底練習

物理大地測量的作業一,用三角函數當基底, 嘗試合成出新的函數,再用正交基底的概念, 將合成函數分解回基底,等同於計算傅立葉轉換參數的過程; 並嘗試在合成函數中加入雜訊,測試含雜訊的分解。 最後再嘗試用測量界通用的最小二乘平差法求解參數, 分析不同做法的差異。

程式

本作業使用相容於 matlab 的程式語言 octave。

基底函數

試以 sin(t), cos(t), sin(2t), cos(2t), sin(3t), cos(3t), sin(4t), cos(4t), sin(5t), cos(5t) 為基底, 在每項給定任意系數,合成出新的函數。

首先產生十個函數基底,存入 2 x 5 的結構體:

global basis = {};
for i = 1:5
  basis{1,i} = @(t) sin(i * t);
  basis{2,i} = @(t) cos(i * t);
end

產生同樣 2 x 5 矩陣的任意系數:

global coeffiecient = rand(2,5);
disp(coeffiecient);
t 1 2 3 4 5
cos 0.9396886768956427 0.4270019532953698 0.220015914369331 0.07659683799706178 0.4415894405693337
sin 0.527726636334051 0.8334814789927278 0.2312067814650228 0.5559265528546949 0.655401249470971

之後畫出各基底的圖形:

sin

cos

合成函數

合成函數 f 如果寫成 matlab 函數:

f(t) = 0.94  cos(t) + 0.43  cos(2t) + 0.22  cos(3t) +
0.08  cos(4t) + 0.44  cos(5t) +  \\
0.53  sin(t) + 0.83  sin(2t) + 0.23  sin(3t) + 0.56  sin(4t) + 0.66  sin(5t)
function sum = sum_function(t)
  global coefficient basis;
  sum = 0;
  for i = [1:5]
    sum += coefficient(1,i) * basis{1,i}(t);
    sum += coefficient(2,i) * basis{2,i}(t);
  end
end

之後畫圖 fplot(@sum_function, [-pi, pi]) , 結果如下:

sum

比較低階項的情況, 以下分別畫出只取到第三、四、五階的圖形:

order345

雜訊

再來,嘗試為函數加入雜訊。 這裡先把之前合成函數的結果存起來, 再和隨機生成的雜訊相加。 這裡定義雜訊為 ±0.25。

range_t = linspace(-pi, pi, 100);
data = sum_function(range_t);
noise = (rand(1,100) .- 0.5) / 2;
noise_data = data + noise;

然後把這二個函數作圖比較, 由於是取樣後再作圖,看起來會稍微不連續。

plot(range_t, data, "b;coefficient;", range_t, noise_data, "r;with noise;");

noise

因為之後還要對雜訊函數後的函數做積分或平差, 所以需要將雜訊的成果。 但 rand 函數是隨機的,每次運行都產生不同的結果, 只能運行後,把該次運行結果存下來, 之後就對該結果做積分或平差。 我是用簡單的取樣,在 [-π, π] 的區間中取樣一百次, 然後就用這一百次結果作圖。

積分

最後要試著對合成函數與加入雜訊後的函數做積分, 嘗試還原原始的參數。 但因為雜訊是不連續的,只能用不連續的小區間累加模擬積分。

function coefficient = restore_coefficient(data)
    count = 100;
    range_x = linspace(-pi, pi, count);
    coefficient = zeros(2,5);
    for i = 1:5
        range = sum(data .* cos(i * range_x)) / count * 2 * pi;
        coefficient(1,i) = range / pi;
        range = sum(data .* sin(i * range_x)) / count * 2 * pi;
        coefficient(2,i) = range / pi;
    end
end

fcoefficient = restore_coefficient(data);
noise_fcoefficient = restore_coefficient(noise_data);

最後還原的參數如下:

t cos sin 直接還原 cos 直接還原 sin 雜訊 cos 雜訊 sin
1 0.939689 0.527727 0.952246 0.522449 0.922092 0.511869
2 0.427002 0.833481 0.400778 0.825147 0.401755 0.781798
3 0.220016 0.231207 0.239770 0.228895 0.224191 0.225057
4 0.076597 0.555927 0.053877 0.550367 0.027566 0.561177
5 0.441589 0.655401 0.459127 0.648847 0.464609 0.626823

結果有無雜訊的積分結果誤差竟然差不多, 應該是離散積分的效果太差了,可能 -π 到 π 只取樣 100 次太少吧; 不過還是有一些比較小的參數在加上雜訊後就完全跑掉了, 例如 t=4 時的 cos 函數。

精密數值積分

如果是用 matlab 內建的 quad 函數做比較精細的數值積分, 還原出來的參數幾乎一模一樣。 因此可以推斷,幾乎是取樣次數太少的問題。

qcoefficient = zeros(2,5);
for i = 1:5
    qcoefficient(1,i) = quad(@(t) f(t) * cos(i * t), -pi, pi) / pi;
    qcoefficient(2,i) = quad(@(t) f(t) * sin(i * t), -pi, pi) / pi;
end
t cos sin quad cos quad sin 離散積分 cos 離散積分 sin
1 0.939689 0.527727 0.939689 0.527727 0.952246 0.522449
2 0.427002 0.833481 0.427002 0.833481 0.400778 0.825147
3 0.220016 0.231207 0.220016 0.231207 0.239770 0.228895
4 0.076597 0.555927 0.076597 0.555927 0.053877 0.550367
5 0.441589 0.655401 0.441589 0.655401 0.459127 0.648847

取樣 999 次的結果

如果提升取樣次數,再次嘗試計算參數, 另外這裡提升誤差到 ±0.5。

range_x = linspace (-pi, pi, 999)
data = zeros(1,999)
data = call_value (cbasis ,range_x)
noise_data = data .+ rand(1,999) - 0.5;
plot(range_x, data, range_x, noise_data)

sample999.png

t cos sin 直接還原 cos 直接還原 sin 雜訊 cos 雜訊 sin
1 0.939689 0.527727 0.940946 0.527198 0.912194 0.534710
2 0.427002 0.833481 0.424377 0.832647 0.427413 0.816731
3 0.220016 0.231207 0.221993 0.230975 0.209362 0.214364
4 0.076597 0.555927 0.074323 0.555370 0.084341 0.571403
5 0.441589 0.655401 0.443345 0.654745 0.441065 0.664710

由於提升了取樣數,使積分結果更精確, 也就能看出加上雜訊確實會減弱用傅立葉轉換回推參數的精度。

最小二乘平差法還原參數

若使用最小二乘平差法還原參數, 用 999 次取樣當作 999 次觀測方程式, 而 cos sin 的參數則當作待求解參數:

L = A X + V

\\

\begin{bmatrix}
    f(\pi) \\
    f(\pi-0.001) \\
    \vdots \\
    f(-\pi)
\end{bmatrix}
= 
\begin{bmatrix}
    cos(\pi) & cos(2  \pi) & \cdots & 
    sin(\pi) & \cdots & sin(5  \pi) \\
    cos(\pi - 0.001) & \ddots \\
    \vdots \\
    cos(-\pi) & \cdots
\end{bmatrix}

\begin{bmatrix}
a_1 \\
a_2 \\
\vdots \\
b_1 \\
\vdots \\
b_5
\end{bmatrix}
design_matrics = zeros(999, 10);
for i = 1:5
    design_matrics(:,i) = cos(i * range_x');
    design_matrics(:,i+5) = sin(i * range_x');
end

求解方法則是求出法方程矩陣的逆, 從而可以得到未知參數與誤差:

N = A^T A \\
\hat X = N^{-1} A^T L \\
V = L - A \hat X
normal_matrics = design_matrics' * design_matrics;
adjustment_coefficient = inv(normal_matrics) * design_matrics' * data';
adjustment_error = data' - design_matrics * adjustment_coefficient;

而帶雜訊的解算亦如下, 最後的結果如下表:

t cos sin 直接平差 cos 直接平差 sin 帶雜訊 cos 帶雜訊 sin
1 0.939689 0.527727 0.939689 0.527727 0.911021 0.535245
2 0.427002 0.833481 0.427002 0.833481 0.429929 0.817549
3 0.220016 0.231207 0.220016 0.231207 0.207485 0.214579
4 0.076597 0.555927 0.076597 0.555927 0.086512 0.571976
5 0.441589 0.655401 0.441589 0.655401 0.439420 0.665376

綜合結論

先上表,將有無雜訊的單獨製表:

無雜訊的

t cos sin 傅立葉轉換離散積分 cos 傅立葉轉換離散積分 sin 傅立葉轉換 quad 積分 cos 傅立葉轉換 quad 積分 sin 直接平差 cos 直接平差 sin
1 0.939689 0.527727 0.940946 0.527198 0.939689 0.527727 0.939689 0.527727
2 0.427002 0.833481 0.424377 0.832647 0.427002 0.833481 0.427002 0.833481
3 0.220016 0.231207 0.221993 0.230975 0.220016 0.231207 0.220016 0.231207
4 0.076597 0.555927 0.074323 0.555370 0.076597 0.555927 0.076597 0.555927
5 0.441589 0.655401 0.443345 0.654745 0.441589 0.655401 0.441589 0.655401

發現在平差的觀測方程式與積分的取樣數都是 999 的情況下, 平差的結果會優於傅立葉轉換的結果。 但內建的數值積分 quad 和平差的結果是差不多的, 因此這裡可以推論傅立葉轉換在這次作業上, 是和平差的精度相當的,只是受限於積分方法只用單純的取樣, 所以積分結果不夠精準。 如果用好的數值積分方法,例如使用 matlab 內的 quadpack, 就能達到和平差相當的精度。

帶雜訊的

t cos sin 傅立葉轉換 cos 傅立葉轉換 sin 直接平差 cos 直接平差 sin
1 0.939689 0.527727 0.912194 0.534710 0.911021 0.535245
2 0.427002 0.833481 0.427413 0.816731 0.429929 0.817549
3 0.220016 0.231207 0.209362 0.214364 0.207485 0.214579
4 0.076597 0.555927 0.084341 0.571403 0.086512 0.571976
5 0.441589 0.655401 0.441065 0.664710 0.439420 0.665376

帶雜訊的分析上,因為是用離散的隨機產生的雜訊, 因此也沒有所謂 絕對準確的積分 。 用積分與平差得到的結果不相上下, 二者的結果都比我預期的好,推論可能原因各是

  1. 因為雜訊是 999 份離散的雜訊,這次選取的傅立葉函數只到 5 階, 也就是 π/5 的解析度,根本看不到 2π/999 解析度的訊號, 因此也能夠免除掉其干擾。

  2. 平差上雖然看似使用到正弦餘弦等非線性函數,但那些只是基底, 真正的觀測方程式和係數的關係還是線性的, 因此平差也能夠簡單計算,達到精確的結果。

參考資料

物理大地測量,交通大學鄭景中教授授課,傅立葉轉換。

Advanced Engineering Mathematics, 10/e (IE-Paperback), Erwin Kreyszig, ISBN:9780470646137, Fourier transform.

測量平差法,唐城,間接觀測平差。

octave help page quad

octave help page global

MathJax: https://mathjax.org/