Bu makalenin konusu

Anomaliler. Ya da daha spesifik olarak, tahmine dayalı bakım için anomali tespiti. Wio Terminal’ın yerleşik ivmeölçerinden veri kullanacağız, sinir ağı model çıkarımı yapacağız ve cihazda anomali tespiti gerçekleştireceğiz, ardından verileri yeni Blynk IoT platformu‘na göndereceğiz; bu platform birkaç gün önce piyasaya sürüldü ve Wio Terminal’ı tamamen destekliyor.
Tam eğitim ve video gösterimi için, eşlik eden videoya göz atın:
Bu, NE, şimdi de NASIL kısmına geçelim, daha aşina olabileceğimiz bir örnekle başlayalım.
Anomali tespiti ve tahmine dayalı bakımın özeti
Bir basit görüntü tanıma modelini, diyelim ki 5 farklı hayvan sınıfını (kaplan, fil, ayı, yılan ve zürafa) tanıyacak şekilde eğitirseniz ve ardından ona bir insan resmi verirseniz, model elinden gelenin en iyisini yaparak tahminde bulunacak ve muhtemelen bunun bir fil olduğunu söyleyecektir. Bu duruma, bu özel modelin iç işleyişini ve genel olarak bilgisayarla görmeyi pek anlamayan sıradan insanların gülüşleri eşlik edecektir.

Elbette, model yanlış bir şey yapmadı – resmi işledi, mevcut özellikleri hesapladı ve ardından bu özelliklere dayanarak sınıflandırma sonucunu çıkardı. Ancak, sınıflardan gelen özellikleri grafik üzerinde gösterirsek ve bunları kümelere ayırırsak, insan resmi özelliklerinin herhangi bir sınıf kümesinden uzak olduğunu ve dolayısıyla bir “aykırı değer” temsil ettiğini göreceğiz.

Bu elbette, hayvanlardan birinin çok garip bir resmi olabilir, ancak çoğu durumda, modelin tanımadığı bir nesne olma olasılığı çok daha yüksektir.
Bilgisayarla görme ve ses tanıma görevleri için genellikle bu sorunu çözmek amacıyla “arka plan” sınıfı ile ilgileniyoruz; bu, temelde ilgi alanındaki sınıflar dışında kalan her şeyi temsil eder. Bazı durumlarda, modelimizin tüm verileri “normal” ve “anormal” olarak yorumlayabilmesini istiyoruz. “Anormal”ın kesin özellikleri önemli değil – bunlar çok farklı olabilir, önemli olan, “anormal” sınıfı tespit edildiğinde bazı önlemlerin alınması gerektiğidir. Şu anda tanımladığım şey, makine öğrenimini tahmine dayalı bakım için kullanmanın temelidir. Cihazın durumunu izliyoruz; bu bir klima, su pompası veya sensörlerle donatılmış diğer makineler olabilir ve bilinen “normal” çalışma profiline dayanarak, bir şeylerin AZ da olsa yanlış gitmeye başladığını tespit etmeye çalışıyoruz, bu da ciddi bir soruna dönüşmeden önce.

Veri toplama ve modeli eğitme
Bu proje için Wio Terminal’ı ofisimizin dış terasındaki bir su pompasına kurdum; burada bazı bitkiler ve balıklar var.

Daha sonra iki kategori örnek topladım – bekleme ve normal çalışma ve bu iki durumu Spectral Features işleme bloğu çıktısına dayanarak tanıyacak şekilde basit bir model eğittim.


İşleme ve öğrenme bloklarının kesin parametreleri için, paylaştığım projenin kamuya açık versiyonuna göz atabilirsiniz. Yaptığım tek önemli değişiklik, filtreyi düşükten yükseğe değiştirmekti; bu, farklı sınıfların özelliklerini daha belirgin hale getirdi. Bekleme ve normal pompa çalışması arasında ayırt etmek elbette oldukça kolay oldu. Daha zorlu görev ise arıza tespitiydi. Arızayı simüle etmek için su pompasını tanktan çıkarıyordum – bu, temelde ses ve titreşim seviyelerinin düşmesine neden oluyordu.

Arıza örneğine baktığımızda, accX RMS, accY RMS ve accZ RMS eksenlerinde özellik keşif aracında, bunun bekleme ve normal çalışma örnekleri arasında bir yerde olduğunu görüyoruz.

