300萬行到100行:機(jī)器學(xué)習(xí)造就更好的開發(fā)體驗(yàn)
本文轉(zhuǎn)載自公眾號(hào)“讀芯術(shù)”(ID:AI_Discovery)。
這個(gè)場(chǎng)景想想就很災(zāi)難了:為了找到發(fā)生在第100萬行上的bug或回歸,不得不在一個(gè)失敗的軟件構(gòu)建中瀏覽2.5GB的日志條目(也就是300萬行),這簡(jiǎn)直難以靠人工手動(dòng)完成!
還好,有一個(gè)巧妙的方法能解救你——執(zhí)行diff命令,將這些行與最近成功的軟件構(gòu)建進(jìn)行對(duì)比,期望bug在日志中生成異常行。
標(biāo)準(zhǔn)的md5 diff命令執(zhí)行速度很快,但它顯示了行之間的字符級(jí)差異,因此仍然會(huì)生成至少數(shù)十萬候選行以供瀏覽。使用機(jī)器學(xué)習(xí)中K-最鄰近聚類的模糊diffing算法(logreduce所做的事情)能產(chǎn)生大約40000條候選行,但需要一個(gè)小時(shí)才能完成。
而我們的解決方案是在20分鐘的計(jì)算時(shí)間內(nèi)生成20000行候選行——而且得益于開放源碼,只需要大約100行Python代碼就能實(shí)現(xiàn)。
該應(yīng)用程序結(jié)合了神經(jīng)嵌入(將單詞和句子中的語義信息進(jìn)行編碼)和局部敏感哈希算法(高效地將大致鄰近的項(xiàng)分配到相同的儲(chǔ)存器,而將遠(yuǎn)處的項(xiàng)分配到不同的儲(chǔ)存器)。將嵌入式系統(tǒng)與LSH(Locality Sensitive Hashing,局部敏感哈希)結(jié)合是個(gè)不錯(cuò)的想法,而這一想法的誕生還不到十年!
我們急不可待地在CPU上使用了Tensorflow 2.2,用于遷移學(xué)習(xí),而將scikit-learnNearestNeighbor用于K-最鄰近算法。實(shí)際上,有一些復(fù)雜的近似最鄰近實(shí)現(xiàn)會(huì)更有助于實(shí)現(xiàn)基于模型的最鄰近解決方案。
嵌入式系統(tǒng)是什么?為什么需要它們?
構(gòu)建k-hot詞袋模型是一個(gè)典型的出發(fā)點(diǎn),常常針對(duì)非結(jié)構(gòu)化或半結(jié)構(gòu)化文本的重復(fù)數(shù)據(jù)刪除、搜索和相似性問題,這類詞袋編碼看起來很像一個(gè)包含單個(gè)單詞及其計(jì)數(shù)的字典。下面以“log in error, checklog”這句話為例:
- {“log”: 2,“in”: 1, “error”: 1, “check”: 1}
這種編碼還可以借助向量表示,其中索引對(duì)應(yīng)一個(gè)單詞,值是計(jì)數(shù)。下面以“log in error, checklog” 為例展示其如何用向量表示,其中第一個(gè)條目保留為“log”單詞計(jì)數(shù),第二個(gè)條目保留為“in”單詞計(jì)數(shù),以此類推:
- [2, 1, 1,1, 0, 0, 0, 0, 0, …]
注意,這個(gè)向量由許多0組成。零值條目表示所有存在于字典中,但未出現(xiàn)在本句中的所有其他單詞??赡艹霈F(xiàn)的向量條目總數(shù),或向量的維數(shù),是你語言字典的容量,通??蛇_(dá)幾百萬條或更多,可以通過一些巧妙的技巧精簡(jiǎn)到幾十萬條。
現(xiàn)在來看看“problem authentication”的字典和向量表示,與前五個(gè)向量條目對(duì)應(yīng)的單詞根本不會(huì)出現(xiàn)在新句子中。
- {“problem”:1, “authenticating”: 1}
- [0, 0, 0, 0, 1, 1, 0, 0, 0, …]
這兩個(gè)句子在語義上是相似的,也就是說它們的意思本質(zhì)上是一樣的,但是在詞匯上是截然不同的,它們沒有出現(xiàn)相同的詞。在模糊區(qū)分設(shè)置中,可能這些句子太相似而不能突出顯示,但是K最鄰近算法中的md5和k-hot文檔編碼不支持該功能。
降維使用線性代數(shù)或人工神經(jīng)網(wǎng)絡(luò)的方式將語義相似的單詞、句子和日志行鄰近放在一個(gè)新的向量空間中,用“嵌入”來表示。在示例中,“log in error,check log”可能有一個(gè)五維嵌入向量:
- [0.1, 0.3,-0.5, -0.7, 0.2]
“problem authenticating”可能是:
- [0.1,0.35, -0.5, -0.7, 0.2]
與它們的k-hot詞袋模型向量不同,這些嵌入向量通過距離度量的方式(比如余弦相似度)彼此接近,密集、低維的表示對(duì)于諸如構(gòu)建行或系統(tǒng)日志的短文檔十分有用。
實(shí)際上,你需要用100個(gè)而不是5個(gè)信息豐富的嵌入維,來替換幾千個(gè)或更多個(gè)字典維,最先進(jìn)的降維方法包括單詞共現(xiàn)矩陣的奇異值分解(GloVe)和專門的神經(jīng)網(wǎng)絡(luò)(word2vec, BERT,ELMo)。
聚類是什么?讓我們?cè)倩氐綐?gòu)建日志應(yīng)用程序
我們開玩笑說Netflix是一個(gè)日志制作服務(wù)商,它有時(shí)會(huì)傳輸視頻。在異常監(jiān)視、日志處理和流處理等領(lǐng)域,每秒會(huì)處理幾十萬個(gè)請(qǐng)求。如果我們想在遙測(cè)和日志空間中應(yīng)用機(jī)器學(xué)習(xí),必須要擴(kuò)展NLP解決方案。
圖源:unsplash
這就是為什么我們關(guān)注擴(kuò)展文本重復(fù)數(shù)據(jù)刪除、語義相似度搜索和文本異常值檢測(cè)等問題——如果需要實(shí)時(shí)解決業(yè)務(wù)問題,這是唯一的辦法。
diff命令解決方案包括將每個(gè)行嵌入到一個(gè)低維向量中(可選擇“微調(diào)”或同時(shí)更新嵌入模型),將其分配到一個(gè)聚類中,并將不同聚類中的行標(biāo)識(shí)為“不同”。局部敏感哈希是一種概率算法,它允許常數(shù)時(shí)間的聚類分配和近常數(shù)時(shí)間的最鄰近搜索。
LSH的工作原理是將一個(gè)向量表示映射到一個(gè)標(biāo)量數(shù)字,或者更準(zhǔn)確地說是映射到一個(gè)標(biāo)量的集合。標(biāo)準(zhǔn)哈希算法的目標(biāo)是避免任何兩個(gè)不相同的輸入之間的沖突,而LSH的目標(biāo)是在輸入距離較遠(yuǎn)的情況下避免沖突,輸入不同但在向量空間中彼此靠近的情況下促進(jìn)沖突。
“log in error, checklog”的嵌入向量可以映射到二進(jìn)制數(shù)01(01表示集群)。“problem authenticating”的嵌入向量很有可能映射到相同的二進(jìn)制數(shù)01。這就是LSH如何實(shí)現(xiàn)模糊匹配、反問題和模糊區(qū)分,LSH早期應(yīng)用于高維詞袋模型向量空間。
使用LSH將字符放在同一個(gè)儲(chǔ)存器中,但方向顛倒。
在構(gòu)建日志的文本離群點(diǎn)檢測(cè)中應(yīng)用LSH和神經(jīng)嵌入,它將允許工程師查看日志的一小部分行來識(shí)別和修復(fù)潛在的關(guān)鍵業(yè)務(wù)軟件中的錯(cuò)誤,并且它還允許我們實(shí)時(shí)獲取幾乎任何日志行的語義聚類。
現(xiàn)在,將語義LSH的這一優(yōu)勢(shì)應(yīng)用到Netflix的每個(gè)構(gòu)建中。語義部分允許我們基于含義對(duì)看似不同的項(xiàng)目進(jìn)行分組,并將它們標(biāo)注在異常值報(bào)告中。
成熟的開源遷移學(xué)習(xí)數(shù)據(jù)產(chǎn)品和SDKs使得我們能夠通過LSH用非常少的代碼行來解決語義最近鄰的搜索問題。遷移學(xué)習(xí)和微調(diào)可能給應(yīng)用程序帶來的優(yōu)勢(shì)特性令我們非常驚喜,機(jī)器學(xué)習(xí)在幫助人們提升工作效率方面還大有可為。