Die Python-Details zu den Zeitreihenglättungsmethoden des gleitenden Durchschnitts, der linearen exponentiellen Glättung, der quadratischen exponentiellen Glättung und der kubischen exponentiellen Glättung ...

Detaillierte Python-Implementierung von Zeitreihen-Glättungsmethoden: gleitender Durchschnitt, lineare exponentielle Glättung, quadratische exponentielle Glättung und kubische exponentielle Glättung

1. Glättungsmethode

Zu den häufig verwendeten Glättungsmethoden gehören:

  • gleitender Durchschnitt

  • Erste exponentielle Glättung, zweite exponentielle Glättung, kubische exponentielle Glättung

Die spezifische Theorie ist leichter zu verstehen, Sie können sich auf Folgendes beziehen:

  • https://zhuanlan.zhihu.com/p/441373033

  • https://zhuanlan.zhihu.com/p/78848809

2. Python-Implementierung

Die folgenden Schreibmethoden werden alle im Streaming-Verfahren geschrieben, d. h. ein Datentyp wird verarbeitet und eine Art von Streaming-Daten wird verarbeitet.

2.1 Gleitender Durchschnitt

class MovAvgSmoothing(object):
    def __init__(self, window_size=7):
        self.window_size = window_size
        self.data_queue = []

    def update(self, data):
        if len(self.data_queue) == self.window_size:
            del self.data_queue[0]
        self.data_queue.append(data)
        return sum(self.data_queue) / len(self.data_queue)

2.2 Exponentielle Glättung

2.2.1 Exponentielle Glättung erster Ordnung

class ExpSmoothing(object):
    def __init__(self, alpha=0.9):
        self.alpha = alpha
        self.prev_smooth = None

    def update(self, data):
        if self.prev_smooth is None:
            self.prev_smooth = data
            return data
        else:
            smooth = self.alpha * data + (1 - self.alpha) * self.prev_smooth
            self.prev_smooth = smooth
            return smooth

2.2.2 Quadratische exponentielle Glättung

"""
Holt指数平滑,方法中包含一个预测方程和两个平滑方程(水平平滑方程+趋势预测方程)
趋势部分又可分为加性趋势和乘性趋势
对于较大时间步长的预测,趋势可能不会无限延长,就需要抑制这种趋势,加性趋势和乘性趋势的抑制分别对应加性抑制(抑制线性趋势)、乘性抑制(抑制指数趋势
"""
class SmoothMode(Enum):
    Addition = "add mode"
    Multiplication = "multiply mode"
    

class DoubleExpSmoothing(object):
    def __init__(self, alpha=0.5, beta=0.5, mode=SmoothMode.Addition):
        self.alpha = alpha
        self.beta = beta
        self.prev_smooth = None
        self.prev_trend = None
        self.mode = mode

    def update(self, data):
        if self.prev_smooth is None:
            self.prev_smooth = data
            return data
        elif self.prev_trend is None:
            smooth = None
            if self.mode == SmoothMode.Addition:
                self.prev_trend = data - self.prev_smooth
                smooth = self.alpha * data + (1 - self.alpha) * (self.prev_smooth + self.prev_trend)
            elif self.mode == SmoothMode.Multiplication:
                self.prev_trend = data / self.prev_smooth
                smooth = self.alpha * data + (1 - self.alpha) * (self.prev_smooth * self.prev_trend)
            self.prev_smooth = smooth
            return smooth
        else:
            trend = None
            smooth = None
            if self.mode == SmoothMode.Addition:
                smooth = self.alpha * data + (1 - self.alpha) * (self.prev_smooth + self.prev_trend)
                trend = self.beta * (smooth - self.prev_smooth) + (1 - self.beta) * self.prev_trend
            elif self.mode == SmoothMode.Multiplication:
                smooth = self.alpha * data + (1 - self.alpha) * (self.prev_smooth * self.prev_trend)
                trend = self.beta * (smooth / self.prev_smooth) + (1 - self.beta) * self.prev_trend
            self.prev_smooth = smooth
            self.prev_trend = trend
            return smooth

2.2.3 Kubische exponentielle Glättung

"""
 Holt-Winters加法模型(Holt-Winters指数平滑)
 方法中包含一个预测方程和三个平滑方程 (一个用于水平,一个用于趋势,一个用于季节性分量)
 当季节变化在时间序列中大致保持不变时,通常选择加法模型
"""

class SmoothMode(Enum):
    Addition = "add mode"
    Multiplication = "multiply mode"

