ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于MLP的时间序列预测实战:焦作空气质量数据课程设计模板

基于MLP的时间序列预测实战:焦作空气质量数据课程设计模板 简介这份资源面向计算机、电子信息工程、数学等专业的大学生及算法入门者提供一套可直接运行的MLP时间序列预测完整方案用于课程设计、期末大作业或毕业设计中的预测建模任务。压缩包共3个文件包含1个Python源码文件与2个CSV数据集整体约46KB源码基于Anaconda、PyCharm与TensorFlow环境编写采用参数化编程关键参数可灵活调整且几乎逐行注释便于新手理解网络结构与训练流程。数据集以焦作地区相关时序数据为样例可直接替换为自己的数据开展实验。目前已有569人学习下载适合希望快速跑通MLP预测流程、掌握数据读取、归一化、模型搭建与结果可视化等环节的读者参考也可作为进一步对比LSTM等模型的基线代码。1. 从一份焦作空气质量数据说起MLP 时间序列预测到底能跑出什么手里这份MLP.zip解压出来只有四个文件MLP.py、焦作.csv、焦作全.csv外加一个压缩包本体。第一次看到这种极简配置很多人会下意识觉得是不是缺了训练脚本、配置文件或者模型权重。实际上这正是它适合拿来当课程设计和入门实战的地方——所有逻辑都压在一个 py 文件里数据是现成的焦作地区时间序列环境锁定在 Anaconda PyCharm TensorFlow注释密度接近一行一注小白顺着读就能把前向传播、反向传播、滑动窗口构造这几件事串起来。它解决的问题很具体给定一段按时间排列的单变量序列焦作.csv 是训练段焦作全.csv 是完整段用多层感知机做多步或单步预测把预测曲线和真实曲线画在一张图上对比。适合计算机、电子信息、数学专业做期末大作业、课程设计、毕业设计的同学也适合已经会 Python 但没亲手搭过神经网络预测流程、想找一个能改参数、能换数据、注释看得懂的模板的从业者。下面按资源是什么 → 怎么用 → 坑在哪的顺序拆开讲参数怎么改、报错看哪里都会落到具体位置。2. 拆开 MLP.py滑动窗口、网络结构与参数化设计2.1 为什么时间序列预测要先做滑动窗口MLP 本身不认识时间它只认一个固定长度的输入向量。所以任何用 MLP 做时间序列预测的代码第一步都是把一维序列切成(样本数, 时间步长)的二维矩阵这一步就是滑动窗口。假设原始序列是[x1, x2, x3, x4, x5]时间步长设为 3那第一条样本输入是[x1, x2, x3]标签是x4第二条输入[x2, x3, x4]标签x5。窗口每滑动一格就产出一条样本这就是监督学习意义上的特征-标签对。MLP.py里这一步通常写成两层循环或者用 numpy 的切片拼接参数化设计体现在时间步长是个变量改一个数字就能从用前 3 天预测第 4 天变成用前 7 天预测第 8 天。这也是它比很多硬编码的示例代码强的地方——你不用去动循环体只改顶部参数区。2.2 网络结构输入层、隐藏层、输出层怎么定MLP 做预测的网络结构不复杂但每一层的维度都有讲究。输入层维度等于时间步长输出层维度等于你要预测的步数单步就是 1。隐藏层是唯一需要凭经验调的部分常见做法是一到两层每层神经元数量在 32 到 128 之间试。MLP.py一般用Sequential堆Dense激活函数隐藏层用relu输出层不激活回归任务或者用linear。import numpy as np import pandas as pd import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout # 参数区改这里就能换实验 TIME_STEP 7 # 滑动窗口长度用前7个点预测第8个点 HIDDEN_1 64 # 第一隐藏层神经元数 HIDDEN_2 32 # 第二隐藏层神经元数 EPOCHS 200 # 训练轮数 BATCH_SIZE 16 # 批大小 LR 0.001 # 学习率 # # 读取数据焦作.csv 为训练段 df pd.read_csv(焦作.csv) series df.iloc[:, -1].values.astype(float32) # 取最后一列作为预测目标 # 构造滑动窗口样本 def make_windows(data, step): X, y [], [] for i in range(len(data) - step): X.append(data[i:i step]) y.append(data[i step]) return np.array(X), np.array(y) X, y make_windows(series, TIME_STEP) print(样本形状:, X.shape, 标签形状:, y.shape) # 搭建 MLP model Sequential([ Dense(HIDDEN_1, activationrelu, input_shape(TIME_STEP,)), Dropout(0.2), Dense(HIDDEN_2, activationrelu), Dense(1) # 回归输出不加激活 ]) model.compile(optimizertf.keras.optimizers.Adam(learning_rateLR), lossmse, metrics[mae]) model.summary()这段代码的逻辑说明make_windows是滑动窗口的核心step决定看多长的历史input_shape(TIME_STEP,)必须和窗口长度一致写错会直接报维度不匹配Dropout(0.2)是防过拟合的常见手段数据量小的时候尤其有用输出层Dense(1)不带激活函数因为预测的是连续数值加了sigmoid或softmax反而会把输出压到 0-1 或变成分类。参数说明TIME_STEP越大模型能看到的历史越长但样本数会减少HIDDEN_1/2不是越大越好数据量小的时候神经元太多会过拟合LR默认 0.001 对 Adam 是稳妥起点loss 不降再考虑调小。2.3 训练、预测与反归一化数据如果量纲差异大比如 PM2.5 数值几百温度只有个位数直接喂给网络会让梯度更新偏向大数值特征所以常见做法是先归一化。MLP.py里一般用MinMaxScaler把序列压到 0-1训练完预测出来的结果再反归一化回原始量纲否则画出来的预测曲线和真实曲线根本不在一个数量级上看着像完全预测错了。from sklearn.preprocessing import MinMaxScaler scaler MinMaxScaler(feature_range(0, 1)) series_scaled scaler.fit_transform(series.reshape(-1, 1)).flatten() X, y make_windows(series_scaled, TIME_STEP) # 按 8:2 划分训练集和测试集 split int(len(X) * 0.8) X_train, X_test X[:split], X[split:] y_train, y_test y[:split], y[split:] history model.fit(X_train, y_train, validation_data(X_test, y_test), epochsEPOCHS, batch_sizeBATCH_SIZE, verbose1) # 预测并反归一化 pred model.predict(X_test) pred_inv scaler.inverse_transform(pred.reshape(-1, 1)).flatten() y_test_inv scaler.inverse_transform(y_test.reshape(-1, 1)).flatten()逻辑说明fit_transform只在训练段上做测试段用同一个 scaler 的transform这是避免数据泄露的关键validation_data直接拿测试集当验证集在入门代码里很常见严格来说应该再切一份验证集但课程设计级别够用。参数说明split比例 0.8 是经验值序列有明显趋势时不要随机打乱时间序列必须按顺序切。反归一化时reshape(-1, 1)不能省scaler 要求二维输入。3. 环境搭建与跑通流程Anaconda、PyCharm、TensorFlow 版本对齐3.1 环境准备为什么推荐 Anaconda 而不是裸 pip摘要里写的是 Anaconda PyCharm TensorFlow这个组合不是随便定的。TensorFlow 对 Python 版本、numpy 版本、protobuf 版本都有隐性依赖裸 pip 装经常出现numpy版本冲突或者ImportError: DLL load failed。Anaconda 用 conda 管理环境能把 Python 解释器和这些底层库锁在一个虚拟环境里出问题直接删环境重建不用去系统 Python 里翻残留。常见做法是建一个独立环境Python 版本选 3.8 或 3.9TensorFlow 2.x 对这两个版本支持最稳然后在这个环境里装 TensorFlow。不要用最新的 Python 3.12 去装老版本 TensorFlow大概率找不到对应 wheel。# 创建独立环境指定 Python 版本 conda create -n mlp_ts python3.8 -y conda activate mlp_ts # 安装 TensorFlow 和依赖 pip install tensorflow2.10.0 pip install pandas numpy scikit-learn matplotlib # 验证安装 python -c import tensorflow as tf; print(tf.__version__)逻辑说明conda create -n mlp_ts建了一个叫 mlp_ts 的隔离环境后面所有安装都只影响这个环境tensorflow2.10.0是 2.x 里对 Windows 和 CUDA 兼容性较好的一个版本如果你机器没有 NVIDIA 显卡装 CPU 版即可pip 默认就是 CPU 版。参数说明Python 3.8 是下限3.9 也可以3.10 以上部分 TensorFlow 版本没有预编译包。验证那行能打印出版本号说明环境通了。3.2 PyCharm 里配置解释器与运行PyCharm 新建项目后最容易翻车的地方是解释器没选对——项目用的还是系统 Python结果import tensorflow报找不到模块。正确做法是在File → Settings → Project → Python Interpreter里把解释器指向刚才 conda 环境下的python.exeWindows 一般在Anaconda安装目录/envs/mlp_ts/python.exe。配置好之后把MLP.py、焦作.csv、焦作全.csv放在同一个目录下直接右键 Run。如果代码里用的是相对路径读 csv工作目录必须是脚本所在目录否则会报FileNotFoundError。PyCharm 默认工作目录是项目根目录脚本如果放在子文件夹里要么改路径要么在 Run Configuration 里把 Working directory 设成脚本目录。3.3 数据文件的分工焦作.csv 和焦作全.csv 各干什么两个 csv 不是重复文件。焦作.csv通常是截取的一段用于训练和测试焦作全.csv是完整序列用来做最终的全段预测或者画完整对比图。常见做法是先用焦作.csv调通流程、调好参数再用焦作全.csv跑一遍完整预测看模型在更长序列上的表现。如果你只有一份数据把焦作全.csv按时间切前 80% 当训练、后 20% 当测试也能跑但要注意切分点不能随机。文件作用使用阶段MLP.py主程序含参数区、滑动窗口、建模、训练、绘图全程焦作.csv训练/测试用序列段调参、验证流程焦作全.csv完整序列最终预测、完整曲线对比提示换自己的数据时只要保证 csv 最后一列是数值型预测目标把文件名改掉即可滑动窗口和建模部分不用动。4. 避坑与排查跑不起来、loss 不降、预测一条直线4.1 报错 ImportError: DLL load failed现象在 PyCharm 里运行import tensorflow直接抛ImportError: DLL load failed while importing _pywrap_tensorflow_internal。原因TensorFlow 依赖的 Visual C 运行库缺失或者 numpy、protobuf 版本和 TensorFlow 不匹配。解决先装 Microsoft Visual C Redistributable然后在 conda 环境里执行pip install --upgrade numpy protobuf还不行就重建环境按 3.1 的版本组合重装。血泪经验是不要在 base 环境里反复 pip 卸载重装越搞越乱。4.2 loss 一直不降或者变成 nan现象训练几十轮loss 停在某个值不动或者直接变 nan。原因通常有三个学习率太大、数据没归一化、序列里有空值或异常值。解决先把LR从 0.001 降到 0.0001 试确认归一化那步没被注释掉用df.isnull().sum()检查空值有的话用df.fillna(methodffill)前向填充。如果原始数据里有极端离群点MinMaxScaler 会被拉偏可以先做一次简单的 3σ 截断。4.3 预测结果是一条直线现象画出来的预测曲线几乎是水平线和真实曲线完全不贴合。原因模型没学到东西常见于时间步长太短比如TIME_STEP1、隐藏层太小、或者训练轮数不够。解决把TIME_STEP调到 7 或 14隐藏层加到 64/32EPOCHS提到 200 以上。另一个容易被忽略的原因是输出层加了激活函数回归任务输出层必须线性检查Dense(1)后面有没有误加activation。4.4 反归一化后数值对不上现象预测值反归一化后和真实值差了一个数量级。原因训练时用了fit_transform预测时又对测试数据重新fit_transform了一遍导致 scaler 的 min/max 不一致。解决scaler 只在训练段 fit 一次测试段和预测结果都用同一个 scaler 的transform和inverse_transform。这个坑很隐蔽因为代码不报错只是结果悄悄错了。4.5 换数据后维度报错现象换成自己的 csv 后报ValueError: Input 0 of layer sequential is incompatible。原因新数据的列选取逻辑和原来不一样df.iloc[:, -1]取到的不是你想预测的那一列或者序列长度小于TIME_STEP导致样本数为负。解决打印series.shape确认长度确认TIME_STEP小于序列长度明确指定目标列名而不是用-1兜底。5. 进阶把单步预测改成多步、用焦作全.csv 做完整验证单步预测只能看下一步实际做课程设计或报告时多步预测一次输出未来 N 个点更能体现工作量。改法不复杂把标签从单个值改成一段窗口输出层维度从 1 改成 N。下面这段是在原结构上的最小改动。# 多步预测用前 TIME_STEP 个点预测未来 PRED_STEP 个点 PRED_STEP 3 def make_windows_multi(data, step, pred_step): X, y [], [] for i in range(len(data) - step - pred_step 1): X.append(data[i:i step]) y.append(data[i step:i step pred_step]) return np.array(X), np.array(y) X, y make_windows_multi(series_scaled, TIME_STEP, PRED_STEP) # 输出层改成 PRED_STEP 维 model Sequential([ Dense(64, activationrelu, input_shape(TIME_STEP,)), Dense(32, activationrelu), Dense(PRED_STEP) # 一次输出未来 PRED_STEP 个点 ]) model.compile(optimizeradam, lossmse)逻辑说明make_windows_multi的标签从标量变成向量循环上界要减去pred_step再 1否则最后几条样本会越界输出层维度必须等于PRED_STEP否则训练时形状对不上。参数说明PRED_STEP越大预测难度越高误差会累积一般 3 到 7 步是比较现实的范围再长建议换 LSTM 或 Transformer 类结构。验证方法上我一般会做两件事一是把预测曲线和真实曲线画在同一张图上肉眼看趋势是否贴合二是算 MAE 和 RMSE和直接用上一个点当预测值的朴素基线比如果模型还不如朴素基线说明参数或结构有问题。用焦作全.csv跑完整序列时注意训练段和预测段的 scaler 要统一否则整条曲线会在拼接处出现跳变。从那以后我每次拿到这种单文件预测模板都会先跑一遍原始数据确认能出图再换自己的数据最后才动网络结构——顺序反了出了问题根本分不清是数据、环境还是模型的锅。希望帮到你。本文还有配套的精品资源点击获取
返回列表