IoT ve Yapay Zekâ

Sensör Verisi için Isolation Forest: Çevrimdışı Eğitin, Canlı MQTT Mesajlarını Puanlayın

Geçmiş çok değişkenli sensör verisi üzerinde scikit-learn ile bir Isolation Forest eğitin, ardından onu canlı MQTT okumalarını puanlayan ve anomali olaylarını yayınlayan bir Python servisine yükleyin.

Karar ağaçlarının çok değişkenli bir sensör akışındaki aykırı bir okumayı yalıttığını gösteren sensör verisi için Isolation Forest çizimi
Bunu kendi MQTT broker’ınızda çalıştırınFree planla özel, yönetilen bir MQTT broker alın ve hazır kod örnekleriyle başlayın.
Ücretsiz deneyin Kod örnekleri Kart gerekmez

Sensör verisinde Isolation Forest, birkaç sinyalin birleşiminde saklanan anomalileri yakalamanın en pratik yollarından biridir. Bu eğitimde geçmiş veri üretecek, pencere özellikleri çıkaracak, scikit-learn ile bir model eğitecek ve onu canlı MQTT mesajlarını puanlayıp anomali olaylarını yayınlayan bir Python servisinde çalıştıracaksınız.

Isolation Forest Sensör Verisinde Neden İyi Çalışır

Isolation Forest basit bir fikre dayanır: anomaliler az ve farklıdır, bu yüzden yalıtılmaları daha kolaydır. Algoritma çok sayıda rastgele ağaç oluşturur; her ağaç tekrar tekrar rastgele bir özellik ve rastgele bir bölme değeri seçer. Normal noktalar yoğun bölgelerde bulunur ve ayrılmaları için çok sayıda bölme gerekir. Anormal noktalar ise yalnızca birkaç bölmeden sonra yalıtılır. Ağaçlar boyunca ortalama yol uzunluğu anomali skoruna dönüşür.

Bu tasarım, birkaç nedenle endüstriyel sensörlere uygundur:

  • Etiket gerekmez. Her fabrikada bolca bulunan, çoğunlukla normal çalışma verisiyle eğitirsiniz.
  • Doğası gereği çok değişkenlidir. Yüksek akım normaldir, düşük debi normaldir; ancak yüksek akımla birlikte düşük debi hızla yalıtılır.
  • Hızlıdır. Yüz binlerce satır üzerinde eğitim saniyeler sürer ve puanlama bir uç gateway için yeterince ucuzdur.
  • Az hiperparametre vardır. Ağaç sayısı, örneklem boyutu ve beklenen kirlilik (contamination) oranı genellikle ayarladığınız her şeydir.

Sınırları da vardır. Zamanı kendi başına anlamaz; bu yüzden zamansal davranışı özelliklere kodlamanız gerekir. Ayrıca eğitim verisine göre puanlar; yazın eğitilmiş bir model kışı anormal olarak işaretleyebilir.

Isolation Forest ile Diğer Dedektörlerin Karşılaştırması

Yöntem Çok değişkenli İlgisiz özellikleri tolere eder Eğitim maliyeti Açıklanabilirlik
Kayan z-skoru Hayır (sinyal başına) Uygulanamaz Yok Yüksek
Isolation Forest Evet Oldukça iyi Düşük Orta
One-Class SVM Evet Zayıf, ölçekleme gerekir Ortadan yükseğe Düşük
Local Outlier Factor Evet Zayıf Orta, bellek yoğun Orta
Autoencoder Evet İyi, yeterli veriyle Yüksek Düşük

Tek sinyalli istatistikleri henüz denemediyseniz, önce Z-skoru, IQR ve EWMA ile sensör verisinde aykırı değer tespiti yazısını okuyun. Isolation Forest, bu yöntemler sinyaller arasındaki ilişkileri kaçırdığında yerini hak eder.

Ön Koşullar

pip install "paho-mqtt>=2.0" scikit-learn pandas numpy joblib

connectmq/demo/if-5d21/... gibi rastgele bir önek seçin. Örnekler, tüm topic'lerin başkaları tarafından okunabildiği broker.connectmq.com genel test alanını kullanır; bu yüzden veriyi sentetik tutun.

Adım 1: Geçmiş Sensör Verisi Oluşturmak

