>  기사  >  기술 주변기기  >  Pytorch 기하학을 사용한 링크 예측 코드 예

Pytorch 기하학을 사용한 링크 예측 코드 예

王林
王林앞으로
2023-10-20 19:33:08968검색

PyTorch 기하학(PyG)은 그래프 신경망 모델을 구축하고 다양한 그래프 컨볼루션을 실험하기 위한 주요 도구입니다. 이번 글에서는 링크 예측을 통해 소개하겠습니다.

使用Pytorch Geometric 进行链接预测代码示例

링크 예측은 다음 질문에 답합니다. 어떤 두 노드를 서로 연결해야 합니까? "변환 분할"을 수행하여 모델링할 데이터를 준비합니다. 일괄 처리를 위한 전용 그래프 데이터 로더를 준비합니다. Torch 기하학에서 모델을 구축하고, PyTorch Lightning을 사용하여 훈련하고, 모델 성능을 확인합니다.

라이브러리 준비

  • Torch 이것은 더 이상 소개할 필요가 없습니다
  • Torch는 기하학적 그래프 신경망의 주요 라이브러리이며 이 기사의 초점입니다
  • PyTorch Lightning은 모델을 훈련, 조정 및 검증하는 데 사용됩니다. 훈련 운영을 단순화합니다
  • Sklearn Metrics와 Torchmetrics는 모델의 성능을 확인하는 데 사용됩니다.
  • PyTorch 기하학에는 몇 가지 특정한 종속성이 있습니다. 설치하는 데 문제가 있는 경우 공식 문서를 참조하세요.

데이터 준비

Cora ML 인용 데이터세트를 사용하겠습니다. 데이터 세트는 Torch 기하학을 통해 액세스할 수 있습니다.

 data = tg.datasets.CitationFull(root="data", name="Cora_ML")

기본적으로 Torch 기하학 데이터세트는 여러 그래프를 반환할 수 있습니다. 단일 그래프가 어떻게 생겼는지 볼까요

data[0] > Data(x=[2995, 2879], edge_index=[2, 16316], y=[2995])

여기서 X는 노드의 기능입니다. edge_index는 2 x (n 모서리) 행렬입니다(첫 번째 차원 = 2, 행 0 - 소스 노드/"발신자", 행 1 - 대상 노드/"수신자"로 해석됨).

링크 분할

데이터세트의 링크를 분할하는 것부터 시작하겠습니다. 그래프 링크의 20%를 검증 세트로 사용하고 10%를 테스트 세트로 사용합니다. 이러한 네거티브 링크는 배치 데이터 로더에 의해 즉시 생성되므로 네거티브 샘플은 훈련 데이터 세트에 추가되지 않습니다.

일반적으로 네거티브 샘플링은 "가짜" 샘플(이 경우 노드 간 링크)을 생성하므로 모델은 실제 링크와 가짜 링크를 구별하는 방법을 학습합니다. 네거티브 샘플링은 샘플링의 이론과 수학을 기반으로 하며 몇 가지 훌륭한 통계적 특성을 가지고 있습니다.

첫 번째: 링크 분할 개체를 만들어 보겠습니다.

 link_splitter = tg.transforms.RandomLinkSplit(num_val=0.2, num_test=0.1, add_negative_train_samples=False,disjoint_train_ratio=0.8)

disjoint_train_ratio는 "감독" 단계에서 훈련 정보로 사용될 가장자리 수를 조정합니다. 나머지 에지는 메시지 전달(네트워크의 정보 전송 단계)에 사용됩니다.

그래프 신경망에서 에지를 분할하는 방법에는 유도 분할과 전도성 분할이라는 두 가지 이상의 방법이 있습니다. 변환 방법은 GNN이 그래프 구조에서 구조적 패턴을 학습해야 한다고 가정합니다. 귀납적 설정에서는 노드/에지 레이블을 학습에 사용할 수 있습니다. 이 문서의 끝 부분에는 이러한 개념을 자세히 논의하고 추가 형식화를 제공하는 두 개의 문서가 있습니다: ([1], [3]).

 train_g, val_g, test_g = link_splitter(data[0])  > Data(x=[2995, 2879], edge_index=[2, 2285], y=[2995], edge_label=[9137], edge_label_index=[2, 9137])

이 작업 후에는 몇 가지 새로운 속성이 있습니다.

edge_label: 가장자리가 참/거짓인지 설명합니다. 이것이 우리가 예측하고 싶은 것입니다.

edge_label_index는 노드 링크를 저장하는 데 사용되는 2 x NUM EDGES 매트릭스입니다.

샘플 분포를 살펴보겠습니다

