STGCN 代码解读(Pytorch)

        本人也是刚接触深度学习,接了个项目要用到图神经网络,现在在学习相关代码和理论。STGCN是一个SOTA GNN 模型,其计算快、效果好,方法简单。因此将其作为我第一个仔细阅读代码的模型。如有不对之处欢迎大家批评指正!

完整代码:hazdzz/STGCN: The PyTorch version of STGCN. (github.com)

实现工具:colab T4 GPU


main.py

set_env(seed):

def set_env(seed):
    # Set available CUDA devices
    # This option is crucial for an multi-GPU device
    os.environ['CUDA_VISIBLE_DEVICES'] = '0, 1'
    # os.environ['CUDA_LAUNCH_BLOCKING'] = '1'
    # os.environ['CUBLAS_WORKSPACE_CONFIG'] = ':16:8'
    os.environ['CUBLAS_WORKSPACE_CONFIG'] = ':4096:8'
    os.environ['PYTHONHASHSEED']=str(seed)
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    torch.backends.cudnn.benchmark = False
    torch.backends.cudnn.deterministic = True
    torch.use_deterministic_algorithms(True)

set_env(seed)函数的作用是设置和配置一些环境变量,以确保实验的稳定性和可重复性。这些环境变量的设置包括以下几个方面:

1. CUDA设备的选择:os.environ['CUDA_VISIBLE_DEVICES'] = '0, 1'用于指定使用的GPU设备。这对于多GPU系统非常重要,它确保代码在指定的GPU设备上执行。如果不设置这个环境变量,PyTorch可能会在所有可用的GPU上分配任务,这可能会导致资源冲突和性能问题。

2. 随机种子的设置:random.seed(seed)np.random.seed(seed)torch.manual_seed(seed)torch.cuda.manual_seed(seed)等语句用于设置伪随机数生成器的种子。通过设置相同的种子,可以确保在不同运行之间获得相同的随机数,从而使实验结果可重复。这对于实验结果的稳定性和比较非常重要。

3. 关于GPU使用的其他设置:torch.backends.cudnn.benchmarktorch.backends.cudnn.deterministictorch.use_deterministic_algorithms等语句用于控制在GPU上的操作。torch.backends.cudnn.benchmark通常设置为False,以确保运行时不会对卷积算法进行优化,这对于稳定性很重要。torch.backends.cudnn.deterministictorch.use_deterministic_algorithms用于启用确定性的CUDA操作,以确保相同输入下的结果相同,从而提高可重复性。

get_parameters():

def get_parameters():
    parser = argparse.ArgumentParser(description='STGCN')
    parser.add_argument('--enable_cuda', type=bool, default=True, help='enable CUDA, default as True')
    parser.add_argument('--seed', type=int, default=42, help='set the random seed for stabilizing experiment results')
    parser.add_argument('--dataset', type=str, default='metr-la', choices=['metr-la', 'pems-bay', 'pemsd7-m'])
    parser.add_argument('--n_his', type=int, default=12)
    parser.add_argument('--n_pred', type=int, default=3, help='the number of time interval for predcition, default as 3')
    parser.add_argument('--time_intvl', type=int, default=5)
    parser.add_argument('--Kt', type=int, default=3)
    parser.add_argument('--stblock_num', type=int, default=2)
    parser.add_argument('--act_func', type=str, default='glu', choices=['glu', 'gtu'])
    parser.add_argument('--Ks', type=int, default=3, choices=[3, 2])
    parser.add_argument('--graph_conv_type', type=str, default='cheb_graph_conv', choices=['cheb_graph_conv', 'graph_conv'])
    parser.add_argument('--gso_type', type=str, default='sym_norm_lap', choices=['sym_norm_lap', 'rw_norm_lap', 'sym_renorm_adj', 'rw_renorm_adj'])
    parser.add_argument('--enable_bias', type=bool, default=True, help='default as True')
    parser.add_argument('--droprate', type=float, default=0.5)
    parser.add_argument('--lr', type=float, default=0.001, help='learning rate')
    parser.add_argument('--weight_decay_rate', type=float, default=0.0005, help='weight decay (L2 penalty)')
    parser.add_argument('--batch_size', type=int, default=32)
    parser.add_argument('--epochs', type=int, default=10000, help='epochs, default as 10000')
    parser.add_argument('--opt', type=str, default='adam', help='optimizer, default as adam')
    parser.add_argument('--step_size', type=int, default=10)
    parser.add_argument('--gamma', type=float, default=0.95)
    parser.add_argument('--patience', type=int, default=30, help='early stopping patience')
    args = parser.parse_args()
    print('Training configs: {}'.format(args))

    # For stable experiment results
    set_env(args.seed)

    # Running in Nvidia GPU (CUDA) or CPU
    if args.enable_cuda and torch.cuda.is_available():
        # Set available CUDA devices
        # This option is crucial for multiple GPUs
        # 'cuda' ≡ 'cuda:0'
        device = torch.device('cuda')
    else:
        device = torch.device('cpu')
    
    Ko = args.n_his - (args.Kt - 1) * 2 * args.stblock_num

    # blocks: settings of channel size in st_conv_blocks and output layer,
    # using the bottleneck design in st_conv_blocks
    blocks = []
    blocks.append([1])
    for l in range(args.stblock_num):
        blocks.append([64, 16, 64])
    if Ko == 0:
        blocks.append([128])
    elif Ko > 0:
        blocks.append([128, 128])
    blocks.append([1])
    
    return args, device, blocks

