基于PyG搭建GCN-LSTM时空犯罪预测

基于PyG搭建GCN-LSTM时空犯罪预测

1.前言

最近针对犯罪时空预测、犯罪分布可视化开展研究,图神经网络是必不可少的研究工具之一,为了记录学习PyG的过程,本文通过结合官网案例(非常晦涩难懂)以及网上各位大佬的学习过程,撰写此文章,以此记录学习过程,以防后面遗忘,如有错误请嘴下留情。如果有用,感谢大家给我个关注。

2. PyG安装过程以及需要的包

此处省略安装过程

3.数据描述

本文采用的是美国纽约州的犯罪数据,具体可视化如图所示:
犯罪可视化过程
在这里插入图片描述

数据被分为训练集、验证集、测试集,数据形状为四维数据:[16, 16, 608, 4],其中分别代表划分成16*16的区域,每个区域上608个时间段,4种犯罪类型。输入是过去n天的犯罪矩阵,输出是n+1天的犯罪矩阵。

4.数据处理

用图神经网络的重要一步就是构建图,如何构建图呢?PyG还是比较人性的,在对数据进行转换后,通过KNN算法,筛选出邻近节点,然后构建边,这里也需要注意,数据的输入维度需要按照PyG指定的格式才行。(在此处进行更新,我们采用美国纽约市NYC Sectors构建图神经网络)。包括时间滑动窗口等

 class MadridDatasetLoader(object):
    def __init__(self, data_norm, adj, device="cuda"):
        super(MadridDatasetLoader, self).__init__()
        self.data = data_norm
        self.adj = adj

    def process_data(self, time_step, pre_step):
        # 时间窗口处理
        nodes, timeLength = self.data.shape[0], self.data.shape[1]
        train_seq, train_label = [], []
        for i in range(0, timeLength - time_step - pre_step + 1, pre_step):
            train_seq.append(self.data[:, i: i + time_step])
            train_label.append(self.data[:, i + time_step: i + time_step + pre_step])

        self.features = train_seq
        self.label = train_label

    def generate_data(self, time_step=3, pre_step=1):
		#这个地方处理图神经网络的地方
        edge_weight = np.ones(Adj_matrix.shape[1])
        self.process_data(time_step, pre_step)
        dataset = torch_geometric_temporal.StaticGraphTemporalSignal(edge_index=self.adj.values.T, edge_weight=edge_weight,
                                                                    features=self.features, targets=self.label)

        return dataset

5.模型构建

此处构建一个GCN+LSTM和TCN模型,简单的来说,核心是有batchsize那么多个图,拼成一个大的,然后你分别用网络处理,处理后呢,再返回成batchsize那么多个图

class GCN(torch.nn.Module):
    def __init__(self, in_feats, h_feats, out_feats,batchsize):
        super(GCN, self).__init__()
        self.conv1 = GCNConv(in_feats, h_feats)
        self.conv2 = GCNConv(h_feats, out_feats)
        self.fc = nn.Sequential(
            nn.Linear(128, out_feats),
            nn.ReLU(),
            nn.Linear(out_feats, 1),
        )
        self.batch = batchsize
        self.lstm = nn.LSTM(out_feats, 128, batch_first=True, dropout=0.5)
    def forward(self, data):
        x, edge_index, batch = data.x, data.edge_index, data.batch
        x = x.float()
        x = F.elu(self.conv1(x, edge_index))
        x = self.conv2(x, edge_index))
        x = x.view(len(x),1,-1)
        x,_ = self.lstm(x)
        out = self.fc(x)
        out = torch.reshape(out,(self.batch,-1))
        return out


class TGCN_model(torch.nn.Module):
    def __init__(self, node_features, unit_num, out_step):
        super(TGCN_model, self).__init__()
        # Temporal Graph Convolutional Cell
        self.tgnn_n = TGCN(in_channels=node_features,
                          out_channels=unit_num)
        self.linear_n = torch.nn.Linear(unit_num, out_step)

    def forward(self, x, edge_index,  edge_weight):
        """
        x = Node features for T time steps
        edge_index = Graph edge indices
        """
        mu_res = self.linear_n(F.softplus(self.tgnn_n(x, edge_index)))
        return mu_res

6.训练和测试

我们在这个地方更新了训练函数和测试函数,验证集没写

