簡體   English   中英

測量線上數據點的變化; 趕上浸

[英]Measure variation of data points from a line; To Catch a Dip

如何在C ++中測量該區域?

(更新:我發布了解決方案和代碼作為答案,而不是再次編輯問題)

如何量化理想曲線和測量曲線之間的藍色區域
理想線(紅色虛線)是從起點開始的圖,每個測量角度均加上平均上升; 我通過平均獲得。 我用黑色測量了測試數據。 如何量化藍色浸入區域? X軸是統一的,因此簡化了斜率和數學運算。

我可以確定像這樣的區域大小的臨界值,然后將其標記為重新測試或失敗。 很少會出現一個更靠近右側的傾斜,但是設置標准偏差的臨界值通常會使這些零件失效。

更新資料

迭戈的答案幫助我形象地看到了這一點。 現在,我可以看到要執行的操作,接下來將研究實現“自制傾斜檢測器”的算法。 :)
更好地可視化問題


為什么?

我創建了一個測試台來測試我要銷售的節氣門位置傳感器。 我正在嘗試通過分析收集的數據以編程方式量化繪圖的直線度。 這個特殊的模型讓我很煩惱。

我不想出售的零件的樣圖: 測試數據中有一條曲線

X軸是節氣門開度的均勻間隔角。 步進電機轉動輸入軸,每0.75°停止一次,以測量10位ADC上的輸出,該輸出轉換為Y軸。 該圖是data[idx]idx,value映射到(x,y)位圖坐標。 然后,我使用Bresenham算法在位圖中的點之間繪制線。

我的其他TPS產品產生令人驚訝的線性輸出

該圖的下部(左側)對於任何汽車的正常使用都是至關重要的。 這是當您在城鎮周圍開車,進入停車場等時。該特定部分趨向於在15°的開度附近出現傾角,我希望使用該程序來量化曲線中的“傾角”,而不再依賴於測試人員的直覺。 在上面的示例中,地勢有所下降,但並未恢復到理想的水平。

即使這是一個嵌入式應用程序,打印報告也需要10秒鍾,因此我不認為多次遍歷120個點的數據數組會浪費周期。 另外,由於我使用的是uC32 PIC32微控制器 ,因此有足夠的內存,因此我能夠在控制器內考慮此問題,這是我的榮幸


我已經在嘗試什么

測試點之間的上升陣列:考慮到X軸是統一的,我將X軸完全消除,然后從一個讀數到下一個讀數進行一系列變化。 此數組有助於報表的“點之間的最小上升:0最大:14”。 我稱這個數組為deltas

我嘗試對增量使用標准偏差 ,但是,在測試期間,我發現對於這部分,低標准偏差不是可靠的度量。 如果跌落很快返回到早期數據點所暗示的原始線,則Std Dev可以說是低的(觀察到低至2.3),但是該部分仍然是我不想使用的東西。 我嘗試將臨界值設置為2.6,但由於積壓大,它使太多零件失效。 上面鏈接的另一個更線性的部分可以可靠地依靠Std Dev來保證質量。

峰態似乎根本不適合這種情況。 我今天了解了峰度 ,並找到了一個包含峰度和偏度的統計資料庫 在繼續測試期間,我發現在這兩個度量中,沒有與通過或失敗相對應的正,負或振幅趨勢。 這位先生共享一個線性回歸庫,但是我相信Lin Reg與我的情況無關,因為我很滿意地認為增量 AVG是我的理想選擇。 線性回歸和R ^ 2更適合從不太理想的數據或更大的數據集中找到一條線。

每個三角洲AVG和標准偏差比較我設置了一個監控器所要檢查的增量的數據的最終平均每個增量。 在這里,我也找不到可靠的指標。 太多合格零件將無法通過將任何差值限制在偏離平均值2倍標准偏差之內的測試。 最終,我可以確定的與AVG唯一的區別是與AVG本身的差異在AVG+Std Dev之內。 任何更嚴格的限制都會使本來不錯的部分失敗。 大約15°的開度難以捉摸,可以通過此測試。

自制的傾角檢測器當將增量提供給計算機的串行監視器時,我在傾角期間觀察到連續的負增量 ,因此我在傾角檢測器中進行了編程,但對我來說卻非常粗糙。 如果連續存在5個或更多的負增量 ,則將它們相加。 我已經看到,如果我將這個總和與AVG的驟降之差相除,然后除以負增量的數量,則大於2.9或3的值可能表示失敗。 我觀察到跌幅持續6至15個三角洲。 容易觀察到的下探值與AVG的總和之間的差值最多為-35。

AVG累積變化趨勢的趨勢上面的內容使我認為,觀察偏離AVG的增量總和可能是答案。 意思是,我遍歷數組並求和AVG中每個增量的差。 我以為我一直在研究某件事,直到很大一部分使這個理論破滅。 我看到一種趨勢,即運行總和與AVG小於AVG2x AVG倍,則直線顯示得越直。 許多理想零件只會顯示8個或更少的增量點,而sumOfDiffs將偏離AVG很遠。

float sumOfDiffs=0.0;
for( int idx=0; idx<stop; idx++ ){
    float spread = deltas[idx] - line->AdcAvgRise;
    sumOfDiffs = sumOfDiffs + spread;
    ...
    testVal = 2*line->AdcAvgRise;
    if( sumOfDiffs > testVal || sumOfDiffs < -testVal ){
        flag = 'S';
    }
    ...
}

然后,通過58個數據點sumOfDiffs了具有奇妙線性圖的零件,其中sumOfDiffs是AVG的兩倍以上! 我發現這很棒,因為在sumOfDiffs個數據點的末尾, sumOfDiffs值為-0.000057。

在測試期間,最終的sumOfDiffs結果通常會記錄為0.000000,並且只有在異常情況下,該結果才大於.000100。 實際上,我發現這很令人驚訝:“不良零件”如何積累出很高的准確性。

監視sumOfDiffs的樣本輸出此下面的輸出顯示發生了下降。 該測試sumOfDiffs ,在整個測試過程中,運行的sumOfDiffs距離AVG的距離是AVG的2 sumOfDiffs以上。 此傾角持續從增量 idx的23至49; 從17.25°開始,持續19.5°。

Avg rise: 6.75    Std dev: 2.577
idx: delta  diff from avg   sumOfDiffs  Flag
 23:   5    -1.75           -14.05      S
 24:   6    -0.75           -14.80      S
 25:   7     0.25           -14.55      S
 26:   5    -1.75           -16.30      S
 27:   3    -3.75           -20.06      S
 28:   3    -3.75           -23.81      S
 29:   7     0.25           -23.56      S
 30:   4    -2.75           -26.31      S
 31:   2    -4.75           -31.06      S
 32:   8     1.25           -29.82      S
 33:   6    -0.75           -30.57      S
 34:   9     2.25           -28.32      S
 35:   8     1.25           -27.07      S
 36:   5    -1.75           -28.82      S
 37:  15     8.25           -20.58      S
 38:   7     0.25           -20.33      S
 39:   5    -1.75           -22.08      S
 40:   9     2.25           -19.83      S
 41:  10     3.25           -16.58      S
 42:   9     2.25           -14.34      S
 43:   3    -3.75           -18.09      S
 44:   6    -0.75           -18.84      S
 45:  11     4.25           -14.59      S
 47:   3    -3.75           -16.10      S
 48:   8     1.25           -14.85      S
 49:   8     1.25           -13.60      S
Final Sum of diffs: 0.000030
RunningStats analysis:
NumDataValues= 125
Mean= 6.752
StandardDeviation= 2.577
Skewness= 0.251
Kurtosis= -0.277

