"""
演示
    指数移动加权平均, 使用近30天的天气温度数据.
结论
    1.对于指数移动加权平均值，β值（调节系数）越大，移动加权平均值越平缓，越考虑历史数据。
    β值越小，移动加权平均值越接近当前数据。
    2.特例：β=0，就是当前数据的原始值；β=1，就是第一天的初始值
"""

# 导包
import torch
import matplotlib.pyplot as plt

ELEMENT_NUMBER = 30

# 1. 实际平均温度
def demo01():
    # 固定随机数种子
    torch.manual_seed(0)
    # 产生30天的随机温度
    temperature = torch.randn(size=[ELEMENT_NUMBER, ]) * 10
    print(temperature)
    # 绘制平均温度
    days = torch.arange(1, ELEMENT_NUMBER + 1, 1)
    plt.plot(days, temperature, color='r')
    plt.scatter(days, temperature)
    plt.tight_layout()
    plt.show()

# 2. 指数加权平均温度
def demo02(beta=0.9):
    # 固定随机数种子，确保每次运行得到相同的随机温度数据
    torch.manual_seed(0)
    # 产生30天的随机温度数据，通过乘以10放大温度范围
    temperature = torch.randn(size=[ELEMENT_NUMBER, ]) * 10
    print(temperature)

    # 存储指数加权平均后的温度值
    exp_weight_avg = []
    # 遍历每天的温度数据，idx从0开始计数
    for idx, temp in enumerate(temperature):
        # 第一天的指数加权平均值就是当天温度本身
        if idx == 0:
            exp_weight_avg.append(temp)
            continue
        # 从第二天开始，按照指数加权平均公式计算：
        # V_t = β * V_{t-1} + (1-β) * θ_t
        # 其中 V_t 是当前时刻的加权平均值，V_{t-1} 是上一时刻的加权平均值
        # θ_t 是当前时刻的实际温度值，β 是权重参数(0<=β<1)
        # idx-1 是因为要访问前一天的加权平均值
        new_temp = exp_weight_avg[idx - 1] * beta + (1 - beta) * temp
        exp_weight_avg.append(new_temp)

    # 创建天数序列用于绘图
    days = torch.arange(1, ELEMENT_NUMBER + 1, 1)
    # 设置图表标题，显示当前使用的beta值
    plt.title(f"beta={beta}")
    # 绘制指数加权平均温度曲线（红色）
    plt.plot(days, exp_weight_avg, color='r')
    # 绘制原始温度数据点
    plt.scatter(days, temperature)
    plt.tight_layout()
    # 显示图表
    plt.show()

if __name__ == '__main__':
    demo01()
    demo02(beta=0)
    demo02(beta=0.5)
    demo02(beta=0.9)
    demo02(beta=1)