知物由學 | 全新文字實時聚類技術,一網打盡同類有害內容

網易易盾發表於2021-09-27


圖片


實際業務場景中,每天文字內容的資料量都在億級以上,為了更高效地處理如此海量的資料,文字聚類技術的運用是必不可少的。

 

所謂文字聚類,指的是將文字按照類別進行聚合,然後以類別為單位對文字進行處理或使用。文字聚類之所以能夠對文字按照類別進行聚類,主要是基於一個聚類假設:同類的文字相似度較大,而不同類的文字相似度較小。從上述文字聚類的定義看,文字聚類似乎與文字分類做的事情差不多,它們有什麼不同嗎?

 

與文字分類相比,文字聚類是一個無監督的演算法,它既沒有模型的訓練過程,也不需要預先對文字進行人工標註類別。此外,文字分類的類別體系一般是事先定義好的,類別的總數量是固定的,並且每個類別都有清晰明確的實際意義。文字聚類的類別則是不固定的,完全取決於資料的實際分佈情況,最後聚合出來的各個類別也沒明確的定義,只是代表類別內的文字之間比較相似,與其他類別的文字比較不同。


易盾在內容安全領域深耕多年,對於文字類不良內容的識別與過濾已經發展出一套融合多類核心技術的成熟方案。易盾的文字內容安全方案裡面綜合使用了黑名單、關鍵詞、規則、分類模型、特徵庫匹配、使用者畫像、高頻監控、實時聚類等技術,這些技術各有其優勢和侷限性,只有靈活運用協同作戰,才能發揮最佳的實際效果


圖片


比如對於一些確定不是正常使用者的賬號,黑名單可以對其進行有力地封禁,徹底杜絕該賬號的發垃圾行為。但如果是正常使用者偶爾發表的一些不當內容,則不可以使用黑名單來處理。關鍵詞比較適合用來攔截帶有明顯特徵詞語的內容。以一些色情詞彙為例,這類內容使用關鍵詞技術乾脆利落,並且不會有漏掉的情況。而如果是一些比較內涵的內容,使用關鍵詞就會存在大量的誤判。其他的技術也是同樣的情況,這裡就不一一贅述了。


圖片


道高一尺魔高一丈,黑灰產與產品方的對抗在內容安全領域是一種常態,任何線上檢測系統都無法保證不會漏過任何有害內容。我們需要建立一種能及時發現漏過的有害內容的機制,以此來保證線上檢測效果的穩定性。

 

一般來說,對於線上檢測未識別的內容,主要透過可疑稽核、走查、聚類稽核三種主要方法來召回漏過的有害內容,並同時維護對應的特徵庫,從而持續完善線上檢測系統的識別能力。其中,可疑稽核主要是透過一些高召回的手段,標記出未識別內容中哪些是比較可疑的,然後進行人工稽核確認。質檢人員會憑經驗透過一些線索詞,從未識別內容中搜尋出一些內容進行走查確認,從中發現漏過的有害內容。作為文字的主角,實時聚類技術則對線上未識別的文字內容進行實時的聚合,把其中大量相似的內容同步到後臺的稽核系統,供稽核人員人工稽核,判斷該內容是否有問題。








引入實時聚類技術用於未識別有害內容召回,主要是基於以下幾方面的考量:

 

1)大部分有害內容為了增加曝光度,往往存在多次釋出的行為,並且為了規避反垃圾系統的過濾,會對內容進行小幅度的修改和變化,聚類技術能夠在海量的未識別內容當中把這批內容聚合到一起。

 

2)有害內容畢竟只佔線上資料的一小部分,未識別內容裡面絕大多數是正常內容,由於語言和表達的多樣性,正常內容之間相似的情況較少,聚類能夠排除掉大量的正常內容,減少人工稽核量。

 

 

3)釋出有害內容的黑產,一直在對內容進行修改,嘗試繞過反垃圾小系統的識別,一旦成功了,就會使用程式的方式在短時間內容把大量的內容刷出去,造成是否惡劣的影響,聚類技術能夠及時發現這種異常,從而控制有害漏過刷量的風險。

 

