5. ünite / 8
Özellik mühendisliği: zaman serisinden tablo
Gecikmeler, kayan ortalama ve sapma, döngüsel saat, ışık ve hedef ufku: bir sıcaklık serisini modelin okuyabileceği bir tabloya çevir, gelecekten sızıntıya düşme.
Bu ünitenin sonunda
- Bir zaman serisinden gecikme (t−k) ve kayan pencere özellikleri üretmek
- Günün saatini sin/cos çiftiyle döngüsel olarak kodlamak
- Hedefi h adım sonraki değer olarak tanımlamak ve NaN satırları dürüstçe atmak
- Geleceği gören bir özelliği (sızıntı) tanımak ve bunu bir testle yakalamak
Ders notları
Doğrusal regresyon, karar ağacı ya da sinir ağı: hepsi bir tablo ister. Her satır bir örnek, her sütun bir özellik, bir de hedef sütunu. Sensör verisi ise tek bir uzun seridir. Özellik mühendisliği, "şu anda bildiklerim" ile "tahmin etmek istediğim" arasındaki köprüyü kurar: t anındaki satıra yalnız t anında ya da öncesinde ölçülmüş değerler girebilir.
Hangi özellikler?
- Gecikmeler:
temp_lag1,temp_lag2,temp_lag6. 10 dakikalık örneklemede lag6 bir saat öncesidir. Sıcaklık yavaş değişir; yakın geçmiş en güçlü ipucudur. - Kayan ortalama ve sapma: son 6 örneğin ortalaması gürültüyü bastırır, sapması "şu an hava ne kadar oynak" bilgisini verir (bulut geçişleri, pencere açılması).
- Döngüsel saat: saat 23,8 ile 0,2 birbirine yakındır ama sayı olarak uzaktır.
sin(2πh/24)vecos(2πh/24)çifti saati bir çemberin üstüne koyar; doğrusal model günlük döngüyü bu iki sütunla öğrenir. - Işık: LDR değeri 0..1023, 1023'e bölünür. Sera güneşten biraz geride ısınır; ışık yarım saat sonraki sıcaklığı haber verir.
Hedef ufku ve atılan satırlar
Ufuk h = 6 ise model bir saat sonrasını tahmin eder. Serinin başındaki 6 satırın gecikmesi yoktur, sonundaki 6 satırın hedefi yoktur: bunlar atılır. Eksik bir hücreyi sıfırla doldurmak modele "o an 0 °C idi" yalanını söyler; temizleme ünitesindeki ara değer ya da satırı atmak dürüst seçeneklerdir. 1008 örnekten yaklaşık 990 satırlık bir tablo kalır.
Sızıntı: sahte başarı
Grafikte güzel duran merkezli ortalama (t − h .. t + h) özellik olarak kullanılırsa hedefin kendisini içerir. Korelasyonu en güçlü gerçek özelliği bile geçer, test hatası şaşırtıcı küçülür; ama cihazda gelecek elinizde olmadığı için bu özellik hesaplanamaz. Sızıntının belirtisi: tek bir özelliğin "fazla iyi" olması. Kural basittir: her özellik yalnız geçmişe bakan, nedensel bir fonksiyon olmalıdır. Bunu sözle değil, testle güvenceye al.
Simülasyon
Özellik tablosu kurucu
Hangi gecikmeleri, kayan pencereyi ve saat bilgisini kullanacağını seç; hedef ufku (kaç adım sonrası) ayarla. Tablonun ilk satırlarını ve her özelliğin hedefle korelasyonunu gör. "Sızıntılı özellik"i açıp geleceği gören bir özelliğin sahte başarısını izle.
| t | temp | temp_lag1 | temp_lag2 | temp_lag3 | temp_lag6 | temp_mean6 | temp_std6 | hour_sin | hour_cos | light | y (t+6) |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 6 | 19,81 | 19,14 | 19,35 | 19,85 | 20,18 | 19,61 | 0,27 | 0,26 | 0,97 | 0,00 | 19,23 |
| 7 | 19,33 | 19,81 | 19,14 | 19,35 | 19,71 | 19,54 | 0,28 | 0,30 | 0,95 | 0,02 | 19,25 |
| 8 | 19,77 | 19,33 | 19,81 | 19,14 | 19,78 | 19,54 | 0,28 | 0,34 | 0,94 | 0,00 | 19,20 |
| 9 | 19,26 | 19,77 | 19,33 | 19,81 | 19,85 | 19,44 | 0,25 | 0,38 | 0,92 | 0,00 | 18,93 |
| 10 | 19,52 | 19,26 | 19,77 | 19,33 | 19,35 | 19,47 | 0,25 | 0,42 | 0,91 | 0,02 | 19,64 |
Kod
#include <math.h>
const int N = 7; // şimdi + 6 gecikme
float hist[N];
int head = 0, filled = 0;
void pushTemp(float t) { // her 10 dakikada bir çağrılır
hist[head] = t;
head = (head + 1) % N;
if (filled < N) filled++;
}
float lagOf(int k) { // k adım önceki değer (0 = şimdi)
return hist[(head - 1 - k + N) % N];
}
bool buildFeatures(float hour, int ldr, float x[10]) {
if (filled < N) return false; // geçmiş yetmiyor: tahmin yok
x[0] = lagOf(0); x[1] = lagOf(1); x[2] = lagOf(2); x[3] = lagOf(3); x[4] = lagOf(6);
float m = 0, s = 0;
for (int k = 0; k < 6; k++) m += lagOf(k);
m /= 6;
for (int k = 0; k < 6; k++) s += (lagOf(k) - m) * (lagOf(k) - m);
x[5] = m; x[6] = sqrtf(s / 6); // kayan ortalama ve sapma
x[7] = sinf(2 * M_PI * hour / 24);
x[8] = cosf(2 * M_PI * hour / 24);
x[9] = ldr / 1023.0f; // eğitimdeki ölçekle aynı
return true;
}import numpy as np
def lag(x, k):
out = np.full(len(x), np.nan)
out[k:] = x[:-k]
return out
def centred(x, k): # grafik için güzel, özellik olarak yasak
out = np.full(len(x), np.nan)
for j in range(k, len(x) - k):
out[j] = x[j - k:j + k + 1].mean()
return out
def leaks(f, n=200, cut=120): # geleceği değiştir, geçmiş özellik değişiyor mu?
a = np.arange(n, dtype=float)
b = a.copy()
b[cut:] = 999.0
return not np.allclose(f(a)[:cut], f(b)[:cut], equal_nan=True)
def test_lags_do_not_leak():
assert not leaks(lambda x: lag(x, 1))
assert not leaks(lambda x: lag(x, 6))
def test_centred_mean_leaks():
assert leaks(lambda x: centred(x, 6))Kodu tarayıcıda çalıştırPython · NumPy · matplotlib · Pyodide
Python ve NumPy bu sayfada, tarayıcında çalışır (Pyodide). Kodu değiştirip yeniden çalıştırabilirsin; dersin veri setleri çalışma klasöründe hazır. Kod matplotlib kullanırsa grafikler çıktının altında görünür, yazdığı dosyalar (ör. egitim_gecmisi.csv) indirilebilir.
Çıktı
Çıktı burada görünecek.Kendin dene
Simülasyonda varsayılan özelliklerle başla ve her özelliğin hedefle korelasyonunu not et. Sonra hedef ufkunu 1'den 12'ye çıkar: hangi gecikmenin korelasyonu en hızlı düşüyor? Saat bilgisini kapatıp aç, tablonun sütun sayısının nasıl değiştiğine bak. Son olarak "sızıntılı özellik" kutusunu işaretle: korelasyonu kaç oldu ve neden cihazda hesaplanamaz? Aşağıdaki Python kodunu çalıştırıp aynı korelasyonları CSV üzerinde doğrula.
Sık yapılan hatalar
- Eksik hücreyi 0 ile doldurmak: model gerçekte hiç olmamış soğuk anlar öğrenir.
- Saati 0..23 tamsayı olarak vermek: doğrusal model 23:50 ile 00:10'un komşu olduğunu bilemez.
- Kayan ortalamayı merkezli almak (pandas rolling(center=True) gibi): özellik geleceği görür, test hatası sahte küçülür.
- Eğitimde 1023'e bölüp cihazda ham LDR değerini vermek: aynı ağırlıklar bin kat büyük bir girdiyle çarpılır.
Yazılım mühendisliği bağlantısı
Özellik kodu iki yerde yaşar: Python'da eğitimde, C++'ta cihazda. İkisi ayrışırsa model sessizce bozulur. Bu, klasik bir eğitim/sunum farkı (training-serving skew) hatasıdır.
- Özellik listesini (ad, gecikme, ölçek) tek bir yapılandırmada tut; iki taraf da onu okusun.
- Aynı 20 satırlık girdiye iki uygulamanın aynı vektörü ürettiğini gösteren bir altın dosya testi yaz.
- "Geleceği değiştir, geçmiş özellik değişmemeli" testi her yeni özellik için CI'da koşsun.
Kendini sına
10 dakikalık örneklemede "temp_lag6" ne demektir?
Günün saatini neden sin ve cos çifti olarak veririz?
Hangisi gelecekten bilgi sızdıran bir özelliktir?
Ufuk h = 6 iken 1008 örnekten tablo kurulunca neden satır kaybedilir?