Okullar için Robotik ve Mühendislik · anaokulundan liseye

7. ünite / 8

Modeli mikrodenetleyiciye taşı: ağırlıklardan C koduna

Eğitilmiş doğrusal modelden C fonksiyonu üret: FPU'lu ESP32 için float, FPU'su olmayan Uno için Q-biçiminde sabit noktalı tamsayı. Nicemleme hatasını, taşma payını, bellek ve süreyi ölç.

Bu ünitenin sonunda

  • Eğitilmiş ağırlıklardan derlenebilir bir C fonksiyonu üretmek
  • Q-biçiminde sabit noktalı aritmetiği ve santi-birim girdileri açıklamak
  • Nicemleme hatasını ve int32 taşma payını hesaplamak
  • Float ve sabit noktalı modelin bellek ve süre maliyetini karşılaştırmak

Ders notları

Model bulutta da çalışabilir; ama ağ koptuğunda serayı korumak, pili korumak ve gecikmeyi sıfıra indirmek için tahmini cihazın üstünde yapmak isteriz. Doğrusal model bunun için idealdir: on özellikli bir model on çarpma ve on toplamadır, 44 baytlık ağırlık tablosudur.

ESP32: float yeterli

ESP32'nin tek duyarlıklı kayan nokta birimi (FPU) vardır. Python'daki ağırlıkları doğrudan float sabitleri olarak yazmak yeterlidir; bir tahmin mikrosaniyenin altında biter. Üretilen kodun tek şartı, girdilerin eğitimdeki ölçekte gelmesidir (ışık 0..1, saat sin/cos).

Uno: sabit noktalı tamsayı

ATmega328P'nin FPU'su yoktur; her float çarpması yazılımla, yüzlerce çevrimde yapılır. Çözüm sabit noktadır:

  • Girdiler santi-birim int16_t: 23,45 °C → 2345. Işık 0..1 → 0..100.
  • Ağırlıklar Q-biçiminde int32_t: wq = round(w · 2q). q = 12 için 0,7955 → 3258.
  • Toplam int32_t biriktiricide yapılır, sonunda acc >> q ile geri ölçeklenir.
ŷsanti = (B + Σ Wi · xi) >> q    B = round(w₀ · 100 · 2q)

İki risk: nicemleme ve taşma

Nicemleme hatası: her ağırlık en çok 2−q−1 kadar yuvarlanır. Sera modelinde q = 12 ile en büyük fark yaklaşık 0,01–0,04 °C'dir, sensörün kendi gürültüsünden çok küçük. q'yu 4'e indirirsen hata derecelere çıkar. Taşma: q büyüdükçe ağırlıklar büyür; en kötü girdide |B| + Σ |Wi| · max|xi| toplamı 2³¹ − 1'i aşarsa sonuç sessizce eksiye döner. Bu sınırı üretim anında hesaplayıp kodun yanına yaz.

Daha büyük modeller: TinyML

Doğrusal model yetmezse küçük bir sinir ağı da cihaza sığar. TensorFlow Lite Micro gibi çatılar ağırlıkları int8'e nicemler ve ESP32-S3'ün vektör komutlarını kullanır. İlke aynıdır: eğitim bilgisayarda, çıkarım cihazda; nicemlemenin bedeli ölçülür, tahmin edilmez.

Simülasyon

Modeli mikrodenetleyiciye taşı: C kodu üreteci

Eğitilmiş ağırlıklardan C fonksiyonu üret: ESP32 için float, FPU'su olmayan Uno için sabit noktalı tamsayı (Q-biçimi). Q bit sayısını değiştir; nicemleme hatasını, int32 taşma payını, bellek ve süre tahminini gör.

// 741 satırda eğitildi, ufuk 60 dk, Q12, girdiler ×100 #include <stdint.h> #define Q 12 static const int32_t W[10] = { 3633, 1424, 400, -689, -732, -482, 2906, 2577, 3169, 15184 }; static const int32_t B = 638926; int16_t predict_temp_c(int16_t temp, int16_t temp_lag1, int16_t temp_lag2, int16_t temp_lag3, int16_t temp_lag6, int16_t temp_mean6, int16_t temp_std6, int16_t hour_sin, int16_t hour_cos, int16_t light) { const int16_t x[10] = { temp, temp_lag1, temp_lag2, temp_lag3, temp_lag6, temp_mean6, temp_std6, hour_sin, hour_cos, light }; int32_t acc = B; for (uint8_t i = 0; i < 10; i++) acc += W[i] * (int32_t)x[i]; return (int16_t)(acc >> Q); }
Float'a göre nicemleme hatası: en çok 0,0368 °C, ortalama 0,0133 °C En kötü toplam 25.919.164 / 2 147 483 647 (%1,2) → int32'ye sığar
10 ağırlık: 44 B · Uno yazılım float ≈ 88 µs, Uno sabit nokta ≈ 25 µs, ESP32 FPU ≈ 0,17 µs / tahmin

Kod