th.unique(train_g.edge_label, return_counts=True) > (tensor([1.]), tensor([9137]))  th.unique(val_g.edge_label, return_counts=True) > (tensor([0., 1.]), tensor([3263, 3263]))  th.unique(val_g.edge_label, return_counts=True) > (tensor([0., 1.]), tensor([3263, 3263]))

훈련 데이터에는 음의 가장자리가 없으며(훈련 중에 생성할 것입니다), val/test 세트에는 이미 50에 "가짜" 링크가 있습니다. 50 비율.

Model

이제

클래스 GNN(nn.Module):

def __init__(self, dim_in: int, conv_sizes: Tuple[int, ...], act_f: nn.Module = th.relu, dropout: float = 0.1,*args, **kwargs):super().__init__()self.dim_in = dim_inself.dim_out = conv_sizes[-1]self.dropout = dropoutself.act_f = act_flast_in = dim_inlayers = [] # Here we build subsequent graph convolutions.for conv_sz in conv_sizes:# Single graph convolution layerconv = tgnn.SAGEConv(in_channels=last_in, out_channels=conv_sz, *args, **kwargs)last_in = conv_szlayers.append(conv)self.layers = nn.ModuleList(layers) def forward(self, x: th.Tensor, edge_index: th.Tensor) -> th.Tensor:h = x# For every graph convolution in the network...for conv in self.layers:# ... perform node embedding via message passingh = conv(h, edge_index)h = self.act_f(h)if self.dropout:h = nn.functional.dropout(h, p=self.dropout, training=self.training)return h

을 구축하여 GNN을 사용하여 모델을 구축할 수 있습니다. 이 모델에서 주목할만한 부분은 그래프 컨볼루션 세트입니다. 우리의 경우에는 SAGEConv입니다. SAGE 컨볼루션의 공식적인 정의는 다음과 같습니다.

使用Pytorch Geometric 进行链接预测代码示例åholdç

v는 현재 노드이고 노드 v의 N(v) 이웃입니다. 이러한 유형의 컨볼루션에 대해 자세히 알아보려면 GraphSAGE[1]의 원본 논문을 확인하세요.

모델이 준비된 데이터를 사용하여 예측을 할 수 있는지 확인해 보겠습니다. 여기서 PyG 모델에 대한 입력은 노드 특성 X의 행렬과 edge_index를 정의하는 링크입니다.

gnn = GNN(train_g.x.size()[1], conv_sizes=[512, 256, 128]) with th.no_grad():out = gnn(train_g.x, train_g.edge_index)  out   > tensor([[0.0000, 0.0000, 0.0051, ..., 0.0997, 0.0000, 0.0000],[0.0107, 0.0000, 0.0576, ..., 0.0651, 0.0000, 0.0000],[0.0000, 0.0000, 0.0102, ..., 0.0973, 0.0000, 0.0000],...,[0.0000, 0.0000, 0.0549, ..., 0.0671, 0.0000, 0.0000],[0.0000, 0.0000, 0.0166, ..., 0.0000, 0.0000, 0.0000],[0.0000, 0.0000, 0.0034, ..., 0.1111, 0.0000, 0.0000]])

우리 모델의 출력은 N 노드 x 임베딩 크기 차원의 노드 임베딩 행렬입니다.

PyTorch Lightning

PyTorch Lightning은 주로 훈련에 사용되지만 여기서는 연결 여부를 예측하기 위한 출력 헤드로 GNN 출력 뒤에 선형 레이어를 추가합니다.

class LinkPredModel(pl.LightningModule):

def __init__(self,dim_in: int,conv_sizes: Tuple[int, ...], act_f: nn.Module = th.relu, dropout: float = 0.1,lr: float = 0.01,*args, **kwargs):super().__init__() # Our inner GNN modelself.gnn = GNN(dim_in, conv_sizes=conv_sizes, act_f=act_f, dropout=dropout) # Final prediction model on links.self.lin_pred = nn.Linear(self.gnn.dim_out, 1)self.lr = lr def forward(self, x: th.Tensor, edge_index: th.Tensor) -> th.Tensor:# Step 1: make node embeddings using GNN.h = self.gnn(x, edge_index) # Take source nodes embeddings- sendersh_src = h[edge_index[0, :]]# Take target node embeddings - receiversh_dst = h[edge_index[1, :]] # Calculate the product between themsrc_dst_mult = h_src * h_dst# Apply non-linearityout = self.lin_pred(src_dst_mult)return out def _step(self, batch: th.Tensor, phase: str='train') -> th.Tensor:yhat_edge = self(batch.x, batch.edge_label_index).squeeze()y = batch.edge_labelloss = nn.functional.binary_cross_entropy_with_logits(input=yhat_edge, target=y)f1 = tm.functional.f1_score(preds=yhat_edge, target=y, task='binary')prec = tm.functional.precision(preds=yhat_edge, target=y, task='binary')recall = tm.functional.recall(preds=yhat_edge, target=y, task='binary') # Watch for logging here - we need to provide batch_size, as (at the time of this implementation)# PL cannot understand the batch size.self.log(f"{phase}_f1", f1, batch_size=batch.edge_label_index.shape[1])self.log(f"{phase}_loss", loss, batch_size=batch.edge_label_index.shape[1])self.log(f"{phase}_precision", prec, batch_size=batch.edge_label_index.shape[1])self.log(f"{phase}_recall", recall, batch_size=batch.edge_label_index.shape[1])return loss def training_step(self, batch, batch_idx):return self._step(batch) def validation_step(self, batch, batch_idx):return self._step(batch, "val") def test_step(self, batch, batch_idx):return self._step(batch, "test") def predict_step(self, batch):x, edge_index = batchreturn self(x, edge_index) def configure_optimizers(self):return th.optim.Adam(self.parameters(), lr=self.lr)

