Um método de filtragem de série temporal com base na média móvel (implementado em Java)

 1 Compreensão da média móvel

  O método de média móvel é um método comum que usa um conjunto de valores de dados reais recentes para prever a demanda pelos produtos da empresa e a capacidade de produção da empresa em um ou vários períodos no futuro. O método de média móvel é adequado para previsão pontual. Quando a demanda do produto não está aumentando nem diminuindo rapidamente, e não há nenhum fator sazonal, o método da média móvel pode efetivamente eliminar as flutuações aleatórias na previsão, o que é muito útil. O método da média móvel varia de acordo com o peso de cada elemento usado na previsão

  O método da média móvel é uma técnica de previsão de suavização simples, cuja ideia básica é: de acordo com os dados da série temporal, item por item, médias de tempo sequenciais contendo um certo número de itens são calculadas sequencialmente para refletir a tendência de longo prazo. Portanto, quando o valor da série temporal flutua muito devido a mudanças periódicas e flutuações aleatórias, e é difícil mostrar a tendência de desenvolvimento do evento, o método da média móvel pode eliminar a influência desses fatores e mostrar a direção e tendência do desenvolvimento do evento (ou seja, a linha de tendência) e, em seguida, analise a tendência de longo prazo da sequência de previsão de acordo com a linha de tendência.

  Tipos de método de média móvel

  O método da média móvel pode ser dividido em: média móvel simples e média móvel ponderada.

 (1) Método de média móvel simples

  O peso de cada elemento da média móvel simples é igual. A fórmula de cálculo de uma média móvel simples é a seguinte: Ft = (At-1 + At-2 + At-3 + ... + At-n) / n onde,

  · Ft - o valor previsto para o próximo período;

  · N-o número de períodos de média móvel;

  · At-1 - Valor real preliminar;

  · At-2, At-3 e At-n representam os valores reais dos primeiros dois períodos, os primeiros três períodos e os primeiros n períodos, respectivamente. 
  

 (2) Método de média móvel ponderada

  A média móvel ponderada dá um peso diferente para cada valor de variável dentro de um período de amplitude fixo. O princípio é: a informação dos dados da demanda histórica do produto em cada período tem um efeito diferente na previsão da demanda no período futuro. Exceto para a mudança periódica com n como o período, a influência do valor da variável distante do período alvo é relativamente baixa, então ela deve receber um peso menor. A fórmula de cálculo do método da média móvel ponderada é a seguinte:

  Ft = w1At-1 + w2At-2 + w3At-3 + ... + wnAt-n onde,

  · W1 - o peso das vendas reais no período t-1;

  · W2 - o peso das vendas reais no período t-2;

  · Wn - o direito de vendas reais no período tn

  · N — o número de períodos de previsão; w1 + w2 + ... + wn = 1

  Ao usar o método da média ponderada, a escolha do peso é um problema a que se deve ter atenção. Métodos empíricos e algoritmos de teste são as maneiras mais fáceis de escolher pesos. De modo geral, os dados mais recentes podem prever melhor a situação futura, portanto, o peso deve ser maior. Por exemplo, com base no lucro e capacidade de produção do mês anterior, é melhor estimar o lucro e capacidade de produção do próximo mês do que com base nos meses anteriores. No entanto, se os dados forem sazonais, os pesos também devem ser sazonais.

  Vantagens e desvantagens do método de média móvel

  Usar o método de média móvel para previsão pode suavizar o impacto de flutuações repentinas na demanda sobre os resultados da previsão. No entanto, também existem os seguintes problemas ao usar o método de média móvel:

  1. Aumentar o número de períodos do método da média móvel (ou seja, aumentar o valor de n) tornará o efeito de suavização melhor, mas tornará o valor previsto menos sensível às mudanças reais nos dados;

  2. A média móvel nem sempre reflete bem a tendência. Por ser um valor médio, o valor previsto sempre permanece no nível passado e não se pode esperar que cause flutuações maiores ou menores no futuro;

  3. O método de média móvel requer uma grande quantidade de registros de dados anteriores.

  Análise de Caso do 
   
  Método da Média Móvel Aplicação do Método da Média Móvel Simples em Imóveis 
O preço de um determinado tipo de imóvel em 2001 é mostrado na segunda coluna da tabela abaixo. Como o preço mensal é afetado por certos fatores incertos, ele é alto e, às vezes, baixo, e o preço flutua muito. Se não for analisado, não é fácil mostrar sua tendência de desenvolvimento. Se você somar os preços a cada poucos meses para calcular a média móvel e estabelecer uma série temporal de média móvel, poderá ver claramente a direção e a extensão de suas mudanças de desenvolvimento a partir da tendência de desenvolvimento suave e, então, poderá prever o preço futuro.

  Ao calcular a média móvel, vários meses devem ser usados ​​de cada vez para calcular, que precisa ser determinado de acordo com o número ordinal da série temporal e o período de mudança. Se houver muitos números ordinais e o período de mudança for longo, pode ser calculado a cada 6 meses ou mesmo a cada 12 meses, ao contrário, pode ser calculado a cada 2 meses ou a cada 5 meses. Para o preço do imóvel neste exemplo em 2001, o valor real de cada 5 meses é usado para calcular a média móvel. O método de cálculo é: some os preços de janeiro a maio e divida por 5 para obter 684 yuan / metro quadrado, some os preços de fevereiro a junho e divida por 5 para obter 694 yuan / metro quadrado, e some os preços de Março a julho Divida por 5 para obter 704 yuan / metro quadrado e assim por diante, consulte a terceira coluna da tabela. Em seguida, calcule o aumento mensal com base na média móvel a cada 5 meses, consulte a quarta coluna da tabela. 
  

