无监督算法与异常检测
一、整體概覽
? ? ? ?反欺詐往往看做是二分類問題,但是仔細(xì)想想是多分類問題,因?yàn)槊糠N不同類型的欺詐都當(dāng)做是一種單獨(dú)的類型。欺詐除了多樣并且不斷變化,欺詐檢測還面臨一下問題:
? ? ? 1). 由于大部分情況數(shù)據(jù)是沒有標(biāo)簽的,各種成熟的監(jiān)督學(xué)習(xí)是沒有辦法應(yīng)用
? ? ? 2). 區(qū)分噪音和異常點(diǎn)時(shí)難度比較大,甚至需要一點(diǎn)點(diǎn)經(jīng)驗(yàn)
? ? ? 3). 當(dāng)多種不同的欺詐結(jié)合在一起時(shí),區(qū)分欺詐類型比較難,因?yàn)椴涣私饷恳环N欺詐定義
? ? ? 4). 即使有真的欺詐數(shù)據(jù),即在有標(biāo)簽的情況下用監(jiān)督學(xué)習(xí),也存在很大的不確定性。用這種歷史數(shù)據(jù)學(xué)出的模型只能檢測當(dāng)時(shí)存在以及比較相似的欺詐,而對于不同的詐騙和從未見過的詐騙,模型預(yù)測效果一般比較差。
? ? ? ?因此,在實(shí)際情況中,一般不直接用任何監(jiān)督學(xué)習(xí),或者說不能至少單獨(dú)依靠一個(gè)監(jiān)督學(xué)習(xí)模型來奢求檢測到所有的欺詐。沒有歷史標(biāo)簽和對詐騙的理解,無法做出對詐騙細(xì)分的模型。一般常見的做法是使用無監(jiān)督模型,且需要不同專家根據(jù)經(jīng)驗(yàn)來驗(yàn)證預(yù)測,提供反饋,便于及時(shí)調(diào)整模型。
? ? ? 拿到含有欺詐的數(shù)據(jù)之后,一般做法有通過關(guān)聯(lián)矩陣分析以及多維尺度變換。
?
二、無監(jiān)督學(xué)習(xí)
? ? ? ? 當(dāng)一個(gè)場景需要做預(yù)判的時(shí)候,有沒有標(biāo)簽,往往能做的主要有遷移學(xué)習(xí)、專家模型、無監(jiān)督算法。
? ?遷移學(xué)習(xí)
? ? 源域樣本和目標(biāo)域樣本分布有比較大的區(qū)別,目標(biāo)域樣本量不夠的話,通過算法縮小邊緣分布之間和條件分布之間的差異。
- 基于特征的遷移
- 基于模型的遷移
- 基于實(shí)例的遷移
? ?不足之處:需要擁有與當(dāng)前目標(biāo)場景相關(guān)的源域數(shù)據(jù)
? ?專家模型
? ? 主要是根據(jù)主觀經(jīng)驗(yàn)進(jìn)行評判,而不是根據(jù)統(tǒng)計(jì)分析或者模型算法來進(jìn)行客觀的計(jì)算。常規(guī)操作過程如下所示:
- ?根據(jù)相關(guān)經(jīng)驗(yàn)判斷特征重要性
- ?根據(jù)相關(guān)經(jīng)驗(yàn)進(jìn)行變量加權(quán)
? ?不足之處:需要大量的行業(yè)經(jīng)驗(yàn)積累,有時(shí)候不太具有說服性
? ?無監(jiān)督算法
? ? ? ?缺乏足夠的先驗(yàn)知識,無法對數(shù)據(jù)進(jìn)行標(biāo)記時(shí),使用的一種機(jī)器學(xué)習(xí)方法,代表聚類、降維等。在風(fēng)控領(lǐng)域中主要使用的是聚類和無監(jiān)督異常檢測。聚類是發(fā)現(xiàn)樣本之間的相似性,異常檢測是發(fā)現(xiàn)樣本之間的差異性。
? ? 聚類
- ?K-Means
- DBSCAN
- 層次聚類
- 社區(qū)發(fā)現(xiàn)
? ? ? ? 一般主要是對負(fù)樣本聚類,將有問題的用戶細(xì)分為幾類。社區(qū)發(fā)現(xiàn)算法一般是識別團(tuán)伙欺詐的主要手段之一,主要方法是通過知識圖譜將小團(tuán)體篩選出來。在知識圖譜中,聚集意味著風(fēng)險(xiǎn)。
? ? ?異常檢測
? ? ? ?異常點(diǎn)檢測,通常也被稱為離群點(diǎn)檢測,是找出與預(yù)期對象的行為差異較大的對象的一個(gè)檢測過程。檢測出來的數(shù)據(jù)被稱為異常點(diǎn)或者離群點(diǎn)。異常點(diǎn)在生產(chǎn)生活中有比較多的應(yīng)用,例如廣告點(diǎn)擊反作弊、設(shè)備損壞等。異常點(diǎn)是一個(gè)數(shù)據(jù)對象,明顯不同于其他的數(shù)據(jù)對象。如下所示,N1,N2為區(qū)域內(nèi)的正常數(shù)據(jù),而離這兩個(gè)正常區(qū)域比較遠(yuǎn)的地方的點(diǎn)為異常點(diǎn)。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? 異常檢測和不均衡學(xué)習(xí)的區(qū)別是,異常檢測一般是無監(jiān)督的;與普通的二分類區(qū)別是異常檢測往往看作為是二分類,但是其實(shí)是多分類(由于造成異常的原因各不相同)
? ? ? ?異常檢測算法的前提假設(shè):1) 異常數(shù)據(jù)跟樣本中大多數(shù)數(shù)據(jù)不太一樣? 2) 異常數(shù)據(jù)在整體數(shù)據(jù)樣本中占比相對比較小
? ? ? ?異常檢測的主要思想是基于樣本(小群體)之間的相似度: 距離、密度、簇
? ? ? ?異常檢測算法的意義:
? ? ? ? 1). 很多場景沒有標(biāo)簽或者標(biāo)簽比較少,不能訓(xùn)練監(jiān)督模型
? ? ? ? 2). 樣本總是在發(fā)生變換,只能從一個(gè)小群體內(nèi)部發(fā)現(xiàn)異常
? ? ? ? 3). 異常檢測假設(shè)異常樣本數(shù)據(jù)量占比較少,并且在某種維度上遠(yuǎn)離其他樣本,符合個(gè)體欺詐的先驗(yàn)知識。在團(tuán)體欺詐不太適用。
? ? ? ? 4). 樣本群體有異構(gòu)成分,可以對樣本進(jìn)行篩選
三、異常檢測的常用算法
? ? ? ? ?常見的異常檢測算法有Z-score算法、KNN算法、Local Outlier Factor、孤立森林等
? ? Z-score算法
? ? ? ? 假設(shè)樣本服從正態(tài)分布,用于描述樣本偏離正態(tài)分布的程度。通過計(jì)算μ和σ得到當(dāng)前樣本所屬于的正態(tài)分布的表達(dá)式,然后分別計(jì)算每個(gè)樣本在這個(gè)概率密度函數(shù)下被生成的概率,當(dāng)概率小于某一閾值我們認(rèn)為這個(gè)樣本是不屬于這個(gè)分布的,因此定義為異常值。計(jì)算公式如下所示:
? ? ? ?
? 根據(jù)獲取平均值和方差的估計(jì)值,然后給定一個(gè)新的訓(xùn)練實(shí)例,根據(jù)模型計(jì)算p(x):
? 當(dāng)p(x) < ep(x) < e時(shí)候,數(shù)據(jù)未異常
? 缺點(diǎn)是需要假設(shè)樣本滿足正態(tài)分布,而大部分場景不滿足正態(tài)分布假設(shè)條件
? ? ? KNN異常檢測
? ? ? ?KNN算法專注于全局異常檢測,所以無法檢測到局部異常。
? ? ? ?首先,對于數(shù)據(jù)集中的每條記錄,必須找到k個(gè)最近的鄰居。然后使用這K個(gè)鄰居計(jì)算異常分?jǐn)?shù)。
我們有三種方法
- 最大:使用到第k個(gè)鄰居的距離作為離群值得分
- 平均值:使用所有k個(gè)鄰居的平均值作為離群值得分
- 中位數(shù):使用到k個(gè)鄰居的距離的中值作為離群值得分
? ? ? ?在實(shí)際方法中后兩種的應(yīng)用度較高。然而,分?jǐn)?shù)的絕對值在很大程度上取決于數(shù)據(jù)集本身、維度數(shù)和規(guī)范化。參數(shù)k的選擇當(dāng)然對結(jié)果很重要。如果選擇過低,記錄的密度估計(jì)可能不可靠。(即過擬合)另一方面,如果它太大,密度估計(jì)可能太粗略。K值的選擇通常在10<k<50這個(gè)范圍內(nèi)。所以在分類方法中,選擇一個(gè)合適的K值,可以用交叉驗(yàn)證法。但是,事實(shí)上基于KNN的算法都是不適用于欺詐檢測的,因?yàn)樗麄儽旧砭蛯υ肼暠容^敏感。
? ? ?Local Outlier Factor
? ? ? 基于密度的LOF算法相對比較更加簡單、直觀以及不需要對數(shù)據(jù)的分布有太多的要求,還能量化每個(gè)數(shù)據(jù)點(diǎn)的異常程度。該算法是基于密度的算法,主要核心的部分是關(guān)于數(shù)據(jù)點(diǎn)密度的刻畫。算法的整個(gè)流程涉及如下概念:
? ? ?1)k-近鄰距離(k-distance): 在距離數(shù)據(jù)點(diǎn)p最近的幾個(gè)點(diǎn)中,第k個(gè)最近的點(diǎn)跟點(diǎn)p之間的距離稱為點(diǎn)p的k-近鄰距離,記為k-distance(p).
? ? ?2)? 可達(dá)距離(rechability distance): 可達(dá)距離的定義跟k-近鄰距離是相關(guān)的,給定參數(shù)k時(shí),數(shù)據(jù)點(diǎn)p到數(shù)據(jù)點(diǎn)o的可達(dá)距離reach-dist(p,o)為數(shù)據(jù)點(diǎn)o的K-近鄰距離和數(shù)據(jù)點(diǎn)p與點(diǎn)o之間的直接距離的最大值。即:
? ? ? ? ? ? ? ? ? ? reachdist-k(p,o) = max{k-distance(o),d(p,o)}
? ? ?3) 局部可達(dá)密度(local rechablity density):局部可達(dá)密度的定義是基于可達(dá)距離的,對于數(shù)據(jù)點(diǎn)p,那些跟點(diǎn)p的距離小于等于k-distance(p)的數(shù)據(jù)點(diǎn)稱為它的k-nearest-neighor,記為Nk(p),數(shù)據(jù)點(diǎn)p的局部可達(dá)密度為它與鄰近的數(shù)據(jù)點(diǎn)的平均可達(dá)距離的倒數(shù),即:
?
? ? ?4) 局部異常因子:?根據(jù)局部可達(dá)密度的定義,如果一個(gè)數(shù)據(jù)點(diǎn)跟其他點(diǎn)比較疏遠(yuǎn)的話,那么顯然它的局部可達(dá)密度就小。但LOF算法衡量一個(gè)數(shù)據(jù)點(diǎn)的異常程度,并不是看它的絕對局部密度,而是看它跟周圍鄰近的數(shù)據(jù)點(diǎn)的相對密度。這樣做的好處是可以允許數(shù)據(jù)分布不均勻、密度不同的情況。局部異常因子即是用局部相對密度來定義的。數(shù)據(jù)點(diǎn) p 的局部相對密度(局部異常因子)為點(diǎn)p的鄰居們的平均局部可達(dá)密度跟數(shù)據(jù)點(diǎn)p的局部可達(dá)密度的比值,即:
? ? ??根據(jù)局部異常因子的定義,如果數(shù)據(jù)點(diǎn) p 的 LOF 得分在1附近,表明數(shù)據(jù)點(diǎn)p的局部密度跟它的鄰居們差不多;如果數(shù)據(jù)點(diǎn) p 的 LOF 得分小于1,表明數(shù)據(jù)點(diǎn)p處在一個(gè)相對密集的區(qū)域,不像是一個(gè)異常點(diǎn);如果數(shù)據(jù)點(diǎn) p 的 LOF 得分遠(yuǎn)大于1,表明數(shù)據(jù)點(diǎn)p跟其他點(diǎn)比較疏遠(yuǎn),很有可能是一個(gè)異常點(diǎn)。
? ? ? ?小結(jié):整個(gè)LOF算法,首先對于每個(gè)數(shù)據(jù)點(diǎn),計(jì)算它與其它所有點(diǎn)的距離,并按從近到遠(yuǎn)排序,然后對于每個(gè)數(shù)據(jù)點(diǎn),找到它的k-nearest-neighbor,最后計(jì)算LOF得分。
/******** LOF算法 ********/from pyod.models.lof import LOF clf = LOF(n_neighbors=20, algorithm='auto', leaf_size=30, metric='minkowski', p=2, metric_params=None, contamination=0.1, n_jobs=1) clf.fit(x)? 計(jì)算出每一個(gè)數(shù)據(jù)點(diǎn)的LOF值,然后在二維空間中展示,如下圖所示,數(shù)據(jù)點(diǎn)的LOF值越大表示該點(diǎn)越異常
? ? ? ?
? ?Trick: LOF算法中關(guān)于局部可達(dá)密度的定義其實(shí)暗含了一個(gè)假設(shè),即:不存在大于等于 k 個(gè)重復(fù)的點(diǎn)。當(dāng)這樣的重復(fù)點(diǎn)存在的時(shí)候,這些點(diǎn)的平均可達(dá)距離為零,局部可達(dá)密度就變?yōu)闊o窮大,會(huì)給計(jì)算帶來一些麻煩。在實(shí)際應(yīng)用時(shí),為了避免這樣的情況出現(xiàn),可以把 k-distance 改為 k-distinct-distance,不考慮重復(fù)的情況。或者,還可以考慮給可達(dá)距離都加一個(gè)很小的值,避免可達(dá)距離等于零。
? ? ? Isolation Forest
? ? ? ? 先用一個(gè)簡單的例子來說明 Isolation Forest 的基本想法。假設(shè)現(xiàn)在有一組一維數(shù)據(jù)(如下圖所示),我們要對這組數(shù)據(jù)進(jìn)行隨機(jī)切分,希望可以把點(diǎn) A 和點(diǎn) B 單獨(dú)切分出來。具體的,我們先在最大值和最小值之間隨機(jī)選擇一個(gè)值 x,然后按照 =x 可以把數(shù)據(jù)分成左右兩組。然后,在這兩組數(shù)據(jù)中分別重復(fù)這個(gè)步驟,直到數(shù)據(jù)不可再分。顯然,點(diǎn) B 跟其他數(shù)據(jù)比較疏離,可能用很少的次數(shù)就可以把它切分出來;點(diǎn) A 跟其他數(shù)據(jù)點(diǎn)聚在一起,可能需要更多的次數(shù)才能把它切分出來。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ?我們把數(shù)據(jù)從一維擴(kuò)展到兩維。同樣的,我們沿著兩個(gè)坐標(biāo)軸進(jìn)行隨機(jī)切分,嘗試把下圖中的點(diǎn)A'和點(diǎn)B'分別切分出來。我們先隨機(jī)選擇一個(gè)特征維度,在這個(gè)特征的最大值和最小值之間隨機(jī)選擇一個(gè)值,按照跟特征值的大小關(guān)系將數(shù)據(jù)進(jìn)行左右切分。然后,在左右兩組數(shù)據(jù)中,我們重復(fù)上述步驟,再隨機(jī)的按某個(gè)特征維度的取值把數(shù)據(jù)進(jìn)行細(xì)分,直到無法細(xì)分,即:只剩下一個(gè)數(shù)據(jù)點(diǎn),或者剩下的數(shù)據(jù)全部相同。跟先前的例子類似,直觀上,點(diǎn)B'跟其他數(shù)據(jù)點(diǎn)比較疏離,可能只需要很少的幾次操作就可以將它細(xì)分出來;點(diǎn)A'需要的切分次數(shù)可能會(huì)更多一些。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ?按照先前提到的關(guān)于“異常”的兩個(gè)假設(shè),一般情況下,在上面的例子中,點(diǎn)B和點(diǎn)B' 由于跟其他數(shù)據(jù)隔的比較遠(yuǎn),會(huì)被認(rèn)為是異常數(shù)據(jù),而點(diǎn)A和點(diǎn)A' 會(huì)被認(rèn)為是正常數(shù)據(jù)。直觀上,異常數(shù)據(jù)由于跟其他數(shù)據(jù)點(diǎn)較為疏離,可能需要較少幾次切分就可以將它們單獨(dú)劃分出來,而正常數(shù)據(jù)恰恰相反。這其實(shí)正是Isolation Forest(IF)的核心概念。IF采用二叉樹去對數(shù)據(jù)進(jìn)行切分,數(shù)據(jù)點(diǎn)在二叉樹中所處的深度反應(yīng)了該條數(shù)據(jù)的“疏離”程度。整個(gè)算法大致可以分為兩步:
- 訓(xùn)練:抽取多個(gè)樣本,構(gòu)建多棵二叉樹(Isolation Tree,即 iTree);
- 預(yù)測:綜合多棵二叉樹的結(jié)果,計(jì)算每個(gè)數(shù)據(jù)點(diǎn)的異常分值。
? ? ? 訓(xùn)練:構(gòu)建一棵 iTree 時(shí),先從全量數(shù)據(jù)中抽取一批樣本,然后隨機(jī)選擇一個(gè)特征作為起始節(jié)點(diǎn),并在該特征的最大值和最小值之間隨機(jī)選擇一個(gè)值,將樣本中小于該取值的數(shù)據(jù)劃到左分支,大于等于該取值的劃到右分支。然后,在左右兩個(gè)分支數(shù)據(jù)中,重復(fù)上述步驟,直到滿足如下條件:
- 數(shù)據(jù)不可再分,即:只包含一條數(shù)據(jù),或者全部數(shù)據(jù)相同。
- 二叉樹達(dá)到限定的最大深度。
? ? ? 預(yù)測:計(jì)算數(shù)據(jù) x 的異常分值時(shí),先要估算它在每棵 iTree 中的路徑長度(也可以叫深度)。具體的,先沿著一棵 iTree,從根節(jié)點(diǎn)開始按不同特征的取值從上往下,直到到達(dá)某葉子節(jié)點(diǎn)。假設(shè) iTree 的訓(xùn)練樣本中同樣落在 x 所在葉子節(jié)點(diǎn)的樣本數(shù)為 T.size,則數(shù)據(jù) x 在這棵 iTree 上的路徑長度 h(x),可以用下面這個(gè)公式計(jì)算:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? h(x)=e+C(T.size)
公式中,e 表示數(shù)據(jù) x 從 iTree 的根節(jié)點(diǎn)到葉節(jié)點(diǎn)過程中經(jīng)過的邊的數(shù)目,C(T.size) 可以認(rèn)為是一個(gè)修正值,它表示在一棵用 T.size 條樣本數(shù)據(jù)構(gòu)建的二叉樹的平均路徑長度。一般的,C(n) 的計(jì)算公式如下:
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?C(n)=2H(n?1)?2(n?1)/n
其中,H(n-1) 可用 ln(n-1)+0.577 估算,這里的常數(shù)是歐拉常數(shù)。數(shù)據(jù) x 最終的異常分值 Score(x) 綜合了多棵 iTree 的結(jié)果
公式中,E(h(x)) 表示數(shù)據(jù) x 在多棵 iTree 的路徑長度的均值,φ表示單棵 iTree 的訓(xùn)練樣本的樣本數(shù),C(φ)表示用φ條數(shù)據(jù)構(gòu)建的二叉樹的平均路徑長度,它在這里主要用來做歸一化。
從異常分值的公式看,如果數(shù)據(jù) x 在多棵 iTree 中的平均路徑長度越短,得分越接近 1,表明數(shù)據(jù) x 越異常;如果數(shù)據(jù) x 在多棵 iTree 中的平均路徑長度越長,得分越接近 0,表示數(shù)據(jù) x 越正常;如果數(shù)據(jù) x 在多棵 iTree 中的平均路徑長度接近整體均值,則打分會(huì)在 0.5 附近。
四、應(yīng)用案例
1、清洗建模數(shù)據(jù)集,將異常樣本通過無監(jiān)督算法進(jìn)行篩選
from pyod.models.iforest import IForest from matplotlib import pyplot as pltclf = IForest(behaviour='new', bootstrap=False, contamination=0.1, max_features=1.0,max_samples='auto', n_estimators=500, n_jobs=-1, random_state=None,verbose=0) clf.fit(x)out_pred = clf.predict_proba(x,method ='linear')[:,1] train['out_pred'] = out_predx = train[train.out_pred< 0.7][feature_lst] y = train[train.out_pred < 0.7]['bad_ind']val_x = val[feature_lst] val_y = val['bad_ind']lr_model = LogisticRegression(C=0.1,class_weight='balanced') lr_model.fit(x,y) y_pred = lr_model.predict_proba(x)[:,1] fpr_lr_train,tpr_lr_train,_ = roc_curve(y,y_pred) train_ks = abs(fpr_lr_train - tpr_lr_train).max() print('train_ks : ',train_ks)y_pred = lr_model.predict_proba(val_x)[:,1] fpr_lr,tpr_lr,_ = roc_curve(val_y,y_pred) val_ks = abs(fpr_lr - tpr_lr).max() print('val_ks : ',val_ks)plt.plot(fpr_lr_train,tpr_lr_train,label = 'train LR') plt.plot(fpr_lr,tpr_lr,label = 'evl LR') plt.plot([0,1],[0,1],'k--') plt.xlabel('False positive rate') plt.ylabel('True positive rate') plt.title('ROC Curve') plt.legend(loc = 'best') plt.show()? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
2、通過樣本異常程度進(jìn)行分析
train.out_pred.groupby(train.obs_mth).mean()train.out_pred.groupby(train.obs_mth).max()train.out_pred.groupby(train.obs_mth).var()train['for_pred'] = np.where(train.out_pred>0.7,1,0)train.for_pred.groupby(train.obs_mth).sum()/train.for_pred.groupby(train.obs_mth).count()#看一下badrate train.bad_ind.groupby(train.for_pred).sum()/train.bad_ind.groupby(train.for_pred).count()3、冷啟動(dòng),假設(shè)沒有標(biāo)簽
y_pred = clf.predict_proba(x,method ='linear')[:,1] fpr_lr_train,tpr_lr_train,_ = roc_curve(y,y_pred) train_ks = abs(fpr_lr_train - tpr_lr_train).max() print('train_ks : ',train_ks)y_pred = clf.predict_proba(val_x,method ='linear')[:,1] fpr_lr,tpr_lr,_ = roc_curve(val_y,y_pred) val_ks = abs(fpr_lr - tpr_lr).max() print('val_ks : ',val_ks) from matplotlib import pyplot as plt plt.plot(fpr_lr_train,tpr_lr_train,label = 'train LR') plt.plot(fpr_lr,tpr_lr,label = 'evl LR') plt.plot([0,1],[0,1],'k--') plt.xlabel('False positive rate') plt.ylabel('True positive rate') plt.title('ROC Curve') plt.legend(loc = 'best') plt.show()參考文獻(xiàn):https://pyod.readthedocs.io/en/latest/pyod.html
總結(jié)
以上是生活随笔為你收集整理的无监督算法与异常检测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 社交网络分析与反欺诈
- 下一篇: 不均衡学习