class TripleExpSmoothing(object):
    def __init__(self, alpha=0.5, beta=0.5, gamma=0.5, m=12, mode=SmoothMode.Addition):
        self.alpha = alpha
        self.beta = beta
        self.gamma = gamma
        self.m = m
        self.prev_smooth = None
        self.prev_trend = None
        self.seasonal = [0] * m
        self.mode = mode

    def update(self, data):
        if self.prev_smooth is None:
            self.prev_smooth = data
            return data
        elif self.prev_trend is None:
            trend, smooth = None, None
            if self.mode == SmoothMode.Addition:
                trend = data - self.prev_smooth
                smooth = self.alpha * data + (1 - self.alpha) * (self.prev_smooth + trend)
            elif self.mode == SmoothMode.Multiplication:
                trend = data / self.prev_smooth
                smooth = self.alpha * data + (1 - self.alpha) * (self.prev_smooth + trend)
            self.prev_smooth = smooth
            self.prev_trend = trend
            return smooth
        else:
            season, trend, smooth = None, None, None
            pre_m_season = self.seasonal[len(self.seasonal) - self.m]
            if self.mode == SmoothMode.Addition:
                smooth = self.alpha * (data - pre_m_season) + (1 - self.alpha) * (self.prev_smooth + self.prev_trend)
                trend = self.beta * (smooth - self.prev_smooth) + (1 - self.beta) * self.prev_trend
                season = self.gamma * (data - self.prev_smooth - self.prev_trend) + (1 - self.gamma) * pre_m_season
            elif self.mode == SmoothMode.Multiplication:
                smooth = self.alpha * (data / pre_m_season) + (1 - self.alpha) * (self.prev_smooth + self.prev_trend)
                trend = self.beta * (smooth - self.prev_smooth) + (1 - self.beta) * self.prev_trend
                season = self.gamma * (data / (self.prev_smooth + self.prev_trend)) + (1 - self.gamma) * pre_m_season
            self.seasonal.append(season)
            self.season_garbage_collection()
            self.prev_smooth, self.prev_trend = smooth, trend
            return smooth

    # 60s 一个点,一天1440,周期如果是一周则是1440*7
    def season_garbage_collection(self):
        if len(self.seasonal) >= 1440 * 7:
            self.seasonal = self.seasonal[-1440 * 7:]

3. Einheitliche Verwaltung

Sie können eine Klasse verwenden, um diese Glättungsmethoden dynamisch und flexibel zu verwalten und dann basierend auf der verwendeten Planung auszuwählen, welche verwendet werden soll.

class MovSmoothManager(object):
    def __init__(self, m):
        self.avg_smooth = MovAvgSmoothing(window_size=3)
        self.exp_smooth = ExpSmoothing(alpha=0.75)
        self.double_exp_smooth_add = DoubleExpSmoothing(alpha=0.75, beta=0.75)
        self.double_exp_smooth_multiply = DoubleExpSmoothing(alpha=0.75, beta=0.75, mode=SmoothMode.Multiplication)
        self.triple_exp_smooth_add = TripleExpSmoothing(alpha=0.75, beta=0.75, gamma=0.75, m=m)
        self.triple_exp_smooth_multiply = TripleExpSmoothing(alpha=0.75, beta=0.75, gamma=0.75, m=m, mode=SmoothMode.Multiplication)

    def update_data(self, fea_pd: pd.DataFrame, fea_cols):
        smooth_pd = fea_pd.copy(deep=True)
        smooth_fea = ['avgSmooth', 'expSmooth', 'doubleExpSmoothAdd', 'doubleExpSmoothMultiply',
                      'tripleExpSmoothAdd', 'tripleExpSmoothMultiply']
        smooth_data = {}
        for fea_col in fea_cols:
            smooth_pd['avgSmooth'] = smooth_pd[fea_col].apply(lambda x: self.avg_smooth.update(x))
            smooth_pd['expSmooth'] = smooth_pd[fea_col].apply(lambda x: self.exp_smooth.update(x))
            smooth_pd['doubleExpSmoothAdd'] = smooth_pd[fea_col].apply(lambda x: self.double_exp_smooth_add.update(x))
            smooth_pd['doubleExpSmoothMultiply'] = smooth_pd[fea_col].apply(lambda x: self.double_exp_smooth_multiply.update(x))
            smooth_pd['tripleExpSmoothAdd'] = smooth_pd[fea_col].apply(lambda x: self.triple_exp_smooth_add.update(x))
            smooth_pd['tripleExpSmoothMultiply'] = smooth_pd[fea_col].apply(lambda x: self.triple_exp_smooth_multiply.update(x))
            smooth_data[fea_col] = smooth_pd[smooth_fea]
        return smooth_data

