AIOps探索:基於VAE模型的周期性KPI異常檢測方法——VAE異常檢測


AIOps探索:基於VAE模型的周期性KPI異常檢測方法

 

作者:林錦進


前言

在智能運維領域中,由於缺少異常樣本,有監督方法的使用場景受限。因此,如何利用無監督方法對海量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模型有什么用呢?有兩個主要功能:

  1. 降噪
  2. 將高緯的特征轉為低緯度的特征(從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模型的基本思想,下面內容主要引用自我覺得講得比較清楚的一篇知乎文章,並根據我的理解將文中一些地方進行修改,保留核心部分,這里假設讀者知道判別模型與生成模型的相關概念。
原文地址:

VAE 跟傳統 AutoEncoder關系並不大,只是思想及架構上也有 Encoder 和 Decoder 兩個結構而已。VAE 理論涉及到的主要背景知識包括:隱變量(Latent Variable Models)、變分推理(Variational Inference)、Reparameterization Trick 等等。

首先,先定義問題:我們希望學習出一個生成模型,能產生訓練樣本中沒有,但與訓練集相似的數據。換一種說法,對於樣本空間 X ,當以 p(x) 抽取數據時,我們希望以較高概率抽取到與訓練樣本近似的數據。對於手寫數字的場景,則表現為生成像手寫數字的圖像。對於數據 x 的產生,我們假設它受一些隱含因素的影響,即隱變量(Latent Variables),寫作 z ,並且假設 p(z)服從標准正態分布 N(0, I)。則原來對 p(x) 建模轉為對 p(x,z) 進行建模,同時有

接下來我們可以開始解決最大化 p(x) 的問題,如果我們知道 p(z) 的分布,我們就可以利用采樣來計算積分,即

我們發現,當 p(x|z)=0 時,對估計 p(x) 沒有幫助,所以其實我們只需要采樣那些對 p(x) 有貢獻的 z 。此時,可以反過來求 p_θ(z|x),然而,p_θ(z|x)是intractable的,VAE中利用Variational Inference,引入 q_Φ(z|x) 分布來近似p_θ(z|x)

最終,可以得到需要優化的目標 ELBO(Evidence Lower Bound),此處其定義為

其中,第一項是我們希望最大化的目標p(x);第二項是在數據 x 下真實分布 p 與假想分布 q 的距離,當 q 的選擇合理時此項會接近為0。但公式中仍然含有intractable的 p(z|x) ,於是將其化簡后得到

於是,對於某個樣本 x_i ,其損失函數可以表示為,每次輸入為一個xi,

其中, q(z|x_i) 意味着在樣本 x_i 下隱變量 z的分布,對應於AutoEncoder中的Encoder部分; p(x_i|z) 意味着將隱變量 z 恢復成 x_i ,對應着 Decoder。於是,VAE 的結構可以表示為

但是,上面這種方式需要在前向傳播時進行采樣,而這種采樣操作是無法進行后向反饋梯度的。於是,作者提出一種“Reparameterization Trick”:將對N(z|\mu(x),\Sigma(x))采樣的操作移到輸入層進行。於是就有了下面的VAE最終形式

采樣時,先對輸入的\epsilon \sim N(0, I)進行采樣,然后計算z=\mu(x)+\Sigma^{\frac{1}{2}}(x)*\epsilon,間接對 z采樣。

我們再結合兩個圖梳理一下VAE的過程。

下圖表示了VAE整個過程。即首先通過Encoder 得到 x 的隱變量分布參數;然后采樣得到隱變量 z 。接下來按公式,應該是利用 Decoder 求得 x 的分布參數,而實際中一般就直接利用隱變量恢復 x

下圖展示了一個具有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) * epsilon input_shape = (seq_len,) intermediate_dim = 100 latent_dim = latent_dim # VAE model = encoder + decoder # build encoder model inputs = 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" isn't necessary with the TensorFlow backend z = Lambda(sampling, output_shape=(latent_dim,), name='z')([z_mean, z_log_var]) # build decoder model x = 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 loss reconstruction_loss = mean_squared_error(inputs, outputs) reconstruction_loss *= seq_len kl_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.5 vae_loss = K.mean(reconstruction_loss + kl_loss) vae.add_loss(vae_loss) vae.compile(optimizer='adam') 

基於VAE的周期性KPI異常檢測方法其實跟AutoEncoder基本一致,可以使用重構誤差來判斷異常,來下面是結果,上圖是原始輸入,下圖是重構結果,我們能夠看到VAE重構的結果比AutoEncoder的更好一些。

缺陷:

基於AutoEncoder和VAE模型在工業界上的使用面臨的2個最大問題是:

  1. 理論上它只能對一個KPI訓練單獨一個模型,不同類型的KPI需要使用不同的模型,為了解決這個問題,裴丹團隊后面又發表了一篇關於KPI聚類的論文《Robust and Rapid Clustering of KPIs for Large-Scale Anomaly Detection》,先對不同的KPI進行模板提取,然后進行聚類,對每個類訓練單獨一個模型。
  2. 需要設置異常閾值。因為我們檢測異常是通過對比重構后的結果與原始輸入的差距,而這個差距多少就算是異常需要人為定義,然而對於大量的不同類型的KPI,我們很難去統一設置閾值,這也是采用VAE模型比較大的一個缺陷。雖然在Dount論文中,采用的是重構概率而不是重構誤差來判斷異常,然而重構概率也需要設置閾值才能得到比較精確的結果。

總結

本文分別介紹了AutoEncoder和VAE模型以及基於這些模型的周期性KPI異常檢測方法。裴丹的論文Dount中對原始的VAE做了一些改進,針對KPI異常檢測這個場景增加了一些細節上的優化,如missing data injection、MCMC等等,這部分細節就不在本文中討論了,有興趣的同學可以看一下他們的開源代碼 haowen-xu/donut

最后,為了讓對AIOps有興趣的同學能夠交流與學習,我創建了一個Awesome-AIOps的倉庫,匯總一些AIOps相關的學習資料、算法/工具庫等等,歡迎大家進行一起補充,互相進步。

linjinjin123/awesome-AIOps​github.com圖標

 

如果文中有什么解釋不清或者說錯的地方,歡迎批評指正。

參考文獻

[1] Unsupervised Anomaly Detection via Variational Auto-Encoder for Seasonal KPIs in Web Applications

[2]
[3] 當我們在談論 Deep Learning:AutoEncoder 及其相關模型


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM