python实现移动平均和指数平滑


一、实验目的

数据:自选或train.csv

  1. 实现移动平均;
    a) 一次移动平均,取多个n值,计算标准差;
    b) 二次移动平均,计算参数a,b,进行预测;

  2. 实现指数平滑。
    a) 一次指数平滑,取多个a值;
    b) 二次指数平滑(可选);

二、实验平台

Python 3.7

三、实验内容与结果:

3.1题目分析

实现移动平均分析:
一次移动平均的公式:
在这里插入图片描述
标准差的公式即为MSE公式开根号:
在这里插入图片描述
二次移动平均公式:
在这里插入图片描述
二次移动平均预测法的预测模型(解析过程中默认了t为最后一期数据,T为1):
在这里插入图片描述
a和b的计算公式:
在这里插入图片描述
实现指数平滑分析:
一次指数平滑公式:
在这里插入图片描述
二次指数平滑公式:
在这里插入图片描述
预测模型以及a和b的值:
在这里插入图片描述
依题意得,就是读入数据,然后带入公式就行

3.2实验代码:

# -*- codeing =utf-8 -*-
# @Time : 2021/4/15 15:13
# @Author : ArLin
# @File : demo2.py
# @Software: PyCharm
import csv
from collections import deque
import numpy
import numpy as np

#读取csv文件
def ReadCsvFile(path):
    File = open(path, 'r')
    f = csv.reader(File)
    i = 0
    data = []
    for row in f:
        if i > 0:#去头处理
            data.append(int(row[2]))
        i = i + 1
    return data

def MovingAverage(data,n): #移动平均法
    ForecastN=len(data)+1
    d1=deque()
    P_data=[]
    for i in data:
        d1.appendleft(i)
        if len(d1) == n:
            P_data.append(np.round(sum(d1) / len(d1),1))
            d1.pop()
    return P_data
#计算标准差
def Forecast_Standard_Deviation(data,Pdata,n):
    s = []
    sn = 0
    for index in range(len(Pdata) - 1):
        s1 = (Pdata[index] - data[n + index]) ** 2 #标准差公式
        s.append(np.round(s1, 1))
    y =int((sum(s) / len(s)) ** 0.5)
    print('N为:',n,'时,一次移动平均计算出的标准差:',y)
    return y
#计算A和B的值和预测值
def CountAandB(P1data,P2data,n):
    for index in range(len(P2data)):
        a1=2*P1data[index+n-1]-P2data[index] #a的公式
        b1=(2/(n-1))*(P1data[index+n-1]-P2data[index])#b的公式
        if index==len(P2data)-1:
            a11=int(a1)
            b11=int(b1)
    F = a11 + b11#默认T为1的情况计算F
    print('N的值为:',n,'时,a的值为:',a11,'b的值为:',b11,'二次移动平均预测法的预测值为:',F)
    return a11,b11


#一次,二次指数平滑值
def One_and_TwoOrderExponentialSmoothing(data,a):
    s1=[]
    s2=[]
    s0 = (data[0] + data[1] + data[2]) / 3
    s1.append(np.round(s0, 2))
    s2.append(np.round(s0, 2))
    for index in range(len(data)):
        si1=a*data[index]+(1-a)*s1[index]
        s1.append(np.round(si1, 2))
        si2=a*s1[index+1]+(1-a)*s2[index]
        s2.append(np.round(si2, 2))
    print('当a为',np.round(a, 1), '时,一次指数平滑值为:', s1[len(data)])
    return s1,s2
#预测模型以及a和b的值
def ABExponentialSmoothing(s1,s2,A):
    for index in range(len(s2)):
        a1 = 2 * s1[index]-s2[index]
        b1 = (A/(1-A))*(s1[index]-s2[index])
        if index == len(s2)-1:
            a11= np.round(a1, 2)
            b11= np.round(b1, 2)
    F = a11+b11
    print('A的值为:',np.round(A, 1), '时,a的值为:', a11, 'b的值为:', b11, '二次指数平滑值的预测值为:', np.round(F, 2))
    return a11, b11

def allMovingAverage(data,n):
    P1_data = MovingAverage(data, n)
    P2_data = MovingAverage(P1_data, n)
    Forecast_Standard_Deviation(data, P1_data, n)
    CountAandB(P1_data, P2_data, n)

if __name__ =='__main__':
    path='train.csv'
    data=ReadCsvFile(path)
    for i in range(2,18):
        allMovingAverage(data,i)
    for i in numpy.arange(0.1, 1, 0.1):
        s=One_and_TwoOrderExponentialSmoothing(data, i)
        ABExponentialSmoothing(s[0],s[1],i)

3.3结果与分析:

结果截图:
移动平均结果截图:
在这里插入图片描述
指数平滑实验结果截图:
在这里插入图片描述

实验结果分析:
从移动平均结果截图中我们可以看出,
在选取从2-20的多个n值中,
当n=2时,一次移动平均计算出的标准差最小,为46。
而从指数平滑实验结果截图中我们可以看出在选取0.1-1的多个a值中
平滑系数a对预测精度影响很大, a越大(接近于1),表示模型越来越重视近期数据的作用,对过程的变化反映越快;
a越小,表示模型越重视离现时更远的历史数据的作用,对过程变化的反映越迟钝。

3.4实验总结

出现的问题与解决方法:

问题1:
读取csv的时候报错
<_csv.reader object at 0x0000026E7F21BCE0>
原代码:

File=open(r'train.csv','r')
f=csv.reader(File)
print(f)

解决方法:
因为csv.reader返回的是一个迭代类型,索引应该用循环来打印信息才行
修改后的代码:

File=open(r'train.csv','r')
f=csv.reader(File)
#print(f)
for row in f:
    print(row)

问题2:
刚开始在保留小数位的时候我采用的是’%.xf’方法后面发现这个貌似只能在print中使用,达不到我的预期,我就又使用了format函数但是导致保留进列表的数据是字符串的形式,就导致多了一步操作
解决方法:
最后我采用了round()函数,发现是最省时省力的了。

问题3:
其实一开始我写的预测模式的t和T是可以自定义的,但是由于数据量非常大,处理起来就会很麻烦,很繁琐
解决方法:
虽然我实现了这个算法函数,但是经过和同学沟通后还是决定把t定为最后一位数据,T为1

知识点总结:

  1. 移动平均:
    以计算算术平均数为基础的算法,适用对象为: 一组随时间变化而波动的数据, 时间序列变动不太剧列,较平稳。方法是每次在时间序列上移动一步求平均值,作用是能消除季节性变动、周期性变动与随机变动的影响, 突出长期趋势
  2. 指数平滑:
    初始值的确定:
    时间序列原始值较多, a较大时可取s0(1)=x1,s0(2)=s0(1)
    数据点不多,初始值对预测精度影响较大时,可取开始几个观测值的算术平均值、加权平均值做初始值。
    a的影响:
    平滑系数a对预测精度影响很大, a越大(接近于1),表示模型越来越重视近期数据的作用,对过程的变化反映越快;a越小,表示模型越重视离现时更远的历史数据的作用,对过程变化的反映越迟钝。
    a的取值经验(通常0.01<a <0.3):
     初始值不可靠时,a倾向取大
     原始数据波动大时, a倾向取大,反之亦反
    3. python保留小数位的三种实现方法
    format函数
    '%.xf’方法
    round()函数

4. dequed队列
在这里插入图片描述

个人总结:
本次的实验比起之前更有亲和感吧,可能是因为是从之前写的纸质版作业到现在的代码实现,有了从纸质到电子版的突破,在实验过程中其实也是按部就班的自己先算一遍,然后把公式变成代码,一遍遍测试,过程中遇到的一些问题也通过debug解决了,而且发现编写代码后,重点留下的是算法思想,而繁琐的工作由计算机完成了,或许这也是编程的魅力吧。老师之前一直有说可以让生活中融入python,慢慢的现在的作业我也有在开始用编程直接实现,省了很多力气吧,但是由于目前的基础原因,其实有很多不懂的知识点还是面向百度,但是学习呢应该就是这样一个积累的过程吧。不积硅步,无以至千里。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值