Gerçek bir projede geçmiş veriyi veritabanınızdan dışa aktarırsınız. Eğitimi kendi içinde bütünlüklü tutmak için bu betik, birbiriyle ilişkili üç sinyale sahip bir pompayı simüle eder: motor akımı, debi ve çıkış basıncı.

# make_history.py
import numpy as np
import pandas as pd

rng = np.random.default_rng(42)
n = 20_000  # saniyede bir okuma, yaklaşık 5,5 saat
load = 0.6 + 0.2 * np.sin(np.arange(n) / 900) + rng.normal(0, 0.02, n)

df = pd.DataFrame({
    "currentA": 10 + 12 * load + rng.normal(0, 0.3, n),
    "flowLpm": 30 + 40 * load + rng.normal(0, 1.0, n),
    "pressureBar": 2 + 3 * load + rng.normal(0, 0.08, n),
})
df.to_csv("pump_history.csv", index=False)
print(df.describe())

Üç sinyal de yükle birlikte hareket eder. Bu korelasyon, tam olarak sinyal başına bir eşiğin göremeyeceği şeydir.

Adım 2: Pencere Özellikleri Çıkarmak

Tekil okumaları puanlamak gürültüyü ve kısa dinamikleri göz ardı eder. Bunun yerine kısa bir kayan pencere üzerinde özellikler hesaplayın: her sinyalin ortalaması, standart sapması ve fiziksel olarak anlamlı birkaç oran.

# features.py
import numpy as np
import pandas as pd

SIGNALS = ["currentA", "flowLpm", "pressureBar"]
WINDOW = 10  # okuma sayısı


def window_features(frame: pd.DataFrame) -> dict:
    feats = {}
    for s in SIGNALS:
        feats[f"{s}_mean"] = frame[s].mean()
        feats[f"{s}_std"] = frame[s].std(ddof=0)
    feats["flow_per_amp"] = feats["flowLpm_mean"] / max(feats["currentA_mean"], 1e-6)
    feats["pressure_per_flow"] = feats["pressureBar_mean"] / max(feats["flowLpm_mean"], 1e-6)
    return feats


def build_feature_table(df: pd.DataFrame, step: int = 5) -> pd.DataFrame:
    rows = [window_features(df.iloc[i:i + WINDOW])
            for i in range(0, len(df) - WINDOW, step)]
    return pd.DataFrame(rows)

Oranlar göründüklerinden daha önemlidir. Tıkanmış bir çark amper başına debiyi, bir sızıntı ise debi başına basıncı düşürür; her ham değer normal aralığında olsa bile.

Adım 3: Isolation Forest'ı Eğitmek

# train.py
import joblib
import pandas as pd
from sklearn.ensemble import IsolationForest

from features import build_feature_table

history = pd.read_csv("pump_history.csv")
X = build_feature_table(history)

model = IsolationForest(
    n_estimators=200,
    max_samples=256,
    contamination=0.005,   # eğitim verisindeki beklenen anomali oranı
    random_state=0,
)
model.fit(X)

scores = -model.score_samples(X)        # yüksek = daha anormal
threshold = float(pd.Series(scores).quantile(0.995))
joblib.dump({"model": model, "columns": list(X.columns),
             "threshold": threshold, "version": "iforest-pump-v1"},
            "iforest_pump.joblib")
print(f"trained on {len(X)} windows, threshold={threshold:.3f}")

İki ayrıntı dikkat gerektirir. Birincisi, scikit-learn'ün score_samples fonksiyonu daha anormal noktalar için daha düşük değerler döndürür; bu yüzden onu negatif almak sezgisel bir "yüksek olan daha kötü" skoru verir. İkincisi, yalnızca predict'e güvenmek yerine eğitim skor dağılımından alınmış açık bir eşik saklayın. Böylece onu daha sonra yeniden eğitim yapmadan ayarlayabilirsiniz.

Adım 4: Canlı MQTT Mesajlarını Puanlamak

Aşağıdaki servis pompanın telemetrisine abone olur, son on okumayı tutar, aynı özellikleri hesaplar ve her okumada bir skor yayınlar.

# live_score.py
import json
import time
import uuid
from collections import deque

import joblib
import pandas as pd
import paho.mqtt.client as mqtt

from features import SIGNALS, WINDOW, window_features

PREFIX = "connectmq/demo/if-5d21/site1/pumps/pump1"
bundle = joblib.load("iforest_pump.joblib")
model, columns, threshold = bundle["model"], bundle["columns"], bundle["threshold"]
buffer = deque(maxlen=WINDOW)
streak = 0


