2025.3.31-2025.4.6文献阅读
目录
- 摘要
- Abstract
- 1 文献阅读
- 1.1 GGNN
- 1.2 总体架构
- 1.3 实验分析
- 总结
摘要
在本周阅读的文献中,作者提出了一种利用GGNN结合稀疏监测数据实现供水网络实时水质预测的创新方法。模型的核心优势在于其能够充分利用供水网络的拓扑结构和稀疏的传感器数据,准确预测整个网络的水质情况。GGNN在传统GNN的基础上引入了门控机制,借鉴了GRU的思想。这种门控机制通过更新门和重置门控制信息流动,使模型能够捕捉长期依赖关系。通过引入掩码操作,模型在训练过程中随机隐藏部分传感器数据,巧妙模拟实际应用中的数据稀疏性,从而显著提升了模型的鲁棒性和泛化能力。这种设计使模型能够在传感器覆盖有限或数据不完整的情况下,依然保持高精度的预测性能。
Abstract
In the literature read this week, the author proposed an innovative method for real-time water quality prediction in water supply networks using GGNN combined with sparse monitoring data. The core advantage of the model lies in its ability to fully utilize the topology and sparse sensor data of the water supply network to accurately predict the water quality of the entire network. GGNN introduces gating mechanism on the basis of traditional graph neural networks and draws on the ideas of GRU. This gating mechanism controls information flow by updating and resetting gates, enabling the model to capture long-term dependencies. By introducing masking operations, the model randomly hides some sensor data during the training process, cleverly simulating the sparsity of data in practical applications, thereby significantly improving the robustness and generalization ability of the model. This design enables the model to maintain high-precision predictive performance even in situations where sensor coverage is limited or data is incomplete.
1 文献阅读
本周阅读了一篇名为Real-time water quality prediction in water distribution networks using graph neural networks with sparse monitoring data 的论文。
论文地址:Real-time water quality prediction in water distribution networks using graph neural networks with sparse monitoring data
在论文中,作者应用了一种将GRU融入GNN的模型GGNN,同时通过引入掩码操作,即在训练中随机掩盖部分传感器数据,从而显著增强了模型对稀疏数据的泛化能力。
1.1 GGNN
GGNN是论文中用于实时水质预测的核心模型,它在传统GNN的基础上引入了门控机制,借鉴了GRU的思想。这种门控机制通过更新门和重置门控制信息流动,使模型能够捕捉长期依赖关系。其工作流程如下图所示:
首先,GGNN将管网的拓扑结构和流动方向编码为有向图。每个节点通过邻接矩阵描述其连接关系。为了捕捉双向信息(如反向传播的可能影响),模型将原始邻接矩阵与其转置拼接,形成扩展邻接矩阵 。
节点特征通过线性变换映射到隐藏空间。假设管网中有n个节点,每个节点在时间窗口内的水质数据构成特征矩阵X。模型通过全连接层和ReLU激活函数将其转换为初始隐藏状态,这一步骤旨在提取节点特征的高阶表示,为后续的图结构信息融合奠定基础。此后模型通过多步迭代更新节点状态,每一步包含聚合和门控更新两个阶段。在聚合阶段,每个节点通过扩展邻接矩阵收集邻居节点的隐藏状态。最后在运用GRU动态调整节点状态更新信息后在经一个全连接层获得输出。其具体流程可总结如下:
GGNN的代码实现如下所示:
import torch
import torch.nn as nn
class AttrProxy(object):
"""
Translates index lookups into attribute lookups.
To implement some trick which able to use list of nn.Module in a nn.Module
see https://discuss.pytorch.org/t/list-of-nn-module-in-a-nn-module/219/2
"""
def __init__(self, module, prefix):
self.module = module
self.prefix = prefix
def __getitem__(self, i):
return getattr(self.module, self.prefix + str(i))
class Propogator(nn.Module):
"""
Gated Propogator for GGNN
Using LSTM gating mechanism
"""
def __init__(self, state_dim, n_node, n_edge_types):
super(Propogator, self).__init__()
self.n_node = n_node
self.n_edge_types = n_edge_types
self.reset_gate = nn.Sequential(
nn.Linear(state_dim*3, state_dim),
nn.Sigmoid()
)
self.update_gate = nn.Sequential(
nn.Linear(state_dim*3, state_dim),
nn.Sigmoid()
)
self.tansform = nn.Sequential(
nn.Linear(state_dim*3, state_dim),
nn.Tanh()
)
def forward(self, state_in, state_out, state_cur, A):
A_in = A[:, :, :self.n_node*self.n_edge_types]
A_out = A[:, :, self.n_node*self.n_edge_types:]
a_in = torch.bmm(A_in, state_in)
a_out = torch.bmm(A_out, state_out)
a = torch.cat((a_in, a_out, state_cur), 2)
r = self.reset_gate(a)
z = self.update_gate(a)
joined_input = torch.cat((a_in, a_out, r * state_cur), 2)
h_hat = self.tansform(joined_input)
output = (1 - z) * state_cur + z * h_hat
return output
class GGNN(nn.Module):
"""
Gated Graph Sequence Neural Networks (GGNN)
Mode: SelectNode
Implementation based on https://arxiv.org/abs/1511.05493
"""
def __init__(self, opt):
super(GGNN, self).__init__()
assert (opt.state_dim >= opt.annotation_dim, \
'state_dim must be no less than annotation_dim')
self.state_dim = opt.state_dim
self.annotation_dim = opt.annotation_dim
self.n_edge_types = opt.n_edge_types
self.n_node = opt.n_node
self.n_steps = opt.n_steps
for i in range(self.n_edge_types):
# incoming and outgoing edge embedding
in_fc = nn.Linear(self.state_dim, self.state_dim)
out_fc = nn.Linear(self.state_dim, self.state_dim)
self.add_module("in_{}".format(i), in_fc)
self.add_module("out_{}".format(i), out_fc)
self.in_fcs = AttrProxy(self, "in_")
self.out_fcs = AttrProxy(self, "out_")
# Propogation Model
self.propogator = Propogator(self.state_dim, self.n_node, self.n_edge_types)
# Output Model
self.out = nn.Sequential(
nn.Linear(self.state_dim + self.annotation_dim, self.state_dim),
nn.Tanh(),
nn.Linear(self.state_dim, 1)
)
self._initialization()
def _initialization(self):
for m in self.modules():
if isinstance(m, nn.Linear):
m.weight.data.normal_(0.0, 0.02)
m.bias.data.fill_(0)
def forward(self, prop_state, annotation, A):
for i_step in range(self.n_steps):
in_states = []
out_states = []
for i in range(self.n_edge_types):
in_states.append(self.in_fcs[i](prop_state))
out_states.append(self.out_fcs[i](prop_state))
in_states = torch.stack(in_states).transpose(0, 1).contiguous()
in_states = in_states.view(-1, self.n_node*self.n_edge_types, self.state_dim)
out_states = torch.stack(out_states).transpose(0, 1).contiguous()
out_states = out_states.view(-1, self.n_node*self.n_edge_types, self.state_dim)
prop_state = self.propogator(in_states, out_states, prop_state, A)
join_state = torch.cat((prop_state, annotation), 2)
output = self.out(join_state)
output = output.sum(2)
return output
GGNN的优势在于其能够同时建模管网的空间拓扑和时序动态。通过门控机制和多步消息传递,模型能够捕捉节点间的非线性相互作用,例如某条管道的突发泄漏如何通过管网拓扑影响下游多个节点。此外,扩展邻接矩阵的引入使得模型能够处理双向信息流,这在传统单向传播的图网络中难以实现。
1.2 总体架构
对于模型的总体架构,大致可以分为三个部分,即数据输入、掩码处理以及GGNN模型三部分,其结构如下图所示:
数据输入部分主要由两部分组成,第一部分是由水源、水箱、用户节点管道、阀门、泵等组成的管网拓扑结构。另一部分是历史水质数据。它们两部分分别组成两个矩阵作为GGNN的输入。
第二部分是掩码操作部分,这部分算是论文的主要创新点。掩码操作通过在训练阶段随机隐藏部分监测节点的输入数据,模拟实际场景中传感器部署稀疏的情况。如下图所示,经掩码操作以后,绿色的节点就是隐藏后的节点。
通过掩码操作迫使模型依赖网络拓扑和邻近节点信息推断被掩码节点的水质。从而避免模型仅记忆监测节点的局部特征,提升了模型的泛化性。除此每次掩码的节点随机变化,相当于在输入层加入动态噪声,从而防止了模型对监测节点过拟合,这也起到了一个正则化的作用。
掩码操作的代码实现如下所示,其中设定的掩盖比例为实现所得的最佳比例,即0.5:
# 掩码操作:随机掩盖部分传感器节点的数据
def apply_mask(x, sensor_nodes, mask_ratio=0.5):
"""
Randomly mask the data of some sensor nodes
parameter:
x: Node feature matrix,shape [N, in_channels]
sensor_nodes: Sensor Node Index List
return:
Concealed node feature matrix
"""
num_mask = int(len(sensor_nodes) * mask_ratio)
mask_nodes = random.sample(sensor_nodes, num_mask)
x_masked = x.clone()
for node in mask_nodes:
x_masked[node] = 0 # 掩盖数据,设为0
return x_masked
对于GGNN部分在第一小节中已经有详细的分析,在此不做过多讲述。经GGNN模块处理后模型再经一个线性变换后得到最终的输出。
1.3 实验分析
(1)数据集
盐田WDN:盐田WDN由两个水源(S1和S2)、952个需求节点和1175根管道组成。网络中共有33个水质传感器站。研究采用EPANET作为模拟工具来生成合成水质数据,用于训练和测试。监测的数据为氯浓度,且仅在部分节点安装传感器,因此实验数据是稀疏的。
(2)评估标准
MAE:
MAPE:
(3)消融研究
掩码操作作为该研究的一个创新点,作者首先通过实验验证了不同掩码率对实验的影响,其结果如下图所示:
由实验结果可知,当运用掩码操作后,实验误差远比没有使用过掩码操作时小的多。由此证明了掩码操作在预测准确性方面的有效性。
为了进一步分析不同掩码条件的影响,作者进行了五重交叉验证。水质数据集分为五个子集,每个子集用作测试集一次,而其余子集用于训练。计算每个掩蔽条件的 MAE,得出每个掩蔽比率的五组MAE值。实验所得箱型图结果如下图所示:
研究结果表明,过小或过大的掩码率会导致模型性能欠佳。当掩码比率设置为0.5时,该模型实现了最高的准确性,这表明适度的掩码比率在捕获相关信息和减少过度拟合之间取得了平衡。除此,不同掩蔽比率之间的平均MAE值差异低于0.03 mg L,进一步证明了该模型对不同掩码条件的稳健性。
(4)节点预测精度的研究
该部分研究是为了证明传感器位置比数量更重要,即验证模型对数据质量而非数量的敏感性。下图显示了WDN测试数据集中各个节点的预测准确性分析:
实验结果表明,该模型在预测WDN中大多数节点的水质方面表现良好。此模型不包含广泛的液压属性。尽管有一小部分节点有传感器数据,但该模型有效地为很大一部分节点提供了准确的预测。这一结果强调了该模型在现实中进行预测的稳健性。
下图显示了GGNN模型在节点级氯浓度预测的具体效果,通过时间序列对比真实值与预测值,验证模型在不同精度等级下的表现。
实验结果证明了GGNN模型在感知氯水平变化方面的有效性。此外,由于位于网络末端的节点以及位置稀疏的传感器节点,它们可能会经历更显著的水质变化。这一观察结果强调了与实际水质预测相关的复杂性,尤其是在复杂的网络结构中。
为了检查传感器距离对预测精度的影响,根据边数计算节点之间的最短路径距离。作者通过利用箱形图根据传感器接近度可视化节点的 MAE分布。其中红叉详细说明了位于给定邻近级别内的节点数。
关键的观察结果是,模型的预测准确性不会因节点和传感器之间的距离而发生显著变化。这表明模型能够从相邻节点捕获相关信息,即使它们相对较远。
(5)传感器放置策略对预测准确性的影响研究
这一部分的实验旨在探究不同传感器布置策略对水质预测模型性能的影响,重点分析传感器布局对预测泛化能力的作用机制。实验通过对比基于网络拓扑的“节点中心性”策略与融合水质数据的ANOVA策略,验证传感器布设中水质动态信息的重要性,同时考察传感器数量与空间分布的协同效应对模型预测能力的边界约束。实验结果如下:
实验结果表明,传感器布设策略的选择对模型预测精度具有决定性影响。基于水质动态特征的ANOVA策略显著优于仅依赖拓扑结构的节点中心性策略。此外,传感器数量并非预测精度提升的核心因素,当布设位置与水质传播的关键路径匹配时,少量传感器即可实现全局预测能力的显著改善。
总结
通过本周的学习,我对GGNN模型有了一定的了解,在该论文中,作者强调的是通过稀疏数据来预测总体水质,从而对模型的复杂度有所要求。若忽略这一要求,将GRU换为复杂度更高的LSTM是否会提高预测的精度,另外将邻接矩阵的建模换为动态邻接矩阵后的预测效果可能更好。