PyTorch Lightning의 역할은 훈련 단계를 단순화하는 데 도움이 됩니다. 다음 명령을 사용하여 모델을 사용할 수 있는지 테스트할 수 있습니다.

Training

훈련 단계에서는 데이터 로더에 특별한 처리가 필요합니다.

그래프 데이터에는 특별한 처리가 필요합니다. 특히 링크 예측이 필요합니다. PyG에는 배치를 올바르게 생성하는 일을 담당하는 특수한 데이터 로더 클래스가 있습니다. 다음 입력을 허용하는 tg.loader.LinkNeighborLoader를 사용합니다:

대량으로 로드할 데이터(이미지). num_neighbors 한 번의 "홉" 동안 노드당 로드할 최대 이웃 수입니다. 이웃 수 1 - 2 - 3 -…-K를 지정하는 목록입니다. 매우 큰 그래픽에 특히 유용합니다.

edge_label_index 속성은 이미 참/거짓 링크를 나타냅니다.

neg_sampling_ratio - 실제 샘플에 대한 음성 샘플의 비율입니다.

 model = LinkPredModel(val_g.x.size()[1], conv_sizes=[512, 256, 128]) with th.no_grad():out = model.predict_step((val_g.x, val_g.edge_label_index))
다음은 학습 모델입니다

 train_loader = tg.loader.LinkNeighborLoader(train_g,num_neighbors=[-1, 10, 5],batch_size=128,edge_label_index=train_g.edge_label_index, # "on the fly" negative sampling creation for batchneg_sampling_ratio=0.5 )  val_loader = tg.loader.LinkNeighborLoader(val_g,num_neighbors=[-1, 10, 5],batch_size=128,edge_label_index=val_g.edge_label_index,edge_label=val_g.edge_label, # negative samples for val set are done already as ground-truthneg_sampling_ratio=0.0 )  test_loader = tg.loader.LinkNeighborLoader(test_g,num_neighbors=[-1, 10, 5],batch_size=128,edge_label_index=test_g.edge_label_index,edge_label=test_g.edge_label, # negative samples for test set are done already as ground-truthneg_sampling_ratio=0.0 )
테스트 데이터 검증, 분류 보고서 및 ROC 곡선을 확인하세요.

model = LinkPredModel(val_g.x.size()[1], conv_sizes=[512, 256, 128]) trainer = pl.Trainer(max_epochs=20, log_every_n_steps=5)  # Validate before training - we will see results of untrained model. trainer.validate(model, val_loader)  # Train the model trainer.fit(model=model, train_dataloaders=train_loader, val_dataloaders=val_loader)
결과가 꽤 좋아 보이네요:

precision recall f1-score support0.0 0.68 0.70 0.69 16311.0 0.69 0.66 0.68 1631accuracy 0.68 3262macro avg 0.68 0.68 0.68 3262

ROC曲线也不错

使用Pytorch Geometric 进行链接预测代码示例

我们训练的模型并不特别复杂,也没有经过精心调整,但它完成了工作。当然这只是一个为了演示使用的小型数据集。

总结

图神经网络尽管看起来很复杂,但是PyTorch Geometric为我们提供了一个很好的解决方案。我们可以直接使用其中内置的模型实现,这方便了我们使用和简化了入门的门槛。

本文代码:https://github.com/maddataanalyst/blogposts_code/blob/main/graph_nns_series/pyg_pyl_perfect_match/pytorch-geometric-lightning-perfect-match.ipynb

위 내용은 Pytorch 기하학을 사용한 링크 예측 코드 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 51cto.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제