4)有些有害內容形式上比較隱蔽,單個內容上面看不出什麼問題,需要全域性考量,才能發現其中的規律。比如下面的內容,好像就是一個女生髮的自拍照,似乎看不出什麼問題。


圖片


但如果放到下面這批資料中,則可以看出這批資料呈現出一定規律,明顯是有問題的。


圖片



















文字聚








文字聚類包含兩個關鍵技術:


相似度量聚合方法


相似度量主要解決如下問題:給定兩個文字,怎麼判斷它們是相似還是不相似的。

 

相似度量在數學上滿足自反性和對稱性,不滿足傳遞性。滿足自反性,即文字A永遠和它自己相似。對稱性指的是如果文字A與文字B相似,則可以得到文字B與文字A相似。假設文字A與文字B相似,文字B與文字C相似,我們無法確定文字A與文字C相似,這就是不滿足傳遞性。聚合方法則解決的是下面的問題:給定一批文字,如何把相似的聚到同一個類別,不相似的聚到不同類別?

 

這個問題看起來似乎很簡單,實際卻需要考慮很多方面。如下面的圖所示,首先,如果一個文字跟兩個類別都比較相似,那它是隻能屬於一個類別還是能同時屬於兩個類別?其次,由於相似度量不滿足傳遞性,相鄰的文字比較相似,但距離比較遠的文字之間其實已經不相似了,要不要把這批文字放到一個類別,還是從中間切割成兩個類別?還有一個問題,我們對文字進行聚類,是直接把文字聚合到一個一個類別,還是採用層次的方法對這些類別進行組織。







圖片

接下來我們結合前面聚類的運用場景,介紹如何選擇合適的相關技術的。







技術選擇







文字的相似度量一般分為兩個步驟:

 

1文字向量化表:把文字轉化成高維向量空間上的點,使用高維向量來表徵文字;

 

 

2相似度計算:基於高維向量的表徵形式,計算向量之間的距離。近幾年來隨著深度學習技術的興起,也有使用互動式深度學習模型直接計算兩個文字之間相似度的方法,不過考慮到線上未識別文字數量巨大,使用深度學習模型對它們進行兩兩計算基本上是不可行的。

 

文字向量化表徵又分為兩大類:基於詞袋的方法和基於語義向量的方法。基於詞袋的方法具體有one-hot、詞頻、TF-IDF、機率主題模型等方法,基於語義向量的方法則主要包括詞向量、深度學習模型表徵等技術。

 

總體而言,語義向量方法能夠在語義層面上衡量文字的相似度,但錯誤的可解釋性較差,詞袋方法則相反。在我們的業務場景中,我們要處理的相似文字往往是下圖的這種形式,並且對聚類結果的解釋性要求比較高,因此文字向量化表徵技術選擇了TF-IDF方法。文字的相似度計算常用的有餘弦距離、歐式距離、Jarcard相似度,由於我們選擇了TF-IDF方法,相似度計算最終使用的是餘弦距離。


圖片


前面講到聚合方法需要考慮的幾個問題,圍繞這些問題學術界展開了相關的研究,並提出了豐富多樣的聚類演算法,對我們的工作具有積極的借鑑意義。不過這些方法多數需要重複迭代,在效能和實時性方面並不友好,滿足不了我們對線上文字聚類的實時性需求。出於聚類實時性的要求,我們選擇了過程相對簡單single-pass cluster演算法,該演算法對新來的資料跟歷史資料比較一遍相似度即可,不需要重複比較的過程,這也是演算法名字的由來。


圖片


讓我們注意力放在新資料跟歷史資料比較這個過程,這其實就是k-近鄰問題,從這個角度看,k-近鄰又有大量的工作專門研究如何加速k-近鄰檢索過程,具體有minhashsimhashcanopyKD-Tree以及最近比較火的Faiss開源專案。考慮到後面的分散式實現,我們選擇了實現相對簡單的canopy演算法作為k-近鄰檢索加速方案。


圖片


