Güncellendi: 28 Şubat 2024
Bugünkü makalede, Wio Terminal ve Tensorflow Lite for Microcontrollers kullanarak, BME280 çevresel sensöründen alınan yerel verilere dayanarak önümüzdeki 24 saat için hava durumu ve yağış tahmini yapabilen bir akıllı meteoroloji istasyonu oluşturacağız.


Daha fazla detay ve görsel için, ilgili videoyu izleyin!
Model optimizasyon tekniklerini nasıl uygulayacağınızı anlatacağım; bu teknikler, sadece orta boyutlu Konvolüsyonel sinir ağını çalıştırmakla kalmayacak, aynı zamanda bu şık GUI ve WiFi bağlantısının günlerce ve aylarca aynı anda çalışmasını sağlayacak!

Bu, son sonuç; ekranda mevcut sıcaklık, nem ve atmosfer basıncı değerlerinin yanı sıra şehir adı, tahmin edilen hava durumu türü ve tahmin edilen yağış olasılığı gösteriliyor – ekranın altında ise aşırı hava bilgilerini, AI şakalarını veya benim tweetlerimi görüntülemek için kolayca yeniden kullanabileceğiniz bir günlük çıktı alanı var. Görünümü güzel ve kullanışlı olsa da, kendiniz ekleyebileceğiniz birçok şey var – örneğin, yukarıda bahsedilen haber/tweet çıktısını ekranda göstermek veya enerji tasarrufu sağlamak için derin uyku modunu kullanmak ve bunu pil ile çalıştırmak gibi.
Bu proje, meslektaşım Jonathan Tan’ın hava durumu tahmini hakkında bir makalesini genişletiyor. Özellikle, o makaledeki temel uygulamadan birkaç şeyi geliştireceğiz:
- Bize atmosfer basıncı bilgisi almayı sağlayacak BME280 sensörünü kullanacağız, bunun yanı sıra sıcaklık ve nem verilerini de elde edeceğiz.
- Orijinal projedeki sinir ağı modeli, önceki 3 saatten alınan veri noktalarına dayanarak, önümüzdeki yarım saat için hava durumunu tahmin etmek üzere eğitilmiştir; her yarım saatte bir ölçüm yapılmaktadır. Bu nedenle, aslında bir hava durumu tanımlayıcısıdır, hava durumu tahmin edicisi değildir. Önceki 24 saatlik ölçümlere dayanarak, önümüzdeki 24 saat için hava durumu türünü ve yağış olasılığını tahmin etmek için daha gelişmiş veri işleme ve model mimarisi kullanacağız.
- Ayrıca, Wio Terminal belleğine daha fazla şey sığdırmamızı sağlayacak daha küçük bir model elde etmemizi sağlayacak model optimizasyonlarını da kullanacağız; örneğin, bir web sunucusu ve güzel bir LVGL arayüzü ile karanlık/aydınlık malzeme temaları.
Veri işleme ve model eğitimi
Peki, nereden başlayalım? Her şey verilerle başlar elbette. Bu eğitim için, Kaggle’dan hazır bir hava durumu veri seti kullanacağız, Tarihsel Saatlik Hava Durumu Verileri 2012-2017. Ben Shenzhen’de yaşıyorum, Güney Çin’de bir şehir – ve bu şehir veri setinde yok, bu yüzden benzer enlemde bulunan ve subtropikal bir iklime sahip bir şehir seçtim – Miami.

Yaşadığınız iklime en azından benzer bir şehir seçmelisiniz – Miami’den alınan verilerle eğitilen bir modelin kışın Chicago’da kullanılması durumunda tamamen şaşıracağını söylemeye gerek yok.