def on_connect(client, userdata, flags, reason_code, properties):
    print("connected:", reason_code)
    client.subscribe(f"{PREFIX}/telemetry", qos=0)


def on_message(client, userdata, msg):
    global streak
    try:
        reading = json.loads(msg.payload)
        buffer.append({s: float(reading[s]) for s in SIGNALS})
    except (ValueError, KeyError):
        return
    if len(buffer) < WINDOW:
        return
    feats = window_features(pd.DataFrame(buffer))
    X = pd.DataFrame([feats], columns=columns)
    score = float(-model.score_samples(X)[0])
    is_anomaly = score > threshold
    streak = streak + 1 if is_anomaly else 0
    result = {"ts": time.time(), "score": round(score, 4),
              "threshold": round(threshold, 4), "isAnomaly": is_anomaly,
              "model": bundle["version"],
              "flowPerAmp": round(feats["flow_per_amp"], 3)}
    client.publish(f"{PREFIX}/anomaly", json.dumps(result), qos=0)
    if streak == 3:
        client.publish(f"{PREFIX}/alerts", json.dumps(result), qos=1)
        print("ALERT", result)


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                     client_id=f"iforest-{uuid.uuid4().hex[:8]}")
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_forever()

Adım 5: Normal ve Arızalı Veri Beslemek

Bu yayıncı normal davranışı yeniden oynatır ve bir dakika sonra tıkanmış bir çarkı simüle eder: akım yüksek kalırken debi düşer.

# replay.py
import json
import time
import uuid

import numpy as np
import paho.mqtt.client as mqtt

PREFIX = "connectmq/demo/if-5d21/site1/pumps/pump1"
rng = np.random.default_rng()
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                     client_id=f"pump-sim-{uuid.uuid4().hex[:8]}")
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_start()

for t in range(240):
    load = 0.6 + rng.normal(0, 0.02)
    reading = {
        "currentA": 10 + 12 * load + rng.normal(0, 0.3),
        "flowLpm": 30 + 40 * load + rng.normal(0, 1.0),
        "pressureBar": 2 + 3 * load + rng.normal(0, 0.08),
    }
    if t > 60:
        reading["flowLpm"] *= 0.75  # tıkanmış çark
    client.publish(f"{PREFIX}/telemetry",
                   json.dumps({k: round(v, 3) for k, v in reading.items()}))
    time.sleep(1)
client.loop_stop()

Önce live_score.py, ardından replay.py betiğini başlatın. Skorlar ilk dakika boyunca eşiğin altında kalır ve debi düştüğü anda keskin şekilde yükselir; çünkü akım ve basınç hâlâ olağan görünürken amper başına debi ilişkisi bozulur.

Bir Uyarıyı Teknisyene Açıklamak

Tek başına bir anomali skoru kimseye neyi kontrol etmesi gerektiğini söylemez. Isolation Forest'ın yerleşik bir özellik bazlı açıklaması yoktur; ancak ucuz bir yaklaşım pratikte iyi çalışır: her özellik için mevcut değerin eğitim dağılımından ne kadar uzakta olduğunu, örneğin eğitim medyanı ve çeyrekler açıklığına göre sağlam bir z-skoru olarak hesaplayın ve en uç iki veya üç özelliği uyarıya ekleyin.

"Skor 0,71, eşik 0,62'nin üzerinde; flow_per_amp olağandışı düşük, flowLpm_mean olağandışı düşük" diyen bir uyarı doğrudan çarka veya emiş tarafına işaret eder. Bu, "pump1 anomalisi"nden çok daha fazla aksiyona dönüştürülebilir. Daha titiz atıflara ihtiyacınız varsa ağaç toplulukları için SHAP değerleri hesaplanabilir; ancak bunlar daha fazla hesaplama gerektirir ve ilk kurulum için nadiren gereklidir.

Özellik değerlerinin kendisini de anomali topic'inde düşük bir hızla yayınlamak faydalıdır. Bir mühendis daha sonra inceleme yaptığında, yalnızca modelin kararını değil, modelin gördüğü girdileri de görebilir.

Sensör Verisinde Isolation Forest için Ayar Kontrol Listesi

  1. Temsil edici normal verilerle eğitin. Görmeyi beklediğiniz tüm olağan çalışma modlarını, vardiyaları ve mevsimleri dahil edin.
  2. Bilinen arızaları eğitimden çıkarın ya da çıkaramıyorsanız kirlilik oranını dürüstçe belirleyin.
  3. Özellikleri fiziksel olarak anlamlı tutun. Oranlar ve farklar çoğu zaman ham değerlerden daha iyi sonuç verir.
  4. Zaman damgalarını ve sayaçları özellik olarak kullanmaktan kaçının; her yeni okumayı yeni ve farklı gösterirler.
  5. Eşiği doğrulama verisinden belirleyin ve uyarıların ilk haftalarından sonra yeniden gözden geçirin.
  6. Uyarı vermeden önce süreklilik arayın, tıpkı yukarıdaki ardışıklık sayacının yaptığı gibi.
  7. Modeli sürümleyin ve sürümü yayınlanan her sonuca ekleyin.
  8. Belirli bir takvimle yeniden eğitin ya da kayma izleme girdi dağılımının değiştiğini söylediğinde.

Son madde, anomali tespitinin IoT için MLOps ile buluştuğu yerdir: dedektörün kendisi de izlenmesi gereken bir modeldir.

Üretimde Çalıştırmak

Servisi bir uç gateway'e veya verinize yakın bir sunucuya taşıyın, broker'ınızın verdiği kimlik bilgileriyle 8883 portunda TLS üzerinden bağlanın ve topic yapısını koruyun. Özel bir ConnectMQ broker'ı, skorları ham telemetrinin yanında izlemeniz için canlı bir topic gezgini sunar; portaldaki eşik tabanlı uyarı kuralları da sayısal bir score değerinin bir sınırı aştığını basit ikinci bir güvenlik ağı olarak işaretleyebilir. Broker işletmekle hiç uğraşmak istemiyorsanız, ConnectMQ gibi barındırılan bir MQTT broker sertifikaları, kimlik doğrulamayı ve çalışma süresini yönetir; modeliniz ise kendi kodunuz olarak kalır. Hesap açmadan prototipleme için broker.connectmq.com genel alanı yeterlidir.

Çevreleyen mimari için IoT anomali tespiti yöntemleri yazısına, bu servisin daha hafif, tek sinyalli bir sürümü için ise Python ile gerçek zamanlı anomali tespiti yazısına bakın. Daha geniş bağlam yapay zeka ve IoT rehberinde.

ConnectMQ ile Başlayın

app.connectmq.com adresinde ücretsiz Serverless planında kredi kartı gerektirmeden bir broker oluşturun ve live_score.py içindeki genel host'u kendi uç noktanız ve kimlik bilgilerinizle değiştirin. Isolation Forest sonuçlarınız, ilk pencere dolduğu anda topic gezgininde görünecek.

Sık Sorulan Sorular

Sensör verisinde Isolation Forest eğitmek için ne kadar veriye ihtiyacım var?

Tüm normal çalışma modlarını kapsayan birkaç bin özellik penceresi başlamak için genellikle yeterlidir. Modların kapsanması, salt veri hacminden daha önemlidir.

Hangi kirlilik (contamination) değerini kullanmalıyım?

Eğitim verisinin ne kadarının anormal olduğuna dair en iyi tahmininizi kullanın; özenle seçilmiş normal veri için bu çoğu zaman yüzde birin oldukça altındadır. Canlı servis kendi eşiğini kullandığından, kirlilik oranı esas olarak varsayılan predict çıktısını etkiler.

Isolation Forest bir mikrodenetleyicide çalışabilir mi?

Eğitilmiş ağaçlar küçüktür, ancak özellik hesaplama ve scikit-learn'ün kendisi Linux sınıfı bir cihaz gerektirir. Bunu bir gateway'de veya Raspberry Pi'de çalıştırın; mikrodenetleyicilerde basit eşiklerle devam edin.

Modelim bir proses değişikliğinden sonra neden her şeyi işaretliyor?

Isolation Forest eğitim verisine göre puanlar; bu yüzden yeni bir ürün veya set değeri anormal görünür. Yeni moddan gelen verilerle yeniden eğitin ya da her mod için ayrı modeller eğitin.

İlgili yazılar

Tüm yazılar →

Özel MQTT broker’ınız birkaç tık uzağınızda

Hesabınızı oluşturun, broker kimlik bilgilerinizi alın ve ilk cihazınızı bağlayın — kurulacak, yamalanacak ya da ölçeklendirilecek sunucu yok.