Rivelatore di oscillazioni: come rilevare efficacemente le oscillazioni di una variabile?

4

Controllo una variabile in tempo reale in cui viene generato un nuovo valore ogni 1/25 di secondo. A seconda delle condizioni, questa variabile può essere stabile, ovvero fluttuare un po '(+/- 1%) attorno ad un certo valore (per semplicità, prenderò il valore reale di 40 dai miei recenti esperimenti) o fluttuare ampiamente da 0 a 6x o 8x volte più grande del valore stabile (200-370 per l'esempio). Il mio obiettivo è rilevare questi periodi stabili.

In questo momento risolvo questo problema come segue:

  1. misura la media e la deviazione della variabile in entrata dal inizio delle misurazioni;
  2. se in qualsiasi momento il rapporto di deviazione / media è maggiore di una soglia (0.15 adesso) I considera che la variabile è entrata in un periodo instabile, altrimenti - il la variabile è considerata stabile.

Questo approccio generalmente funzionava, ma non così bene. A volte, il rilevatore non riesce a rilevare periodi instabili. Ecco l'immagine del recente esperimento in cui il rapporto (in percentuale) era inferiore al 15%, il rilevatore considerato periodo come stabile, tuttavia si può vedere chiaramente che la variabile diventa instabile verso la fine del grafico (l'asse sinistro è per la media e "delta" - valore della variabile, asse destro per la deviazione / rapporto medio in percentuale):

Comepuoivedere,lavariabile(lineablu,delta)iniziaafluttuareselvaggiamenteallafinedelgrafico,tuttavialadeviazione/mediadelrapportorimanesottolasoglia(ilmassimoèintornoall'8%)enonattivailrilevatore.

Quindimichiedo,secisonoalcunetecniche/algoritmidirivelatoridioscillazioniesistentichepossonoaiutarearegolarelasensibilitàdelrivelatore?Attualmente,stopensandodiutilizzarelamediamobileperilvaloremedioeabbassarelasogliafinoall'8%.

Descrizionedelsistemadialtolivello

C'èunproduttorechegenerapacchettiavelocitàcostante,anchesepotrebbeessereinterrottoeilritardotraproduttoripotrebbenonessereesattamentequelloscelto(cioèiltargetè25fps,mailritardopuòvariaretra30e50ms,moltoraramentepuòessereinterrottoeilritardopuòdiventareildoppio).Questipacchettisonodisponibilisullareteememorizzatinellacache.Ilconsumatorerichiedequestipacchettiinviandorichieste.Miraaesaurirelacache-emettendounagrandequantitàdirichieste.Quellerichiestecherichiedonodatiinesistenti,diventerannoinsospesoeavrannorispostanonappenaverrannogeneratipacchetticorrispondenti.Pertanto,ilconsumatoresapràchehaesauritolacacheunavoltacheidatiarriverannoconunperiodo"stabile", cioè quello che "approssimativamente" corrisponde al tasso di produzione target. Come si può vedere, questo ritardo inter-arrivo è influenzato 1 / dal produttore (non è esattamente 40ms) e 2 / interruzioni di rete.

Ecco i dati di esempio; ci sono molti parametri aggiuntivi, ma il vero valore osservato è nella colonna "delta".

    
posta peetonn 05.09.2015 - 20:02
fonte

1 risposta

1

Ho testato una soluzione che mantiene una media costante dei precedenti N campioni, e N campioni prima. Ciò ha l'effetto di attenuare il rumore, ma è possibile confrontare le differenze tra le due medie per determinare se si sono verificati cambiamenti significativi tra i due.

Se questa soluzione non funziona, ho altre idee, ma questo è semplice e sembra funzionare bene con i dati di esempio che hai postato.

Ho fatto un mock up in Python. Non sono sicuro del tuo livello di comfort, quindi non l'ho reso molto pythonic , in modo che possa essere facilmente trascritto in qualunque lingua tu stia utilizzando.

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()

La trama di quel rapporto assomiglia a questo:

Come puoi vedere, presenta una buona metrica per la tua instabilità osservata. Potresti facilmente impostare una soglia del 10% e catturare quell'instabilità alla fine. Potresti anche voler sintonizzare N. La dimensione di N sarà un compromesso tra livellamento e sensibilità ai cambiamenti. Se N è troppo grande, allora il segnale dovrà crescere più velocemente per superare la finestra di calcolo della media.

Inoltre, dovrai disattivare l'allarme all'inizio mentre le medie convergono in valori correnti.

HTH.

    
risposta data 06.09.2015 - 03:43
fonte

Leggi altre domande sui tag