尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

新能源汽车销量预测实战:SARIMA-LSTM混合模型与Python源码解析

发布时间:2026/9/24 23:12:15

资讯中心
01
ARTICLE

新能源汽车销量预测实战:SARIMA-LSTM混合模型与Python源码解析

新能源汽车销量预测实战:SARIMA-LSTM混合模型与Python源码解析
简介这份资源是面向数据分析初学者与新能源汽车行业研究者的Python实战项目源码围绕全国新能源汽车销售数据展开帮助读者掌握从数据获取到建模对比的完整分析流程。压缩包共34个文件、约1.15MB包含10个Python源码文件、10张可视化图表、5个XML配置、4个Excel数据表及CSV、TXT等辅助文件其中源码覆盖爬虫获取、日期处理、逻辑回归、KNN、随机森林、AdaBoost、SARIMA及SarimaLstm对比实验等模块图表则对应各模型的预测效果与销量趋势。项目以真实销量数据为支撑读者可据此复现数据清洗、特征工程、模型训练与结果评估的全过程并借助多算法横向对比理解各自适用场景同时参考配置文件与目录组织方式快速搭建自己的分析工程。目前已有619人学习适合作为课程设计、毕业设计或行业数据分析入门的参考案例。1. 从一份 32 个文件的源码包说起新能源销量数据到底怎么跑通去年帮一个做车企市场分析的朋友看数据他手里有 2023 全年到 2024 年 8 月的电动车销量表想预测下个季度走势结果卡在三个地方Excel 打开就卡、SARIMA 参数不会调、LSTM 训练完不知道准不准。后来我翻到这份「基于新能源汽车数据分析的 Python 设计源码」32 个文件10 个 Python 脚本、4 个 Excel 数据表、10 张结果图从爬虫取数到 SARIMA-LSTM 混合预测全链路都齐了。它不是那种只丢一个main.py的玩具项目而是把对比实验、参数文件、可视化结果都摊开给你看的实战包。如果你正在做新能源汽车销量分析、时间序列预测或者想找一个能直接改参数跑起来的数据分析项目这份源码值得拆开看一遍。下面我按「数据怎么进 → 模型怎么跑 → 坑在哪」的顺序把这份包里的东西讲透。2. 数据层拆解爬虫脚本、Excel 表与 date_process 的配合2.1 数据获取-爬虫.py 到底抓了什么这份包里第一个要看的不是模型是数据获取-爬虫.py。新能源汽车销量数据不像股票有现成 API常见做法是从公开销量榜单页面抓月度数据。这个脚本的定位就是「把网页上的销量表变成结构化数据」输出成 Excel 供后面模型用。# 数据获取-爬虫.py 核心逻辑按常见实现还原 import requests from bs4 import BeautifulSoup import pandas as pd def fetch_sales_data(url, month): headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) } resp requests.get(url, headersheaders, timeout10) resp.encoding utf-8 soup BeautifulSoup(resp.text, html.parser) rows [] for tr in soup.select(table tbody tr): tds tr.find_all(td) if len(tds) 4: continue rows.append({ 车型: tds[0].get_text(stripTrue), 销量: int(tds[1].get_text(stripTrue).replace(,, )), 月份: month }) return pd.DataFrame(rows) if __name__ __main__: df fetch_sales_data(https://example.com/sales, 2024-08) df.to_excel(20240801-20240831之间的电动车销量新.xlsx, indexFalse)逻辑说明requests拿页面BeautifulSoup解析表格tds[1]取销量列并去掉千分位逗号转 int。参数上timeout10防止页面卡死encodingutf-8避免中文乱码。这里最容易翻车的是目标页面用了 JS 动态渲染requests拿到的 HTML 里根本没有表格数据这时候要么换接口要么上 Selenium别硬刚。2.2 四张 Excel 表的时间跨度与用途区分包里 4 个 Excel 不是随便放的时间跨度明显分了三层文件名时间范围典型用途20230101-20231231之间的电动车销量.xlsx2023 全年年度趋势基线20230101-20231231之间的电动车销量新.xlsx2023 全年清洗后建模输入20240801-20240831之间的电动车销量新.xlsx2024 年 8 月单月短期验证20190901-20240901之间的电动车销量新.xlsx2019.9–2024.9 五年长周期训练带「新」字的通常是清洗过缺失值、统一了车型名称的版本。做时间序列时五年那张表才是主力2023 全年那张适合做年度对比。注意别把单月表直接丢进 SARIMA样本量不够季节性项根本估不出来。2.3 date_process.py 做的三件事date_process.py是数据层的胶水脚本一般干三件事把「2023年1月」这种中文月份转成2023-01标准格式、按月份排序、补齐缺失月份。常见写法# date_process.py 关键处理 import pandas as pd df pd.read_excel(20190901-20240901之间的电动车销量新.xlsx) df[月份] pd.to_datetime(df[月份], format%Y-%m) df df.sort_values(月份).reset_index(dropTrue) # 补齐缺失月份销量填 0 或前值填充 full_range pd.date_range(df[月份].min(), df[月份].max(), freqMS) df df.set_index(月份).reindex(full_range).rename_axis(月份).reset_index() df[销量] df[销量].fillna(methodffill)参数说明freqMS是月初频率和销量按月统计对齐ffill用前一个月值填充比填 0 更合理因为销量不会突然归零。这一步不做后面 SARIMA 会因为时间索引不连续直接报错属于血泪经验级别的坑。3. 模型层实战SARIMA、LSTM 与四种对比实验怎么跑3.1 对比试验-SARIMA.py 的参数怎么定对比试验-SARIMA.py和对比试验-SarimaLstm.py是两个不同脚本前者纯 SARIMA后者是混合模型。SARIMA 的核心是(p,d,q)(P,D,Q,s)七个参数s 是季节周期月度数据取 12。# 对比试验-SARIMA.py 建模片段 import pandas as pd from statsmodels.tsa.statespace.sarimax import SARIMAX df pd.read_excel(20190901-20240901之间的电动车销量新.xlsx, parse_dates[月份]) series df.set_index(月份)[销量] model SARIMAX( series, order(1, 1, 1), # 非季节项 p,d,q seasonal_order(1, 1, 1, 12), # 季节项 P,D,Q,s enforce_stationarityFalse, enforce_invertibilityFalse ) result model.fit(dispFalse) print(result.summary()) forecast result.get_forecast(steps6) print(forecast.predicted_mean)逻辑说明d1表示做一阶差分让序列平稳D1是季节差分。enforce_stationarityFalse在数据本身不够平稳时能避免报错但代价是结果可能不可信所以跑完一定要看summary()里的 AIC 和残差检验。参数怎么改先用 ADF 检验定 d再看 ACF/PACF 图定 p、q别一上来就(1,1,1)硬套这是新手最容易踩的玄学坑。3.2 SarimaLstm 混合模型的拼接思路对比试验-SarimaLstm.py的思路是SARIMA 抓线性趋势和季节性LSTM 抓残差里的非线性部分最后相加。这是新能源销量预测里比较常见的组合因为销量既有明显季节性年底冲量又有政策驱动的突变。# 对比试验-SarimaLstm.py 混合逻辑 from statsmodels.tsa.statespace.sarimax import SARIMAX from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense import numpy as np # 第一步SARIMA 拟合 sarima SARIMAX(series, order(1,1,1), seasonal_order(1,1,1,12)).fit(dispFalse) linear_part sarima.fittedvalues residual series - linear_part # 第二步LSTM 学残差 def make_dataset(data, lookback3): X, y [], [] for i in range(len(data) - lookback): X.append(data[i:ilookback]) y.append(data[ilookback]) return np.array(X), np.array(y) X, y make_dataset(residual.values) X X.reshape((X.shape[0], X.shape[1], 1)) model Sequential([ LSTM(32, activationrelu, input_shape(3, 1)), Dense(1) ]) model.compile(optimizeradam, lossmse) model.fit(X, y, epochs50, batch_size4, verbose0) # 第三步预测相加 sarima_pred sarima.get_forecast(steps6).predicted_mean.values lstm_pred model.predict(X[-1].reshape(1,3,1)).flatten() final sarima_pred lstm_pred[0]参数说明lookback3表示用前 3 个月残差预测下一个月样本少时别设太大LSTM(32)是隐藏单元数数据量小的话 16–32 够用设 128 直接过拟合。拼接时注意 SARIMA 预测和 LSTM 预测的时间对齐错位一个月结果就全废。3.3 四种对比实验脚本的差异包里除了 SARIMA 和 SarimaLstm还有对比实验-随机森林.py、对比实验-AdaBoost.py、对比实验-逻辑回归.py、对比实验-knn.py。这四个是机器学习基线用来和时序模型对比。脚本模型类型输入特征适用场景对比实验-随机森林.py集成树月份、车型、历史销量特征多的分类/回归对比实验-AdaBoost.py提升树同上小样本提升对比实验-逻辑回归.py线性分类销量分档涨跌二分类对比实验-knn.py近邻归一化销量相似月份匹配注意逻辑回归和 KNN 在这里多半是把销量预测转成「涨/跌」分类问题不是直接回归。跑之前要确认标签怎么构造否则准确率看着高其实是类别不平衡导致的假象。3.4 数据分析.py 与 metra.py 的分工数据分析.py是主入口负责读表、调date_process、跑各模型、输出图表。metra.py从命名看是评估脚本常见做法是算 MAE、RMSE、MAPE 三个指标。# metra.py 评估指标 import numpy as np def evaluate(y_true, y_pred): mae np.mean(np.abs(y_true - y_pred)) rmse np.sqrt(np.mean((y_true - y_pred) ** 2)) mape np.mean(np.abs((y_true - y_pred) / y_true)) * 100 return {MAE: mae, RMSE: rmse, MAPE: mape}参数说明MAPE 在销量接近 0 时会爆炸新能源早期月份销量低建议同时看 MAE。别只盯一个指标这是对比实验最容易自欺的地方。4. 避坑与排查跑这份源码最容易翻车的五个地方4.1 现象SARIMA 报「数组索引越界」→ 原因时间索引不连续 → 解决先跑 date_process很多人直接read_excel就丢给 SARIMAX结果报IndexError。原因是 Excel 里月份有跳月statsmodels 要求时间索引严格等间隔。解决就是先过一遍date_process.py的reindex把缺失月份补上再建模。4.2 现象LSTM 损失不下降 → 原因销量没归一化 → 解决MinMaxScaler 到 0–1销量动辄几万辆直接喂 LSTM梯度直接炸。常见做法是先MinMaxScaler缩到 0–1预测完再inverse_transform还原。别忘了还原否则你拿到的预测值是 0.3 这种小数根本没法用。4.3 现象中文图表全是方框 → 原因matplotlib 没配中文字体 → 解决指定 SimHeiimport matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] FalseLinux 上没有 SimHei 就换WenQuanYi Micro Hei或者把字体文件路径写死。这个坑不解决10 张 PNG 全是乱码白跑。4.4 现象随机森林准确率 99% → 原因特征泄漏 → 解决检查是否把未来销量当特征对比实验里最容易出的问题是把「下月销量」不小心当成输入特征。构造特征时只能用当前及历史月份shift(-1)这种操作要反复确认方向。看到异常高的准确率先怀疑泄漏别急着高兴。4.5 现象Excel 读取报编码错误 → 原因xlsx 与 xls 混用 → 解决统一用 openpyxl 引擎df pd.read_excel(xxx.xlsx, engineopenpyxl)包里都是 xlsx但如果你自己替换成 xlsxlrd新版本不支持会直接报错。统一engineopenpyxl最省事。5. 进阶技巧把对比实验做成可复现的评估流水线跑通单个脚本只是第一步真正有价值的是把六个模型放进同一条评估流水线用同一份测试集、同一套指标对比。我一般会写一个run_all.py把各模型的预测结果收集起来输出一张对比表加一张折线图。# run_all.py 统一评估 import pandas as pd from metra import evaluate results {} # 假设各脚本已把预测存成 csv for name in [SARIMA, SarimaLstm, RF, AdaBoost, LR, KNN]: pred pd.read_csv(fpred_{name}.csv) results[name] evaluate(pred[y_true], pred[y_pred]) df pd.DataFrame(results).T df.to_csv(model_compare.csv) print(df.sort_values(MAPE))参数说明测试集建议固定为最后 6 个月训练集用前面全部这样六个模型可比。sort_values(MAPE)直接看谁最稳。注意 SARIMA 类模型和机器学习模型的输入窗口不同对齐测试集时以月份为准别按行号切。还有一个技巧把对比试验-SarimaLstm.py里的lookback和 LSTM 单元数做成命令行参数用argparse传进去这样调参不用改代码。import argparse parser argparse.ArgumentParser() parser.add_argument(--lookback, typeint, default3) parser.add_argument(--units, typeint, default32) args parser.parse_args()这样你可以批量跑lookback2,3,4和units16,32,64的组合看哪组 MAPE 最低。我自己的习惯是每次改完参数先跑一遍metra.py存指标再画图绝不凭感觉说「这个模型更好」。从那以后我每次做时序对比都强制先固定测试集再动模型不然调着调着就忘了基线在哪。希望这份拆解帮到你源码包里的脚本按上面顺序过一遍基本能跑出和 PNG 里一致的结果。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。