def train(model, dataset, test_dataset):
    optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
    for epoch in range(100):
        step = 0
        loss_batch = []
        for snapshot in dataset:
            snapshot = snapshot.to('cuda')
            # Get model predictions
            if four == False:
                phi_res, rou_res, mu_res = model(snapshot.x, snapshot.edge_index, snapshot.edge_attr)
                loss = nb_zeroinflated_nll_loss(snapshot.y, phi_res, rou_res, mu_res)
                loss_batch.append(loss.item())
            else:
                phi_res, rou_res, mu_res, pi_res = model(snapshot.x, snapshot.edge_index, snapshot.edge_attr)
                loss = zb_tweedie_nll_loss(snapshot.y, phi_res, rou_res, mu_res, pi_res)
                loss_batch.append(loss.item())
            # Mean Squared Error
            loss.backward()
            optimizer.step()
            optimizer.zero_grad()
        torch.cuda.empty_cache()
        print("Epoch {} train zb_Tweedie: {:.4f}".format(epoch, np.mean(loss_batch)))

        result = test_point(model, test_dataset)
        print("Epoch {} train zb_Tweedie: {:.4f} Mae: {:.4f}".format(epoch, np.mean(loss_batch), result))


def test(model, dataset):
    with torch.no_grad():
        model.eval()
        prediction, true = [], []
        for snapshot in dataset:
            snapshot = snapshot.to('cuda')
            # Get model predictions
            if four == False:
                phi_res, rou_res, mu_res = model(snapshot.x, snapshot.edge_index, snapshot.edge_attr)
            else:
                phi_res, rou_res, mu_res, pi_res = model(snapshot.x, snapshot.edge_index, snapshot.edge_attr)
            point = nb_zeroinflated_draw(phi_res.cpu().numpy(), rou_res.cpu().numpy(), mu_res.cpu().numpy())
            prediction.append(point)
            true.append(snapshot.y)
        # Flatten prediction and true lists into one-dimensional tensors
        prediction_flat = torch.cat([p.flatten() for p in prediction])
        true_flat = torch.cat([t.flatten() for t in true])

        # Compute MAE
        mae = metrics.mean_absolute_error(true_flat.numpy(), prediction_flat.numpy())
    return mae

7.结果分析

由于实验不多,仅仅用了传统CNN算法、GCN算法、和GCN-LSTM算法进行分析,在Mape上指标差异巨大,GCN算法提升效果很高,感兴趣的可以自己试试,相对GCN呢,引入LSTM处理时序数据,在一定程度上可以提高点数。

在时间序列预测中,LSTM网络因其能够处理长期依赖关系,特别适合捕捉时间序列数据中的动态特征,而GCN网络则能够通过图结构提取非欧几里得数据的高级特征,二者结合可以大幅提升预测的准确性。以下步骤和关键要素是结合《LSTMGCN结合的感染病人数预测模型源码详解》资源提供的参考: 参考资源链接:[LSTMGCN结合的感染病人数预测模型源码详解](https://wenku.csdn.net/doc/2rc9wkk84q) 1. 数据预处理:首先,需要对时间序列数据进行清洗和归一化处理。考虑到时间序列的周期性和趋势性,可能需要进行去噪、季节性调整等操作。数据预处理是整个预测过程中的重要环节,直接影响到模型的性能。 2. 构建LSTM网络结构:在搭建LSTM模型时,需要设计合适的网络层数、隐藏单元数和激活函数。例如,使用Stacked LSTM结构可以增强模型捕捉长期依赖的能力。激活函数的选择也要根据问题的性质来决定,如使用tanh或ReLU。 3. 构建GCN网络结构:GCN层能够提取数据中的图结构特征,需要定义图结构以及相应的邻接矩阵。GCN层的数目和每层的节点数是关键参数,需要根据数据集的特性和预测任务来调整。 4. 特征融合:将LSTM提取的时间序列特征与GCN提取的空间特征进行融合。这一步骤非常关键,因为融合方法将决定两种类型特征如何互补。 5. 损失函数和优化器选择:选择合适的损失函数和优化器对训练模型至关重要。在时间序列预测中,常用的损失函数是均方误差(MSE),而优化器可以选择Adam或RMSprop。 6. 训练与验证:利用训练数据对模型进行训练,同时采用交叉验证来评估模型的泛化能力。在训练过程中,监控损失函数值的变化以及过拟合现象,必要时进行早停(early stopping)。 7. 模型评估与调优:使用验证集评估模型的预测性能,根据评估结果调整模型参数,如学习率、批次大小、网络结构等。此外,可以通过集成学习、模型剪枝等方法进一步优化模型。 8. 预测与应用:完成模型的训练和调优后,使用测试集进行最终的模型评估,确保模型在未见过的数据上具有良好的预测能力,然后将模型部署到实际应用中。 通过以上步骤,结合《LSTMGCN结合的感染病人数预测模型源码详解》中的源码和文档,可以系统地构建和优化一个结合LSTMGCN深度学习模型,用于时间序列预测任务。 参考资源链接:[LSTMGCN结合的感染病人数预测模型源码详解](https://wenku.csdn.net/doc/2rc9wkk84q)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值