4. Gesamtcode

from enum import Enum
import pandas as pd


class SmoothMode(Enum):
    Addition = "add mode"
    Multiplication = "multiply mode"


class MovAvgSmoothing(object):
    def __init__(self, window_size=7):
        self.window_size = window_size
        self.data_queue = []

    def update(self, data):
        if len(self.data_queue) == self.window_size:
            del self.data_queue[0]
        self.data_queue.append(data)
        return sum(self.data_queue) / len(self.data_queue)


class ExpSmoothing(object):
    def __init__(self, alpha=0.9):
        self.alpha = alpha
        self.prev_smooth = None

    def update(self, data):
        if self.prev_smooth is None:
            self.prev_smooth = data
            return data
        else:
            smooth = self.alpha * data + (1 - self.alpha) * self.prev_smooth
            self.prev_smooth = smooth
            return smooth


"""
Holt指数平滑,方法中包含一个预测方程和两个平滑方程(水平平滑方程+趋势预测方程)
趋势部分又可分为加性趋势和乘性趋势
对于较大时间步长的预测,趋势可能不会无限延长,就需要抑制这种趋势,加性趋势和乘性趋势的抑制分别对应加性抑制(抑制线性趋势)、乘性抑制(抑制指数趋势
"""


class DoubleExpSmoothing(object):
    def __init__(self, alpha=0.5, beta=0.5, mode=SmoothMode.Addition):
        self.alpha = alpha
        self.beta = beta
        self.prev_smooth = None
        self.prev_trend = None
        self.mode = mode

    def update(self, data):
        if self.prev_smooth is None:
            self.prev_smooth = data
            return data
        elif self.prev_trend is None:
            smooth = None
            if self.mode == SmoothMode.Addition:
                self.prev_trend = data - self.prev_smooth
                smooth = self.alpha * data + (1 - self.alpha) * (self.prev_smooth + self.prev_trend)
            elif self.mode == SmoothMode.Multiplication:
                self.prev_trend = data / self.prev_smooth
                smooth = self.alpha * data + (1 - self.alpha) * (self.prev_smooth * self.prev_trend)
            self.prev_smooth = smooth
            return smooth
        else:
            trend = None
            smooth = None
            if self.mode == SmoothMode.Addition:
                smooth = self.alpha * data + (1 - self.alpha) * (self.prev_smooth + self.prev_trend)
                trend = self.beta * (smooth - self.prev_smooth) + (1 - self.beta) * self.prev_trend
            elif self.mode == SmoothMode.Multiplication:
                smooth = self.alpha * data + (1 - self.alpha) * (self.prev_smooth * self.prev_trend)
                trend = self.beta * (smooth / self.prev_smooth) + (1 - self.beta) * self.prev_trend
            self.prev_smooth = smooth
            self.prev_trend = trend
            return smooth


"""
 Holt-Winters加法模型(Holt-Winters指数平滑)
 方法中包含一个预测方程和三个平滑方程 (一个用于水平,一个用于趋势,一个用于季节性分量)
 当季节变化在时间序列中大致保持不变时,通常选择加法模型
"""