Bunu avantajımıza kullanabiliriz; daha önce gördüğümüz verilerin etrafında kümeler oluşturan yeni (ikinci) bir ağ eğiterek ve gelen verileri bu kümelerle karşılaştırarak. Eğer bir kümeden uzaklık çok büyükse, örnek anomali olarak işaretlenir.
Deneme yanılma ile, anomali tespiti için çok düşük küme sayısı ve 0.5 mesafe eşiğinin en iyi sonucu verdiğini buldum, ancak bu çok spesifik bir duruma bağlıdır ve verilerinize bağlıdır. Doğruluğu artırmaya yardımcı olan bir şey, Wio Terminal’ı su pompasına sağlam bir şekilde yapıştırmaktı – gerçek cihaz için vidalar kullanabilirsiniz. Sağlam bir şekilde sabitlemeden önce, Wio Terminal rastgele sallanıyordu, bu da normal çalışma örneklerine çok fazla gürültü ekliyordu.
Dağıtım ve test
Model eğitildikten ve Canlı sınıflandırma modu kullanılarak test edildikten sonra, onu tekrar cihaza dağıtma zamanı geldi. Arduino kütüphanesini derliyoruz ve indiriyoruz, Arduino kütüphaneleri klasörüne çıkarıyoruz ve ardından nano33_ble_sense_accelerometer şemasını Wio Terminal’daki ivmeölçerle eşleştirecek şekilde değiştiriyoruz. Basit bir test için, anomali tespit edildiğinde kırmızı yanacak bir LCD ekran kullanıyoruz.
#define ANOMALY_THRESHOLD 0.5
/* Includes ---------------------------------------------------------------- */
#include <wio_anomaly_detection_inference.h>
#include "LIS3DHTR.h"
#include "TFT_eSPI.h"
TFT_eSPI tft;
LIS3DHTR<TwoWire> lis;
/* Constant defines -------------------------------------------------------- */
#define CONVERT_G_TO_MS2 9.80665f
/* Private variables ------------------------------------------------------- */
static bool debug_nn = false; // Ham sinyallerden üretilen özellikleri görmek için bunu true yapın
/**
* @brief Arduino kurulum fonksiyonu
*/
void setup()
{
// sadece bir kez çalışacak kurulum kodunuzu buraya koyun:
Serial.begin(115200);
//while (!Serial) {delay(10);}
Serial.println("Edge Impulse Inferencing Demo");
tft.begin();
tft.setRotation(3);
lis.begin(Wire1);
if (!lis.available()) {
Serial.println("IMU'yu başlatmakta başarısız!");
while (1);
}
else {
ei_printf("IMU başlatıldı\r\n");
}
lis.setOutputDataRate(LIS3DHTR_DATARATE_100HZ); // Çıkış veri hızını 25Hz olarak ayarlama, 5kHz'ye kadar ayarlanabilir
lis.setFullScaleRange(LIS3DHTR_RANGE_16G); // Ölçek aralığını 2g olarak ayarlama, 2, 4, 8, 16g'den seçin
if (EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME != 3) {
ei_printf("HATA: EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME 3'e eşit olmalıdır (3 sensör ekseni)\n");
return;
}
}
/**
* @brief Printf fonksiyonu vsnprintf kullanır ve Arduino Serial ile çıktı verir
*
* @param[in] format Değişken argüman listesi
*/
void ei_printf(const char *format, ...) {
static char print_buf[1024] = { 0 };
va_list args;
va_start(args, format);
int r = vsnprintf(print_buf, sizeof(print_buf), format, args);
va_end(args);
if (r > 0) {
Serial.write(print_buf);
}
}
/**
* @brief Veri al ve çıkarım yap
*
* @param[in] debug Eğer true ise hata ayıklama bilgisi al
*/
void loop()
{
ei_printf("Örnekleme...\n");
// IMU'dan okuyacağımız değerler için burada bir tampon ayırın
float buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = { 0 };
for (size_t ix = 0; ix < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; ix += 3) {
// Bir sonraki tick'i belirleyin (ve sonra uykuya dalın)
uint64_t next_tick = micros() + (EI_CLASSIFIER_INTERVAL_MS * 1000);
lis.getAcceleration(&buffer[ix], &buffer[ix+1], &buffer[ix + 2]);
buffer[ix + 0] *= CONVERT_G_TO_MS2;
buffer[ix + 1] *= CONVERT_G_TO_MS2;
buffer[ix + 2] *= CONVERT_G_TO_MS2;
delayMicroseconds(next_tick - micros());
}
// Ham tamponu sınıflandırabileceğimiz bir sinyale dönüştürün
signal_t signal;
int err = numpy::signal_from_buffer(buffer, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, &signal);
if (err != 0) {
ei_printf("Tampon'dan sinyal oluşturmakta başarısız (%d)\n", err);
return;
}
// Sınıflandırıcıyı çalıştır
ei_impulse_result_t result = { 0 };
err = run_classifier(&signal, &result, debug_nn);
if (err != EI_IMPULSE_OK) {
ei_printf("HATA: Sınıflandırıcıyı çalıştırmakta başarısız (%d)\n", err);
return;
}
// tahminleri yazdır
ei_printf("Tahminler ");
ei_printf("(DSP: %d ms., Sınıflandırma: %d ms., Anomali: %d ms.)",
result.timing.dsp, result.timing.classification, result.timing.anomaly);
ei_printf(": \n");
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
ei_printf(" %s: %.5f\n", result.classification[ix].label, result.classification[ix].value);
}
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf(" anomali skoru: %.3f\n", result.anomaly);
if (result.anomaly > ANOMALY_THRESHOLD)
{
tft.fillScreen(TFT_RED);
tft.setFreeFont(&FreeSansBoldOblique12pt7b);
tft.drawString("Anomali tespit edildi", 20, 80);
delay(1000);
tft.fillScreen(TFT_WHITE);
}
#endif
}
#if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR != EI_CLASSIFIER_SENSOR_ACCELEROMETER
#error "Geçerli sensör için geçersiz model"
#endif
Elbette, gerçek uygulama için bu tür bir bildirim çalışmayacaktır, çünkü sürekli olarak üzerinde izlenecek bir kişi yoktur.
Blynk IoT platformunun yeni sürümünü kullanma
Bu demoyu kullanışlı hale getirmek için, Blynk IoT platformunun yeni sürümünü kullanacağız.