get_parameters()函数用于解析命令行参数,配置模型的各种超参数,以及确定是否使用CUDA(GPU加速)来运行模型。

1. 解析命令行参数:parser = argparse.ArgumentParser(description='STGCN')创建一个解析器对象,用于解析命令行参数。description参数指定了解析器的描述信息

2.定义各种命令行参数:

  • --enable_cuda:是否启用CUDA,类型为布尔值,默认为True。
  • --seed:随机数种子,用于实验结果的稳定性,默认为42。
  • --dataset:数据集名称,有三种选择:'metr-la'、'pems-bay'和'pemsd7-m'。
  • --n_his:历史时间步数,表示用于预测的历史时间步数,默认为12。
  • --n_pred:预测时间步数,表示每个时间步需要预测的时间步数,默认为3。
  • --time_intvl:时间间隔,表示数据采样的时间间隔,默认为5。
  • --Kt:时间卷积核的大小,默认为3。
  • --stblock_num:STGCN中的ST块数量,默认为2。
  • --act_func:激活函数类型,有两种选择:'glu'和'gtu'。
  • --Ks:空间卷积核的大小,有两种选择:3和2。
  • --graph_conv_type:图卷积类型,有两种选择:'cheb_graph_conv'和'graph_conv'。
  • --gso_type:图的 Laplacian 矩阵类型,有四种选择:'sym_norm_lap'、'rw_norm_lap'、'sym_renorm_adj'和'rw_renorm_adj'。
  • --enable_bias:是否启用偏置,默认为True。
  • --droprate:dropout率,默认为0.5。
  • --lr:学习率,默认为0.001。
  • --weight_decay_rate:权重衰减率(L2正则化),默认为0.0005。
  • --batch_size:批大小,默认为32。
  • --epochs:训练轮数,默认为10000。
  • --opt:优化器类型,有三种选择:'adam'、'rmsprop'和'adamw'。
  • --step_size:学习率衰减的步数,默认为10。
  • --gamma:学习率衰减的因子,默认为0.95。
  • --patience:早停的耐心参数,默认为30。

3. 使用parser.parse_args()解析命令行参数,并将结果存储在args变量中。

4. 打印参数:通过print('Training configs: {}'.format(args))将解析后的参数打印出来,以便用户知道配置了哪些参数.

5. 设置随机种子和GPU设备:根据参数中的enable_cuda来决定是否使用CUDA(GPU加速)。如果启用CUDA且GPU可用,将device设置为cuda,否则设置为cpu。此外,还设置了随机种子,以确保实验结果的稳定性。

data_preparate(args, device)