class TripleExpSmoothing(object):
    def __init__(self, alpha=0.5, beta=0.5, gamma=0.5, m=12, mode=SmoothMode.Addition):
        self.alpha = alpha
        self.beta = beta
        self.gamma = gamma
        self.m = m
        self.prev_smooth = None
        self.prev_trend = None
        self.seasonal = [0] * m
        self.mode = mode

    def update(self, data):
        if self.prev_smooth is None:
            self.prev_smooth = data
            return data
        elif self.prev_trend is None:
            trend, smooth = None, None
            if self.mode == SmoothMode.Addition:
                trend = data - self.prev_smooth
                smooth = self.alpha * data + (1 - self.alpha) * (self.prev_smooth + trend)
            elif self.mode == SmoothMode.Multiplication:
                trend = data / self.prev_smooth
                smooth = self.alpha * data + (1 - self.alpha) * (self.prev_smooth + trend)
            self.prev_smooth = smooth
            self.prev_trend = trend
            return smooth
        else:
            season, trend, smooth = None, None, None
            pre_m_season = self.seasonal[len(self.seasonal) - self.m]
            if self.mode == SmoothMode.Addition:
                smooth = self.alpha * (data - pre_m_season) + (1 - self.alpha) * (self.prev_smooth + self.prev_trend)
                trend = self.beta * (smooth - self.prev_smooth) + (1 - self.beta) * self.prev_trend
                season = self.gamma * (data - self.prev_smooth - self.prev_trend) + (1 - self.gamma) * pre_m_season
            elif self.mode == SmoothMode.Multiplication:
                smooth = self.alpha * (data / pre_m_season) + (1 - self.alpha) * (self.prev_smooth + self.prev_trend)
                trend = self.beta * (smooth - self.prev_smooth) + (1 - self.beta) * self.prev_trend
                season = self.gamma * (data / (self.prev_smooth + self.prev_trend)) + (1 - self.gamma) * pre_m_season
            self.seasonal.append(season)
            self.season_garbage_collection()
            self.prev_smooth, self.prev_trend = smooth, trend
            return smooth

    # 60s 一个点,一天1440,周期如果是一周则是1440*7
    def season_garbage_collection(self):
        if len(self.seasonal) >= 1440 * 7:
            self.seasonal = self.seasonal[-1440 * 7:]


class MovSmoothManager(object):
    def __init__(self, m):
        self.avg_smooth = MovAvgSmoothing(window_size=3)
        self.exp_smooth = ExpSmoothing(alpha=0.75)
        self.double_exp_smooth_add = DoubleExpSmoothing(alpha=0.75, beta=0.75)
        self.double_exp_smooth_multiply = DoubleExpSmoothing(alpha=0.75, beta=0.75, mode=SmoothMode.Multiplication)
        self.triple_exp_smooth_add = TripleExpSmoothing(alpha=0.75, beta=0.75, gamma=0.75, m=m)
        self.triple_exp_smooth_multiply = TripleExpSmoothing(alpha=0.75, beta=0.75, gamma=0.75, m=m, mode=SmoothMode.Multiplication)

    def update_data(self, fea_pd: pd.DataFrame, fea_cols):
        smooth_pd = fea_pd.copy(deep=True)
        smooth_fea = ['avgSmooth', 'expSmooth', 'doubleExpSmoothAdd', 'doubleExpSmoothMultiply',
                      'tripleExpSmoothAdd', 'tripleExpSmoothMultiply']
        smooth_data = {}
        for fea_col in fea_cols:
            smooth_pd['avgSmooth'] = smooth_pd[fea_col].apply(lambda x: self.avg_smooth.update(x))
            smooth_pd['expSmooth'] = smooth_pd[fea_col].apply(lambda x: self.exp_smooth.update(x))
            smooth_pd['doubleExpSmoothAdd'] = smooth_pd[fea_col].apply(lambda x: self.double_exp_smooth_add.update(x))
            smooth_pd['doubleExpSmoothMultiply'] = smooth_pd[fea_col].apply(lambda x: self.double_exp_smooth_multiply.update(x))
            smooth_pd['tripleExpSmoothAdd'] = smooth_pd[fea_col].apply(lambda x: self.triple_exp_smooth_add.update(x))
            smooth_pd['tripleExpSmoothMultiply'] = smooth_pd[fea_col].apply(lambda x: self.triple_exp_smooth_multiply.update(x))
            smooth_data[fea_col] = smooth_pd[smooth_fea]
        return smooth_data

Literatur-Empfehlungen:

Meine Rekrutierungsfreigabe für die Internetschule 2022

Meine Zusammenfassung für 2021

Eine kurze Diskussion über den Unterschied zwischen Algorithmuspositionen und Entwicklungspositionen

Gehaltsübersicht für die Rekrutierung von Internetschulen im Bereich Forschung und Entwicklung

Öffentliches Konto:KI-Schneckenauto

Bleiben Sie bescheiden, bleiben Sie diszipliniert und verbessern Sie sich weiter

9cc7ec25479b33cff8852a7f9059e6b3.jpeg

Senden Sie [Snail], um eine Kopie von „Hand-in-Hand AI Project“ (AI Snail Cart) zu erhalten.

Senden Sie [1222], um eine gute Leetcode-Testnotiz zu erhalten

Senden Sie [Vier klassische Bücher über KI], um vier klassische KI-E-Books zu erhalten

Supongo que te gusta

Origin blog.csdn.net/qq_33431368/article/details/134901683
Recomendado
Clasificación