Escreva a descrição da imagem aqui

Se for necessário prever o preço desse tipo de imóvel em janeiro de 2002, o método de cálculo é o seguinte: Como a última média móvel 762 está a 3 meses de janeiro de 2002, o preço desse tipo de imóvel em janeiro de 2002 é previsto para ser: 762 + 12 × 3 = 798 (yuan / metro quadrado)

2 Implementação Java da média móvel

  • Número de pontos restantes = comprimento da janela-1 = número de complementos necessários
  • Se os pontos restantes não forem considerados, o comprimento final de retorno da matriz de resultado = o comprimento da matriz original - o comprimento da janela + 1
import java.util.Arrays;

import static org.apache.commons.math.stat.StatUtils.mean;

/**
 * 滑动平均计算
 * Created by dandan.
 * 属性解释:
 * movWindowSize:移动平均计算的滑动窗口
 * movLeaveTemp:临时数组记录最后得不到均值处理的点
 * movResBuff:输出最终结果数组
 * movResBuffLen:输出最终结果数组长度
 * inputBuff:输入数据数组
 * winArray:滑动窗口所形成的数组
 * winArrayLen:滑动窗口所形成的数组长度
 * tempCal:原始数组+插值后的扩容数组
 */

public class movingAverage {

    private static final int WINDOWS = 5;
    private int movWindowSize = WINDOWS; //窗口大小

    public movingAverage() {

    }

    public movingAverage(int size) {

        movWindowSize = size;
    }

    // 均值滤波方法,输入一个inputBuff数组,返回一个movResBuff数组,两者下标不一样,所以定义不同的下标,inputBuff的下标为i,movResBuff的下标为movResBuffLen.
    // 同理,临时的winArray数组下表为winArrayLen
    public double[] movingAverageCal(double[] inputBuff) {
        int movResBuffLen = 0;
        int winArrayLen = 0;
        //定义返回结果数组
        double[] movResBuff = new double[inputBuff.length];
        //定义窗口数组
        double[] winArray = new double[movWindowSize];
        //求整体输入序列的平均值作为一个插值点
        double replace = mean(inputBuff);
        //对原始数组扩容,将插值点放进去.剩余点个数是窗口大小-1.需要补充值的个数等于剩余点的个数
        double[] tempCal = new double[inputBuff.length + movWindowSize-1];
        //拷贝原始数组到临时计算数组
        System.arraycopy(inputBuff, 0, tempCal, 0, inputBuff.length);
        //将平均值插入进去
        for (int m = inputBuff.length; m <tempCal.length ; m++) {
            tempCal[m]=replace;
        }
        //开始计算
        for (int i = 0; i < tempCal.length; i++) {
            if ((i + movWindowSize) > tempCal.length) {
                break; 
            } else { 
                for (int j = i; j < (movWindowSize + i); j++) {
                    winArray[winArrayLen] = tempCal[j];
                    winArrayLen++; 
                }
                movResBuff[movResBuffLen] = mean(winArray);
                movResBuffLen++;
                winArrayLen = 0; 
            } 
        }
        return movResBuff; 
    }

    public static void main(String[] args) {

       double[] inputBuff={670,680,690,680,700,720,730,740,740,760,780,790};

        movingAverage movingAverage = new movingAverage();

        double[] filter = movingAverage.movingAverageCal(inputBuff);

        System.out.println(filter.length);
        System.out.println(Arrays.toString(filter));
        System.out.println(mean(filter));

    }
}

3 Realização da função UDF.

Com base no valor de retorno acima, o valor próprio é calculado novamente

import org.apache.hadoop.hive.ql.exec.UDF;
import java.util.ArrayList;
import java.util.List;
import static org.apache.commons.math.stat.StatUtils.mean;

public class movingAverageFeaCal extends UDF {

    public static void main(String[] args) {
        String num_all = "3.1002," +
                "3.0984," +
                "3.147," +
                "3.197," +
                "3.1002," +
                "3.1002," +
                "3.0854," +
                "3.0982," +
                "3.12," +
                "3.09," +
                "3.a091";

        movingAverageFeaCal movingAverageFeaCal = new movingAverageFeaCal();

        Double evaluate = movingAverageFeaCal.evaluate(num_all, 3);
        System.out.println(evaluate);
    }


    public Double evaluate(String num_all,int windowSize) {

        if (num_all == null || num_all.isEmpty()) {
            return null;//参数不全,不需要计算
        }
        String[] numArr = num_all.split(",");
        List<Double> list = new ArrayList();
        double num = 0;

        if (numArr.length > 0) {
            for (String aNumArr : numArr) {
//                boolean flag = Utils.isNumber(numArr[i]);
                if (aNumArr != null && !aNumArr.isEmpty() && !aNumArr.equals("null") && !aNumArr.equals("NULL") && Utils.isNumber(aNumArr)) {
                    num = Double.parseDouble(aNumArr);
                    list.add(num);
                }
            }
            // Double[] arr1 = list.toArray(new Double[list.size()]);
            double[] inputBuff= list.stream().mapToDouble(i -> i).toArray();
            movingAverage movingAverage = new movingAverage(windowSize);
            double[] feaArr = movingAverage.movingAverageCal(inputBuff);
            return mean(feaArr);

        } else {
            return null;
        }

    }


}

 

Acho que você gosta

Origin blog.csdn.net/godlovedaniel/article/details/114635797
Recomendado
Clasificación