def data_preparate(args, device):    
    adj, n_vertex = dataloader.load_adj(args.dataset)
    gso = utility.calc_gso(adj, args.gso_type)
    if args.graph_conv_type == 'cheb_graph_conv':
        gso = utility.calc_chebynet_gso(gso)
    gso = gso.toarray()
    gso = gso.astype(dtype=np.float32)
    args.gso = torch.from_numpy(gso).to(device)

    dataset_path = './data'
    dataset_path = os.path.join(dataset_path, args.dataset)
    data_col = pd.read_csv(os.path.join(dataset_path, 'vel.csv')).shape[0]
    # recommended dataset split rate as train: val: test = 60: 20: 20, 70: 15: 15 or 80: 10: 10
    # using dataset split rate as train: val: test = 70: 15: 15
    val_and_test_rate = 0.15

    len_val = int(math.floor(data_col * val_and_test_rate))
    len_test = int(math.floor(data_col * val_and_test_rate))
    len_train = int(data_col - len_val - len_test)

    train, val, test = dataloader.load_data(args.dataset, len_train, len_val)
    zscore = preprocessing.StandardScaler()
    train = zscore.fit_transform(train)
    val = zscore.transform(val)
    test = zscore.transform(test)

    x_train, y_train = dataloader.data_transform(train, args.n_his, args.n_pred, device)
    x_val, y_val = dataloader.data_transform(val, args.n_his, args.n_pred, device)
    x_test, y_test = dataloader.data_transform(test, args.n_his, args.n_pred, device)

    train_data = utils.data.TensorDataset(x_train, y_train)
    train_iter = utils.data.DataLoader(dataset=train_data, batch_size=args.batch_size, shuffle=False)
    val_data = utils.data.TensorDataset(x_val, y_val)
    val_iter = utils.data.DataLoader(dataset=val_data, batch_size=args.batch_size, shuffle=False)
    test_data = utils.data.TensorDataset(x_test, y_test)
    test_iter = utils.data.DataLoader(dataset=test_data, batch_size=args.batch_size, shuffle=False)

    return n_vertex, zscore, train_iter, val_iter, test_iter

data_preparate(args, device) 函数用于数据准备,包括加载数据集的相关信息,生成图的邻接矩阵,划分训练、验证和测试数据集,进行数据标准化处理,并创建 PyTorch 数据加载器 (DataLoader) 以便后续训练和测试。

1. 加载邻接矩阵和图信息:adj, n_vertex = dataloader.load_adj(args.dataset) 用于加载数据集的邻接矩阵和节点数量。adj 是一个描述节点之间关系的邻接矩阵,n_vertex 是节点的数量。

2. 计算图的 Laplacian 矩阵:gso = utility.calc_gso(adj, args.gso_type) 使用 utility.calc_gso 函数计算图的 Laplacian 矩阵,args.gso_type 参数指定了 Laplacian 矩阵的类型,有四种选择:'sym_norm_lap'、'rw_norm_lap'、'sym_renorm_adj' 和 'rw_renorm_adj'。

3. 如果 graph_conv_type 为 'cheb_graph_conv',则计算 ChebNet 的 Laplacian 矩阵:gso = utility.calc_chebynet_gso(gso),这是一个额外的处理步骤,用于 ChebNet 图卷积的计算。

4. 转换邻接矩阵为 NumPy 数组:gso = gso.toarray() 将 Laplacian 矩阵从稀疏矩阵格式转换为 NumPy 数组。

5. 将 NumPy 数组的数据类型转换为 np.float32gso = gso.astype(dtype=np.float32) 以确保数据类型适用于后续的计算。

6. 使用 PyTorch 将 Laplacian 矩阵 gso 转换为张量格式,并将其发送到指定的 device(GPU 或 CPU):args.gso = torch.from_numpy(gso).to(device)。这将准备好后续模型的输入。

7. 加载数据集:根据指定的数据集路径,加载原始数据集。在示例中,数据集路径是 './data',并根据 args.dataset 参数指定特定的数据集。

8. 划分数据集:根据指定的划分比例,将数据集分为训练、验证和测试集。示例中使用了 len_trainlen_vallen_test 这些变量来确定每个数据集的大小。

