ARIMA时间序列分析气温变化项目(杂记)
一年后会有同样任务的人看到这篇文章吗……
简介
这其实是一个项目作业,做一个预测一周气温的前后端均有的项目,大概老师只是想让我们尽可能多的学习新的东西吧,所以项目说明以及最后结课时各个小组的完成内容有乱七八糟各种东西:
- 在 Ubuntu 虚拟机上手动搭建 spark/hadoop 计算集群
- 使用 ARIMA 时间序列模型对某地气温数据进行建模,也可以采用其他模型
- socket 传输数据
- 搭建 Flask 微服务
- 使用 Tomcat 服务器
- 使用 Spring MVC 等后端框架,前后端交互
- 使用 Websocket
- 用户管理、部门管理、角色管理、权限管理(这四个好像叫支线任务)
- 数据库
- 部署到云服务器
- DevOps
- ……
当然好像也不一定全用上……不知道老师那里是怎么评分的
初始数据只有一个城市,30年每天的完整数据和10年的残缺数据,也说了这点数据量用Excel就出结果了,所以也提供了更多的一些数据,比如一个总共8G(解压前),40G左右(解压后)的全球气象站数据,只用到了里面的中国的最高温最低温平均温降水量,其他的不清楚
技术可替换,然后我们最后就用了 LSTM时间序列分析+SpringBoot+Shiro+MySQL+Vue,我只负责模型,所以前后端的不是很清楚。
所以我只说一下模型方面的事情。根据结课答辩上看到的,各小组用到的有 ARIMA、SARIMAX、LSTM、Fbpropbet 等模型
提醒
- Google 真好
- 官网的 API 文档真好,即便是英文的,
也能让我感到心潮澎湃阅读起来有时候也比在内容繁杂的博客园啊 CSDN 啊这些地方要轻松 - Ubuntu 虚拟机手动配置spark集群不影响项目进程,不要把时间耗在这里(就算你配置好了最后清洗数据的时候电脑也不一定带的动,还不如直接用Python-pandas或者Spark本地单节点
数据处理
获取到的数据,有气象站编号和站名,CH 开头的是中国的气象站,包不包括港澳台没仔细看,中国的各个气象站名都是近似拼音的单词,为什么说是近似拼音呢,因为 hohhot 指的是呼和浩特,lhasa 指的是拉萨,harbin 是哈尔滨,可能是我孤陋寡闻了吧。。。
或许可以在这里查到中文地名对应的气象站编号,再通过编号去找气象站 https://wenku.baidu.com/view/2c1f92d9ce2f0066f533221b.html
中国气象网也有一个文档 http://data.cma.cn/article/showPDFFile.html?file=/pic/static/doc/A/A.0012.0001/SURF_CHN_MUL_HOR_STATION.pdf
理论部分
没什么说的,还是不清楚如何根据ACF图和PACF图来估计ARIMA中p、q的值
LSTM也只是用Keras很随意的搭了一个双层LSTM+全连接层,理解不深
代码
在这里你可以看到:
- python pandas 的使用
- spark 的 Python API,即 pyspark 的使用
- python statsmodels 的使用,构建ARIMA等模型
- python pmdarima 的使用,有一个auto_ARIMA可以自动选择arima的参数
- Fbpropbet 的安装
Pandas
- 中文文档:https://www.pypandas.cn/docs/
- 读取.csv文件:
df = pandas.read_csv(filename, index_col='column_name', header=None)
,index_col表示把指定列作为DataFrame的index,header设置为None是针对没有表头的csv文件 - 取DataFrame的某行,某列:
df['column_name']
,某列,得到一个Seriesdf[start_index : end_index]
,按行切片,得到DataFramedf.loc[start_index:end_index, column_name/list]
,二维切片,单个列名返回Series,传入列表返回DataFrame- ……
- 修改DataFrame表头:df.columns=列名字符串构成的列表
- 取DataFrame中特定的内容:
df = df[df.column_name=xxx]
,取df中某列为xxx值的所有数据 - 根据某列对齐合并
DataFrame:df = pd.merge(df1, df2, how='outer', on='date')
,将df1和df2按照date列对齐,取并集 - 存储csv:
df.to_csv(filename, index=None)
,index=None表示不保存index - DataFrame转np.array:
df.values
pyspark
- 官方文档:http://spark.apache.org/docs/latest/api/python/index.html
- 读取.csv文件:
df = spark.read.csv(filename)
- 删掉某些列:
df = df.drop('column_1', 'column_2', 'column_3', ...)
- 取特定内容:
df = df.filter("column_1 == 'special'")
- 取特定列:
df = df.select('column_1', 'column_2', 'column_3', ...)
- 修改表头:
df = df.toDF('new_1', 'new_2', 'new_3', ...)
- 某一列统一修改值:
df = df.withColumn('column_1', df2.column_1 / 10)
- 上下合并:
df = df.unionAll(df1)
- pyspark转pandas:
df.toPandas()
statsmodels
-
使用例子:
from statsmodels.tsa.arima_model import ARIMA # 到底用tsa.arima_model还是tsa.arima.model还是api.tsa.ARIMA,不是很清楚 model = ARIMA(data, order=(1, 1, 1)).fit(disp=0) # disp=0 表示不输出构建模型时的一堆log信息 # 预测start到end之间的值,注意如果差分d不为0,predict默认的结果为差分后的结果,不是原始数据,需要把类型设置为levels才能返回原始数据。 # dynamic=False指的是,如果要预测的部分在训练数据内,预测结果会使用训练数据修正,就不是纯粹的“预测”了。 # 如果设为True,那么就是纯粹的预测,只根据start之前的训练数据进行预测。 # 返回一个预测值构成的DataFrame还是Series的 forecasts = model.predict(start=start, end=end, typ='levels', dynamic=True) # 在训练数据范围之外预测predict_num个数据,如果差分d不为0,默认返回也正常 # 返回一个大概是[值,置信度,置信区间]的列表 forecasts = model.forecast(predict_num) # 直接画出结果,训练数据范围之内的会画出真实数据曲线 # 之外的会画出置信区间,没有typ参数,预测出的值正常 model.plot_predict(start=start, end=end, dynamic=True)
pmdarima
-
作者的Github:https://github.com/alkaline-ml/pmdarima
-
使用例子:
import pmdarima as pm model = pm.auto_arima(data) # 这里可以传入更多参数来调节,细节见官方文档 forecasts = model.predict_in_sample(start=start, end=end) # 在训练数据范围内预测 forecasts = model.predict(predict_num) # 在训练数据范围外预测 predict_num 个数据
Windows下安装 Fbprophet
-
conda install -c conda-forge fbprophet
-
如果 import 报错 ERROR:
fbprophet:Importing plotly failed. Interactive plots will not work.
那就 conda install plotly -y
总结
做完了这个学到了什么呢?感觉自己理论没完全理解,模型效果也很差。而且时间序列模型以后可能也不可能再遇到了。硬要说的话,Git/Linux倒是稍微熟悉了一些;如果以后还有数据分析方面的大作业的话,Spark也能熟悉一点;如果以后想了解RNN的应用的话,LSTM也能稍微熟悉一点,大概也仅此而已了