Pixie 旨在幫助開發者快速了解并調試產品系統。為了實現這一目標,我們將提供支持,幫助開發者輕松訪問其生產系統中的一系列指標和日志數據。如,幫助收集系統中各個進程的 CPU 和內存用量的結構化數據,以及許多類型的非結構化數據(例如HTTP 請求的正文,或者程序發出的錯誤消息)。
以上只是其中兩個示例,此外我們還收集許多其他類型的數據。在本篇文章中,我們將重點介紹在 Pixie 中收集如 HTTP 請求/相應正文等大量非結構化數據。在可以預見的未來中,我們認為查詢此類非結構化計算機數據,可以像查詢結構化數據一樣輕松高效。為了實現這一目標,我們利用最先進的 NLP 技術來學習數據的結構。
我們將在本文中與您分享經驗和進展,希望能為您在思考類似問題時提供一些幫助。
HTTP 聚類
假設使用 Pixie 的開發者想要了解哪些類型的 HTTP 請求特別慢。他們無需手動篩查大量單獨的 HTTP 請求,因為我們可以將 HTTP 請求進行語義聚類,然后顯示每種語義聚類請求的延遲時間序列。為了對此進行說明,我們先講解最終結果,然后再回過頭來講解如何得到這些結果。我們將利用 Pixie 對一款名為 Online Boutique 的演示版應用進行探索。將 Pixie 部署至運行 Online Boutique 的 Kubernetes 集群之后,就可以開始了。舉個例子,我們可以看看 Online Boutique 應用中的網絡連接示意圖:
Online Boutique
https://github.com/GoogleCloudPlatform/microservices-demo
從這個服務示意圖中可以看出,前端服務處理傳入請求,并將其發送至各自的微服務。接下來,我們深入了解一下發送至前端服務的 HTTP 請求及其相應延遲時間。
HTTP 請求正文延遲時間 (ms)
“product_id=L9ECAV7KIM&quantity=33.325302
“email=someone%40example.com&street_ad
dress=1600+Amphitheatr.。.102.625462
“product_id=OLJCESPC7Z&quantity=3”3.4530790000000002
“product_id=L9ECAV7KIM&quantity=5”4.828718
“product_id=0PUK6V6EV0&quantity=2”5.319163
“email=someone%40example.com&street_ad
dress=1600+Amphitheatr107.361424
”product_id=0PUK6V6EV0&quantity=4“3.81733
”currency_code=EUR“0.203676
”currency_code=USD“0.220932
”product_id=0PUK6V6EV0&quantity=4“4.538055
請求的樣本數較少,無法立即明確判斷出情況。包含 “email=。..?address=。..” 的請求似乎比其他請求慢很多,但我們無法確定這些示例并非離群值。數據就看到這里,接下來,我們使用非結構化文本聚類技術(稍后對此進行介紹),通過 HTTP 請求正文的內容對其進行語義聚類。
這是各個語義集群請求的第 99 百分位平均響應延遲時間圖表。利用此圖表,您可以快速確定發送至前端服務的三大類請求,以及這些請求的延遲概況。我們能夠立即看到“電子郵件”請求集群的第 99 百分位平均延遲時間明顯高于其他集群,而且“產品”集群偶爾會出現延遲尖峰。針對這兩種可行的數據分析,我們可以進一步進行調試。現在,讓我們來深入探討如何達成這一目標。
模型開發詳細信息
要求
我們的模型將部署至客戶的產品集群中,因此這些模型必須為輕量級,且具有高性能;理想狀態下,還應具備足夠的速度,能夠在最小 CPU 消耗的前提下以線速處理數據。為了保障數據隔離,必須在客戶集群中訓練客戶數據。此外,由于數據平面完全包含在客戶集群中,我們對數據有嚴格的存儲空間限制,因此我們必須利用 ML 技術對我們收集的數據進行智能采樣。
數據集
我們對數據隔離有嚴格要求,因此我們使用 Loghub 數據集來引導模型訓練。此數據集是來自各種上下文的日志消息(Android 系統日志、Apache 服務器日志、超級計算機/HPC 日志等)的集合。為了測試未知日志格式的模型泛化,我們保留了 Android 日志數據用來進行測試,并基于日志數據的其余部分進行訓練。
Loghub
https://github.com/logpai/loghub
我們使用 Google 的 SentencePiece 來對日志消息進行詞條化,尤其是利用對詞匯大小為 16k 的子詞的詞條化實現(基于 Unigram 語言模型)。下圖是我們進行詞條化后生成的所有 16k 詞匯子詞片段構成的詞云圖。字詞的大小表示其在數據集中出現的頻率。
SentencePiece
https://github.com/google/sentencepiece
詞云圖,展示對 Logpai Loghub 計算機日志數據集進行詞條化后的詞匯子詞片段
此詞云能夠顯示出我們數據集的偏向。舉個例子,約 30% 的數據為 Windows 日志,從“windows”和“microsoft”詞條的高頻率就可以看出。此外,若您目光敏銳,您可能會發現我們的數據集中有很多“哭臉”,但實際上“):”幾乎總是以左括號開頭,如下例所示:
[Thu Jan 2612:23:072006] [error] config.update(): Can‘t create vm
[Fri Jan 27 1116 2006] [error] [client 202.143.128.18] client sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /
模型架構
我們可以使用此詞條化的數據集,利用從左到右的下一字詞預測(按照 OpenAI’s GPT 模型)來訓練基于自注意力的模型。從左到右的下一字詞預測的任務是,在給定一系列上文詞條的情況下嘗試預測下一個詞條。這種從左到右的方式使我們的模型有別于使用雙向上下文的模型,比如 BERT。我們將在未來嘗試雙向模型。此 TensorFlow教程演示了對類似架構的訓練,唯一的區別是我們在教程中省略了架構的編碼器端。
TensorFlow 教程
https://tensorflow.google.cn/tutorials/text/transformer
下圖展示了我們所使用的架構。我們有 6 個解碼器塊,每個塊都有一個自注意力層和一個前饋層。請注意,為簡潔起見,該圖省略了自注意力和前饋層上的跳躍連接,以及與這些跳躍連接相關的層規范化。
GPT 類語言模型架構
總而言之,此架構有 647 萬個參數,與最先進的語言模型相比,這是一個非常小的架構。舉個例子,DistillBERT 有 6,600 萬個參數。另一方面,最大版本的 GPT-3 有 1,750 億個參數。
我們對此架構進行了 10 個 epoch 的訓練,每個紀元 epoch 大約有 1 億條獨特的日志消息。在每個 epoch 之后,我們在驗證集上運行模型,并將驗證準確率最高的紀元中的模型用作最終模型。在保留的 Android 日志數據上,我們下一字詞預測的測試準確率達到 63.13%。鑒于我們尚未進行超參數調優或其他優化,此準確率水平在未來還有很大的提升空間。
我們現在有一種方法可以從上下文中預測計算機日志數據中的未來詞條,并且具有不錯的準確性。然而,這并不能立即幫助我們實現從數據中提取結構化特征的最初目標。為了進一步實現這一目標,我們將探索語言模型生成的特征空間,而不是語言模型的預測。
我們的目標是將復雜的數據空間轉換為固定維度的特征空間,然后將其用于后續任務。為了實現這一目標,我們需要將語言模型的輸出轉換為一個固定維度的向量,我們稱之為特征向量。要實現此目標,一種方法是使用 BERT 那樣的模型。
使用 BERT 這類模型,將預訓練語言模型擴展到監督任務的方法是在句子的 《CLS》(或 《s》)詞條的輸出上添加一個全連接網絡,然后在全連接網絡中,對某些分類任務的模型進行微調(如下圖所示)。由此得出的自然特征向量可作為 Softmax 層之前的輸出。
Alammar, J (2018),轉換器圖解
我們計劃在未來對這種方法進行進一步研究,但是現在我們想看看在不添加任何額外監督的情況下能得到什么結果。這需要一種啟發式方法將我們的輸出序列轉換為固定長度的向量。實現此目標的一種方法是,在輸出的序列維度上使用最大池化運算符。假設我們的語言模型輸出一個 256 維向量的序列,那么序列維度最大池化將輸出一個單獨的 256 維向量,其中每個維度都是序列的所有輸出中該維度的最大值。這種方法背后的理念是,在最終表示中包含具有更強響應的神經元更為重要。
結果
我們可以測試這種方法對 Loghub 數據子集(我事先將其手動標記為不同語義集群)進行聚類的效果如何。以下是手動標記的測試數據集中的三個日志消息。前兩個被標記為在同一個語義集群中,因為兩者都與文件查找失敗有關,最后一個來自不同的集群,因為它是關于刷新數據的無關消息。
Loghub
https://github.com/logpai/loghub
[Wed Nov 0922:30:052005] [error] [client 216.138.114.25] script not found or unable to stat: /var/www/cgi-bin/awstats.p
[Sat Jan 2819:29:292006] [error] [client 211.154.174.50] File does not exist: /var/www/html/modules
20171230-12:25:37:318|Step_StandStepCounter|30002312|flush sensor data
同時可以利用手動標記的測試集,衡量模型分離不同集群的效果。為了實現這個目標,我們使用 KMeans 算法根據模型的輸出進行聚類,然后將這種聚類結果與手動標記的聚類結果進行比較。在此測試集上,模型調整后的隨機性分數是 0.53,0.0 是隨機標記,1.0 是完美標記。與下一字詞預測的準確率一樣,此性能不是很好,但卻是一個很好的起點。
我們還可以查看模型特征空間的低維度表示,使用 PCA 將維數減少至二。下圖顯示了測試數據集中每個點的嵌入的前兩個 PCA 維度。顏色代表點所屬的語義集群。請注意,由于這些是嵌入空間的二維子空間中的分布圖,點的絕對位置幾乎沒有意義,更多的意義來自每個集群的緊密度。在下圖中,我們可以看到模型很好地分離了一些類,但在其他類上卻失敗了。
模型特征空間的二維表示
使用此方法,我們應該能夠在 Pixie 中對非結構化數據進行聚類,并用其語義集群 ID 對其進行標記,從而從非結構化數據中提取結構化特征。到目前為止,此特殊特征的可解釋性并不是很高,但未來我們會著手于這一點
推斷
現在,讓我們嘗試在 Pixie 系統中實現此方法。為此,我們首先需要將模型轉換為 TensorFlow Lite,然后將其加載到 Pixie 執行引擎中。決定使用 TensorFlow Lite 是因為我們需要盡可能減少消耗,并且我們希望未來能夠靈活地將其部署至異構邊緣設備,包括 Raspberry PI 和 ARM 微控制器。
轉換至 TensorFlow Lite 十分簡單。我們為自己的模型創建一個 TF 函數并調用內置轉換器來生成一個 TensorFlow Lite 模型 Protobuf 文件:
model = tf.keras.models.load_model(model_path)
@tf.function(input_signature=[tf.TensorSpec([1, max_length], dtype=tf.int32)def pred_fn(encoded_text):# Create a mask that masks out 0 tokens, and future tokens for next word prediction.
mask = create_padded_lookahead_mask(max_length)
# Our saved model outputs both its next word predictions, and the activations of its final layer. We only use the activations of the final layer for clustering purposes.
model_preds, last_layer_output = model([encoded_text, mask], training=False)
# Max pool over the seq dimension.return tf.reduce_max(last_layer_output, axis=1)
converter = tf.lite.TFLiteConverter.from_concrete_functions([fn.get_concrete_function()])
tflite_model = converter.convert()
Pixie 的查詢引擎可以查詢和使用 Pixie 收集的數據。此引擎已經有了 KMeans 運算符,所以我們需要做的就是將我們的 TFLite 模型加載到引擎中,然后編寫一個自定義的 PxL 腳本(一個基于 Python/Pandas 的 Pixie 腳本語言中的腳本)來對我們的數據進行聚類。我們正在開發一個公共 API,為的是將自定義 ML 模型加載到引擎中,但現在我們將使用一些內部特征來實現這一目標。模型加載完成后,我們就可以在 Pixie 平臺中的任何非結構化數據上使用此模型。
責任編輯:haq
-
數據
+關注
關注
8文章
7057瀏覽量
89098 -
機器學習
+關注
關注
66文章
8421瀏覽量
132703
原文標題:利用機器學習在 Pixie 上進行非結構化數據處理
文章出處:【微信號:yingjiansanrenxing,微信公眾號:硬件三人行】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論