9. 数据标准化处理:使用 preprocessing.StandardScaler 对数据进行标准化处理。首先对训练数据进行拟合(fit_transform),然后使用相同的均值和方差对验证和测试数据进行转换(transform)。

10. 数据转换:将标准化后的数据转换为模型所需的输入格式。使用 dataloader.data_transform 函数,将数据集划分为输入 x 和目标 y。这些输入数据将用于模型训练和测试。

11. 创建 PyTorch 数据加载器:通过 utils.data.TensorDataset 创建训练、验证和测试数据集,并使用 utils.data.DataLoader 创建数据加载器,以便能够批量加载数据进行训练和测试。

train()

def train(loss, args, optimizer, scheduler, es, model, train_iter, val_iter):
    for epoch in range(args.epochs):
        l_sum, n = 0.0, 0  # 'l_sum' is epoch sum loss, 'n' is epoch instance number
        model.train()
        for x, y in tqdm.tqdm(train_iter):
            y_pred = model(x).view(len(x), -1)  # [batch_size, num_nodes]
            l = loss(y_pred, y)
            optimizer.zero_grad()
            l.backward()
            optimizer.step()
            l_sum += l.item() * y.shape[0]
            n += y.shape[0]
        scheduler.step()
        val_loss = val(model, val_iter)
        # GPU memory usage
        gpu_mem_alloc = torch.cuda.max_memory_allocated() / 1000000 if torch.cuda.is_available() else 0
        print('Epoch: {:03d} | Lr: {:.20f} |Train loss: {:.6f} | Val loss: {:.6f} | GPU occupy: {:.6f} MiB'.\
            format(epoch+1, optimizer.param_groups[0]['lr'], l_sum / n, val_loss, gpu_mem_alloc))

        if es.step(val_loss):
            print('Early stopping.')
            break

train() 函数用于训练模型,它负责训练模型并在每个训练周期(epoch)之后评估模型性能。

1. 循环训练:for epoch in range(args.epochs): 开始一个训练周期的循环。args.epochs 指定了总共要进行的训练周期数。

2. 初始化损失和实例数:l_sum, n = 0.0, 0 分别表示当前训练周期中的总损失和训练实例数。这些变量用于在训练周期结束后计算平均损失。

3. 将模型设置为训练模式:model.train() 将模型设置为训练模式,这会启用一些在训练时需要的特性,例如启用 dropout 和批规范化(如果有的话)。

4. 批量训练:for x, y in tqdm.tqdm(train_iter): 开始一个批次的训练。x 是输入数据,y 是目标数据。tqdm提供了一个快速、可扩展的进度条,用于在命令行界面中显示循环操作的进度。tqdm 的名称来自“taqaddum”(阿拉伯语),意为“进展”。通过使用 tqdm,可以在终端中看到循环操作的进度,包括当前迭代的百分比、已完成的迭代数、预计的剩余时间等信息。这对于长时间运行的任务、循环和数据处理非常有用,因为它可以让你清晰地了解操作的进展,以及估计操作完成的时间。 在上面的代码中,for x, y in tqdm.tqdm(train_iter): 使用了 tqdm 来创建一个循环,用于遍历训练数据集,并在命令行中显示进度条,以显示每个批次的训练进度。

5. 前向传播和计算损失:y_pred = model(x).view(len(x), -1) 执行前向传播,得到模型的预测结果 y_predl = loss(y_pred, y) 计算模型的损失,这里使用的是均方误差(MSE)损失。

6. 清零梯度:optimizer.zero_grad() 清零模型参数的梯度,以准备进行反向传播。

7. 反向传播和参数更新:l.backward() 执行反向传播,计算模型参数的梯度。optimizer.step() 使用优化器更新模型参数,以减小损失。

8. 计算总损失和实例数:l_sum += l.item() * y.shape[0] 累积当前批次的损失。y.shape[0] 是当前批次中的实例数,用于将批次损失加权累积到总损失中。

9. 累积实例数:n += y.shape[0] 累积当前批次中的实例数。

10. 学习率调度:scheduler.step() 在每个训练周期结束后,调用学习率调度器来调整学习率。这有助于在训练的不同阶段动态调整学习率以获得更好的模型性能。

