Tutorial 6: GAE & VGAE¶
Graph AutoEncoders GAE &
Variational Graph Autoencoders VGAE
Graph AutoEncoder GAE¶
[ ]:
import os
import torch
os.environ['TORCH'] = torch.__version__
print(torch.__version__)
!pip install -q torch-scatter -f https://data.pyg.org/whl/torch-${TORCH}.html
!pip install -q torch-sparse -f https://data.pyg.org/whl/torch-${TORCH}.html
!pip install -q git+https://github.com/pyg-team/pytorch_geometric.git
1.12.1+cu113
|████████████████████████████████| 7.9 MB 2.9 MB/s
|████████████████████████████████| 3.5 MB 2.9 MB/s
Building wheel for torch-geometric (setup.py) ... done
[ ]:
import torch
from torch_geometric.datasets import Planetoid
import torch_geometric.transforms as T
from torch_geometric.nn import GCNConv
from torch_geometric.utils import train_test_split_edges
Load the data¶
[ ]:
dataset = Planetoid("\..", "CiteSeer", transform=T.NormalizeFeatures())
dataset.data
Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.x
Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.tx
Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.allx
Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.y
Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.ty
Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.ally
Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.graph
Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.test.index
Processing...
Done!
Data(x=[3327, 3703], edge_index=[2, 9104], y=[3327], train_mask=[3327], val_mask=[3327], test_mask=[3327])
[ ]:
data = dataset[0]
data.train_mask = data.val_mask = data.test_mask = None
data
Data(x=[3327, 3703], edge_index=[2, 9104], y=[3327])
[ ]:
data = train_test_split_edges(data)
/usr/local/lib/python3.7/dist-packages/torch_geometric/deprecation.py:12: UserWarning: 'train_test_split_edges' is deprecated, use 'transforms.RandomLinkSplit' instead
warnings.warn(out)
[ ]:
data
Data(x=[3327, 3703], y=[3327], val_pos_edge_index=[2, 227], test_pos_edge_index=[2, 455], train_pos_edge_index=[2, 7740], train_neg_adj_mask=[3327, 3327], val_neg_edge_index=[2, 227], test_neg_edge_index=[2, 455])
Define the Encoder¶
[ ]:
class GCNEncoder(torch.nn.Module):
def __init__(self, in_channels, out_channels):
super(GCNEncoder, self).__init__()
self.conv1 = GCNConv(in_channels, 2 * out_channels, cached=True) # cached only for transductive learning
self.conv2 = GCNConv(2 * out_channels, out_channels, cached=True) # cached only for transductive learning
def forward(self, x, edge_index):
x = self.conv1(x, edge_index).relu()
return self.conv2(x, edge_index)
Define the Autoencoder¶
[ ]:
from torch_geometric.nn import GAE
[ ]:
# parameters
out_channels = 2
num_features = dataset.num_features
epochs = 100
# model
model = GAE(GCNEncoder(num_features, out_channels))
# move to GPU (if available)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = model.to(device)
x = data.x.to(device)
train_pos_edge_index = data.train_pos_edge_index.to(device)
# inizialize the optimizer
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
[ ]:
def train():
model.train()
optimizer.zero_grad()
z = model.encode(x, train_pos_edge_index)
loss = model.recon_loss(z, train_pos_edge_index)
#if args.variational:
# loss = loss + (1 / data.num_nodes) * model.kl_loss()
loss.backward()
optimizer.step()
return float(loss)
def test(pos_edge_index, neg_edge_index):
model.eval()
with torch.no_grad():
z = model.encode(x, train_pos_edge_index)
return model.test(z, pos_edge_index, neg_edge_index)
[ ]:
for epoch in range(1, epochs + 1):
loss = train()
auc, ap = test(data.test_pos_edge_index, data.test_neg_edge_index)
print('Epoch: {:03d}, AUC: {:.4f}, AP: {:.4f}'.format(epoch, auc, ap))
Epoch: 001, AUC: 0.6337, AP: 0.6519
Epoch: 002, AUC: 0.6552, AP: 0.6692
Epoch: 003, AUC: 0.6580, AP: 0.6722
Epoch: 004, AUC: 0.6616, AP: 0.6797
Epoch: 005, AUC: 0.6632, AP: 0.6863
Epoch: 006, AUC: 0.6626, AP: 0.6855
Epoch: 007, AUC: 0.6621, AP: 0.6845
Epoch: 008, AUC: 0.6620, AP: 0.6862
Epoch: 009, AUC: 0.6618, AP: 0.6885
Epoch: 010, AUC: 0.6615, AP: 0.6903
Epoch: 011, AUC: 0.6612, AP: 0.6919
Epoch: 012, AUC: 0.6610, AP: 0.6933
Epoch: 013, AUC: 0.6604, AP: 0.6951
Epoch: 014, AUC: 0.6600, AP: 0.6980
Epoch: 015, AUC: 0.6597, AP: 0.7008
Epoch: 016, AUC: 0.6591, AP: 0.7037
Epoch: 017, AUC: 0.6580, AP: 0.7055
Epoch: 018, AUC: 0.6575, AP: 0.7077
Epoch: 019, AUC: 0.6571, AP: 0.7103
Epoch: 020, AUC: 0.6569, AP: 0.7115
Epoch: 021, AUC: 0.6568, AP: 0.7126
Epoch: 022, AUC: 0.6572, AP: 0.7140
Epoch: 023, AUC: 0.6575, AP: 0.7156
Epoch: 024, AUC: 0.6576, AP: 0.7160
Epoch: 025, AUC: 0.6581, AP: 0.7170
Epoch: 026, AUC: 0.6589, AP: 0.7179
Epoch: 027, AUC: 0.6599, AP: 0.7190
Epoch: 028, AUC: 0.6614, AP: 0.7207
Epoch: 029, AUC: 0.6642, AP: 0.7226
Epoch: 030, AUC: 0.6675, AP: 0.7248
Epoch: 031, AUC: 0.6728, AP: 0.7279
Epoch: 032, AUC: 0.6793, AP: 0.7310
Epoch: 033, AUC: 0.6861, AP: 0.7349
Epoch: 034, AUC: 0.6937, AP: 0.7385
Epoch: 035, AUC: 0.7008, AP: 0.7417
Epoch: 036, AUC: 0.7081, AP: 0.7452
Epoch: 037, AUC: 0.7170, AP: 0.7496
Epoch: 038, AUC: 0.7271, AP: 0.7550
Epoch: 039, AUC: 0.7404, AP: 0.7618
Epoch: 040, AUC: 0.7528, AP: 0.7688
Epoch: 041, AUC: 0.7631, AP: 0.7748
Epoch: 042, AUC: 0.7691, AP: 0.7786
Epoch: 043, AUC: 0.7730, AP: 0.7811
Epoch: 044, AUC: 0.7755, AP: 0.7828
Epoch: 045, AUC: 0.7782, AP: 0.7846
Epoch: 046, AUC: 0.7807, AP: 0.7862
Epoch: 047, AUC: 0.7833, AP: 0.7879
Epoch: 048, AUC: 0.7862, AP: 0.7899
Epoch: 049, AUC: 0.7886, AP: 0.7913
Epoch: 050, AUC: 0.7892, AP: 0.7917
Epoch: 051, AUC: 0.7897, AP: 0.7919
Epoch: 052, AUC: 0.7902, AP: 0.7921
Epoch: 053, AUC: 0.7906, AP: 0.7924
Epoch: 054, AUC: 0.7910, AP: 0.7927
Epoch: 055, AUC: 0.7917, AP: 0.7933
Epoch: 056, AUC: 0.7923, AP: 0.7934
Epoch: 057, AUC: 0.7920, AP: 0.7930
Epoch: 058, AUC: 0.7919, AP: 0.7926
Epoch: 059, AUC: 0.7924, AP: 0.7928
Epoch: 060, AUC: 0.7935, AP: 0.7941
Epoch: 061, AUC: 0.7944, AP: 0.7951
Epoch: 062, AUC: 0.7952, AP: 0.7958
Epoch: 063, AUC: 0.7956, AP: 0.7961
Epoch: 064, AUC: 0.7955, AP: 0.7959
Epoch: 065, AUC: 0.7963, AP: 0.7965
Epoch: 066, AUC: 0.7975, AP: 0.7974
Epoch: 067, AUC: 0.7988, AP: 0.7985
Epoch: 068, AUC: 0.8003, AP: 0.7996
Epoch: 069, AUC: 0.8012, AP: 0.8003
Epoch: 070, AUC: 0.8015, AP: 0.8005
Epoch: 071, AUC: 0.8021, AP: 0.8005
Epoch: 072, AUC: 0.8021, AP: 0.8006
Epoch: 073, AUC: 0.8022, AP: 0.8007
Epoch: 074, AUC: 0.8031, AP: 0.8013
Epoch: 075, AUC: 0.8044, AP: 0.8024
Epoch: 076, AUC: 0.8055, AP: 0.8034
Epoch: 077, AUC: 0.8063, AP: 0.8042
Epoch: 078, AUC: 0.8070, AP: 0.8045
Epoch: 079, AUC: 0.8067, AP: 0.8043
Epoch: 080, AUC: 0.8063, AP: 0.8042
Epoch: 081, AUC: 0.8061, AP: 0.8041
Epoch: 082, AUC: 0.8068, AP: 0.8049
Epoch: 083, AUC: 0.8077, AP: 0.8058
Epoch: 084, AUC: 0.8090, AP: 0.8068
Epoch: 085, AUC: 0.8101, AP: 0.8078
Epoch: 086, AUC: 0.8105, AP: 0.8080
Epoch: 087, AUC: 0.8106, AP: 0.8081
Epoch: 088, AUC: 0.8102, AP: 0.8078
Epoch: 089, AUC: 0.8098, AP: 0.8078
Epoch: 090, AUC: 0.8092, AP: 0.8074
Epoch: 091, AUC: 0.8091, AP: 0.8072
Epoch: 092, AUC: 0.8098, AP: 0.8076
Epoch: 093, AUC: 0.8105, AP: 0.8078
Epoch: 094, AUC: 0.8112, AP: 0.8084
Epoch: 095, AUC: 0.8114, AP: 0.8086
Epoch: 096, AUC: 0.8112, AP: 0.8083
Epoch: 097, AUC: 0.8103, AP: 0.8077
Epoch: 098, AUC: 0.8096, AP: 0.8073
Epoch: 099, AUC: 0.8097, AP: 0.8074
Epoch: 100, AUC: 0.8106, AP: 0.8079
[ ]:
Z = model.encode(x, train_pos_edge_index)
Z
tensor([[ 0.5298, -0.5418],
[-1.0118, 1.0432],
[ 0.7511, -0.7225],
...,
[-0.4363, 0.4364],
[ 0.7787, -0.7425],
[ 0.7711, -0.7370]], grad_fn=<AddBackward0>)
Are the results (AUC) and (AP) easy to read and compare?¶
Use Tensorboard¶
[ ]:
from torch.utils.tensorboard import SummaryWriter
[ ]:
# parameters
out_channels = 2
num_features = dataset.num_features
epochs = 100
# model
model = GAE(GCNEncoder(num_features, out_channels))
# move to GPU (if available)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = model.to(device)
x = data.x.to(device)
train_pos_edge_index = data.train_pos_edge_index.to(device)
# inizialize the optimizer
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
Import tensorboard¶
Installation: (if needed) “pip install tensorboard”¶
[ ]:
writer = SummaryWriter('runs/GAE1_experiment_'+'2d_100_epochs')
[ ]:
for epoch in range(1, epochs + 1):
loss = train()
auc, ap = test(data.test_pos_edge_index, data.test_neg_edge_index)
print('Epoch: {:03d}, AUC: {:.4f}, AP: {:.4f}'.format(epoch, auc, ap))
writer.add_scalar('auc train',auc,epoch) # new line
writer.add_scalar('ap train',ap,epoch) # new line
Epoch: 001, AUC: 0.6347, AP: 0.6360
Epoch: 002, AUC: 0.6439, AP: 0.6539
Epoch: 003, AUC: 0.6446, AP: 0.6555
Epoch: 004, AUC: 0.6477, AP: 0.6601
Epoch: 005, AUC: 0.6503, AP: 0.6644
Epoch: 006, AUC: 0.6523, AP: 0.6686
Epoch: 007, AUC: 0.6535, AP: 0.6723
Epoch: 008, AUC: 0.6542, AP: 0.6742
Epoch: 009, AUC: 0.6542, AP: 0.6751
Epoch: 010, AUC: 0.6543, AP: 0.6766
Epoch: 011, AUC: 0.6543, AP: 0.6787
Epoch: 012, AUC: 0.6549, AP: 0.6810
Epoch: 013, AUC: 0.6551, AP: 0.6834
Epoch: 014, AUC: 0.6551, AP: 0.6856
Epoch: 015, AUC: 0.6555, AP: 0.6895
Epoch: 016, AUC: 0.6555, AP: 0.6924
Epoch: 017, AUC: 0.6553, AP: 0.6956
Epoch: 018, AUC: 0.6555, AP: 0.6995
Epoch: 019, AUC: 0.6553, AP: 0.7023
Epoch: 020, AUC: 0.6547, AP: 0.7048
Epoch: 021, AUC: 0.6540, AP: 0.7062
Epoch: 022, AUC: 0.6533, AP: 0.7078
Epoch: 023, AUC: 0.6524, AP: 0.7085
Epoch: 024, AUC: 0.6517, AP: 0.7091
Epoch: 025, AUC: 0.6518, AP: 0.7101
Epoch: 026, AUC: 0.6521, AP: 0.7116
Epoch: 027, AUC: 0.6524, AP: 0.7128
Epoch: 028, AUC: 0.6533, AP: 0.7147
Epoch: 029, AUC: 0.6548, AP: 0.7165
Epoch: 030, AUC: 0.6569, AP: 0.7181
Epoch: 031, AUC: 0.6596, AP: 0.7201
Epoch: 032, AUC: 0.6632, AP: 0.7225
Epoch: 033, AUC: 0.6685, AP: 0.7254
Epoch: 034, AUC: 0.6738, AP: 0.7281
Epoch: 035, AUC: 0.6794, AP: 0.7307
Epoch: 036, AUC: 0.6874, AP: 0.7343
Epoch: 037, AUC: 0.6978, AP: 0.7392
Epoch: 038, AUC: 0.7114, AP: 0.7455
Epoch: 039, AUC: 0.7239, AP: 0.7519
Epoch: 040, AUC: 0.7368, AP: 0.7587
Epoch: 041, AUC: 0.7481, AP: 0.7653
Epoch: 042, AUC: 0.7575, AP: 0.7708
Epoch: 043, AUC: 0.7646, AP: 0.7751
Epoch: 044, AUC: 0.7717, AP: 0.7798
Epoch: 045, AUC: 0.7767, AP: 0.7830
Epoch: 046, AUC: 0.7814, AP: 0.7863
Epoch: 047, AUC: 0.7843, AP: 0.7883
Epoch: 048, AUC: 0.7876, AP: 0.7905
Epoch: 049, AUC: 0.7894, AP: 0.7918
Epoch: 050, AUC: 0.7906, AP: 0.7927
Epoch: 051, AUC: 0.7914, AP: 0.7931
Epoch: 052, AUC: 0.7917, AP: 0.7935
Epoch: 053, AUC: 0.7928, AP: 0.7942
Epoch: 054, AUC: 0.7933, AP: 0.7947
Epoch: 055, AUC: 0.7934, AP: 0.7947
Epoch: 056, AUC: 0.7939, AP: 0.7951
Epoch: 057, AUC: 0.7940, AP: 0.7952
Epoch: 058, AUC: 0.7941, AP: 0.7953
Epoch: 059, AUC: 0.7946, AP: 0.7958
Epoch: 060, AUC: 0.7953, AP: 0.7967
Epoch: 061, AUC: 0.7962, AP: 0.7973
Epoch: 062, AUC: 0.7971, AP: 0.7982
Epoch: 063, AUC: 0.7974, AP: 0.7983
Epoch: 064, AUC: 0.7974, AP: 0.7981
Epoch: 065, AUC: 0.7975, AP: 0.7981
Epoch: 066, AUC: 0.7979, AP: 0.7983
Epoch: 067, AUC: 0.7990, AP: 0.7994
Epoch: 068, AUC: 0.8003, AP: 0.8008
Epoch: 069, AUC: 0.8010, AP: 0.8018
Epoch: 070, AUC: 0.8018, AP: 0.8025
Epoch: 071, AUC: 0.8023, AP: 0.8027
Epoch: 072, AUC: 0.8023, AP: 0.8028
Epoch: 073, AUC: 0.8029, AP: 0.8035
Epoch: 074, AUC: 0.8038, AP: 0.8041
Epoch: 075, AUC: 0.8051, AP: 0.8048
Epoch: 076, AUC: 0.8064, AP: 0.8059
Epoch: 077, AUC: 0.8067, AP: 0.8059
Epoch: 078, AUC: 0.8062, AP: 0.8057
Epoch: 079, AUC: 0.8057, AP: 0.8054
Epoch: 080, AUC: 0.8057, AP: 0.8055
Epoch: 081, AUC: 0.8063, AP: 0.8058
Epoch: 082, AUC: 0.8075, AP: 0.8069
Epoch: 083, AUC: 0.8077, AP: 0.8069
Epoch: 084, AUC: 0.8077, AP: 0.8068
Epoch: 085, AUC: 0.8078, AP: 0.8069
Epoch: 086, AUC: 0.8081, AP: 0.8073
Epoch: 087, AUC: 0.8083, AP: 0.8075
Epoch: 088, AUC: 0.8086, AP: 0.8078
Epoch: 089, AUC: 0.8089, AP: 0.8078
Epoch: 090, AUC: 0.8095, AP: 0.8083
Epoch: 091, AUC: 0.8097, AP: 0.8084
Epoch: 092, AUC: 0.8097, AP: 0.8084
Epoch: 093, AUC: 0.8098, AP: 0.8086
Epoch: 094, AUC: 0.8101, AP: 0.8088
Epoch: 095, AUC: 0.8103, AP: 0.8090
Epoch: 096, AUC: 0.8108, AP: 0.8094
Epoch: 097, AUC: 0.8110, AP: 0.8090
Epoch: 098, AUC: 0.8111, AP: 0.8091
Epoch: 099, AUC: 0.8110, AP: 0.8092
Epoch: 100, AUC: 0.8107, AP: 0.8089
Graph Variational AutoEncoder (GVAE)¶
[ ]:
from torch_geometric.nn import VGAE
[ ]:
dataset = Planetoid("\..", "CiteSeer", transform=T.NormalizeFeatures())
data = dataset[0]
data.train_mask = data.val_mask = data.test_mask = data.y = None
data = train_test_split_edges(data)
class VariationalGCNEncoder(torch.nn.Module):
def __init__(self, in_channels, out_channels):
super(VariationalGCNEncoder, self).__init__()
self.conv1 = GCNConv(in_channels, 2 * out_channels, cached=True) # cached only for transductive learning
self.conv_mu = GCNConv(2 * out_channels, out_channels, cached=True)
self.conv_logstd = GCNConv(2 * out_channels, out_channels, cached=True)
def forward(self, x, edge_index):
x = self.conv1(x, edge_index).relu()
return self.conv_mu(x, edge_index), self.conv_logstd(x, edge_index)
/usr/local/lib/python3.7/dist-packages/torch_geometric/deprecation.py:12: UserWarning: 'train_test_split_edges' is deprecated, use 'transforms.RandomLinkSplit' instead
warnings.warn(out)
[ ]:
out_channels = 2
num_features = dataset.num_features
epochs = 300
model = VGAE(VariationalGCNEncoder(num_features, out_channels)) # new line
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = model.to(device)
x = data.x.to(device)
train_pos_edge_index = data.train_pos_edge_index.to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
[ ]:
def train():
model.train()
optimizer.zero_grad()
z = model.encode(x, train_pos_edge_index)
loss = model.recon_loss(z, train_pos_edge_index)
loss = loss + (1 / data.num_nodes) * model.kl_loss() # new line
loss.backward()
optimizer.step()
return float(loss)
def test(pos_edge_index, neg_edge_index):
model.eval()
with torch.no_grad():
z = model.encode(x, train_pos_edge_index)
return model.test(z, pos_edge_index, neg_edge_index)
[ ]:
writer = SummaryWriter('runs/VGAE_experiment_'+'2d_100_epochs')
for epoch in range(1, epochs + 1):
loss = train()
auc, ap = test(data.test_pos_edge_index, data.test_neg_edge_index)
print('Epoch: {:03d}, AUC: {:.4f}, AP: {:.4f}'.format(epoch, auc, ap))
writer.add_scalar('auc train',auc,epoch) # new line
writer.add_scalar('ap train',ap,epoch) # new line
Epoch: 001, AUC: 0.6136, AP: 0.6422
Epoch: 002, AUC: 0.6263, AP: 0.6626
Epoch: 003, AUC: 0.6308, AP: 0.6676
Epoch: 004, AUC: 0.6333, AP: 0.6699
Epoch: 005, AUC: 0.6336, AP: 0.6702
Epoch: 006, AUC: 0.6337, AP: 0.6702
Epoch: 007, AUC: 0.6334, AP: 0.6699
Epoch: 008, AUC: 0.6343, AP: 0.6703
Epoch: 009, AUC: 0.6359, AP: 0.6710
Epoch: 010, AUC: 0.6369, AP: 0.6710
Epoch: 011, AUC: 0.6374, AP: 0.6703
Epoch: 012, AUC: 0.6368, AP: 0.6687
Epoch: 013, AUC: 0.6346, AP: 0.6665
Epoch: 014, AUC: 0.6301, AP: 0.6624
Epoch: 015, AUC: 0.6231, AP: 0.6573
Epoch: 016, AUC: 0.6175, AP: 0.6534
Epoch: 017, AUC: 0.6119, AP: 0.6499
Epoch: 018, AUC: 0.6091, AP: 0.6483
Epoch: 019, AUC: 0.6122, AP: 0.6520
Epoch: 020, AUC: 0.6227, AP: 0.6605
Epoch: 021, AUC: 0.6325, AP: 0.6692
Epoch: 022, AUC: 0.6374, AP: 0.6754
Epoch: 023, AUC: 0.6403, AP: 0.6805
Epoch: 024, AUC: 0.6431, AP: 0.6848
Epoch: 025, AUC: 0.6446, AP: 0.6874
Epoch: 026, AUC: 0.6455, AP: 0.6884
Epoch: 027, AUC: 0.6463, AP: 0.6892
Epoch: 028, AUC: 0.6472, AP: 0.6900
Epoch: 029, AUC: 0.6482, AP: 0.6903
Epoch: 030, AUC: 0.6490, AP: 0.6908
Epoch: 031, AUC: 0.6495, AP: 0.6910
Epoch: 032, AUC: 0.6500, AP: 0.6913
Epoch: 033, AUC: 0.6502, AP: 0.6916
Epoch: 034, AUC: 0.6507, AP: 0.6920
Epoch: 035, AUC: 0.6510, AP: 0.6925
Epoch: 036, AUC: 0.6512, AP: 0.6930
Epoch: 037, AUC: 0.6516, AP: 0.6939
Epoch: 038, AUC: 0.6516, AP: 0.6946
Epoch: 039, AUC: 0.6516, AP: 0.6951
Epoch: 040, AUC: 0.6517, AP: 0.6958
Epoch: 041, AUC: 0.6516, AP: 0.6967
Epoch: 042, AUC: 0.6515, AP: 0.6978
Epoch: 043, AUC: 0.6515, AP: 0.6989
Epoch: 044, AUC: 0.6513, AP: 0.7002
Epoch: 045, AUC: 0.6509, AP: 0.7016
Epoch: 046, AUC: 0.6511, AP: 0.7034
Epoch: 047, AUC: 0.6508, AP: 0.7049
Epoch: 048, AUC: 0.6507, AP: 0.7065
Epoch: 049, AUC: 0.6502, AP: 0.7080
Epoch: 050, AUC: 0.6494, AP: 0.7092
Epoch: 051, AUC: 0.6488, AP: 0.7104
Epoch: 052, AUC: 0.6480, AP: 0.7111
Epoch: 053, AUC: 0.6475, AP: 0.7119
Epoch: 054, AUC: 0.6467, AP: 0.7127
Epoch: 055, AUC: 0.6461, AP: 0.7135
Epoch: 056, AUC: 0.6460, AP: 0.7140
Epoch: 057, AUC: 0.6460, AP: 0.7149
Epoch: 058, AUC: 0.6462, AP: 0.7160
Epoch: 059, AUC: 0.6459, AP: 0.7162
Epoch: 060, AUC: 0.6458, AP: 0.7167
Epoch: 061, AUC: 0.6463, AP: 0.7176
Epoch: 062, AUC: 0.6463, AP: 0.7182
Epoch: 063, AUC: 0.6466, AP: 0.7190
Epoch: 064, AUC: 0.6470, AP: 0.7198
Epoch: 065, AUC: 0.6482, AP: 0.7208
Epoch: 066, AUC: 0.6500, AP: 0.7223
Epoch: 067, AUC: 0.6524, AP: 0.7237
Epoch: 068, AUC: 0.6557, AP: 0.7258
Epoch: 069, AUC: 0.6591, AP: 0.7274
Epoch: 070, AUC: 0.6638, AP: 0.7295
Epoch: 071, AUC: 0.6679, AP: 0.7312
Epoch: 072, AUC: 0.6725, AP: 0.7333
Epoch: 073, AUC: 0.6780, AP: 0.7355
Epoch: 074, AUC: 0.6849, AP: 0.7386
Epoch: 075, AUC: 0.6929, AP: 0.7423
Epoch: 076, AUC: 0.7015, AP: 0.7464
Epoch: 077, AUC: 0.7100, AP: 0.7507
Epoch: 078, AUC: 0.7201, AP: 0.7562
Epoch: 079, AUC: 0.7314, AP: 0.7628
Epoch: 080, AUC: 0.7406, AP: 0.7689
Epoch: 081, AUC: 0.7490, AP: 0.7745
Epoch: 082, AUC: 0.7562, AP: 0.7794
Epoch: 083, AUC: 0.7626, AP: 0.7841
Epoch: 084, AUC: 0.7664, AP: 0.7873
Epoch: 085, AUC: 0.7696, AP: 0.7898
Epoch: 086, AUC: 0.7724, AP: 0.7920
Epoch: 087, AUC: 0.7749, AP: 0.7939
Epoch: 088, AUC: 0.7777, AP: 0.7959
Epoch: 089, AUC: 0.7807, AP: 0.7983
Epoch: 090, AUC: 0.7842, AP: 0.8014
Epoch: 091, AUC: 0.7881, AP: 0.8049
Epoch: 092, AUC: 0.7907, AP: 0.8075
Epoch: 093, AUC: 0.7921, AP: 0.8091
Epoch: 094, AUC: 0.7933, AP: 0.8105
Epoch: 095, AUC: 0.7945, AP: 0.8115
Epoch: 096, AUC: 0.7958, AP: 0.8124
Epoch: 097, AUC: 0.7972, AP: 0.8133
Epoch: 098, AUC: 0.7986, AP: 0.8143
Epoch: 099, AUC: 0.7995, AP: 0.8151
Epoch: 100, AUC: 0.8004, AP: 0.8158
Epoch: 101, AUC: 0.8011, AP: 0.8166
Epoch: 102, AUC: 0.8019, AP: 0.8176
Epoch: 103, AUC: 0.8032, AP: 0.8187
Epoch: 104, AUC: 0.8043, AP: 0.8195
Epoch: 105, AUC: 0.8048, AP: 0.8200
Epoch: 106, AUC: 0.8056, AP: 0.8204
Epoch: 107, AUC: 0.8070, AP: 0.8215
Epoch: 108, AUC: 0.8082, AP: 0.8224
Epoch: 109, AUC: 0.8091, AP: 0.8230
Epoch: 110, AUC: 0.8097, AP: 0.8234
Epoch: 111, AUC: 0.8105, AP: 0.8238
Epoch: 112, AUC: 0.8117, AP: 0.8247
Epoch: 113, AUC: 0.8124, AP: 0.8251
Epoch: 114, AUC: 0.8128, AP: 0.8254
Epoch: 115, AUC: 0.8135, AP: 0.8257
Epoch: 116, AUC: 0.8146, AP: 0.8263
Epoch: 117, AUC: 0.8156, AP: 0.8269
Epoch: 118, AUC: 0.8158, AP: 0.8271
Epoch: 119, AUC: 0.8155, AP: 0.8267
Epoch: 120, AUC: 0.8157, AP: 0.8268
Epoch: 121, AUC: 0.8161, AP: 0.8270
Epoch: 122, AUC: 0.8160, AP: 0.8267
Epoch: 123, AUC: 0.8160, AP: 0.8267
Epoch: 124, AUC: 0.8166, AP: 0.8272
Epoch: 125, AUC: 0.8170, AP: 0.8273
Epoch: 126, AUC: 0.8173, AP: 0.8273
Epoch: 127, AUC: 0.8172, AP: 0.8270
Epoch: 128, AUC: 0.8174, AP: 0.8268
Epoch: 129, AUC: 0.8172, AP: 0.8263
Epoch: 130, AUC: 0.8170, AP: 0.8260
Epoch: 131, AUC: 0.8172, AP: 0.8259
Epoch: 132, AUC: 0.8175, AP: 0.8258
Epoch: 133, AUC: 0.8178, AP: 0.8259
Epoch: 134, AUC: 0.8177, AP: 0.8257
Epoch: 135, AUC: 0.8174, AP: 0.8254
Epoch: 136, AUC: 0.8171, AP: 0.8248
Epoch: 137, AUC: 0.8170, AP: 0.8246
Epoch: 138, AUC: 0.8168, AP: 0.8242
Epoch: 139, AUC: 0.8171, AP: 0.8242
Epoch: 140, AUC: 0.8175, AP: 0.8243
Epoch: 141, AUC: 0.8178, AP: 0.8243
Epoch: 142, AUC: 0.8175, AP: 0.8239
Epoch: 143, AUC: 0.8170, AP: 0.8234
Epoch: 144, AUC: 0.8164, AP: 0.8227
Epoch: 145, AUC: 0.8161, AP: 0.8223
Epoch: 146, AUC: 0.8162, AP: 0.8223
Epoch: 147, AUC: 0.8167, AP: 0.8228
Epoch: 148, AUC: 0.8168, AP: 0.8229
Epoch: 149, AUC: 0.8170, AP: 0.8228
Epoch: 150, AUC: 0.8169, AP: 0.8227
Epoch: 151, AUC: 0.8170, AP: 0.8229
Epoch: 152, AUC: 0.8167, AP: 0.8226
Epoch: 153, AUC: 0.8158, AP: 0.8218
Epoch: 154, AUC: 0.8147, AP: 0.8209
Epoch: 155, AUC: 0.8144, AP: 0.8206
Epoch: 156, AUC: 0.8145, AP: 0.8207
Epoch: 157, AUC: 0.8147, AP: 0.8207
Epoch: 158, AUC: 0.8145, AP: 0.8204
Epoch: 159, AUC: 0.8140, AP: 0.8201
Epoch: 160, AUC: 0.8135, AP: 0.8196
Epoch: 161, AUC: 0.8128, AP: 0.8191
Epoch: 162, AUC: 0.8121, AP: 0.8185
Epoch: 163, AUC: 0.8114, AP: 0.8178
Epoch: 164, AUC: 0.8109, AP: 0.8173
Epoch: 165, AUC: 0.8113, AP: 0.8178
Epoch: 166, AUC: 0.8118, AP: 0.8181
Epoch: 167, AUC: 0.8119, AP: 0.8182
Epoch: 168, AUC: 0.8115, AP: 0.8178
Epoch: 169, AUC: 0.8111, AP: 0.8175
Epoch: 170, AUC: 0.8109, AP: 0.8171
Epoch: 171, AUC: 0.8106, AP: 0.8168
Epoch: 172, AUC: 0.8104, AP: 0.8166
Epoch: 173, AUC: 0.8102, AP: 0.8165
Epoch: 174, AUC: 0.8103, AP: 0.8168
Epoch: 175, AUC: 0.8101, AP: 0.8166
Epoch: 176, AUC: 0.8098, AP: 0.8161
Epoch: 177, AUC: 0.8096, AP: 0.8160
Epoch: 178, AUC: 0.8095, AP: 0.8159
Epoch: 179, AUC: 0.8092, AP: 0.8156
Epoch: 180, AUC: 0.8092, AP: 0.8157
Epoch: 181, AUC: 0.8089, AP: 0.8154
Epoch: 182, AUC: 0.8087, AP: 0.8152
Epoch: 183, AUC: 0.8084, AP: 0.8150
Epoch: 184, AUC: 0.8078, AP: 0.8145
Epoch: 185, AUC: 0.8072, AP: 0.8140
Epoch: 186, AUC: 0.8074, AP: 0.8143
Epoch: 187, AUC: 0.8078, AP: 0.8146
Epoch: 188, AUC: 0.8080, AP: 0.8147
Epoch: 189, AUC: 0.8079, AP: 0.8146
Epoch: 190, AUC: 0.8072, AP: 0.8141
Epoch: 191, AUC: 0.8061, AP: 0.8134
Epoch: 192, AUC: 0.8054, AP: 0.8128
Epoch: 193, AUC: 0.8056, AP: 0.8129
Epoch: 194, AUC: 0.8057, AP: 0.8128
Epoch: 195, AUC: 0.8061, AP: 0.8132
Epoch: 196, AUC: 0.8060, AP: 0.8132
Epoch: 197, AUC: 0.8058, AP: 0.8130
Epoch: 198, AUC: 0.8054, AP: 0.8127
Epoch: 199, AUC: 0.8053, AP: 0.8127
Epoch: 200, AUC: 0.8042, AP: 0.8117
Epoch: 201, AUC: 0.8037, AP: 0.8113
Epoch: 202, AUC: 0.8039, AP: 0.8114
Epoch: 203, AUC: 0.8039, AP: 0.8115
Epoch: 204, AUC: 0.8044, AP: 0.8118
Epoch: 205, AUC: 0.8041, AP: 0.8115
Epoch: 206, AUC: 0.8036, AP: 0.8112
Epoch: 207, AUC: 0.8028, AP: 0.8106
Epoch: 208, AUC: 0.8026, AP: 0.8103
Epoch: 209, AUC: 0.8026, AP: 0.8104
Epoch: 210, AUC: 0.8031, AP: 0.8109
Epoch: 211, AUC: 0.8030, AP: 0.8107
Epoch: 212, AUC: 0.8024, AP: 0.8102
Epoch: 213, AUC: 0.8017, AP: 0.8096
Epoch: 214, AUC: 0.8011, AP: 0.8091
Epoch: 215, AUC: 0.8004, AP: 0.8085
Epoch: 216, AUC: 0.8001, AP: 0.8082
Epoch: 217, AUC: 0.8009, AP: 0.8090
Epoch: 218, AUC: 0.8020, AP: 0.8098
Epoch: 219, AUC: 0.8030, AP: 0.8103
Epoch: 220, AUC: 0.8026, AP: 0.8100
Epoch: 221, AUC: 0.8007, AP: 0.8086
Epoch: 222, AUC: 0.7985, AP: 0.8066
Epoch: 223, AUC: 0.7990, AP: 0.8072
Epoch: 224, AUC: 0.8001, AP: 0.8081
Epoch: 225, AUC: 0.8013, AP: 0.8089
Epoch: 226, AUC: 0.8016, AP: 0.8090
Epoch: 227, AUC: 0.8001, AP: 0.8080
Epoch: 228, AUC: 0.7980, AP: 0.8065
Epoch: 229, AUC: 0.7965, AP: 0.8050
Epoch: 230, AUC: 0.7973, AP: 0.8058
Epoch: 231, AUC: 0.7986, AP: 0.8066
Epoch: 232, AUC: 0.7988, AP: 0.8068
Epoch: 233, AUC: 0.7985, AP: 0.8065
Epoch: 234, AUC: 0.7982, AP: 0.8061
Epoch: 235, AUC: 0.7976, AP: 0.8056
Epoch: 236, AUC: 0.7965, AP: 0.8048
Epoch: 237, AUC: 0.7953, AP: 0.8037
Epoch: 238, AUC: 0.7956, AP: 0.8039
Epoch: 239, AUC: 0.7966, AP: 0.8046
Epoch: 240, AUC: 0.7973, AP: 0.8051
Epoch: 241, AUC: 0.7971, AP: 0.8049
Epoch: 242, AUC: 0.7964, AP: 0.8043
Epoch: 243, AUC: 0.7949, AP: 0.8030
Epoch: 244, AUC: 0.7942, AP: 0.8023
Epoch: 245, AUC: 0.7950, AP: 0.8030
Epoch: 246, AUC: 0.7957, AP: 0.8036
Epoch: 247, AUC: 0.7966, AP: 0.8042
Epoch: 248, AUC: 0.7962, AP: 0.8038
Epoch: 249, AUC: 0.7958, AP: 0.8034
Epoch: 250, AUC: 0.7959, AP: 0.8035
Epoch: 251, AUC: 0.7952, AP: 0.8028
Epoch: 252, AUC: 0.7938, AP: 0.8016
Epoch: 253, AUC: 0.7940, AP: 0.8018
Epoch: 254, AUC: 0.7949, AP: 0.8025
Epoch: 255, AUC: 0.7959, AP: 0.8033
Epoch: 256, AUC: 0.7962, AP: 0.8034
Epoch: 257, AUC: 0.7946, AP: 0.8020
Epoch: 258, AUC: 0.7932, AP: 0.8008
Epoch: 259, AUC: 0.7922, AP: 0.7999
Epoch: 260, AUC: 0.7928, AP: 0.8003
Epoch: 261, AUC: 0.7948, AP: 0.8019
Epoch: 262, AUC: 0.7956, AP: 0.8025
Epoch: 263, AUC: 0.7959, AP: 0.8026
Epoch: 264, AUC: 0.7953, AP: 0.8023
Epoch: 265, AUC: 0.7941, AP: 0.8013
Epoch: 266, AUC: 0.7923, AP: 0.7999
Epoch: 267, AUC: 0.7913, AP: 0.7991
Epoch: 268, AUC: 0.7910, AP: 0.7988
Epoch: 269, AUC: 0.7931, AP: 0.8008
Epoch: 270, AUC: 0.7943, AP: 0.8019
Epoch: 271, AUC: 0.7938, AP: 0.8016
Epoch: 272, AUC: 0.7936, AP: 0.8014
Epoch: 273, AUC: 0.7924, AP: 0.8005
Epoch: 274, AUC: 0.7914, AP: 0.7997
Epoch: 275, AUC: 0.7911, AP: 0.7995
Epoch: 276, AUC: 0.7916, AP: 0.8000
Epoch: 277, AUC: 0.7922, AP: 0.8007
Epoch: 278, AUC: 0.7927, AP: 0.8012
Epoch: 279, AUC: 0.7924, AP: 0.8010
Epoch: 280, AUC: 0.7917, AP: 0.8004
Epoch: 281, AUC: 0.7909, AP: 0.7998
Epoch: 282, AUC: 0.7905, AP: 0.7995
Epoch: 283, AUC: 0.7912, AP: 0.8001
Epoch: 284, AUC: 0.7913, AP: 0.8002
Epoch: 285, AUC: 0.7910, AP: 0.7999
Epoch: 286, AUC: 0.7905, AP: 0.7996
Epoch: 287, AUC: 0.7901, AP: 0.7993
Epoch: 288, AUC: 0.7902, AP: 0.7994
Epoch: 289, AUC: 0.7905, AP: 0.7997
Epoch: 290, AUC: 0.7911, AP: 0.8002
Epoch: 291, AUC: 0.7906, AP: 0.7997
Epoch: 292, AUC: 0.7897, AP: 0.7989
Epoch: 293, AUC: 0.7888, AP: 0.7981
Epoch: 294, AUC: 0.7887, AP: 0.7980
Epoch: 295, AUC: 0.7898, AP: 0.7990
Epoch: 296, AUC: 0.7915, AP: 0.8003
Epoch: 297, AUC: 0.7925, AP: 0.8009
Epoch: 298, AUC: 0.7917, AP: 0.8004
Epoch: 299, AUC: 0.7903, AP: 0.7991
Epoch: 300, AUC: 0.7891, AP: 0.7979