2014-03-02 49 views
1

我有許多傳感器數據,我需要能夠可靠地檢測到變化。基本上來自遠程客戶端的水位傳感器。它使用加速度傳感器&浮標來獲取水位。我的問題是有時候數據可能很嘈雜(每次測量它會變化2-5個單位),有時我需要檢測低至7-9個單位的變化。檢測傳感器數據的變化點

當我繪製數據圖時,人眼很明顯地發現有變化,但我怎麼去編程呢?現在我只是試圖通過編程方式檢測到比x更大的變化,但它不太可靠。我附上了一個示例圖並用箭頭指出了這些更改。一開始的巨大變化只是測試,所以這不是數據的正常行爲。

數據在MYSQL數據庫中,代碼是用PHP編寫的,所以如果你能指出我正確的方向,我將非常感激!

編輯:也可能有一些峯值的數據,這不被認爲是有效的,而是在數據中的錯誤。

編輯:可以從http://pastebin.com/x8C9AtAk 找到示例數據算法需要每30分鐘左右運行一次,並且應該能夠檢測到最近2-4次ping內的變化。每個ping在3-5分鐘的時間間隔內。

enter image description here

+0

如何卡爾曼濾波? –

+2

給我們提供一些數據可以玩嗎?不知道你的樣本有多頻繁,所以也許上傳數據到不同的網站,並提供一個鏈接,如果有很多。另外,如果僅僅是事後看來才能檢測到變化,或者必須在「數據到達」或「即時」類型中檢測到這些變化,那麼可以嗎? –

+1

你應該看看[平滑算法](http://en.wikipedia.org/wiki/Smoothing)。另一種選擇是通過取k個數據點範圍的平均值,將一系列數據點轉換爲單個數據點。然後,您會比較每個其他數據點,以查看是否存在平均值的顯着變化(大於可能計入錯誤的值)。如果有,則更改可能發生在您檢查的兩個數據點之間的數據點內。無論如何,要玩的數據都會有很大的幫助。 – Nuclearman

回答

1

我做了一些awk,你或其他人可能喜歡試驗。我平均排除當前樣本的最後10(m)個樣本,並平均最後2個樣本(n),然後計算兩者之間的差值,並在絕對差值超過閾值時輸出消息。

#!/bin/bash 
awk -F, ' 
            # j will count number of samples 
            # we will average last m samples and last n samples 
    BEGIN {j=0;m=10;n=2} 

    {d[j]=$3;id[j++]=$1" "$2}  # Store this point in array d[] 

    END {       # Do this at end after reading all samples 
     for(i=m-1;i<j;i++){   # Iterate over all samples, except first few while building average 

     totlastm=0     # Calculate average over last m not incl current 
     for(k=m;k>0;k--)totlastm+=d[i-k] 
     avelastm=totlastm/m  # Average = total/m 

     totlastn=0     # Calculate average over last n 
     for(k=n-1;k>=0;k--)totlastn+=d[i-k] 
     avelastn=totlastn/n  # Average = total/n 

     dif=avelastm-avelastn  # Calculate difference between ave last m and ave last n 
     if(dif<0)dif=-dif   # Make absolute 

     mesg=""; 
     if(dif>4)mesg="<-Change detected"; # Make message if change large 
     printf "%s: Sample[%d]=%d,ave(%d)=%.2f,ave(%d)=%.2f,dif=%.2f%s\n",id[i],i,d[i],m,avelastm,n,avelastn,dif,mesg; 
     } 
    } 
    ' <(tr -d '"' < levels.txt) 

最後一位<(tr...)文件levels.txt發送到awk之前只是刪除了雙引號。

下面是輸出的摘錄:

18393344 2014-03-01 14:08:34: Sample[1319]=343,ave(10)=342.00,ave(2)=342.00,dif=0.00 
18393576 2014-03-01 14:13:37: Sample[1320]=343,ave(10)=342.10,ave(2)=343.00,dif=0.90 
18393808 2014-03-01 14:18:39: Sample[1321]=343,ave(10)=342.10,ave(2)=343.00,dif=0.90 
18394036 2014-03-01 14:23:45: Sample[1322]=342,ave(10)=342.30,ave(2)=342.50,dif=0.20 
18394266 2014-03-01 14:28:47: Sample[1323]=341,ave(10)=342.20,ave(2)=341.50,dif=0.70 
18394683 2014-03-01 14:38:16: Sample[1324]=346,ave(10)=342.20,ave(2)=343.50,dif=1.30 
18394923 2014-03-01 14:43:17: Sample[1325]=348,ave(10)=342.70,ave(2)=347.00,dif=4.30<-Change detected 
18395167 2014-03-01 14:48:25: Sample[1326]=345,ave(10)=343.20,ave(2)=346.50,dif=3.30 
18395409 2014-03-01 14:53:28: Sample[1327]=347,ave(10)=343.60,ave(2)=346.00,dif=2.40 
18395645 2014-03-01 14:58:30: Sample[1328]=347,ave(10)=343.90,ave(2)=347.00,dif=3.10 
+0

謝謝。我會嘗試一下。然而,這有一個小問題,因爲如果傳感器受到干擾並且有變化,但水位回到之前的水平,那麼這個代碼會導致誤報。我想一種方法可能是先找到變化點,然後再比較變化前後的5-10個數據點的平均值。那麼可以簡單地排除誤報。感謝您的想法! – Tuxie

0

去了解這類問題的正確途徑是打造感興趣的現象,並且噪聲過程的模型的模型,然後做出給出了一些數據的現象推論。這些推論必然是概率性的。您需要執行的一般計算是P(H_k | data) = P(data | H_k) P(H_k)/(sum_k (P(data | H_k) P(H_k))(貝葉斯規則的一般形式),其中H_k是所有的假設,如「時間量級」或「量級噪聲」。在這種情況下,可能會有大量合理的假設,涵蓋所有可能的大小和時間。您可能需要限制所考慮的假設範圍,以便使問題易於處理,例如,只回顧一定數量的時間步驟。