11. 打印训练信息:print('Epoch: {:03d} | Lr: {:.20f} |Train loss: {:.6f} | Val loss: {:.6f} | GPU occupy: {:.6f} MiB'.format(epoch+1, optimizer.param_groups[0]['lr'], l_sum / n, val_loss, gpu_mem_alloc)) 打印每个训练周期的信息,包括当前周期数、学习率、训练损失、验证损失以及 GPU 内存占用情况。

12. 早停检测:if es.step(val_loss): 使用早停策略来检查验证损失是否已经停止改善。如果验证损失连续 patience 轮没有改善(小于 min_delta),则早停被触发。

13. 早停终止:如果早停被触发,print('Early stopping.') 打印早停信息并跳出训练循环,提前终止训练。这是为了防止过拟合或在验证损失不再改善时节省时间。

@torch.no_grad()

@torch.no_grad() 是 PyTorch 中的一个装饰器(Decorator),用于在特定的代码块中关闭梯度跟踪(gradient tracking)。梯度跟踪是 PyTorch 中用于自动计算梯度的核心功能,它在训练神经网络时非常有用。然而,在某些情况下,你可能希望临时关闭梯度跟踪,以节省内存并提高运行速度。

在代码中,@torch.no_grad() 装饰器用于标记以下函数或代码块,以告诉PyTorch在其中不需要跟踪梯度:

  • @torch.no_grad() def val(model, val_iter): 函数 val 用于在验证数据上评估模型的性能,这里关闭了梯度跟踪,因为在验证时通常不需要计算梯度。

  • @torch.no_grad() def test(zscore, loss, model, test_iter, args): 函数 test 也用于在测试数据上评估模型,同样关闭了梯度跟踪。

这样可以确保在验证和测试阶段不会浪费计算资源来计算梯度,从而提高运行效率。

val(model, val_iter)

在验证数据集上计算模型的损失,以评估模型性能。

test(zscore, loss, model, test_iter, args)

在测试数据集上执行模型的测试,并计算测试数据集上的性能指标,如均方误差(MSE)、平均绝对误差(MAE)等。

main主函数

这部分代码是脚本的入口点,执行以下步骤:

  • 获取参数和配置。
  • 数据准备。
  • 初始化模型、损失函数、优化器和学习率调度器。
  • 执行训练。
  • 进行测试,并输出性能指标。

script

utility.py

1.calc_gso(dir_adj, gso_type)

  • 这个函数用于计算图的图结构关系矩阵(Graph Structure Operator,GSO),它接受两个参数:dir_adj 表示一个有向邻接矩阵,gso_type 表示图结构操作类型。
  • 首先,它将有向邻接矩阵 dir_adj 转换为对称邻接矩阵,以使图变得对称。
  • 然后,根据给定的 gso_type,它计算不同的图结构操作,包括对称归一化邻接矩阵(sym_norm_adj)、随机游走归一化邻接矩阵(rw_norm_adj)等。
  • 返回计算得到的图结构操作矩阵 gso

2.calc_chebynet_gso(gso)

  • 这个函数用于对图结构操作矩阵 gso 进行进一步的处理,以确保其特征值的范围。
  • 如果输入的 gso 不对称且特征值较大,它会减去单位矩阵(id)。
  • 如果 gso 对称,它会将其缩放到特征值的范围在 2 以内。
  • 返回处理后的图结构操作矩阵 gso

3. cnv_sparse_mat_to_coo_tensor(sp_mat, device)

  • 这个函数用于将稀疏矩阵(sp_mat)转换为 PyTorch 的稀疏张量(Sparse COO Tensor)。
  • 它接受稀疏矩阵 sp_mat 和计算设备 device 作为输入参数。
  • 将稀疏矩阵转换为稀疏 COO 张量,并根据 sp_mat 的数据类型,将其转换为适当的 PyTorch 数据类型。
  • 返回稀疏 COO 张量。

4. evaluate_model(model, loss, data_iter)

  • 这个函数用于评估模型的性能,计算模型在给定数据集上的均方误差(MSE)。
  • 它接受训练好的 model、损失函数 loss 和数据迭代器 data_iter 作为输入。
  • 在模型评估过程中,它会迭代数据迭代器,计算模型的预测结果和实际标签之间的均方误差。
  • 返回均方误差(MSE)作为性能度量。

5. evaluate_metric(model, data_iter, scaler)

  • 这个函数用于评估模型的性能,计算模型在给定数据集上的多个性能指标,包括平均绝对误差(MAE)、均方根误差(RMSE)、加权平均绝对百分比误差(WMAPE)等。
  • 它接受训练好的 model、数据迭代器 data_iter 和标准化器 scaler 作为输入。
  • 在模型评估过程中,它会迭代数据迭代器,计算模型的预测结果和实际标签之间的误差,并计算多个性能指标。
  • 返回 MAE、RMSE 和 WMAPE 作为性能度量。

model

models.py

models.py 中定义了两个不同的模型类:STGCNChebGraphConvSTGCNGraphConv,它们用于处理空间-时间图卷积网络。这两个类主要包含了模型的结构以及前向传播的逻辑。

  1. STGCNChebGraphConv 模型类:

    • 这个类基于 "TGTND TGTND TNFF" 结构构建,包含了多个层次的图卷积层。
    • 模型使用 Chebyshev 多项式作为图卷积的滤波器,它有多个层次的 Gated Temporal Convolution Layer(GLU or GTU)和 Graph Convolution Layer(ChebGraphConv)。
    • 图中的 T 表示 Gated Temporal Convolution Layer,G 表示 Graph Convolution Layer,N 表示 Layer Normolization,D 表示 Dropout。
    • 这个模型适用于基于 Chebyshev 多项式的图卷积。
  2. STGCNGraphConv 模型类:

    • 这个类也基于 "TGTND TGTND TNFF" 结构构建,包含了多个层次的图卷积层。
    • STGCNChebGraphConv 不同,这个模型使用标准的 GCN(Graph Convolution Network)进行图卷积,而不是 Chebyshev 多项式。
    • 图中的 T 表示 Gated Temporal Convolution Layer,G 表示 Graph Convolution Layer,N 表示 Layer Normolization,D 表示 Dropout。
    • 这个模型适用于使用 GCN 进行图卷积的情况,采用了标准的 renormalization 技巧,防止过度平滑。

这两个模型类的构造函数都接受一些参数,包括 args(包含各种模型配置信息)、blocks(表示模型中不同层次的配置)、n_vertex(表示图中节点的数量)。模型类的主要组成部分包括:

  • STConvBlock:这是定义了 STGCN 中的每个图卷积块的类,包括图卷积层、激活函数、规范化和丢弃层等。
  • OutputBlock:这是定义了模型输出层的类,其中包括全连接层等。

前向传播的逻辑包括将输入数据经过一系列的 STConvBlock 层,然后根据 Ko(时间延迟步数)的不同值选择不同的输出处理方式。如果 Ko > 1,则通过 output 层进行处理;如果 Ko == 0,则使用全连接层进行处理。

layers.py