predict_esp32.ino: float model ve süre ölçümü (ESP32, C++)
// export.py çıktısı: ağırlıklar ham ölçekte, ölçekleme gerekmez
float predict_temp(float temp, float lag1, float lag6,
                   float hour_sin, float hour_cos, float light) {
  return 2.498785f
       + 0.795491f * temp + 0.233786f * lag1 - 0.190635f * lag6
       + 0.592475f * hour_sin + 0.569771f * hour_cos + 3.463065f * light;
}

void setup() {
  Serial.begin(115200);
  uint32_t t0 = micros();
  volatile float p = 0;
  for (int i = 0; i < 1000; i++) p = predict_temp(24.1f, 24.0f, 23.2f, 0.5f, -0.87f, 0.62f);
  uint32_t us = micros() - t0;         // 1000 tahmin
  Serial.printf("forecast %.2f C, %.3f us each\n", p, us / 1000.0f);
}
void loop() {}
predict_uno.ino: sabit noktalı model, FPU yok (Uno, C++)
#include <stdint.h>
#define Q 12                           // ağırlık = round(w x 4096)
static const int32_t W[6] = { 3258, 958, -781, 2427, 2334, 14185 };
static const int32_t B = 1023503;      // sabit terim, santi-birim x 4096

// girdiler santi-birim int16: 23,45 °C -> 2345, ışık 0..1 -> 0..100
int16_t predict_temp_c(const int16_t x[6]) {
  int32_t acc = B;
  for (uint8_t i = 0; i < 6; i++) acc += W[i] * (int32_t)x[i];  // en kötü durum int32'ye sığmalı
  return (int16_t)(acc >> Q);          // aritmetik kaydırma = aşağı yuvarlama
}

void setup() {
  Serial.begin(9600);
  int16_t x[6] = { 2410, 2400, 2320, 50, -87, 62 };
  int16_t c = predict_temp_c(x);
  Serial.print(c / 100); Serial.print('.'); Serial.println(abs(c % 100));
}
void loop() {}
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.

disa_aktar.pypython

Çıktı

Çıktı burada görünecek.

Kendin dene

Simülasyonda önce float hedefini (ESP32) seç ve üretilen C fonksiyonunu oku. Sonra sabit noktalı hedefe (Uno) geç ve Q bit sayısını 12'den 4'e, sonra 20'ye taşı: en büyük nicemleme hatası ve int32 taşma payı nasıl değişti? Hatanın 0,05 °C altında, taşma payının güvenli olduğu en küçük q'yu bul. Python kodunu çalıştır, kendi ağırlıklarınla üretilen C kodunu Wokwi'deki bir Uno ya da ESP32 projesine yapıştırıp seri çıktıyı karşılaştır.

Sık yapılan hatalar

  • Cihazda girdiyi eğitimdekinden farklı ölçekte vermek (ışığı 0..1023 olarak): model tutarlı ama yanlış tahmin üretir.
  • Uno'da float kullanıp sürenin önemsiz olduğunu varsaymak: özellik hesabıyla birlikte milisaniyelere çıkabilir.
  • Taşma payını hesaplamadan q'yu büyütmek: uç bir girdide toplam int32 sınırını aşar ve tahmin eksiye döner.
  • Ağırlıkları elle kopyalamak: model yeniden eğitilince C dosyası eski kalır; kodu betikle üret.

Yazılım mühendisliği bağlantısı

Üretilen kod, elle yazılan koddan daha güvenilir olabilir; yeter ki üreticinin kendisi test edilsin.

  • Üreticiyle birlikte aynı tamsayı hesabını yapan bir referans uygulama yaz ve ikisinin bin rastgele girdide bit bit aynı sonucu verdiğini test et.
  • Üretilen dosyaya model sürümü, eğitim tarihi ve q değerini yorum olarak göm; sahadaki cihazın hangi modeli çalıştırdığı bilinmeli.
  • Model değişince C dosyasını CI üretsin; elle düzenleme yasak olsun.

Kendini sına

  1. q = 12 ile 0,75 ağırlığı Q-biçiminde hangi tamsayıdır?

  2. Arduino Uno'da sabit noktalı model neden tercih edilir?

  3. q değerini çok büyütmenin riski nedir?

  4. Santi-birim girdide 23,45 °C hangi int16 değeridir?

Bu üniteden sonra bitirme projesinde

  • Cihaz kodu: Float ve sabit noktalı C kodu, nicemleme hatası ve taşma denetimi, bellek ve süre hesabı (G6, G7).

Parçalar ve ilgili sayfalar

Esc
  • PanelAna sayfaSayfa
  • ModüllerTüm modüllerSayfa
  • ParçalarParça ansiklopedisiSayfa
  • Mühendislik yoluBüyükler için robotik: 128 parça, 7 seviyeSayfa
  • Robotik dersi (ESOF 323)Üniversite robotik dersi, 14 haftaSayfa
  • Drone dersiBüyükler için: parça, simülasyon, yazılım; 10 üniteSayfa
  • Blok atölyesiSerbest blok programlamaAraç
  • Devre laboratuvarıSanal Arduino ve devreAraç
  • Robot arenasıSanal robot sürüşüAraç
  • OyunlarBloklarla 8 öğretici oyunAraç
  • Mikro Kart atölyesiSanal LED kartı bloklarla programlaAraç
  • Robot atölyesiMikro Kart'ı robota tak, bloklarla görev yapAraç