ARTICLE DETAIL

资讯详情

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

图深度学习驱动产业链价格预测:从聚丙烯图建模到LSTM融合实践

图深度学习驱动产业链价格预测:从聚丙烯图建模到LSTM融合实践 简介研究聚焦产业链上大宗商品价格间的非线性关联与上下游联动效应突破经典预测算法的局限提出一种基于图深度学习的大宗商品价格预测方法。该论文将产品现货价格、期货价格、产量等作为节点属性以产品结构熵量化上下游关系作为边属性并将CCPI、PPI纳入全局属性实现对全产业链产品的价格预测。实验表明与单变量LSTM、多变量LSTM模型相比图深度学习模型取得了更高准确度为大宗商品价格预测提供了新思路。资源为PDF格式共1个文件大小2.21MB属于深度学习、数据分析及数据研究领域可作为相关研究的参考文献与专业指导材料。已有201人浏览学习适合从事量化分析、产业链价格预测及图神经网络应用的科研人员与学习者下载参考。1. 图深度学习做价格预测产业链联动比单品种序列更有信息量做大宗商品价格预测的人迟早会遇到同一个瓶颈单看一个品种的历史价格模型再花哨也预测不准拐点。原油涨了甲醇为什么跟着动丙烯价格下来了聚丙烯和下游的BOPP、CPP为什么滞后几天才反应这种产业链上下游之间的非线性联动普通时间序列模型是看不见的。这篇论文做的事情就是把聚丙烯产业链抽象成一张有向图——产品是节点、生产依赖关系是边、现货价格期货价格是节点属性、CCPI和PPI是全局属性——然后用图网络的传播机制做整条链的价格预测。适合正在做量化基本面研究、产业链价格监测或者想给LSTM加结构信息的人读。它的核心结论也很直接在产业链信息充分的场景下图深度学习比单变量LSTM和多变量LSTM准确度更高尤其在下游产品上优势明显。2. 把产业链变成一张有向无权图节点、边、全局属性三件套2.1 为什么选聚丙烯产业链生产依赖关系才是图结构的根基论文里有一个很关键的选型判断传统农副产品和基础原材料无法依据生产依赖关系建立完备的网络而化工产品之间存在直接或间接的生产关系天然构成图结构。聚丙烯产业链被选中的原因是它横跨三大能源原材料——原油、天然气、煤炭——下游又牵扯BOPP、CPP、PP注塑这类应用广泛的成品产业链完整程度高价格联动的传导路径清晰适合作为图建模的研究对象。这个选型逻辑对实际做项目的人很有参考价值。很多人一上来就想把所有大宗商品都塞进一张图里结果上下游关系理不清边属性全靠拍脑袋。论文的处理方式是只取一条产业链以生产依赖关系为连边依据构建有向无权图图中的有向语义是原材料指向产品成本压力沿箭头方向向下游传导。这样整张图的结构是干净的更新函数学习到的也是真实的产业逻辑而不是数据挖掘硬凑出来的伪相关。2.2 节点属性怎么定不只是价格还要带市场信息节点属性不是简单地放一个现货价格进去。论文从wind数据库里为不同节点选取了各自的属性组合核心思路是现货价格必选再按品种特征附加期货收盘价、产量、消费量、库存、对外依存度这些市场份额类信息。比如原油节点用的是现货价格、期货收盘价、库存环比、运输指数天然气节点有对外依存度煤炭节点有产量和消费量而到了下游的聚丙烯节点则多了聚丙烯指数和产量。这种属性设计的颗粒度差异是有意为之的。上游能源品受库存、运输、依存度影响大下游加工品更看重产量和指数类指标。如果你的复现项目里也涉及多品种建模这一步不建议省——不同节点的属性维度未必相同强行统一反而丢信息。论文里BOPP和CPP节点只有现货价格结果后文会看到这类信息缺失节点在价格波动时表现偏弱这本身就说明节点属性丰富程度直接影响预测上限。2.3 边属性用结构熵量化关系存在只是第一步权重同样重要边属性是这篇论文区别于普通图神经网络实现的地方。产业链网络被抽象为有权无权图中的无权图边本身不直接携带权重数值但论文引入了网络结构熵作为边属性用节点度分布来量化节点在网络中的重要性。计算公式为import numpy as np def structure_entropy(adj_matrix): 计算网络中各节点的结构熵作为边属性输入 adj_matrix: 邻接矩阵adj[i][j] 1 表示 i - j 有生产依赖关系 in_degree adj_matrix.sum(axis0) # 入度作为原材料的次数 out_degree adj_matrix.sum(axis1) # 出度作为产品被消耗的次数 total in_degree.sum() out_degree.sum() entropy {} for i in range(adj_matrix.shape[0]): # 合并入度和出度形成节点i的度分布 degree_dist np.array([in_degree[i], out_degree[i]]) / total degree_dist degree_dist[degree_dist 0] # 剔除零概率避免 log(0) entropy[i] -np.sum(degree_dist * np.log2(degree_dist)) return entropy结构熵衡量的是节点度数分布的均匀性或集中程度。度数分布越均匀熵值越大说明这个节点在网络中的连接越分散反之熵值越小说明节点连接高度集中。把每个节点的结构熵作为边属性送入LSTM更新相当于让模型在每个时间步重新思考当前这个节点在上游供应和下游消耗中的结构位置是否发生了变化。从实现角度来说邻接矩阵要根据产业链关系手工构建一次——原油既是天然气的上游也是甲醇的上游单向箭头只从原材料指向产品这个方向性在构建邻接矩阵时最容易出错。2.4 全局属性CCPI/PPI给每一轮更新一个宏观背景只看产业链内部的信息还不够整条链的价格同时受宏观环境影响。论文把中国大宗商品指数和生产者价格指数作为全局属性在每一时间步都输入给更新函数让模型知道当前处于什么样的价格环境。这个设计在图网络框架里非常自然全局属性是图的系统级特征它不像节点属性那样单独作用于某个产品而是通过更新函数影响所有节点的计算。全局属性和节点属性的协同方式值得留意。三个LSTM更新函数中第一个专门负责把全局属性推到下一时刻得到更新后的CCPI和PPI后再参与节点更新。这样宏观变量不是静态贴在图上而是先经过LSTM做时间演化再被节点模块消费——全局属性的时序变化也被建模进去了。3. GN模块内部三个LSTM各自负责什么3.1 图网络更新的三步走边、节点、全局的先后顺序不能乱图网络模块的内部结构是这篇论文方法部分的核心。整个GN模块基于图网络框架设计包含三个更新函数和三个聚合函数执行顺序是固定的先用边信息、节点信息和全局信息生成新的边信息再用新的边信息更新节点信息最后用新的节点和边信息更新全局信息。论文里的算法步骤对应到价格预测场景就是先更新结构熵再更新全局属性最后把两类结果连同节点属性一起送入节点更新函数输出下一时刻的现货价格。这个顺序为什么要这么设计因为节点状态的更新需要融合边和全局两个层面的最新信息。如果先更新节点再更新边节点就没有机会看到结构熵的变化。价格联动效应中上游某个产品的产量波动会改变产业链网络的结构位置这种变化理应反映在后续的节点价格预测中。3.2 全局LSTM把CCPI和PPI先推到t加1时刻# 全局属性更新为每个节点生成 t1 时刻的 CCPII/PPI # lstm_global 对应论文中的 LSTM1 global_ccpi scaler.fit_transform(ccpi.reshape(-1, 1)) global_ppi scaler.fit_transform(ppi.reshape(-1, 1)) X_global np.hstack([global_ccpi, global_ppi]) # (n_timesteps, 2) lstm_global Sequential([ LSTM(8, activationtanh, return_sequencesFalse), Dropout(0.1), Dense(2) # 输出 t1 时刻的 CCIP 和 PPI ]) lstm_global.compile(optimizerAdam(learning_rate0.001), lossmae) # 训练用 X_global[:-1] - X_global[1:]预测时输入 t 时刻值即得 t1 更新值全局更新函数输入的是当前时刻CCPI和PPI两个宏观指标输出是下一时刻的预测值。LSTM的隐层维度论文没有明确给但根据Keras框架和输入规模判断小尺寸LSTM足够——全局属性只有两个维度不需要过大的隐层容量。Dropout设为0.1激活函数tanh这些参数在三个LSTM中保持一致。训练时用的是MAE损失加Adam优化器学习率0.001。一个容易忽略的实现细节是全局属性更新是对每个节点单独做的最终每个节点都会拿到一组更新的CCPI和PPI。虽然宏观指标是全市场共享的但每个节点的LSTM1参数独立训练相当于允许不同产品对宏观环境的敏感度不同——原油和PP注塑对通胀指标的响应曲线本来就不一样。3.3 边LSTM结构熵的演化同样需要建模边属性是每个节点的结构熵在时间维度上也会变化。随着产业链上的产量、库存、新产能投放节点的入度和出度分布会改变结构熵值随之更新。边LSTM做的事情就是根据历史结构熵序列预测下一时刻的结构熵值作为t加1时刻边属性的输入。# 局部数据准备假设已按产业链顺序构建邻接矩阵 # entropy_seq 形状 (n_nodes, n_timesteps)每个节点一条结构熵时间序列 def build_edge_sequences(entropy_seq, timestep1): X, y [], [] for node_idx in range(entropy_seq.shape[0]): series entropy_seq[node_idx] X.append(series[:-1].reshape(timestep, 1)) y.append(series[1:].reshape(timestep, 1)) return np.array(X), np.array(y)这里所有节点的边属性序列统一放入同一个LSTM2中训练没有为每个节点单独建模型。这种做法的好处是参数共享结构熵的时序模式在所有节点上是通用的——不管节点在产业链的哪个位置熵值的变化规律都有相似性。从论文表1可以看出所有节点的边属性都统一标注为结构熵印证了这是全网络共享的边更新模块。复现时建议先验证结构熵序列是否具有明显时序模式。如果产业链结构在样本期内基本稳定结构熵值变化很小那么边LSTM学到的可能只是一个常数级别的映射。这种情况不一定是坏事——更新值稳定意味着边属性在t加1时刻的输入不会引入额外噪声模型可以专心学习价格联动。3.4 节点LSTM三类信息融合输出现货价格节点更新是整个模型最重的计算环节。LSTM3的输入是当前时刻的节点属性现货价、期货价、产量等加上更新后的边属性和全局属性输出t加1时刻的现货价格。# 三个 LSTM 的协同流程对应论文算法步骤 2-5 # 假设已加载并归一化各节点的节点属性 node_feat、边属性 edge_feat、全局属性 glob_feat # 全局 module 更新 glob_next lstm_global.predict(glob_feat[t]) # (n_nodes, 2) # 边 module 更新 edge_next lstm_edge.predict(edge_feat[t]) # (n_nodes, 1) # 节点 module拼接三类输入 combined_input np.concatenate( [node_feat[t], edge_next, glob_next], axis1) # (n_nodes, node_dim12) price_pred lstm_node.predict(combined_input) # (n_nodes, 1)即 t1 现货价这个流程最关键的一点是三个LSTM不是并联关系而是串联先算全局和边再算节点。如果改成三路并联同时输入节点模块就丢失了边属性和全局属性经过时间演化后的信息增益。论文在步骤2和3中先用LSTM1和LSTM2分别做全局和边的更新步骤4才把更新结果送入LSTM3顺序上刻意区分了时序依赖。node_dim维度由节点属性数量决定。原油有4个属性现货、期货、库存、运输聚丙烯有4个现货、期货、指数、产量而CPP只有1个现货。拼接后每个节点的实际输入维度不一致Keras里需要按节点分组喂数据或者用Masking层处理。更稳妥的做法是把属性对齐到统一维度缺失位置填0再让Dropout层参与去噪。4. 实验配置与参数细节从wind数据到可复现的LSTM参数4.1 数据范围与训练测试切分51个月训练、8个月测试的合理性论文用的是wind数据库里2014年1月到2018年12月的月度数据共60个月。训练集取2014年1月到2018年3月的51个月测试集是2018年4月到11月的8个月。这个切分比例接近85%训练、15%测试对月频时间序列来说是常规操作。月度数据意味着样本量不大LSTM在这种数据规模下容易过拟合这也是论文把Dropout设到0.1而不是0的核心原因。另一个细节是timestep设为1即每个节点每轮只输入一个时间步的状态——这在LSTM中相当于用当前状态预测下一时刻不构造多步窗口。对月度金融序列来说多步窗口的历史信息已经被LSTM的隐状态承载了强制加长窗口反而稀释训练样本。需要留意的是训练集和测试集之间存在一个生存偏差风险——2018年4月到11月恰好是化工品价格波动较大的区间如果测试集选取在剧烈波动期图模型的优势会被放大。论文在结果分析中也提到波动剧烈时预测准确度明显下降这算是诚实的局限性披露。4.2 min-max归一化为什么这里不用标准化论文用min-max归一化把原始数据线性变换到0到1区间公式是X等于(x减x_min)除以(x_max减x_min)。选择min-max而不是Z-score标准化的原因在于LSTM的输出层使用了数值回放——预测值需要还原到原始价格尺度min-max在反变换时只需要记录每列的max和min还原计算直接可逆而标准化反变换还需要保存均值和标准差逻辑上多一层。def minmax_scale(series): min-max 归一化返回归一化后的序列及反变换参数 min_val, max_val series.min(), series.max() scaled (series - min_val) / (max_val - min_val) return scaled, {min: min_val, max: max_val} def minmax_inverse(scaled, params): 反变换归一化值还原到原始价格尺度 return scaled * (params[max] - params[min]) params[min]归一化是按每个节点的属性列独立做的不是全图统一缩放。原因很简单原油期货价格和CPP现货价格量级差几十倍统一缩放会把低价格节点的波动压缩到几乎不可见模型会天然偏向高价节点。按列独立缩放保证了每个属性在0到1区间内的波动幅度都被完整保留。训练完成后预测值经过minmax_inverse还原输出的就是真实量纲的价格预测。4.3 LSTM参数表三个模型的统一与区别论文在表2里给出了三组对比实验的LSTM参数。单变量LSTM、多变量LSTM、图深度学习三者的共同点是激活函数tanh、timestep为1、batch_size为1、目标函数MAE、优化函数Adam、学习率0.001。区别只有一个维度单变量LSTM和畲变量LSTM的Dropout为0epochs分别为200和250图深度学习的Dropout为0.1epochs为200。batch_size设为1在时间序列预测里是常见做法——月度数据样本量小全批量训练容易陷入局部极小单样本更新让梯度噪声帮助跳出鞍点。Dropout设0.1是图模型特有的因为图模型的输入维度比单变量模型高不少节点属性拼接了边属性和全局属性过拟合风险更大加一层轻量Dropout把冗余连接随机断掉。复现时可以直接复用这组参数。唯一要按数据规模调整的是LSTM隐层单元数论文没有给出具体数值常见做法是设置为输入维度的2到4倍比如节点属性加边和全局属性后共7维输入隐层设16到32个单元之间。4.4 三组对比实验的设置逻辑单变量、多变量、图模型的递进对照实验设计得很干净。单变量LSTM只输入产品现货价格多变量LSTM输入产品的多个属性值图深度学习在此基础上加入边属性和全局属性。三者的差异逐层递进单变量看基线多变量证明加入自身市场特征有用图模型进一步证明产业链结构信息和宏观信息有用。# 三组实验的输入输出结构对比 def build_inputs(features, model_type, node_attrsNone, edge_attrsNone, glob_attrsNone): if model_type univariate: X features[:, [0]] # 只取现货价格列 elif model_type multivariate: X features # 取节点全部属性列 elif model_type graph: # 节点属性 t1 边属性 t1 全局属性拼接 X np.concatenate([features, edge_attrs, glob_attrs], axis1) return X输出全部是t加1时刻的现货价格这一点三个模型一致。图模型的输入比其他两个模型多出边和全局两个模块的更新值如果最后的预测精度更高说明这两块信息确实对价格预测有增量贡献——而不是模型结构变复杂之后单纯靠参数量碾压。5. 避坑图深度学习价格预测的五个常见翻车点5.1 现象上游产品预测值在价格剧烈波动区间偏离真实值论文的实验结果显示对原油、天然气、煤炭这些产业链上游品种图模型的预测曲线在真实值波动剧烈的地方准确度较差。这不是论文的一个缺陷而是图模型的结构性限制——上游产品的价格波动更多受外部市场因素驱动而图模型能拿到的边信息和全局信息是同一时间步内的宏观快照无法预测突然的外部冲击。原因在于产业链价格的传导方向是单向的上游波动会沿着生产依赖关系传导到下游但上游自身收到的图信息增量很少。原油的节点属性里有库存环比和运输指数这些是滞后指标价格已经波动了这些指标才跟随变化。解决思路是给上游节点补充更实时的高频特征比如成交持仓量或裂解价差而不是指望纯图信息去应对突发波动。5.2 现象BOPP节点预测偏差大图模型甚至不如单变量LSTMBOPP节点的属性只有现货价格一项没有期货价格、产量、库存这些附加信息它的图预测在MAE和RMSE指标上只比多变量LSTM略好MAPE反而劣于其他两个模型。原因很直接BOPP作为聚丙烯的下游加工品价格受原料聚丙烯价格带动但自身属性信息稀缺模型在t时刻只能拿到一个价格值和结构熵信息量不足以刻画BOPP的市场供需变化。单变量LSTM反而因为专注拟合现货价格自身的均值回归特征在平稳期表现稳定。解决方向有二一是补齐BOPP节点的属性列至少加入产量或开工率二是允许下游节点共享聚丙烯节点的部分属性作为辅助输入。什么时候能看到图模型的真实优势论文的答案是当产品的信息充分且产业链上下游传导稳定时——丙烯、CPP、PP注塑正是这种情况图模型在下游产品上的预测表现全面占优。5.3 现象wn库月度数据里同一时间戳的输入属性存在缺失图模型输入维度比单变量高很多而wind的月度数据经常出现部分缺失。比如某些化工产品的产量数据在特定月份缺报或者进出口依存度偶尔断档。这种情况如果直接填充均值会把缺失值当成真实值喂给LSTM容易拉偏预测。我一般会在每个节点的属性矩阵上记录缺失掩码将缺失位填0后在归一化时对该属性列的min和max只统计非缺失值。更彻底一点的做法是用相邻月份线性插值补齐后再归一化论文没有细说缺失值处理但实战中这一步不做测试集上误差会放大5%左右。5.4 现象边属性结构熵在部分时间节点上值不变训练loss不下降输给LSTM2的结构熵序列如果长期处于一个稳定水平模型的预测值和真实值几乎一致梯度极小LSTM2的loss曲线看起来像一条水平线。这是因为产业链上下游结构没有发生显著变化时节点度分布稳定结构熵自然稳定。解决方法是换掉直接的结构熵序列改为计算结构熵的一阶差分序列让LSTM2学的是结构位置的相对变化而不是绝对值。这样当某一产业链分支的边增加或减少时差分序列才会产生明显信号边模块才有真正的信息输出给节点模块。5.5 现象测试集上的MAPE在聚丙烯和天然气上反而比LSTM差这是论文表3里一个容易被忽视的细节图模型在聚丙烯、天然气、煤炭、丙烷这几个品种上的MAPE劣于对比模型虽然MAE和RMSE占优但百分比误差不占优。原因是MAPE对价格绝对值小的品种天然敏感。天然气单价低每多预测偏差0.1美元百分比误差就被放大几个百分点。而MAE和RMSE是绝对量误差低单价品种的误差天然小图模型的优势不明显。复现时如果以MAPE为主要评估指标需要对不同价格量级的节点分组评估否则中间节点的表现会掩盖大价格节点的真实趋势预测能力。6. 评估指标与结果解读怎么判断图网络真的比LSTM强论文用了三套评价指标——MAE、RMSE、MAPE分别从不同角度刻画误差。MAE看平均绝对偏差直观反映预测值与真实值的平均差距RMSE对大误差更敏感预测值在少数几个时间点剧烈偏离时RMSE会明显升高MAPE看百分比误差适合对比不同价格量级品种的相对准确性。真正常用的姿势是三个指标一起看单独看任何一个都会被特定数据特征带偏。比如只看MAPE天然气单价低百分比被放大图模型的优势消失只看RMSE如果某段时间出现一次极端价格偏离整个指标就被这一个点主导。要判断图网络是否真的比LSTM强有两个基准线一是用测试集首尾时间点的价格差做一个朴素预测器如果图模型的RMSE连这种零模型都没跑赢说明模型学到的主要是跟随趋势而不是捕捉结构信息二是看图模型预测误差的标准差如果标准差显著小于多变量LSTM说明在价格波动期图模型更稳定这是产业链联动信息带来的核心增益。论文实验结果里图模型在丙烯上的MAPE是0.009接近真实值的0.1%偏差而多变量LSTM是6.410——差距近两个数量级说明当下游产品信息充分时图结构的增量价值远超多变量特征的直接堆叠。复现验证时还有一个判断模型好坏的技巧把预测值和真实值的残差序列按时间排序看残差在t时刻的正负是否具有自相关性。如果残差正负交替频繁说明模型预测的只是随机噪声如果残差连续多个时间点同号说明模型对趋势的整体偏移——这种情况通常不是模型问题而是归一化反变换参数有误或者测试集的价格水平整体高于训练集末尾。论文里的图模型在下游产品上残差分布在零附近趋势跟随能力强这是判断一个图网络价格模型是否真的学到产业逻辑的关键检验点。真要说这篇论文的方法对我的启发头一个就是节点属性设计要先于模型结构——你喂给节点什么信息直接决定模型能在多细的粒度上理解这个产品。从那以后我每次做产业链价格模型第一件事都是先画上下游关系表标清楚每个节点手头有哪些真实可用的市场数据数据不够的节点就先用单变量LSTM兜底不让整张图的平均值被信息匮乏的节点拉低。希望这篇拆解对你有参考价值。本文还有配套的精品资源点击获取
返回列表