2012-02-08 21 views
9

I essenzialmente hanno una matrice di valori simili:Implementazione media mobile esponenziale in Java

0.25, 0.24, 0.27, 0.26, 0.29, 0.34, 0.32, 0.36, 0.32, 0.28, 0.25, 0.24, 0.25 

La matrice di cui sopra è semplificato eccessivamente, sto raccogliendo 1 valore per millisecondo nel mio codice vero e devo elaborare la uscita su un algoritmo che ho scritto per trovare il picco più vicino prima di un punto nel tempo. La mia logica non riesce perché nel mio esempio sopra, il picco reale è 0.36, ma il mio algoritmo guarderebbe indietro e vedrà l'ultimo numero 0.25 come il picco, poiché c'è una diminuzione a prima di esso.

L'obiettivo è di prendere questi valori e applicare un algoritmo a loro che li "li uniformi" un po 'in modo da avere più valori lineari. (es .: vorrei che i miei risultati fossero sinuosi, non frastagliati)

Mi è stato detto di applicare un filtro esponenziale a media mobile ai miei valori. Come posso fare questo? È davvero difficile per me leggere equazioni matematiche, mi occupo molto meglio del codice.

Come si elaborano i valori nel mio array, applicando un calcolo della media mobile esponenziale per eliminarli?

float[] mydata = ... 
mySmoothedData = exponentialMovingAverage(mydata, 0.5); 

float[] exponentialMovingAverage(float[] input, float alpha) { 
    // what do I do here? 
    return result; 
} 

risposta

27

Per calcolare uno exponential moving average, è necessario mantenere uno stato intorno ed è necessario un parametro di regolazione. Questo richiede un po 'di classe (supponendo che si sta utilizzando Java 5 o successivo):

class ExponentialMovingAverage { 
    private double alpha; 
    private Double oldValue; 
    public ExponentialMovingAverage(double alpha) { 
     this.alpha = alpha; 
    } 

    public double average(double value) { 
     if (oldValue == null) { 
      oldValue = value; 
      return value; 
     } 
     double newValue = oldValue + alpha * (value - oldValue); 
     oldValue = newValue; 
     return newValue; 
    } 
} 

un'istanza di decadimento con il parametro che si desidera (può prendere sintonizzazione; dovrebbe essere compreso tra 0 e 1) e quindi utilizzare per filtrare average(…) .


Durante la lettura di una pagina su qualche ricorrenza mathmatical, tutti si ha realmente bisogno di sapere quando trasformandolo in codice è che i matematici piace scrivere indici in array e sequenze con gli indici. (Hanno anche alcune altre notazioni, il che non aiuta.) Tuttavia, l'EMA è piuttosto semplice in quanto è sufficiente ricordare un vecchio valore; non sono richiesti array di stati complicati.

+0

Infatti, l'EMA è la _easiest_ media in codice (a patto di avere un posto per memorizzare lo stato dello stato come un Java in movimento oggetto) perché non è necessario eseguire una gestione dello stato complessa. –

+1

Quindi in sostanza sono semplicemente 'for (float dude: input) {output [index] = ema.average (dude); } '? –

+1

@TKKocheran: praticamente. Non è bello quando le cose possono essere semplici? (Se si inizia con una nuova sequenza, ottenere un nuovo media.) Si noti che i primi termini della sequenza media salteranno un po 'a causa degli effetti di confine, ma si otterranno anche quelli con altre medie mobili. Tuttavia, un buon vantaggio è che puoi avvolgere la media mobile della media nel mediatore e sperimentare senza disturbare troppo il resto del tuo programma. –

-4

Se hai problemi con la matematica, potresti utilizzare una media mobile semplice anziché esponenziale. Quindi l'output che ottieni sarebbe l'ultimo x termini diviso per x. pseudocodice testato:

int data[] = getFilled(); 
int outdata[] = initializeme() 
for (int y = 0; y < data.length; y++) 
    int sum = 0; 
    for (int x = y; x < y-5; x++) 
     sum+=data[x]; 
    outdata[y] = sum/5; 