上圖是我們的文字聚類單機流程:系統接收到一個新的文字以後,首先把文字轉化成高維空間上的TF-IDF向量;接下來需要從歷史資料中搜尋與該向量距離比較近的資料,這裡先使用canopy演算法進行粗聚類,從海量的歷史資料中篩選出少數候選資料;然後再分別與新文字計算TF-IDF向量的餘弦相似度,如果有候選資料相似度大於閾值,則把新文字歸到該資料所屬的類別中,否則新建一個類別,新文字作為新類別的初始成員。


上面只是線上文字實時聚類的一個原型設計,實際上的業務場景存在一些特點,對實時聚類實現方案提出更高的要求。線上的文字資料是以連續不間斷資料流形式源源不斷的進來的,聚類系統內部在進行聚類的同時,需要能夠實時地接收每一個新的文字資料,即已接收文字的聚類處理和新文字的接收必須同時進行。實時聚類主要是服務於未識別內容稽核的,當聚類中的某個類別滿足我們設定的條件時,需要把該類別的所有文字發到稽核系統進行人工稽核,這個過程越實時越好。另外線上未識別的文字流量巨大,無論是計算量還是記憶體使用量,單個機器都無法承載,需要使用多臺伺服器共同完成實時聚類任務。


圖片


可以看出,我們的業務場景非常適合使用流計算技術,目前市面上也有比較多成熟的流計算框架,stormflinkspark stream都是其中的佼佼者。這些流計算框架大都擁有優異的效能表現,對分散式的支援也非常友好,我們只需要基於這些框架的程式設計正規化把上述聚類設計實現好即可。

 

不過這裡有一個核心問題,那就是一般的流計算任務流資料之間的處理是獨立的,即當前資料的處理與其他資料無關,因此比較容易實現分散式處理。而聚類問題研究的就是資料之間的關係,因此在分散式實現方面存在困難。比如為了找到當前文字的相似文字,需要對所有的歷史資料作比對,這要求所有資料存放在同一個記憶體裡面,如果分散式實現把資料放在不同伺服器節點,那就很難實現這個相似查詢的功能。

 

下面介紹一下我們是怎麼解決這個問題的。








問題解決





圖片


如上圖,分散式實時聚類系統由兩個子系統組成:藍色虛線圈起來的聚類子系統和Recorder子系統。其中Recorder負責把需要稽核的資料同步到稽核系統,最核心還是聚類子系統,它基於分散式流計算框架實現,包括SpoutClusterBoltOutputBolt 3個模組。


Spout的功能包括從kafka讀資料、資料清洗分詞等預處理、把文字轉化成TF-IDF向量。這些功能沒有涉及到多資料間的關係,因此可以實現完全的分散式。

 

ClusterBolt收到Spout發來的TF-IDF向量後,先進行canopy粗聚類,篩選出候選資料,再進行基於餘弦聚類的聚類。由於需要歷史資料,ClusterBolt無法完全分散式實現,同時儲存歷史資料對記憶體要求較高,內容容易成為系統瓶頸。考慮到聚類是發生在業務內部,不同業務之間的文字內容是不需要聚類的,我們根據業務對聚類進行劃分,把不同業務的聚類分散到不同的節點上面進行,從而減少單個節點上面的資料規模。

 

當聚類到的類別滿足稽核條件時,ClusterBolt把相應的文字傳送給OutputBolt,再由OutputBolt統一寫到kafka。可以看到OutputBolt功能比較簡單,因此分配的節點數會比較少。

 

接下來我們分析一下上述設計是否完成了我們的分散式目標。之所以需要分散式,無非就是單機的系統資源不夠滿足任務的需求(也有因為高可用需要多個伺服器的情況)。對於文字實時聚類來說,主要的因素就是CPU、記憶體、網路頻寬的需求。CPU方面,分詞和餘弦距離計算都是計算型的操作,系統的CPU主要消耗在這兩塊。記憶體的使用主要集中在儲存原始文字資料和TF-IDF向量上面。至於頻寬方面,主要是讀kafka和寫kafka,不過目前的情況看頻寬還不構成問題。









首先,分詞已經隨Spout模組已分散式的方式分攤到多個節點上面了。餘弦距離計算和記憶體使用則發生在ClusterBolt,也以業務為維度分攤到多個節點了。因此,上述設計可以認為基本達成分散式目標了。不過這裡還遺留一個問題,那就是業務間的差異比較大,一方面,不同的業務資料的規模相差很大,另一方面,不同業務波峰波谷在時間上的分佈也不同。因此基於這個設計的系統存在以下待最佳化的問題:

 

1)不同業務規模的不一樣,導致節點之間的資源利用率不同,有些節點比較空閒,浪費系統資源;

 

2)由於波峰波谷的變化,節點有些時間段比較空閒,有些時間段比較繁忙,產生較大的波動性,並且不同業務的節點是隔離的,無法實現削峰平谷;

 

3)對於資料規模特別巨大的業務,還是存在單個節點資源不夠的問題。


圖片


為了克服上述問題,我們在原有系統的基礎進行改進,形成了上圖所示的方案。主要改進點有兩個:

 

1)增加了DistributeBolt模組,Spout只負責讀kafka資料,資料清洗分詞等預處理、把文字轉化成TF-IDF向量這些轉到DistributeBolt上面做。這樣可以實現更精細的資源分配,把讀資料和複雜計算的功能解耦,各自按需分配。

 

原來的ClusterBolt細分成LocalClusterBolt和MergeClusterBolt兩個模組。同一個業務的資料可以分發到不同的LocalClusterBolt節點,先在節點內部進行區域性聚類(聚類方法跟原來的一樣),區域性聚類以後符合條件的資料再傳送到MergeClusterBolt進行合併。當然相同業務的資料還是需要在同一個MergeClusterBolt節點上面進行合併的。







這裡可能會有一個疑問:要是運氣不好同一個類別的資料剛好分發到不同區域性聚類節點,比如每個節點剛好分到一條資料,那麼這批資料是不是就聚不出來了?為了避免這種情況,我們對資料的分發演算法進行了精心的設計,如下圖所示:


圖片


一條資料只分發到一個區域性聚類節點,確實存在較大的可能性聚不出來,所以我們會發資料傳送給k個節點。透過對TF-IDF向量數值top k的分量對應的token id進行partition操作,得到k個區域性聚類節點的編號,然後把資料同時發給這k個節點。這其實很好理解,數值比較大的分類,對餘弦相似度計算的貢獻越大,上述操作能保證在相同分量上面都具有較大值的文字會被分發到相同的節點。


圖片


值得一提的是,這裡的k不是固定的,而是基於歷史聚類資料訓練機器學習迴歸模型,對不同的文字內容,動態決定k的值。經過實測,k的平均值大概在3左右,相似文字在同一個區域性聚類節點聚出來的比例達到98%以上。但還是還會有個別資料被分發到的區域性聚類節點沒法聚出來,可能同個類別的資料在其他節點都已經聚出來了,只留它孤零零的在這個節點上面。我們的方案也考慮到這種情況了,下圖是資料從區域性聚類節點到合併聚類節點的邏輯圖。


圖片


一個文字在LocalClusterBolt完成聚類流程以後,如果它所在的類別已經滿足入庫稽核的條件,則直接把該類別所有資料發往MergeClusterBoltMergeClusterBolt直接把收到的資料發往OutputBolt進行後續入庫稽核流程,同時在記憶體中繼續保留這些資料。如果在LocalClusterBolt為滿足入庫稽核條件,則等待一段時間後再把資料發往MergeClusterBoltMergeClusterBolt收到資料後,在記憶體中的其他資料查詢是否有相似的文字,如果有相似文字則把收到的資料發往OutputBolt進行後續入庫稽核流程,不管是否有相似資料,MergeClusterBolt永遠不會保留這類資料。













思考












透過上面的介紹可以看出,改進後的系統已經比較好地解決了實時分散式文字聚類問題,並且隨著業務規模的增長,我們的系統完全可以透過橫向擴充套件增加伺服器來實現整體處理能力的線性提升。文字聚類技術的應用對提升易盾內容安全整體防控能力起到了非常大的作用,對線上漏識別的有害內容召回效果比較突出。









相關文章