一種簡(jiǎn)單的方法,可通過Python實(shí)現(xiàn)在數(shù)據(jù)流中查找異常值
在上一篇文章中,我解釋了流算法的概念,并給出了許多如何應(yīng)用流算法的示例。 其中之一是在不保存數(shù)據(jù)流元素的情況下計(jì)算數(shù)據(jù)流的滾動(dòng)平均值。 現(xiàn)在,我想擴(kuò)展這個(gè)示例,并在異常值檢測(cè)的背景下向您展示另一種流算法的用例。
當(dāng)我們監(jiān)視機(jī)器的功耗以檢測(cè)任何異常行為時(shí),可能會(huì)出現(xiàn)類似的問題。 如果我們發(fā)現(xiàn)異常值有所增加(異常觀察),則可能表明這臺(tái)機(jī)器的默認(rèn)值,可能值得檢查。
定義和示例
離群值可以通過多種方式定義。 在本文中,我們將使用以下定義:
如果數(shù)字?jǐn)?shù)據(jù)流中的元素與到目前為止所見元素的平均值不在3個(gè)標(biāo)準(zhǔn)偏差之內(nèi),則該元素被視為離群值。
這需要一個(gè)小例子。 假設(shè)我們按順序獲得數(shù)據(jù)3、2、4、3、5、3、2、10、2、3、1。 讓我們進(jìn)一步假設(shè),我們從零的均值和方差(以及因此的標(biāo)準(zhǔn)差)開始,即,如果不等于零,則始終將第一個(gè)元素視為離群值。
因此,將3視為離群值,因?yàn)?> 0 3 * 0。 現(xiàn)在,我們根據(jù)到目前為止看到的元素(僅是數(shù)字3)更新均值和方差。因此,新均值是3,方差是0。
然后我們看到2。我們有2> 3 3 * 0,所以2也被認(rèn)為是離群值。 這是有道理的,因?yàn)榈侥壳盀橹刮覀冎豢吹搅?,所以其他任何數(shù)字都不適合該模式。 平均值更新為(3 2)/2=2.5,方差更新為((3-2.5)2(2-2.5)2)/2=0.25,這意味著標(biāo)準(zhǔn)偏差為0.5。
現(xiàn)在我們看到4。由于2.5–3 *0.5≤4≤2.53 * 0.5,因此該數(shù)字不是異常值(即正常值)。 平均值更新為(3 2 4)/ 3 = 3,方差更新為((3–3)2(2–3)2(4–3)2)/ 3 = 2/3,因此標(biāo)準(zhǔn)偏差為 約0.81。
以下數(shù)字3、5、3、2被認(rèn)為是正常的。 憑直覺,我們將下面的數(shù)字10視為離群值。 讓我們看看該算法的作用。 此時(shí)的平均值約為3.1,標(biāo)準(zhǔn)偏差約為1。由于10> 3.1 3 * 1,因此我們希望將10視為離群值。
如果繼續(xù)最后三個(gè)元素,您將看到它們都是正常的。
問題:要計(jì)算平均值和標(biāo)準(zhǔn)偏差,我們必須記住到目前為止看到的所有元素。 如果我們有一個(gè)每天輸出成千上萬(wàn)個(gè)元素的系統(tǒng),那么這不是一個(gè)選擇。
救援的流式算法
解決此問題的一種方法是使用流算法,該算法在從數(shù)據(jù)流中每個(gè)被掃描元素之后更新其內(nèi)部狀態(tài)。 內(nèi)部狀態(tài)由到目前為止在任何點(diǎn)看到的所有元素的均值和方差組成,從看到任何元素之前的均值和方差為零開始。 確切地說,在看到數(shù)據(jù)流的第n個(gè)元素之后,令m?為平均值,v?為方差,并附加定義m?=v?= 0。
計(jì)算均值
在我有關(guān)流算法的文章中,我們看到了如何僅使用舊的均值,正在掃描的最新元素以及到目前為止看到的元素?cái)?shù)量來更新均值。 這意味著我們只需要隨時(shí)使用這種方法存儲(chǔ)兩個(gè)數(shù)字,而不是像幼稚的方法那樣存儲(chǔ)n。 讓我再次顯示它,將數(shù)據(jù)流的第i個(gè)傳入元素表示為a?:
這個(gè)公式不難開發(fā),對(duì)吧? 有了它,我們就有了我們期望的元素大小的基線。 現(xiàn)在,我們只需要可以用均值圍繞的標(biāo)準(zhǔn)偏差即可將輸入的示例分類為離群值和正常數(shù)據(jù)點(diǎn)。 我們通過計(jì)算方差來做到這一點(diǎn),然后取其平方根即可達(dá)到標(biāo)準(zhǔn)偏差。
計(jì)算方差
在這種情況下,我們也可以輕松找到遞歸公式。 首先,看到n個(gè)元素后的方差為
讓我們嘗試再次根據(jù)n,v?和最新元素來寫。 由于方差取決于均值,因此我們也要包含m?。 在開始之前,讓我們重新安排這個(gè)公式,以使事情變得更容易:
現(xiàn)在,目標(biāo)是使v?進(jìn)入那里。 一種進(jìn)行方式是從以下簡(jiǎn)單的重新排列開始,以隔離平方和直到索引n,它也以v?中的一項(xiàng)出現(xiàn):
這相當(dāng)于
反過來導(dǎo)致
現(xiàn)在,我們有了公式,讓我們看看它在Python中是如何工作的!
用Python實(shí)現(xiàn)
我們可以通過以下方式實(shí)現(xiàn)上述解釋:
class StreamingMeanAndVariance:
def __init__(self):
self.mean = 0
self.variance = 0
self.n_elements = 0
def update(self, element):
self.variance = ((self.variance + self.mean ** 2) * self.n_elements + element ** 2) / (self.n_elements + 1)
self.mean = ((self.mean * self.n_elements) + element) / (self.n_elements + 1)
self.variance = self.variance - self.mean ** 2
self.n_elements += 1
關(guān)于此的注釋:update方法的第一行計(jì)算方差,但不減去當(dāng)前均方根。 在第二行中,計(jì)算當(dāng)前平均值。 在第三行中,然后將其從方差中減去,因?yàn)樵诘谝恍兄腥匀蝗鄙俅酥怠?/p>
要使用它,我們會(huì)
import numpy as np
m = StreamingMeanAndVariance()
n = 10000
for i, s in enumerate(np.random.randn(n)):
if not - 3 <= (s - m.mean) / np.sqrt(m.variance) <= 3:
print(i, s)
m.update(s)
這將掃描數(shù)據(jù)流,該數(shù)據(jù)流在此示例中由10000個(gè)正態(tài)分布的數(shù)字組成(我們將其表示為N(0,1)),并在出現(xiàn)異常時(shí)打印異常值。
如果將法線的間隔和平均值(以黃色表示)作圖,則會(huì)得到以下圖片:
以藍(lán)色顯示,您可以看到測(cè)量值。綠色區(qū)域包含法線點(diǎn),其外部的測(cè)量值(紅色表示)被認(rèn)為是異常值。以黃色顯示您的期望值(平均值)。
討論區(qū)
該算法可以達(dá)到我們的期望! 但是,到目前為止,我們還沒有看到它如何處理分配的變化,而是始終只有標(biāo)準(zhǔn)的正態(tài)分布數(shù)。
讓我們測(cè)試執(zhí)行以下操作時(shí)算法的行為:
結(jié)果看起來像這樣:
Everything adapts slowly to the new data.
優(yōu)點(diǎn)
這看起來很有希望! 一切都會(huì)自動(dòng)適應(yīng)新數(shù)據(jù)。 當(dāng)數(shù)據(jù)的平均值從0變?yōu)?時(shí),我們可以看到很多離群值,這是有道理的。 新平均值2越多,觀測(cè)到的異常值就越少,因?yàn)?左右是新的常態(tài)。
當(dāng)將平均值從2更改為-2時(shí),我們可以看到更多的離群值,因?yàn)檫@種變化要嚴(yán)重得多。 到目前為止,一切都很好。
缺點(diǎn)
如果查看圖的右半部分,可以看到對(duì)新數(shù)據(jù)的適應(yīng)非常慢。 如您所見,平均值和標(biāo)準(zhǔn)偏差將在一段時(shí)間后再次達(dá)到正確的水平,因?yàn)辄S線(均值)下降并且綠色區(qū)域再次變窄。 但是直到穩(wěn)定為止,沒有發(fā)現(xiàn)異常值。
為了解決這個(gè)問題,我們只能使用最后k個(gè)樣本來計(jì)算均值和標(biāo)準(zhǔn)差,因?yàn)?/p>
這會(huì)破壞第一次測(cè)量的影響。 如果將k設(shè)置為無(wú)窮大,則可以從之前獲得算法。
我們將k設(shè)置得越低,算法就越快地適應(yīng)新數(shù)據(jù)。 但是,將k設(shè)置得太小可能會(huì)導(dǎo)致丟棄異常值,因?yàn)樵撍惴ㄕJ(rèn)為新數(shù)據(jù)就是這樣。 在設(shè)置k = 1的極端情況下,沒有元素被視為離群值,因?yàn)閮H考慮了最新元素。
根據(jù)用例,可能幾百或幾千個(gè)就可以了。
結(jié)論
在本文中,我們已經(jīng)看到了如何為數(shù)據(jù)流建立一個(gè)非常簡(jiǎn)單的異常檢測(cè)機(jī)制。 我們的算法不需要存儲(chǔ)所有測(cè)量值,因此非常容易應(yīng)用,也可以在極其受限制的硬件上使用,并且只需固定存儲(chǔ)即可。 該算法甚至可以適應(yīng)數(shù)據(jù)更改,因此無(wú)需手動(dòng)更新。
唯一需要調(diào)整的是自適應(yīng)率,我們?cè)诒疚闹袥]有介紹,但是很容易做到。
-
數(shù)據(jù)流
+關(guān)注
關(guān)注
0文章
125瀏覽量
14898 -
python
+關(guān)注
關(guān)注
56文章
4827瀏覽量
86766
發(fā)布評(píng)論請(qǐng)先 登錄
FX3板是否兼容2k和4k分辨率的視頻數(shù)據(jù)流?
使用FX3測(cè)試程序中的數(shù)據(jù)流時(shí),遇到了每8個(gè)字節(jié)重復(fù)的場(chǎng)景,是什么原因?qū)е碌模?/a>
ad77681數(shù)據(jù)讀取異常的原因?
利用SSIS源、查找及目標(biāo)組件集成PostgreSQL數(shù)據(jù)至ETL流程

使用ADS1281做調(diào)制器,兩個(gè)調(diào)制器都是輸出1位的數(shù)據(jù)流,那合并之后數(shù)據(jù)流是幾位的呢?
適用于Oracle的SSIS數(shù)據(jù)流組件:提供快速導(dǎo)入及導(dǎo)出功能

Devart SSIS數(shù)據(jù)流組件

cmp在數(shù)據(jù)處理中的應(yīng)用 如何優(yōu)化cmp性能
ADS1299+RK3399在數(shù)據(jù)采樣的過程中,有數(shù)據(jù)丟失的情況怎么解決?
Python中dict支持多個(gè)key的方法
柔性測(cè)斜儀數(shù)據(jù)異常故障分析及解決方法

魯棒性算法在數(shù)據(jù)處理中的應(yīng)用
理解ECU數(shù)據(jù)流的分析方法
請(qǐng)問TLV320AIC3254EVM-K怎么讀取音頻數(shù)據(jù)流?
統(tǒng)一日志數(shù)據(jù)流圖

評(píng)論