Fourier bileşenleri beni faza sokmaz#
Rastlantı eseri regresyon modellerinde Fourier bileşenlerinin kullanımı bu hafta iki ayrı projede karşıma çıktı. Bu notebook, nasıl çalıştıklarını gösteren küçük bir örnek sunuyor.
Not: Özgün İngilizce başlık, “phase” ve “faze” eşseslilerine dayanan bir kelime oyunudur.
Bu notebook’u Colab’da çalıştırmak için buraya tıklayın
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
np.printoptions(legacy='1.25')
plt.rcParams["figure.dpi"] = 100
plt.rcParams["figure.figsize"] = [6, 3.5]
Frekans f, genlik A ve faz kayması phi ile parametrelenen dönemsel bileşen içeren bir sinyalimiz olduğunu varsayın. Parametrelere keyfî değerler verip geri elde edip edemeyeceğimize bakacağız.
f = 1
A = 1.5
phi = 0.5
Sinyali sentezlemek için bu parametreli kosinüsü üç döngü boyunca değerlendireceğim.
ts = np.linspace(0, 3, endpoint=False)
ys = A * np.cos(2 * np.pi * f * ts + phi)
np.mean(ys)
np.float64(-2.220446049250313e-16)
Ardından ortalaması sıfır olan Gauss gürültüsü ekleyeceğim.
np.random.seed(1)
noise = np.random.normal(0, 0.5, size=len(ts))
ys += noise - noise.mean()
Sinyal şöyle görünür.
plt.plot(ts, ys)
plt.xlabel('t')
plt.ylabel('y');
Şimdi sinyalden parametreleri tahmin edip edemeyeceğimize bakalım. Temel fikir şu trigonometrik özdeşliktir:
Faz kaymalı kosinüs, faz kayması olmayan sinüs ve kosinüsün ağırlıklı toplamı olarak yazılabilir. Dolayısıyla dönemsel bileşenin frekansını biliyorsanız sinüs ve kosinüsü öngörücü alan regresyonla genlik ile fazı tahmin edebilirsiniz.
Göstermek için verileri Fourier bileşenleriyle birlikte DataFrame içine koyacağım.
data = pd.DataFrame(dict(ys=ys, ts=ts))
data['cos'] = np.cos(2 * np.pi * f * ts)
data['sin'] = np.sin(2 * np.pi * f * ts)
Şimdi regresyon modelini çalıştırabiliriz (sentezlenen sinyale kesişim eklemediğimiz için burada da dışlıyoruz).
import statsmodels.formula.api as smf
res = smf.ols('ys ~ 0 + cos + sin', data=data).fit()
res.summary()
| Dep. Variable: | ys | R-squared (uncentered): | 0.815 |
|---|---|---|---|
| Model: | OLS | Adj. R-squared (uncentered): | 0.808 |
| Method: | Least Squares | F-statistic: | 106.0 |
| Date: | Mon, 24 Aug 2026 | Prob (F-statistic): | 2.46e-18 |
| Time: | 15:20:03 | Log-Likelihood: | -34.513 |
| No. Observations: | 50 | AIC: | 73.03 |
| Df Residuals: | 48 | BIC: | 76.85 |
| Df Model: | 2 | ||
| Covariance Type: | nonrobust |
| coef | std err | t | P>|t| | [0.025 | 0.975] | |
|---|---|---|---|---|---|---|
| cos | 1.2602 | 0.098 | 12.794 | 0.000 | 1.062 | 1.458 |
| sin | -0.6846 | 0.098 | -6.950 | 0.000 | -0.883 | -0.487 |
| Omnibus: | 0.306 | Durbin-Watson: | 2.389 |
|---|---|---|---|
| Prob(Omnibus): | 0.858 | Jarque-Bera (JB): | 0.244 |
| Skew: | 0.160 | Prob(JB): | 0.885 |
| Kurtosis: | 2.877 | Cond. No. | 1.00 |
Notes:
[1] R² is computed without centering (uncentered) since the model does not contain a constant.
[2] Standard Errors assume that the covariance matrix of the errors is correctly specified.
Uydurulan modelin verilerle karşılaştırması şöyledir.
data['yhat'] = res.fittedvalues
plt.plot(data['ts'], data['ys'], label='veri', alpha=0.6)
plt.plot(data['ts'], data['yhat'], label='uyum')
plt.xlabel('t')
plt.ylabel('y')
plt.legend();
Uyum eğrisi dönemsel bileşenin fazını geri kazanmış gibi görünüyor. Tahmini genlik ile faz model parametrelerinde açıkça gösterilmez; Kartezyen koordinatlardan kutupsal koordinatlara dönüştürerek hesaplayabiliriz.
a = res.params['cos']
b = res.params['sin']
A_hat = np.hypot(a, b)
phi_hat = np.arctan2(-b, a)
A_hat, phi_hat
(np.float64(1.4341371792799407), np.float64(0.49760870975866645))
Parametreleri en azından yaklaşık olarak geri elde ettik.
Fourier analizi hemen hemen aynı ilkeyle çalışır; sinüs ve kosinüs yerine karmaşık üstel kullanır.
ws = np.exp(2 * np.pi * 1j * f * ts)
Karmaşık üstel ile sinyalin nokta çarpımını —özünde korelasyonu— hesaplayarak parametreleri tahmin edebiliriz.
c = 2 / len(ts) * np.vdot(ws, ys)
c
np.complex128(1.2602143401738164+0.68455041144776j)
Sonuç sinyalin tahmini genlik ve fazını temsil eden karmaşık sayıdır.
A_hat = np.abs(c)
phi_hat = np.angle(c)
A_hat, phi_hat
(np.float64(1.4341371792799409), np.float64(0.49760870975866645))
Tahminler doğrusal regresyondan elde ettiklerimizle aynıdır.
Bu, \(e^{i\theta}=\cos\theta+i\sin\theta\) olduğu için çalışır. Sinyali karmaşık üstel tabana yansıttığımızda sinüs ve kosinüs bileşenlerini sıkıştırılmış biçimde hesaplarız.