web-dev-qa-db-ja.com

振動検出器:変数の振動を効果的に検出する方法?

変数をリアルタイムで監視し、1/25秒ごとに新しい値が生成されます。条件に応じて、この変数は安定している可能性があります。つまり、ある値を中心に少し(+/- 1%)変動します(簡単にするために、最近の実験から実際の値は40とします)、または0から安定値よりも6倍または8倍大きい(例では200〜370)。私の目標は、これらの安定した期間を検出することです。

今、私はこの問題を次のように解決します:

  1. 測定の開始以来、入力変数の平均と偏差を測定します。
  2. ある時点で偏差/平均の比率がしきい値(現在は0.15)より大きい場合、変数は不安定な期間に入ったと見なします。それ以外の場合、変数は安定していると見なされます。

このアプローチは一般的にはうまくいきましたが、あまり良くありません。時々、検出器は不安定な期間の検出に失敗します。これは、比率(パーセンテージ)が15%未満の最近の実験の画像です。検出器は周期を安定と見なしますが、グラフの終わりに向かって変数が不安定になることがはっきりとわかります(左軸は平均値であり、 「デルタ」-変数の値、パーセントでの偏差/平均比の右軸):

enter image description here

ご覧のように、変数(青い線、デルタ)はグラフの最後で激しく変動し始めますが、比率の偏差/平均はしきい値(最大値は約8%)未満に留まり、検出器をトリガーしません。

だから私は、検出器の感度を調整するのに役立ついくつかの既存の振動検出器技術/アルゴリズムがあるかどうか疑問に思っていますか?現在、平均値にスライド平均を使用し、しきい値を最大8%下げることを考えています。


高レベルのシステム記述

一定の速度でパケットを生成するプロデューサーがありますが、中断される可能性があり、内部生成遅延は選択されたものとは正確に一致しない可能性があります(つまり、ターゲットは25fpsですが、遅延は30〜50ミリ秒の間で変動する可能性があり、非常にまれに中断され、遅延が2倍になることがあります)。これらのパケットはネットワーク上で利用可能であり、キャッシュされます。コンシューマは、リクエストを発行してこれらのパケットを要求します。大量のリクエストを発行することにより、キャッシュを使い果たすことを目的としています。存在しないデータを要求する要求は、対応するパケットが生成されるとすぐに保留になり、応答されます。したがって、コンシューマは、データが「安定した」期間、つまりターゲットのプロデューサレートに「ほぼ」対応する期間で到着すると、キャッシュを使い果たしたことを認識します。ご覧のとおり、この到着間遅延は、プロデューサーの影響を受けます(正確には40ミリ秒ではありません)および2 /ネットワークの中断。

こちら サンプルデータ;追加のパラメータがたくさんありますが、実際の観測値は「デルタ」列にあります。

4
peetonn

以前のNサンプルとその前のNサンプルの移動平均を維持するソリューションをテストしました。これはノイズを平滑化する効果がありますが、2つの平均値の差を比較して、2つの平均値の間に大きな変化があったかどうかを判断できます。

この解決策が機能しない場合、私は他のアイデアを持っていますが、これは単純であり、投稿したサンプルデータでうまく機能するようです。

Pythonでモックアップを行いました。私はそれであなたの快適さのレベルがわからないので、私はそれをあまり作りませんでしたPythonic、それはどんな言語にも簡単に転記できるようにあなたが使用しています。

import numpy as np
from collections import deque
import pylab as plt

N = 25
windowA=deque(maxlen=N)
windowB=deque(maxlen=N)

avgA = []
avgB = []

with open('stab-estimator - Sheet1.tsv', 'r') as f:
  f.readline() # skip header
  for line in f:
    delta = float( line.split()[1] )
    windowB.append(delta)
    windowA.append(windowB[0])
    # I'll store the averages so we can plot them, but you can just use
    # avgA/avgB as a metric for stability, without storing a history.
    avgA.append(np.sum(windowA)/len(windowA))
    avgB.append(np.sum(windowB)/len(windowB))


# Plot the result:
avgA = np.array(avgA)
avgB = np.array(avgB)
plt.figure()
# plt.plot(avgA-avgB)
# Or equally telling:
plt.plot(avgA/avgB)
plt.show()

その比率のプロットは次のようになります: enter image description here

ご覧のように、観測された不安定性の良い指標を示しています。 10%のしきい値を簡単に設定して、最後にその不安定さを見つけることができます。また、Nを調整することもできます。Nのサイズは、スムージングと変更に対する感度の妥協点になります。 Nが大きすぎる場合、大きな平均化ウィンドウに打ち勝つために、信号はより速く成長する必要があります。

また、平均値が現在の値に収束する間、最初にアラームをミュートする必要があります。

HTH。

1
Timtro