論文選讀 — Detecting Spacecraft Anomalies Using LSTMs and Nonparametric Dynamic Thresholding
Detecting Spacecraft Anomalies Using LSTMs and Nonparametric Dynamic Thresholding
一般的異常偵測 (Anomaly Detection) 系統中,最基礎的就是用靜態閾值 (Static Threshold) 來作為判斷異常的基準,如記憶體使用率超過 85%、硬碟使用量超過 90% 等,但時常需要有經驗的人提供一個「看起來合理的範圍」。本篇是由 NASA 噴射推進實驗室所發表的 paper,示範了他們使用的動態閾值的方法 (Dynamic Threshold)。
如果用在產品中的話,應該可以在說明中加上一行告示
- 本系統包含 NASA 噴射推進實驗室之技術
本篇目標寫給無統計基礎或是對於充滿符號的數學公式困擾的人。作者亦無統計基礎,如果翻譯或理解有誤歡迎指正。
目標
如同現代許多系統一樣,NASA 的太空船也會回傳大量的遙測資訊回來,並且交由 Operations Engineers 監控是否有異常。
現行的監測系統只專注在部分的異常事件,卻需要大量的專家知識 (Export Knowledge) 來開發與維護。而改良後的異常偵測系統可以大幅降低人力的負擔與運作風險。
本篇示範了使用LSTM 模型、非監督式非參數閾值 (Unsupervised Nonparametric Anomaly Thresholding) 以及提供降低偽陽性的策略 (False Positive Mitigation Strategies)。
LSTM Model
對於 NASA 來說,他們最需要的是可追溯 (Trackable)的異常警告,因此他們採用的資料上圖第二區。將那個時間點收到和送出的指令 (Command) 以 one-hot encoding 的方式,再加上單一一組遙測資料 (Telemetry Value) 組合成輸入資料。
輸入 LSTM Model 後就可以獲得一個預測值 y,並且與原始值對照取得誤差值 e。
Dynamic Thresholding
動態閾值的概念很簡單,就是計算了誤差值 e的移動平均數與標準差這兩個東西,只是他們使用了 Exponential Weighted Moving Average (EWMA) 來平滑化移動平均。
EWMA
與一般移動平均的差別,在於時間越舊的資料點其權重會指數性的下降,較詳細的公式可以參考 Pandas 的文件。
以較簡單的方式來說,我們會定一個介於零到一之間的參數 alpha、在總數 n 個值的數列 values、計算第 i 個值的話,計算方式如下。
# 1 <= i <= n
weighted[i] = (1-alpha) ^ (n - i) * values[i]
用 Python 計算一個 1~10 數列的 EWMA,最後的結果明顯比一般的平均還要高。
data = [x for x in range(1, 11)]
length = len(data)
alpha = 0.2
total = 0.0
total_weight = 0.0
for index, value in enumerate(data):
weight = (1 - alpha) ** (length - index - 1)
weighted_value = weight * value
print(f"[{index}] {value} * {weight:.4f} = {weighted_value:.4f}")
total += weighted_value
total_weight += weight
ewma = total / total_weight
print(f"EWMA: {ewma:.4f}")
print(f"Mean: {sum(data)/len(data)}")
[0] 1 * 0.1342 = 0.1342
[1] 2 * 0.1678 = 0.3355
[2] 3 * 0.2097 = 0.6291
[3] 4 * 0.2621 = 1.0486
[4] 5 * 0.3277 = 1.6384
[5] 6 * 0.4096 = 2.4576
[6] 7 * 0.5120 = 3.5840
[7] 8 * 0.6400 = 5.1200
[8] 9 * 0.8000 = 7.2000
[9] 10 * 1.0000 = 10.0000
EWMA: 7.2029
Mean: 5.5
Thresholding
讀了這篇 paper 以後,發現基本作法與我之前寫過的一篇類似
若是預測值與實際值的誤差,超過了 k 個標準差時就判定為異常。根據他們的實驗結果,設定在 10 個標準差內可以得到較佳的效果。
如此一來整個系統只需調整一個變數即可,大幅降低了監控更多數據的開發成本,但隨之而來的是整體雜訊卻也大幅增加。
False Positive Mitigation
就算再低的假陽性率(False Positive Rate),當整體數據的基數足夠龐大時,對於人們來說都是無法負荷的程度。
因此他們先將單一個 Window 中,所有誤差值 e 超出上步驟取得之閾值的點標示為異常,接著取出這些誤差值由大到小降冪排列,並在最後面加上非異常中最大的數值。
因此在上圖的範例中,取出的數列 e_max 如下,並計算每個步驟到下一步驟的斜率 d。
e_max = [0.01396, 0.01072, 0.00994]
d[i] = (e_max[i] - e_max[i+1]) / e_max[i]
接著是指定一個最小下降率 p (minimum descending percentage),若是 d[i] > p 則所有 i 以前的點保持為異常,反之 d[i] < p 則將 i 之後的點視為非異常。
上圖範例中設 p=0.1 ,Anomaly 2 的斜率 d[0] 為 (0.01396–0.01072)/0.01396 = 0.23,因此依舊是異常。而 Anomaly 1 的斜率 d[1] = 0.07 小於 p,所以將其視為正常。
他們透過此方法去除誤差值序列中的常態雜訊,專注在最重要的異常事件。
結語
本篇內容不難但實用,比起傳統的方式可以節省不少麻煩。
Paper 後也有一些相關的實驗數據可參考,GitHub 上也有相關程式碼可以使用 khundman/telemanom,如果有相關需求的可以嘗試看看。
沒想到這系列能來到第二篇,希望之後有機會可以再多分享一些,我們下回再見。