關於質量的清晰提示:踏上這一旅程的第一步是學習主要的汽車OEM供應商如何將4點測試作為這些零件的標准度量。 我的第一個測試台使用的是Arduino,內存為8k,沒有TFT顯示屏,也沒有打印機,機械分辨率僅為3°! 那時,我只是簡單地測試了增量在任意總范圍內,並選擇了單個增量可能有多大的限制。 與之前的30點測試相比,我的120分以上的測試感覺上乘,但是該測試對這些下降並不了解。

處所

  • 一組數據的平均值具有數學性質,即與平均值的偏差之和為0。
    • 這解釋了為什么壞數據集和好的數據集都給出幾乎為零的原因。
    • 基本上,當結果不同於零時,本質上是差異中舍入誤差的累積,這就是為什么不幸地無法保存有用信息的原因
  • 最清楚地定義您正在尋找的東西是您的圖像:您正在尋找一個區域 ,這就是為什么您不能以這種方式找到解決方案的原因:
    • 在單點上尋找指標太本地化而無法提取該信息
    • 尋求全局累積或參數(全局標准偏差)過於籠統,您將丟失太多信息和變異源中的數據
    • 峰度(您已經告訴我,但出於完整性考慮)不在其應用范圍內,因為這不是概率分布
    • 最后,您已經嘗試過的方法中更合適的方法是“自制傾角檢測器”,因為它以本地方式思考,但不會過多。
  • 最后但並非最不重要的:
    • 您要選擇的任何算法都有其默認點。
      • 因此,也許有人正在尋找一種超級聰明的算法,該算法無需進行參數化和調整即可自動適應問題,並可以自定義問題。
      • 另一方面,存在一種算法,它將基於作者對典型數據行為(好的和壞的)的知識,並且該算法本身很愚蠢,即如果存在另一種不同的和無法預期的行為,則結果是不可預測的
      • 好的,正確的方法是這兩種方法之一,或介於兩者之間,具體取決於應用程序。 因此,如果它也可以使用“自制傾角檢測器”可以解決。 沒有理由將其定義為粗略的,但是根據應用程序的需求可能還不夠,這是另一回事。

如何尋找地區

  • 獲得數據后,首先要做的就是清楚地定義“理論直線”。 我提供一些選擇:
    • 使用RANSAC算法( 正式上是IMHO的最佳選擇)
      • 這使您最適合對齊點,而不管未對齊點
      • 這項工作相當困難,甚至可能過大(恕我直言)
    • 考慮由第一點和最后一點定義的線
      • 您告訴我們,逢低點幾乎總是在不靠近邊界的同一位置,因此可以認為第一點和最后一點是負擔得起的
      • 非常容易實現
      • 這是使用我之前講過的有關預期行為的知識的示例,因此您需要考慮您是否以及對該假設有多大的信心
    • 考慮前10個點和后10個點的線性擬合
      • 只是以前版本的更實惠的版本,因為使用更多的點,您可以不必擔心僅第一個點或最后一個點會受到任何度量問題的影響,因此所有操作都會因此失敗
      • 也很容易實現
      • 如果我是你,我將使用這個或啟發這個的東西
  • 計算每個X的直線給出的Y值
  • 使用以下過程計算兩條曲線之間的面積(或函數Y_dev = Y_data - Y_straight在數學上相同的Y_dev = Y_data - Y_straight ):
    • PositiveMax = 0; NegativeMax = 0;
    • 從第一個點開始(值可以為正或負),然后放入臨時區域累加器tmp_Area
    • 對於每個下一個點
      • 如果符號相同,則累加值
      • 如果不同
        • 停止積累
        • 檢查累計值是否大於PositiveMax或小於NegativeMax,以及是否大於等於存儲為新的PositiveMax或NegativeMax
        • 無論如何,用tmp_Area = Y_dev;復位累加器tmp_Area = Y_dev; 到以這種方式開始的當前值的新積累
    • 最后,您將獲得最大高估的連續區域和最大低估的連續區域的值,我認為這是您想要的分數。
    • 如果需要,您只能根據觀察到的和預期的數據行為來管理NegativeMax
    • 您可能會發現放置閾值很有用,因此,如果Y_dev值小於閾值,則不會累加該值。
    • 為了不從接近直線的許多點獲得大的累積,而這可能類似於遠離直線的少數點的累積
      • 需要對此和適當的閾值進行一些樣本數據評估
    • 您需要為該連續區域找到合適的閾值,並且只能從觀察樣本數據中獲得該閾值。
      • 再次:可以是您觀察並確定閾值,也可以構建好樣本和壞樣本的存儲庫,並編寫一個程序來自動了解要使用的閾值。 但是他不是算法,這是找到其操作參數的方法,人腦沒什么可做的.....這僅取決於我們是否正在尋找一種方法,將好事分開,還是重新尋找執行此操作的自適應算法.....您確定目標。

事實證明,這是我的直覺的結果,而Diego的方法是積分的平均值。 我仍然不喜歡該名稱,因此我已經描述了算法,並在Math.SE上詢問了該名稱的含義,該名稱已遷移到“交叉驗證”(Stats.SE)

在對Math.SE問題進行大量編輯之后,我更新了圖表。 事實證明,我正在獲取數據導數的閉合積分的平均值。 :P首先,我們收集數據:

收集的數據圖,突出顯示下降

接下來是“導數”:逐步遍歷原始數據數組以形成增量數組,這是ADC值從一個0.75°步進到下一個步進的增量 “上升”或“斜率”是派生詞:dy / dx。

在“斜率”或平均水平趨於平穩的情況下,我可以連續找到多個負增量 ,將其相加,然后在下降結束時除以計數。 總和是平均值和增量之間面積的整數,當下降幅度返回正值時,我可以將總和除以下降幅度的計數。

微分數值積分的平均值

在測試過程中,我得出了該平均值的平均值的截止值2.6。 這是衡量我的“直覺”來衡量部分認為好壞的好方法。

萬一有人發現自己試圖對此進行量化,這是我實現的代碼。 請注意,它只是在尋找負跌幅。 另外,在其他地方將dipCountLimit定義為5。除了傾角檢測器/累加器(即,數值積分器)之外,我還具有一個尖峰檢測器,如果有任何數據點偏離平均值+平均值+標准,則可以任意將測試標記為不良。偏差。 根據觀察到的可能會損壞的零件圖,任意選擇AVG + STD DEV作為峰值限制。

int dipdx=0;
//  inDipFlag also counts the length of this dip
int inDipFlag=0;
float dips[140] = { 0.0 };
for( int idx=0; idx<stop; idx++ ){
    const float diffFromAvg = deltas[idx] - line->AdcAvgRise;
    //  state machine to monitor dips
    const int _stop = stop-1;
    if( diffFromAvg < 0 && idx < _stop ) {
        //  check NEXT data point for negative diff & set dipFlag to put state in dip
        const float nextDiff = deltas[idx+1] - line->AdcAvgRise;
        if( nextDiff < 0 && inDipFlag == 0 )
            inDipFlag = 1;
        //  already IN a dip, and next diff is negative
        if( nextDiff < 0 && inDipFlag > 0 ) {
            inDipFlag++;
        }

        //  accumulate this dip
        dips[dipdx]+= diffFromAvg;

        //  next data point ends this dip and we advance dipdx to next dip
        if( inDipFlag > 0 && nextDiff > 0 ) {
            if( inDipFlag < dipCountLimit ){
                //  reset the accumulator, do not advance dipdx to next entry
                dips[dipdx]=0.0;
            } else {
                //  change this entry's value from dip sum to its ratio
                dips[dipdx] = -dips[dipdx]/inDipFlag;
                //  advance dipdx to next entry
                dipdx++;
            }
            //  Next diff isn't negative, so the dip is done
            inDipFlag = 0;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM