AIOps探索:基於VAE模型的周期性KPI異常檢測方法
來自專欄智能運維(AIOps)18 人贊了文章
作者:林錦進
前言
在智能運維領域中,由於缺少異常樣本,有監督方法的使用場景受限。因此,如何利用無監督方法對海量KPI進行異常檢測是我們在智能運維領域探索的方向之一。最近學習了清華裴丹團隊發表在WWW 2018會議上提出利用VAE模型進行周期性KPI無監督異常檢測的論文:《Unsupervised Anomaly Detection via Variational Auto-Encoder for Seasonal KPIs in Web Applications 》[1](以下簡稱為Dount)。基於Dount論文的學習,本文將介紹如何使用Keras庫,實現基於VAE模型的周期性KPI異常檢測方法,包括其思路、原理與代碼實現,幫助大家理解這個方法。
背景介紹:
在AI in All的時代,工業界中的運維領域提出了:智能運維(AIOps, Artificial Intelligence for IT Operations)這個概念,即採用機器學習、數據挖掘或深度學習等方法,來解決KPI異常檢測、故障根因分析、容量預測等運維領域中的關鍵問題。
其中KPI異常檢測是在運維領域中非常重要的一個環節。KPI(key performance indicators)指的是對服務、系統等運維對象的監控指標(如延遲、吞吐量等)。其存儲的形式是按其發生的時間先後順序排列而成的數列,也就是我們通常所說的時間序列。從運維的角度來看,存在多種不同類型的KPI,周期性KPI是其中一種典型的KPI,其特點表現為具有周期性,如下圖:
要進行KPI異常檢測,首先我們要定義一下什麼是異常。如上圖所示,我們將KPI的異常點定義為超過期望值一定範圍的點,而在期望值的小範圍內波動的點我們將其認為是雜訊。對周期性KPI的異常檢測在工業界和學術界已有不少探索,本文將介紹基於深度學習模型VAE的無監督周期性KPI異常檢測方法。
正文:
- AutoEncoder
因為VAE跟AutoEncoder在網路整體結構上相似,都分為Encoder和Decoder模型,那麼在了解VAE之前,我們先了解什麼是AutoEncoder模型。
AutoEncoder的意思是自編碼器,這個模型主要由兩個部分組成:encoder和decoder,可以把它理解為兩個函數:z = encoder(x), x = decoder(z)。在AutoEncoder模型的思想中,我們期望能夠利用encoder模型,將我們的輸入X轉換到一個對應的z,利用decoder模型,我們能夠將z還原為原來的x,可以把AutoEncoder理解為有損的壓縮與解壓。
AutoEncoder模型有什麼用呢?有兩個主要功能:
- 降噪
- 將高緯的特徵轉為低緯度的特徵(從X到z)。
要實現一個AutoEncoder其實非常簡單(其實就是單個隱藏層的神經網路),有接觸過深度學習的人應該都可以理解:
input = Input(shape=(seq_len,)) encoded = Dense(encoding_dim, activation=relu)(input) decoded = Dense(seq_len)(encoded) autoencoder = Model(input, decoded)
我們先來考慮一下能否用AutoEncoder進行KPI異常檢測,以及它有什麼缺點。因為AutoEncoder具有降噪的功能,那它理論上也有過濾異常點的能力,因此我們可以考慮是否可以用AutoEncoder對原始輸入進行重構,將重構後的結果與原始輸入進行對比,在某些點上相差特別大的話,我們可以認為原始輸入在這個時間點上是一個異常點。
下面是一個簡單的實驗結果展示,我們訓練了一個輸入層X的維度設置為180(1分鐘1個點,3小時數據),Z的維度設置為5(可以理解為原始輸入降維後表達),輸出成X的維度設置為180的AutoEncoder模型,並且測試集的數據進行重構(滑動窗口形式,每次重構後只記錄最後一個點,然後窗口滑動到下一個時間點),能夠得到以下結果:
- 基於AutoEncoder的周期性KPI異常檢測:
上面提到,AutoEncoder具有降噪功能,那它怎麼降噪呢?這裡簡單舉一個例子:假設我們現在訓練出來的模型可以得到這樣的映射關係[1, 2](X)->[1](z)->[1 ,2]X_r, 其中[1, 2]表示二維向量, [1]表示一維向量,X_r表示重構後的X。這個例子表示了一個理想的AutoEncoder模型,它能將[1,2]降維到[1], 並且能從[1]重構為[1,2]。接下來,假設我們的輸入為[1, 2.1],其中第二維度的0.1表示一個雜訊,將其輸入到encoder部分後得到的Z為[1],並且重構後得到的X_r是[1, 2], 這也就達到了一個對原始輸入去噪的作用。
而我們的當前的目標是進行KPI異常檢測,從上圖可以看到,一些肉眼可見的異常在重構後被去除掉了(類似降噪了),通過對比與原始輸入的差距,我們可以判斷是否為異常。
然而,AutoEncoder模型本身沒有什麼多少正則化手段,容易過擬合,當訓練數據存在較多異常點的時候,可能模型的效果就不會特別好,而我們要做的是無監督異常檢測(要是有label的話就用有監督模型了),因此我們的場景是訓練的時候允許數據存在少量異常值的,但當異常值佔比較大的話,AutoEncoder可能會過擬合(學習到異常模式)。
- Variational AutoEncoder(VAE)
接下來介紹一些VAE模型,如果不需要對VAE有比較清楚的了解,也可以直接跳過這部分內容。
對於VAE模型的基本思想,下面內容主要引用自我覺得講得比較清楚的一篇知乎文章,並根據我的理解將文中一些地方進行修改,保留核心部分,這裡假設讀者知道判別模型與生成模型的相關概念。
原文地址:https://zhuanlan.zhihu.com/p/27865705VAE 跟傳統 AutoEncoder關係並不大,只是思想及架構上也有 Encoder 和 Decoder 兩個結構而已。VAE 理論涉及到的主要背景知識包括:隱變數(Latent Variable Models)、變分推理(Variational Inference)、Reparameterization Trick 等等。
首先,先定義問題:我們希望學習出一個生成模型,能產生訓練樣本中沒有,但與訓練集相似的數據。換一種說法,對於樣本空間 ,當以 抽取數據時,我們希望以較高概率抽取到與訓練樣本近似的數據。對於手寫數字的場景,則表現為生成像手寫數字的圖像。對於數據 的產生,我們假設它受一些隱含因素的影響,即隱變數(Latent Variables),寫作 ,並且假設 服從標準正態分布 。則原來對 建模轉為對 進行建模,同時有
接下來我們可以開始解決最大化 的問題,如果我們知道 的分布,我們就可以利用採樣來計算積分,即
我們發現,當 時,對估計 沒有幫助,所以其實我們只需要採樣那些對 有貢獻的 。此時,可以反過來求 ,然而,是intractable的,VAE中利用Variational Inference,引入 分布來近似。
最終,可以得到需要優化的目標 ELBO(Evidence Lower Bound),此處其定義為
其中,第一項是我們希望最大化的目標;第二項是在數據 下真實分布 與假想分布 的距離,當 的選擇合理時此項會接近為0。但公式中仍然含有intractable的 ,於是將其化簡後得到
於是,對於某個樣本 ,其損失函數可以表示為,每次輸入為一個xi,
其中, 意味著在樣本 下隱變數 的分布,對應於AutoEncoder中的Encoder部分; 意味著將隱變數 恢復成 ,對應著 Decoder。於是,VAE 的結構可以表示為
但是,上面這種方式需要在前向傳播時進行採樣,而這種採樣操作是無法進行後向反饋梯度的。於是,作者提出一種「Reparameterization Trick」:將對採樣的操作移到輸入層進行。於是就有了下面的VAE最終形式
採樣時,先對輸入的進行採樣,然後計算,間接對 採樣。
我們再結合兩個圖梳理一下VAE的過程。
下圖表示了VAE整個過程。即首先通過Encoder 得到 的隱變數分布參數;然後採樣得到隱變數 。接下來按公式,應該是利用 Decoder 求得 的分布參數,而實際中一般就直接利用隱變數恢復 。
下圖展示了一個具有3個隱變數的 VAE 結構示意圖。
- 基於VAE的周期性KPI異常檢測
上面介紹了VAE的原理,看起來很複雜,其實最終VAE也實現了跟AutoEncoder類似的作用,輸入一個序列,得到一個隱變數(從隱變數的分布中採樣得到),然後將隱變數重構成原始輸入。不同的是,VAE學習到的是隱變數的分布(允許隱變數存在一定的雜訊和隨機性),因此可以具有類似正則化防止過擬合的作用。
以下的構建一個VAE模型的keras代碼,修改自keras的example代碼,具體參數參考了Dount論文:
def sampling(args): """Reparameterization trick by sampling fr an isotropic unit Gaussian. # Arguments: args (tensor): mean and log of variance of Q(z|X) # Returns: z (tensor): sampled latent vector """ z_mean, z_log_var = args batch = K.shape(z_mean)[0] dim = K.int_shape(z_mean)[1] # by default, random_normal has mean=0 and std=1.0 epsilon = K.random_normal(shape=(batch, dim)) std_epsilon = 1e-4 return z_mean + (z_log_var + std_epsilon) * epsiloninput_shape = (seq_len,)intermediate_dim = 100latent_dim = latent_dim# VAE model = encoder + decoder# build encoder modelinputs = Input(shape=input_shape, name=encoder_input)x = Dense(intermediate_dim, activation=relu, kernel_regularizer=regularizers.l2(0.001))(inputs)x = Dense(intermediate_dim, activation=relu, kernel_regularizer=regularizers.l2(0.001))(x)z_mean = Dense(latent_dim, name=z_mean)(x)z_log_var = Dense(latent_dim, name=z_log_var, activation=softplus)(x)# use reparameterization trick to push the sampling out as input# note that "output_shape" isnt necessary with the TensorFlow backendz = Lambda(sampling, output_shape=(latent_dim,), name=z)([z_mean, z_log_var])# build decoder modelx = Dense(intermediate_dim, activation=relu, kernel_regularizer=regularizers.l2(0.001))(z)x = Dense(intermediate_dim, activation=relu, kernel_regularizer=regularizers.l2(0.001))(x)x_mean = Dense(seq_len, name=x_mean)(x)x_log_var = Dense(seq_len, name=x_log_var, activation=softplus)(x)outputs = Lambda(sampling, output_shape=(seq_len,), name=x)([x_mean, x_log_var])vae = Model(inputs, outputs, name=vae_mlp)# add lossreconstruction_loss = mean_squared_error(inputs, outputs)reconstruction_loss *= seq_lenkl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)kl_loss = K.sum(kl_loss, axis=-1)kl_loss *= -0.5vae_loss = K.mean(reconstruction_loss + kl_loss)vae.add_loss(vae_loss)vae.compile(optimizer=adam)
基於VAE的周期性KPI異常檢測方法其實跟AutoEncoder基本一致,可以使用重構誤差來判斷異常,來下面是結果,上圖是原始輸入,下圖是重構結果,我們能夠看到VAE重構的結果比AutoEncoder的更好一些。
缺陷:
基於AutoEncoder和VAE模型在工業界上的使用面臨的2個最大問題是:
- 理論上它只能對一個KPI訓練單獨一個模型,不同類型的KPI需要使用不同的模型,為了解決這個問題,裴丹團隊後面又發表了一篇關於KPI聚類的論文《Robust and Rapid Clustering of KPIs for Large-Scale Anomaly Detection》,先對不同的KPI進行模板提取,然後進行聚類,對每個類訓練單獨一個模型。
- 需要設置異常閾值。因為我們檢測異常是通過對比重構後的結果與原始輸入的差距,而這個差距多少就算是異常需要人為定義,然而對於大量的不同類型的KPI,我們很難去統一設置閾值,這也是採用VAE模型比較大的一個缺陷。雖然在Dount論文中,採用的是重構概率而不是重構誤差來判斷異常,然而重構概率也需要設置閾值才能得到比較精確的結果。
總結
本文分別介紹了AutoEncoder和VAE模型以及基於這些模型的周期性KPI異常檢測方法。裴丹的論文Dount中對原始的VAE做了一些改進,針對KPI異常檢測這個場景增加了一些細節上的優化,如missing data injection、MCMC等等,這部分細節就不在本文中討論了,有興趣的同學可以看一下他們的開源代碼 haowen-xu/donut。
最後,為了讓對AIOps有興趣的同學能夠交流與學習,我創建了一個Awesome-AIOps的倉庫,匯總一些AIOps相關的學習資料、演算法/工具庫等等,歡迎大家進行一起補充,互相進步。
linjinjin123/awesome-AIOps如果文中有什麼解釋不清或者說錯的地方,歡迎批評指正。
參考文獻
[1] Unsupervised Anomaly Detection via Variational Auto-Encoder for Seasonal KPIs in Web Applications
[2] https://blog.keras.io/building-autoencoders-in-keras.html
[3] 當我們在談論 Deep Learning:AutoEncoder 及其相關模型推薦閱讀: