一、实验目的:
实现趋势外推法:一次、二次、三次等;
步骤:
1.收集研究对象的动态数列(自选);
2.画数据点分布图,判断近似曲线;
3.计算差分,确定曲线方程;
4.求曲线参数;
5.预测;
要求:
1.画出数据的散点图;
2.打印出差分:一阶、二阶、一阶差比率;
3.求出方差的参数;(t可以自取)
4.预测;
二、实验平台:
Python 3.7
三、实验内容与结果:
3.1 题目分析
找寻一个自己要预测的数据集,绘制散点图;
计算差分:一阶、二阶、一阶差比率;
一阶差比率为yy=Y(t)/Y(t-1)
求各个模型参数,这里的t我是按照ppt取中间的值为0,然后对称+1,-1.
则有,指数曲线Y=lga+lgb,预测值y=e**Y
3.2 代码
# -*- codeing =utf-8 -*-
# @Time : 2021/4/22 14:28
# @Author : ArLin
# @File : demo1.py
# @Software: PyCharm
import csv
from pylab import *
mpl.rcParams['font.sans-serif'] = ['SimHei']#正常显示汉字
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
#读取csv文件
def ReadCsvFile(path):
File = open(path, 'r')
f = csv.reader(File)
i = 0
data = []
year=[]
for row in f:
if i > 0:#去头处理
data.append(float(row[1]))
year.append(float(row[0]))
i = i + 1
return year,data
#绘制散点图
def draw1(year,data):
ryear=[]
rdata=[]
for index in range(len(year)):
ryear.append(year[index])
rdata.append(data[index])
plt.figure(1)
plt.title("1978-2010中国研究生招生数")
plt.plot(ryear, rdata, '.')
plt.xlabel('指标(年)')
plt.ylabel('研究生招生数(万人)')
plt.show()
return ryear,rdata
def draw2(ryear,rdata):
a1 = []
a2 = []
b = []
for index in range(len(rdata)):
# 一阶差分和一阶比率
if index > 0:
a1.append(rdata[index] - rdata[index - 1])
# 一阶比率
b1 = rdata[index] / rdata[index - 1]
b.append(np.round(b1, 2))
# 二阶差分
for index in range(len(a1)):
if index > 0:
a2.append(a1[index] - a1[index - 1])
plt.figure(2)
plt.plot(a1, '--', label="一阶差分")
plt.plot(a2, ':', label="二阶差分")
plt.plot(b,'r', label="一阶差比率")
plt.legend(["一阶差分", "二阶差分", "一阶差比率"])
plt.show()
#求出方差的参数(取中间值为t,两边对称)
def forecast1(rdata):
t = []
Yt = []
ysum = 0
tyt = 0
tsum = 0
for index in range(len(rdata)):
# 计算和t的平方
t1 = (len(rdata) - 1) / 2 * -1 + index
t.append(t1)
tsum = tsum + t1 * t1
# 计算Yt
yt = math.log(rdata[index])
ysum = ysum + yt
Yt.append(np.round(yt, 2))
# 计算lgb
tyt = tyt + t[index] * yt
# lga
lga = np.round((ysum / len(rdata)), 2)
print('lga的值',lga)
# lgb
lgb = np.round((tyt / tsum), 2)
print('lgb的值',lgb)
print("2021年的研究生招生人数:",e ** (lga + lgb *((len(rdata) - 1) / 2 * -1 + len(rdata)+1)))
return lga,lgb,t
#1978-2010中国研究生招生数(预测值和真实值比较)
def forecast2(year1,data1,lga,lgb,t):
fy=[]
#预测值
for i in t:
z = e ** (lga + lgb * i)
fy.append(np.round(z, 3))
#图1
plt.figure(3)
plt.title("1978-2010中国研究生招生数(预测值和真实值比较)表一")
plt.plot(year1,fy,'r',label="预测值")
plt.plot(year1,data1, '.g',label="真实值")
plt.legend(["预测试", "真实值"])
plt.xlabel('指标(年)')
plt.ylabel('研究生招生数(万人)')
plt.show()
#图二
year2=[]
for i in year1:
year2.append(i+0.3)
plt.figure(4)
plt.title("1978-2010中国研究生招生数(预测值和真实值比较)表二")
plt.bar(year1, fy, width=0.3, color='r',label="预测值")
plt.bar(year2, data1,width=0.3,color='g',label="真实值")
plt.legend(["预测试", "真实值"])
plt.xlabel('指标(年)')
plt.ylabel('研究生招生数(万人)')
plt.show()
#图三
error=[]
for index in range(len(data1)):
error1=data1[index]-fy[index]
if error1<0:
error1=-1*error1
error.append(error1)
plt.figure(5)
plt.title("1978-2010中国研究生招生数(预测值和真实值比较)表三")
plt.bar(year1, error, label="误差值")
plt.legend(["误差值"])
plt.xlabel('指标(年)')
plt.ylabel('研究生招生数(万人)')
plt.show()
3.3结果与分析:
结果截图:
散点图:
我选取的是1978-2020年中国研究生招生数的数据集,通过绘制的散点图,我们可以看出中国研究生招生数大致成指数分布,我们可以大胆的猜测可以使用指数曲线的模型来进行预测。
打印出差分:
通过差分表我们可以看出,一阶差分和二阶差分的波动幅度较大,一阶差比率基本相等,基本在0值附近成一条直线段,这个结果验证了中国研究生招生数成指数分布,我们可以使用指数曲线的模型来进行预测。
预测值:
1978-2010中国研究生招生数(预测值和真实值比较):
散点图:
条形图:
3.4实验总结
出现的问题与解决方法:
问题1:
程序报错:
TypeError: ufunc ‘bitwise_xor’ not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ‘‘safe’’
TypeError:输入类型不支持ufunc“按位\u xor”,并且无法根据强制转换规则“safe”将输入安全地强制为任何受支持的类型
代码行:
forecasty=e^(lga+lgb*1)
解决方法:
经过查询资料后,在python中要表示指数的形式应该为**,而不是^,之后把代码改成forecasty=e**(lga+lgb*1)方式就可通过
问题2:
我打印出来的表格刚开始是这样
非常乱码,而且也看不出来曲线的趋势
解决方法:
经过查询后,我发现我从csv读出来的数据是带‘’,也就是如图以字符串的形式存在
而我们需要把他们转成数据,我使用的是强制转换,如图:
则可以解决图表错乱
问题3:
刚开始我发现我的预测值特别不准,只有12万多,相比2020的110.7万相差的非常多
解决方法:
我先检查了我的代码,确保我的参数和公式是对的,接着我又检查了数据集,确定数据集也没问题后,我发现我的t值取错了
上面的错误预测值是因为我的t取了1这个值,而我前面说过我的t=0是在中间的值,也就是说我要预测2021年应该取t=22这个值
个人总结
本次的数据集要求自己去选取的,我就在国家统计局的官网选取了1978-2020年中国研究生招生数的数据集来进行预测
本次的实验和上次的实验三有类似之处,要对数据进行判断进行分析预测的模型,求出参数,带入预测模型,然后进行预测
使用的知识点基本也都是matplotlib+numpy,不同的是相较于上一次的实验,我这次对于数据的处理比较偏向可视化,用了散点-折线图和条形图来展现结果,这样更加具像。
(努力学习才能变成像罗翔老师一样优秀的人,定下目标后,只要实现就好了。冲冲冲!!!