Yeni sürüm, cihazları izlemek için bir web kontrol paneli, verilere erişimi yönetmek için bir WI-FI yöneticisi, cihaz modeli oluşturma için yeni bir yaklaşım ve diğerleri gibi özellikler içeriyor. Bu video yayınlandığında, bu özelliklerin hepsi genel kamuya sunulmuş olmalıdır. blynk.cloud adresine gidin, bir hesap kaydedin veya yeni bir tane oluşturun. Ardından yeni bir şablon oluşturun – şablonlar, benzer işlevselliğe sahip birden fazla cihaz tarafından miras alınabilen cihazların dijital modelleridir. Şablonların gücü, cihaz filosunuzun boyutuna bakılmaksızın cihaz veri modelinin anında güncellenmesidir.
Donanım olarak Arduino Uno’yu ve bağlantı türü olarak Wi-Fi’yi seçin. Ardından, aşağıdaki ekran görüntülerinde olduğu gibi Datastreams ve Dashboard sekmelerini doldurun ve değişiklikleri kaydedin.


Bu projede Metadata veya Events sekmelerini kullanmıyoruz. Cihaz şablonunun ana bileşenlerinin ana amacı:
• Metadata – yapılandırabileceğiniz cihaz hakkında ek veriler.
• Datastreams – cihazdan giren ve çıkan verileri tanımlamak için bir varlık. Genel olarak, sanal pinlere (bunlar da kullanılabilir) çok benzer.
• Events – önemli uyarı ve bildirimlerin listesi
• Web Dashboard – Web uygulamasındaki Widget’ların bir seti
• Mobil Dashboard – Mobil uygulamadaki Widget’ların bir seti
My Devices sekmesinde yeni bir cihaz oluşturun – oluşturduğunuz şablonu seçin ve ona benzersiz bir isim verin.
Artık web arayüzü, cihazımızdan veri almak için hazır. Seeed Wio Terminal örnek şemalar deposundan örnek şemayı indirin – ana şema dosyasının yanı sıra, Wi-Fi yöneticisi kodunun bulunduğu yardımcı dosyaları da içerir. Ana şema dosyasında, LCD ekran ile test etmek için kullandığımız veri toplama/veri işleme/çıkarım kodu run_inference() fonksiyonuna taşındı. En yüksek güvene sahip sınıfın sınıf ID’si (güven eşiğin üzerinde ise) best_result global değişkenine kaydedilir ve ışık ve ses sensörleri verileri ile birlikte belirli aralıklarla Blynk sunucusuna gönderilir. BLYNK_TEMPLATE_ID ve BLYNK_DEVICE_NAME değerlerini cihaz şablonunuzdan olanlarla değiştirmeyi unutmayın.

Kodu Wio Terminal’a yükledikten sonra, telefonunuzla bağlanabileceğiniz bir hotspot oluşturacaktır. Bağlandığınızda, WiFi kimlik bilgilerinizi, API token’ınızı (Bunu My Devices sekmesinde cihazınıza tıklayarak ve ardından Device Info’ya giderek bulabilirsiniz) girmeniz gereken basit bir yapılandırma sayfasına otomatik olarak yönlendirileceksiniz ve ardından Bağlan’a tıklayın. Ardından Wio Terminal, WiFi ağına ve Blynk bulut sunucusuna bağlanacak ve verileri göndermeye başlayacaktır. My Devices sekmesinde cihaza tıklayarak güzel grafikler ve durum mesajını görebilirsiniz. Test sonuçlarını videonun sonunda görebilirsiniz.
Aynı yaklaşım, diğer makinelerin çalışmasındaki düzensizlikleri tespit etmek için de uygulanabilir – hareketli parçalara sahip her şey için ivmeölçer kullanabiliriz, çünkü bunlar ölçebileceğimiz titreşim üretir. Cihaz ses çıkarıyorsa, mikrofon da kullanabiliriz. Sensörlerin bir kombinasyonu daha iyi çalışabilir. Öngörücü bakımın kullanılabileceği başka iyi uygulamalar var mı? Fikirlerinizi yorumlarda yazın! Umarım bu makale ve video sizin için faydalı olmuştur!
