2012-02-08 20 views
9

esencialmente que tienen una matriz de valores de esta manera:media móvil exponencial de 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 matriz anterior se simplifica, estoy recogiendo 1 Valor por milisegundo en mi código real y necesito para procesar la salida en un algoritmo que escribí para encontrar el pico más cercano antes de un punto en el tiempo. Mi lógica falla porque en mi ejemplo anterior, 0.36 es el pico real, pero mi algoritmo miraría hacia atrás y vería el último número 0.25 como el pico, ya que hay una disminución de 0.24 antes.

El objetivo es tomar estos valores y aplicar un algoritmo a los que va a "suave" hacia fuera un poco, así que tengo los valores más lineales. (Es decir: Me gustaría que mis resultados sean curvas, no jaggedy)

Me han dicho que para aplicar un filtro de media móvil exponencial de mis valores. ¿Cómo puedo hacer esto? Es realmente difícil para mí leer ecuaciones matemáticas, me ocupo mucho mejor del código.

¿Cómo proceso los valores en mi matriz, aplicando un cálculo de la media móvil exponencial para igualar a cabo?

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

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

Respuesta

27

para calcular una exponential moving average, es necesario mantener un cierto estado alrededor y que necesita un parámetro de ajuste. Esto requiere un poco de clase (asumiendo que usted está utilizando Java 5 o posterior):

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; 
    } 
} 

Instantiate con el parámetro de decaimiento que desee (puede tomar la sintonización; debe estar entre 0 y 1) y luego usar para filtrar average(…) .


Al leer una página en cierta recurrencia mathmatical, todo lo que necesita saber cuando convirtiéndolo en código es que los matemáticos les gusta escribir en los índices de matrices y secuencias con subíndices. (También tienen algunas otras anotaciones, lo que no ayuda.) Sin embargo, la EMA es bastante simple, ya que solo necesita recordar un valor anterior; no se requieren arreglos de estado complicados

+0

De hecho, la EMA es la _easiest_ promedio de código (siempre que tenga un lugar para almacenar el estado de estado como un movimiento de Java objeto) porque no necesita hacer una administración de estado compleja. –

+1

Así que esencialmente solo 'para (flotar amigo: entrada) {salida [índice] = ema.average (amigo); } '? –

+1

@TKKocheran: Bastante. ¿No es agradable cuando las cosas pueden ser simples? (Si comienza con una nueva secuencia, obtenga un nuevo promediador). Tenga en cuenta que los primeros términos de la secuencia promediada saltan un poco debido a los efectos de frontera, pero también los obtiene con otros promedios móviles. Sin embargo, una buena ventaja es que puede ajustar la lógica del promedio móvil en el promediador y experimentar sin perturbar demasiado el resto del programa. –

-4

Si tiene problemas con las matemáticas, podría ir con un promedio móvil simple en lugar de exponencial. Entonces, la salida que obtendrías serían los últimos x términos divididos por x. pseudocódigo no probado:

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; 

Tenga en cuenta que se necesita para manejar las partes inicial y final de los datos, ya que claramente no se puede promediar los últimos 5 términos cuando usted está en su segundo punto de datos. Además, hay formas más eficientes de calcular esta media móvil (suma = suma - más antigua + más reciente), pero esto es para obtener el concepto de lo que está pasando.

4

Estoy teniendo dificultades para entender sus preguntas, pero intentaré responder de todos modos.

1) Si el algoritmo encontró 0,25 en lugar de 0,36, entonces está mal. Está mal porque supone un aumento o disminución monótona (es decir, "siempre sube" o "siempre baja"). A menos que promedie TODOS sus datos, sus puntos de datos, tal como los presenta, no son lineales. Si realmente desea encontrar el valor máximo entre dos puntos en el tiempo, luego corte su matriz de t_min a t_max y encuentre el máximo de ese subcampo.

2) Ahora bien, el concepto de "medias móviles" es muy simple: imaginar que tengo la siguiente lista: [1.4, 1.5, 1.4, 1.5, 1.5]. Puedo "suavizarlo" tomando el promedio de dos números: [1.45, 1.45, 1.45, 1.5].Observe que el primer número es el promedio de 1.5 y 1.4 (segundo y primer número); el segundo (nueva lista) es el promedio de 1.4 y 1.5 (tercera y segunda lista anterior); el tercero (nueva lista) el promedio de 1.5 y 1.4 (cuarto y tercero), y así sucesivamente. Pude haberlo convertido en "período tres" o "cuatro" o "n". Observe cómo los datos son mucho más suaves. Una buena forma de "ver promedios móviles en el trabajo" es ir a Google Finance, seleccionar un stock (prueba Tesla Motors, bastante volátil (TSLA)) y hacer clic en "técnicos" en la parte inferior del gráfico. Seleccione "Promedio móvil" con un período determinado y "Promedio móvil exponencial" para comparar sus diferencias.

La media móvil exponencial es solo otra elaboración de esto, pero pondera los datos "anteriores" menos que los datos "nuevos"; esta es una forma de "sesgar" el suavizado hacia la parte posterior. Por favor, lea la entrada de Wikipedia.

Por lo tanto, esto es más un comentario que una respuesta, pero el pequeño cuadro de comentarios era demasiado pequeño. Buena suerte.

+0

+1: es relativamente fácil encontrar los mínimos y los máximos, pero es mucho más difícil determinar su importancia, ya que debe observar las desviaciones de los patrones a largo plazo. Bajo la suposición de que tales patrones existen en absoluto. –

0

En una manera rodante .... yo también uso commons.apache biblioteca matemática

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

FAVOR UTILIZAR la biblioteca de matemáticas commons.apache ANTES DE DAR UN PULGAR ABAJO :( – user3392362

Cuestiones relacionadas