Veri işleme ve model eğitimi adımı için, bu proje için Github deposunda hazırlayıp paylaştığım Colab Not Defterini açalım. Jupyter Not Defterleri, hem metin hem de çalıştırılabilir kodu aynı ortamda bulundurdukları için verileri keşfetmek ve sunmak için harika bir yoldur. Genel iş akışı videoda ve Colab Not Defteri metin bölümlerinde açıklanmıştır.
Ortamı hazırlayın
Eğitilmiş modeli aldıktan sonra, onu Wio Terminal’e dağıtma zamanı. Daha önce belirttiğim gibi, Tensorflow Lite for Microcontrollers kullanacağız, buna Tensorflow Micro diyeceğim, çünkü Tensorflow Lite for Microcontrollers biraz uzun bir isim.
Tensorflow Micro, nispeten genç bir çerçeve, bu nedenle modelimizi Wio Terminal’e dağıtmak için birkaç engeli aşmamız gerekecek. Ancak, tanıtıldığından beri çok daha iyi hale geldi – sadece birkaç yıl önce sahnede ilk canlı demosunu yaparken oldukça gergin olan Tensorflow bakımcısı Pete Warden’ın bu videosuna bakın.
Bu projeyi Windows’ta yapıyorsanız, ilk yapmanız gereken şey, Arduino IDE’nin gece sürümünü indirmek, çünkü mevcut kararlı sürüm 1.18.3, birçok kütüphane bağımlılığı olan skeçleri derlemeyecek (sorun, Windows’ta derleme sırasında bağlayıcı komutunun maksimum uzunluğu aşmasıdır).
İkincisi, `__SXTB16_RORn` tanımlanmadığı için cmsis_gcc.h dosyasının içeriğini daha yeni bir sürümle değiştirmeniz gerekiyor. Daha yeni sürümü, bu projenin Github deposunda bulacaksınız. Ardından, bunu Windows’ta C:\Users\[your_user_name]\AppData\Local\Arduino15\packages\Seeeduino\tools\CMSIS\5.4.0\CMSIS\Core\Include ve Linux’ta /home/[your_user_name]/.arduino15/packages/Seeeduino/tools/CMSIS/5.4.0/CMSIS/Core/Include dizinine kopyalayın.
Son olarak, bir Konvolüsyonel sinir ağı kullanıyoruz ve bunu Keras API ile inşa ettiğimiz için, mevcut kararlı sürümde desteklenmeyen bir işlem içeriyor. Github’da Tensorflow sorunlarını tararken, bu işlemi (EXPAND_DIMS) mevcut işlemler listesine eklemek için bir çekme isteği buldum, ancak bu video yapılırken ana dalda birleştirilmedi. Tensorflow deposunu git clone yapabilir, PR dalına geçebilir ve Arduino kütüphanesini derleyebilirsiniz; bunu Linux makinesinde ./tensorflow/lite/micro/tools/ci_build/test_arduino.sh komutunu çalıştırarak yapabilirsiniz – elde edilen kütüphane tensorflow/lite/micro/tools/make/gen/arduino_x86_64/prj/tensorflow_lite.zip içinde bulunabilir. Alternatif olarak, bu projenin Github deposundan zaten derlenmiş kütüphaneyi indirebilir ve Arduino skeçleri kütüphane klasörünüze yerleştirebilirsiniz – sadece aynı anda yalnızca bir Tensorflow lite kütüphaneniz olduğundan emin olun!
“`html
Sahte verilerle test et
Tüm bunlar tamamlandıktan sonra, boş bir şematik oluşturun ve kaydedin. Ardından, eğittiğiniz modeli şematik klasörüne kopyalayın ve şematiği yeniden açın. Modelin değişken adını ve model uzunluğunu daha kısa bir şeyle değiştirin. Ardından, test için wio_terminal_tfmicro_weather_prediction_static.ino dosyasındaki kodu kullanın:
C++ kodunda sahip olduğumuz ana adımları gözden geçirelim
Tensorflow kütüphanesi için başlıkları ve model flatbuffer dosyasını dahil ediyoruz
#include <TensorFlowLite.h>
//#include "tensorflow/lite/micro/micro_mutable_op_resolver.h"
#include "tensorflow/lite/micro/all_ops_resolver.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
#include "tensorflow/lite/micro/system_setup.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "model_Conv1D.h"
micro_mutable_op_resolver.h dosyasının yorum satırına alındığını ve all_ops_resolver.h dosyasının etkin olduğunu fark edin – all_ops_resolver.h başlığı, Tensorflow Micro’da mevcut olan tüm işlemleri derler ve test için uygundur, ancak test işlemini tamamladıktan sonra cihazın belleğini korumak için micro_mutable_op_resolver.h’ya geçmek çok daha iyidir – bu büyük bir fark yaratır.
Sonraki adımda hata raporlayıcı, model, giriş ve çıkış tensörleri ile yorumlayıcı için işaretçileri tanımlıyoruz. Modelimizin iki çıktısı olduğunu unutmayın – biri yağış miktarı için, diğeri ise hava durumu tipi için. Ayrıca, giriş, çıkış ve ara dizileri tutan bir tensör arenası tanımlıyoruz – gerekli boyut, kullandığınız modele bağlı olacaktır ve deneyimle belirlenmesi gerekebilir.
// Arduino tarzı şemalarla uyumluluk için kullanılan global değişkenler.
namespace {
tflite::ErrorReporter* error_reporter = nullptr;
const tflite::Model* model = nullptr;
tflite::MicroInterpreter* interpreter = nullptr;
TfLiteTensor* input = nullptr;
TfLiteTensor* output_type = nullptr;
TfLiteTensor* output_precip = nullptr;
constexpr int kTensorArenaSize = 1024*25;
uint8_t tensor_arena[kTensorArenaSize];
} // namespace
Sonra setup fonksiyonunda, hata raporlayıcı, op çözücü, yorumlayıcı oluşturma, modeli eşleme, tensörleri ayırma ve nihayet ayırmadan sonra tensör şekillerini kontrol etme gibi daha fazla hazırlık işlemi var. Burada, model işlemlerinin mevcut Tensorflow Micro kütüphanesi sürümü tarafından desteklenmediği durumlarda kodun çalışma zamanında hata verebileceği yer. Desteklenmeyen işlemleriniz varsa, model mimarisini değiştirebilir veya genellikle Tensorflow Lite’dan port ederek operatör için destek ekleyebilirsiniz.
void setup() {
Serial.begin(115200);
while (!Serial) {delay(10);}
// Günlük kaydı ayarlayın. Google tarzı, yaşam süresi belirsizliği nedeniyle global veya statiklerden kaçınmaktır, ancak bu basit bir yok ediciye sahip olduğu için sorun değil.
// NOLINTNEXTLINE(runtime-global-variables)
static tflite::MicroErrorReporter micro_error_reporter;
error_reporter = µ_error_reporter;
// Modeli kullanılabilir bir veri yapısına haritalayın. Bu, herhangi bir kopyalama veya ayrıştırma içermez, çok hafif bir işlemdir.
model = tflite::GetModel(Conv1D_tflite);
if (model->version() != TFLITE_SCHEMA_VERSION) {
TF_LITE_REPORT_ERROR(error_reporter,
"Sağlanan model şema sürümü %d, desteklenen sürüm %d ile eşit değil.",
model->version(), TFLITE_SCHEMA_VERSION);
return;
}
// Gerekli tüm işlem uygulamalarını getirir.
// NOLINTNEXTLINE(runtime-global-variables)
//static tflite::MicroMutableOpResolver<1> resolver;
static tflite::AllOpsResolver resolver;
// Modeli çalıştırmak için bir yorumlayıcı oluşturun.
static tflite::MicroInterpreter static_interpreter(model, resolver, tensor_arena, kTensorArenaSize, error_reporter);
interpreter = &static_interpreter;
// Modelin tensörleri için tensor_arena'dan bellek ayırın.
TfLiteStatus allocate_status = interpreter->AllocateTensors();
if (allocate_status != kTfLiteOk) {
TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() başarısız oldu");
return;
}
// Modelin giriş ve çıkış tensörlerine işaretçileri alın.
input = interpreter->input(0);
output_type = interpreter->output(1);
output_precip = interpreter->output(0);
Serial.println(input->dims->size);
Serial.println(input->dims->data[1]);
Serial.println(input->dims->data[2]);
Serial.println(input->type);
Serial.println(output_type->dims->size);
Serial.println(output_type->dims->data[1]);
Serial.println(output_type->type);
Serial.println(output_precip->dims->size);
Serial.println(output_precip->dims->data[1]);
Serial.println(output_precip->type);
}
Son olarak, döngü fonksiyonunda, kuantize edilmiş INT8 değerleri için bir yer tutucu ve karşılaştırma için Colab defterinden kopyalayıp yapıştırabileceğiniz bir float değerler dizisi tanımlıyoruz.
void loop() {
int8_t x_quantized[72];
float x[72] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
Float değerleri for döngüsünde INT8’e kuantize ediyoruz ve bunları giriş tensörüne birer birer yerleştiriyoruz:
for (byte i = 0; i < 72; i = i + 1) {
input->data.int8[i] = x[i] / input->params.scale + input->params.zero_point;
}
Daha sonra, Tensorflow Micro yorumlayıcısı tarafından çıkarım gerçekleştirilir ve eğer hata rapor edilmezse, değerler çıkış tensörlerine yerleştirilir.
// Çıkarımı çalıştırın ve herhangi bir hatayı raporlayın
TfLiteStatus invoke_status = interpreter->Invoke();
if (invoke_status != kTfLiteOk) {
TF_LITE_REPORT_ERROR(error_reporter, "Invoke başarısız oldu");
return;
}
Girişte olduğu gibi, modelin çıktısı da kuantize edildiği için, ters işlemi gerçekleştirmemiz ve INT8’den float’a dönüştürmemiz gerekiyor.
// Modelin çıkış tensöründen kuantize edilmiş çıktıyı alın
float y_type[4];
// Çıktıyı tam sayıdan floating-point'e dekuantize edin
int8_t y_precip_q = output_precip->data.int8[0];
Serial.println(y_precip_q);
float y_precip = (y_precip_q - output_precip->params.zero_point) * output_precip->params.scale;
Serial.print("Yağış: ");
Serial.print(y_precip);
Serial.print("\t");
Serial.print("Tip: ");
for (byte i = 0; i < 4; i = i + 1) {
y_type[i] = (output_type->data.int8[i] - output_type->params.zero_point) * output_type->params.scale;
Serial.print(y_type[i]);
Serial.print(" ");
}
Serial.print("\n");
}
Aynı veri noktası için değerleri kontrol edin ve karşılaştırın, bunlar Colab defterindeki kuantize edilmiş Tensorflow Lite modeli ile Wio Terminal’da çalışan Tensorflow Micro modeli için aynı olmalıdır.
Tam sürüm şemayı keşfedin ve deneyin
Harika! Yani çalışıyor, şimdi bir sonraki adım bunu bir demo olmaktan gerçekten faydalı bir projeye dönüştürmek. Seeed Arduino şematik kitaplığı deposundan şemayı açın ve içeriğine göz atın.
Kodu ana şemaya, get_historical_data ve GUI parçalarına ayırdım. Modelimizin geçmiş 24 saatlik verilere ihtiyacı olduğundan, ilk çıkarımı gerçekleştirmek için 24 saat beklememiz gerekecek, bu çok fazla – bu sorunu çözmek için openweathermap.com API’sinden geçmiş 24 saatlik hava durumunu alıyoruz ve cihaz açıldığında ilk çıkarımı hemen gerçekleştirebiliyoruz ve ardından değerleri Wio Terminal I2C Grove soketine bağlı BME280 sensöründen gelen sıcaklık, nem ve basınç ile dairesel tampon içinde değiştiriyoruz. GUI için LVGL kullandım, bu Küçük ve Çok Yönlü Grafik Kütüphanesi – bu da hızla gelişen bir projedir ve kullanımı çok kolay değildir, ancak işlevselliği buna değer!

Gerekli kütüphaneleri yüklemek ve LVGL’i demo çalıştırmak için yapılandırmak için Github deposundaki talimatları izleyin.
Bunu başardık – Wio Terminal’da tüm detayları ve optimizasyonları ile orta boy bir Konvolüsyonel sinir ağı eğittik ve dağıttık, böylece cihaz uzun süreler boyunca kararlı çalışabilir ve keskin görünebilir! Bu projeyi kendiniz yapmayı deneyin ve mümkünse geliştirin! Videolarımın ve eğitimlerimin diğer insanlar için faydalı ve ilham verici olduğunu görmek her zaman bir zevktir.
Bir sonraki sefere kadar!
TinyML projeniz için en iyi aracı seçin
Grove – Vision AI Modülü V2
Himax WiseEye2 HX6538 işlemcisi ile güçlendirilmiş bir MCU tabanlı görsel AI modülüdür, rm Cortex-M55 ve Ethos-U55 özelliklerine sahiptir. Vektör veri işleme için ince bir şekilde optimize edilmiş Arm Helium teknolojisini entegre eder, şunları sağlar:
“`
- Ödüllü düşük güç tüketimi
- DSP ve ML yeteneklerinde önemli artış
- Pil ile çalışan uç nokta AI uygulamaları için tasarlandı

Tensorflow ve Pytorch framework’lerini destekleyerek, kullanıcıların hem hazır hem de özel AI modellerini Seeed Studio’dan SenseCraft AI ile dağıtmasına olanak tanır. Ayrıca, modül IIC, UART, SPI ve Type-C gibi çeşitli arayüzler sunarak, Seeed Studio XIAO, Grove, Raspberry Pi, BeagleBoard ve ESP tabanlı ürünler gibi popüler ürünlerle kolay entegrasyon sağlar.
Seeed Studio XIAO ESP32S3 Sense & Seeed Studio XIAO nRF52840 Sense
Seeed Studio XIAO Serisi, benzer bir donanım yapısına sahip, parmak boyutunda küçücük geliştirme kartlarıdır. Buradaki kod adı “XIAO”, yarı özelliği “Tiny”yi, diğer yarısı ise “Puissant”ı temsil eder.


Seeed Studio XIAO ESP32S3 Sense, bir OV2640 kamera sensörü, dijital mikrofon ve SD kart desteği entegre eder. Gömülü ML hesaplama gücü ve fotoğrafçılık yeteneğini birleştirerek, bu geliştirme kartı akıllı ses ve görüntü AI ile başlamanız için harika bir araç olabilir.
Seeed Studio XIAO nRF52840 Sense, Bluetooth 5.0 kablosuz yeteneğine sahiptir ve düşük güç tüketimi ile çalışabilir. Yerleşik IMU ve PDM ile, gömülü Makine Öğrenimi projeleri için en iyi aracınız olabilir.
Buraya tıklayın XIAO ailesi hakkında daha fazla bilgi edinmek için!
SenseCraft AI
SenseCraft AI kolay AI modeli eğitimi ve dağıtımı için no-code/low-code ile bir platformdur. Seeed ürünlerini yerel olarak destekleyerek, eğitilen modellerin Seeed ürünlerine tam uyumunu sağlar. Ayrıca, bu platform aracılığıyla modellerin dağıtılması, web sitesinde tanımlama sonuçlarının anında görselleştirilmesini sağlar ve model performansının hızlı bir şekilde değerlendirilmesine olanak tanır.

tinyML uygulamaları için ideal olan bu platform, cihazı bağlayarak, bir model seçerek ve tanımlama sonuçlarını görüntüleyerek, hazır veya özel AI modellerini zahmetsizce dağıtmanıza olanak tanır.