layers.py 中包含了用于构建 STGCN 模型中不同层次的模块和层定义。以下是这些层和模块的主要内容:

  1. Align 模块:

    • Align 模块用于调整输入的通道数,确保输入与输出的通道数一致。
    • 如果输入通道数大于输出通道数,它会应用 1x1 卷积层以减少通道数。
    • 如果输入通道数小于输出通道数,它会在通道维度上填充零,以增加通道数。
    • 这有助于保持一致的通道数以进行后续计算。
  2. CausalConv1dCausalConv2d 模块:

    • 这两个模块实现了因果卷积(Causal Convolution),在处理时间序列数据时常用。
    • CausalConv1d 用于处理 1D 数据,而 CausalConv2d 用于处理 2D 数据。
    • 这些模块的主要特点是具有 "因果性",即卷积操作不会使用未来的信息,只使用过去和当前的信息。
    • 这是通过适当设置填充参数来实现的。
  3. TemporalConvLayer 模块:

    • TemporalConvLayer 是一种时间卷积层,它采用 "GLU"(Gated Linear Unit)或其他激活函数处理输入数据。
    • 该层通过时间维度执行卷积操作,并使用 "GLU" 或其他激活函数将卷积结果与输入数据组合起来。
    • 可根据配置选择 "GLU"、ReLU 或 SiLU(Sigmoid-Weighted Linear Unit)激活函数。
    • 这个模块用于处理时间维度上的卷积操作,通常用于时间序列数据。
  4. ChebGraphConvGraphConv 模块:

    • 这两个模块分别实现了基于 Chebyshev 多项式的图卷积(ChebGraphConv)和标准图卷积(GraphConv)。
    • 这些模块用于在图结构数据上执行卷积操作,其中 ChebGraphConv 使用 Chebyshev 多项式,而 GraphConv 使用标准的卷积操作。
    • 这些卷积层可以在图数据上传播信息,用于处理图数据的特征。
  5. GraphConvLayer 模块:

    • GraphConvLayer 包含了一个时间卷积层(TemporalConvLayer)和一个图卷积层(ChebGraphConvGraphConv)。
    • 这个模块用于处理时空图数据,它接受输入数据,先在时间维度上执行时间卷积,然后在图结构上执行图卷积。
    • 这有助于在时空图数据中传播信息。
  6. STConvBlock 模块:

    • STConvBlock 表示一个完整的 ST-GCN 模型中的一个卷积块,包括了时间卷积、图卷积、激活函数和规范化。
    • 该块由多个卷积层组成,用于处理时空图数据。
    • 通过多个卷积层的组合,可以在时空图数据中提取特征。
  7. OutputBlock 模块:

    • OutputBlock 用于模型的输出层,包括时间卷积、全连接层和激活函数。
    • 这个模块用于生成模型的最终输出,通常用于预测任务。