Nota che sarà necessario per gestire le parti iniziali e finali dei dati dal momento che chiaramente non è possibile calcolare la media dei 5 ultimi termini quando si è sul secondo punto dati. Inoltre, ci sono modi più efficienti per calcolare questa media mobile (somma = somma - più vecchia + nuova), ma questo è per ottenere il concetto di ciò che sta accadendo attraverso.

4

Ho difficoltà a comprendere le tue domande, ma proverò a rispondere comunque.

1) Se il tuo algoritmo ha trovato 0,25 anziché 0,36, allora è sbagliato. È sbagliato perché presuppone un aumento o una diminuzione monotona (cioè "salendo sempre" o "scendendo sempre"). A meno che non importi TUTTI i tuoi dati, i tuoi punti di dati, come li presenti, non sono lineari. Se si desidera veramente trovare il valore massimo tra due punti nel tempo, suddividere l'array da t_min a t_max e trovare il massimo di tale sottoarray.

2) Ora, il concetto di "medie mobili" è molto semplice: immagina di avere il seguente elenco: [1.4, 1.5, 1.4, 1.5, 1.5]. Posso "arrotondarlo" prendendo la media di due numeri: [1.45, 1.45, 1.45, 1.5].Si noti che il primo numero è la media di 1,5 e 1,4 (secondo e primo numero); il secondo (nuova lista) è la media di 1,4 e 1,5 (terza e seconda lista vecchia); il terzo (nuova lista) la media di 1.5 e 1.4 (quarta e terza), e così via. Avrei potuto fare "periodo tre" o "quattro" o "n". Nota come i dati sono molto più agevoli. Un buon modo per "vedere le medie mobili sul lavoro" è andare su Google Finanza, selezionare un titolo (prova Tesla Motors, piuttosto volatile (TSLA)) e fare clic su "technicals" nella parte inferiore del grafico. Seleziona "Media mobile" con un determinato periodo e "Media mobile esponenziale" per confrontare le loro differenze.

La media mobile esponenziale è solo un'altra elaborazione di questo, ma pesa i dati "meno recenti" meno dei "nuovi" dati; questo è un modo per "pregiudicare" la levigatura verso la parte posteriore. Si prega di leggere la voce di Wikipedia.

Quindi, questo è più un commento che una risposta, ma la piccola casella di commento era solo minuscola. In bocca al lupo.

+0

+1: È relativamente facile trovare minimi e massimi, ma è molto più difficile calcolare il loro significato, poiché è necessario considerare le deviazioni dagli schemi a lungo termine. Partendo dal presupposto che tali modelli esistano del tutto. –

0

In un modo di laminazione .... Io uso anche commons.apache libreria matematica

public LinkedList EMA(int dperiods, double alpha) 
       throws IOException { 
      String line; 
      int i = 0; 
      DescriptiveStatistics stats = new SynchronizedDescriptiveStatistics(); 
      stats.setWindowSize(dperiods); 
      File f = new File(""); 
      BufferedReader in = new BufferedReader(new FileReader(f)); 
      LinkedList<Double> ema1 = new LinkedList<Double>(); 
      // Compute some statistics 
      while ((line = in.readLine()) != null) { 
       double sum = 0; 
       double den = 0; 
       System.out.println("line: " + " " + line); 
       stats.addValue(Double.parseDouble(line.trim())); 
       i++; 
       if (i > dperiods) 
        for (int j = 0; j < dperiods; j++) { 
         double var = Math.pow((1 - alpha), j); 
         den += var; 
         sum += stats.getElement(j) * var; 
         System.out.println("elements:"+stats.getElement(j)); 
         System.out.println("sum:"+sum); 
        } 
       else 
        for (int j = 0; j < i; j++) { 
         double var = Math.pow((1 - alpha), j); 
         den += var; 
         sum += stats.getElement(j) * var; 
        } 
       ema1.add(sum/den); 
       System.out.println("EMA: " + sum/den); 
      } 
      return ema1; 
     } 
+0

PER FAVORE, PREGA DI UTILIZZARE la libreria di matematica di commons.apache PRIMA DI DARE UN POLLICE GIÙ :( – user3392362

Problemi correlati