这些模块和层在 ST-GCN 模型中的组合和堆叠,用于处理时空图数据,提取特征,并生成模型的输出。这有助于模型在各种时空图数据的任务中表现出色。

  • 3
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: GCN(Graph Convolutional Network)是一种用于图数据的深度学习模型,广泛应用于社交网络、推荐系统、生物学等领域。而PyTorch是一个基于Python的深度学习框架,提供了高效的自动求导机制和丰富的神经网络模块。 在PyTorch中实现GCN通常包括以下几个步骤: 1. 数据准备:将图数据表示为邻接矩阵和特征矩阵的形式。邻接矩阵描述了图中节点之间的连接关系,特征矩阵则包含了每个节点的特征向量。 2. 定义图卷积层:在PyTorch中,可以通过定义一个继承自`nn.Module`的新类来实现图卷积层。此类通常包括权重矩阵、激活函数和前向传播函数。权重矩阵用于将当前节点的特征与相邻节点的特征进行线性组合,激活函数则引入非线性变换。 3. 构建GCN模型:利用上述定义的图卷积层构建一个多层的GCN模型。在PyTorch中,可以通过将多个图卷积层串联起来构建一个`nn.Sequential`模型。 4. 定义损失函数和优化器:根据任务的不同,可以选择适合的损失函数来评估模型的性能,如交叉熵损失函数。同时,需要选择合适的优化器,如Adam优化器,用于更新模型的参数。 5. 训练模型:使用训练数据对模型进行训练。在每个训练迭代中,通过前向传播计算模型的输出,并与真实标签进行比较以计算损失。然后,使用反向传播算法计算梯度,并利用优化器更新模型的参数。 6. 测试模型:使用测试数据对训练好的模型进行测试。通过前向传播计算模型的输出,并与真实标签进行比较以评估模型的性能。 需要注意的是,在实现GCN过程中,还可以对模型进行一些调优,如添加正则化项、使用dropout技术等,以增强模型的泛化能力。此外,还可以使用一些效果更好的GCN变体,如GraphSAGE、GAT等。 综上所述,使用PyTorch实现GCN的过程涉及数据准备、图卷积层定义、GCN模型构建、损失函数和优化器选择、模型训练和测试等环节。掌握了这些步骤后,就可以利用PyTorch实现自己的GCN模型,并在图数据上进行监督学习任务。 ### 回答2: Graph Convolutional Network (GCN) 是一种用于图数据的深度学习模型,它在节点级别上进行特征表示学习和预测。下面是对GCN代码PyTorch中的讲解。 GCN代码的主要结构如下: 1. 定义图结构:首先,需要定义节点之间的图结构。常见的方式是使用邻接矩阵来表示图中的连接关系。 2. 定义图卷积层:GCN的核心是图卷积层,它采用邻居节点的特征来更新目标节点的特征。在PyTorch中,可以使用torch.nn模块中的GraphConvolution类来实现。 - 在GraphConvolution类中,首先需要定义输入特征的维度和输出特征的维度。 - 在forward方法中,通过邻接矩阵和输入特征,计算每个节点的邻居节点的加权和。 - 然后,通过激活函数(如ReLU)进行非线性变换,得到更新后的特征表示。 - 最后,返回更新后的节点特征。 3. 定义整个GCN模型:GCN模型由多个图卷积层组成。在PyTorch中,可以通过定义一个包含多个图卷积层的类来实现。 - 在类的初始化方法中,定义每一层的输入特征维度、输出特征维度以及层数。 - 在forward方法中,将输入特征作为第一层的输入,并通过多个图卷积层进行特征的传递和更新。 - 返回最后一层的节点特征表示。 4. 数据准备和训练:在训练GCN模型之前,需要准备好带标签的图数据集。可以使用常见的数据处理库(如DGL、NetworkX等)来加载和处理图数据。然后,使用PyTorch的数据加载工具(如DataLoader)将数据转换为可供GCN模型使用的格式。 5. 定义损失函数和优化器:根据具体的问题,选择适合的损失函数和优化器。常见的损失函数包括交叉熵损失函数(CrossEntropyLoss),均方误差损失函数(MSELoss)等。优化器一般选择Adam、SGD等。 6. 模型训练和验证:使用准备好的训练数据和测试数据,对GCN模型进行训练和验证。通过计算损失函数进行参数更新,并根据验证结果确定模型的优化方向。 以上就是对GCN代码PyTorch中的基本讲解。通过构建图结构、定义图卷积层和整个GCN模型,准备数据并进行训练,可以实现对图数据进行特征表示学习和预测的任务。 ### 回答3: GCN(Graph Convolutional Network)是一种用于图结构数据的深度学习模型,旨在解决图结构数据上的节点分类、链接预测等问题。PyTorch是一种广泛使用的深度学习框架,提供了灵活且高效的计算图表示和自动微分功能。 GCN的PyTorch代码讲解可以从以下几个方面展开: 1. 数据准备:首先,需要将图结构数据表示为邻接矩阵或稀疏矩阵的形式,并将其作为PyTorch的Tensor输入。同时,还需准备标签数据作为模型的监督信号。 2. 模型定义:使用PyTorch构建GCN模型,可以继承`torch.nn.Module`类,并在`forward`函数中定义模型的前向传播逻辑。在GCN中,通常包括图卷积层和非线性激活函数。可以使用`torch.nn`模块提供的函数或自定义函数实现这些操作。 3. 图卷积层:GCN的核心是图卷积层,它在前一层节点的特征基础上,通过邻居节点的信息来更新每个节点的特征表示。可以使用`torch_geometric`等第三方库提供的图卷积层实现,也可以自己编写代码实现。 4. 优化器和损失函数:将模型输出与标签数据进行比较,并定义损失函数衡量模型预测与真实标签之间的差异。可选择常见的损失函数,例如交叉熵损失函数,并使用PyTorch提供的优化器,如随机梯度下降(SGD)或Adam优化器。 5. 训练过程:定义训练过程的具体逻辑,包括正向传播、计算损失、反向传播、更新模型参数等步骤。可以设置训练迭代次数和学习率等超参数,并使用训练集和验证集对模型进行训练和评估。 总之,GCN的PyTorch代码实现主要包括数据准备、模型定义、图卷积层的实现、优化器和损失函数的选择、以及训练过程的编写。深入理解GCN模型的原理和PyTorch的使用,可以更好地理解和运用GCN的PyTorch代码
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值