I’m trying to adapt this code that currently works for regression to work for classification but I get multiple errors, thought it would be as simple as converting the loss functions and output size but I am getting multiple errors. This is my code.
Class GNN(torch.nn.Module):
def __init__(self, gnn, n_layer, tfeature_len, dim, mlp_hidden_unit, feature_mode):
super(GNN, self).__init__()
self.gnn = gnn
self.n_layer = n_layer
self.tfeature_len = tfeature_len
self.dim = dim
self.gnn_layers = ModuleList([])
if gnn in ['gcn', 'gat', 'sage', 'tag']:
for i in range(n_layer):
if gnn == 'gcn':
self.gnn_layers.append(GraphConv(in_feats=tfeature_len if i == 0 else dim,
out_feats=dim,
activation=None if i == n_layer - 1 else torch.relu))
elif gnn == 'gat':
num_heads = 16 # make sure that dim is dividable by num_heads
self.gnn_layers.append(GATConv(in_feats=tfeature_len if i == 0 else dim,
out_feats=dim // num_heads,
activation=None if i == n_layer - 1 else torch.relu,
num_heads=num_heads))
elif gnn == 'sage':
agg = 'pool'
self.gnn_layers.append(SAGEConv(in_feats=tfeature_len if i == 0 else dim,
out_feats=dim,
activation=None if i == n_layer - 1 else torch.relu,
aggregator_type=agg))
elif gnn == 'tag':
hops = 2
self.gnn_layers.append(TAGConv(in_feats=tfeature_len if i == 0 else dim,
out_feats=dim,
activation=None if i == n_layer - 1 else torch.relu,
k=hops))
elif gnn == 'sgc':
self.gnn_layers.append(SGConv(in_feats=tfeature_len, out_feats=dim, k=n_layer))
else:
raise ValueError('unknown GNN model')
self.factor = None
self.pooling_layer = SumPooling()
self.mlp_hidden_unit = mlp_hidden_unit
self.feature_mode = feature_mode
if self.feature_mode == 'concat':
self.mlp_hidden_layer = torch.nn.Linear(2 * self.dim, self.mlp_hidden_unit)
elif self.feature_mode == 'subtract':
self.mlp_hidden_layer = torch.nn.Linear(self.dim, self.mlp_hidden_unit)
else:
raise ValueError('unknown feature mode')
self.mlp_output_layer = torch.nn.Linear(self.mlp_hidden_unit, 2)
def forward(self, graph1, graph2):
graph1_embedding = self.calculate_embedding(graph1)
graph2_embedding = self.calculate_embedding(graph2)
if self.feature_mode == 'concat':
hidden = relu(self.mlp_hidden_layer(torch.concat([graph1_embedding, graph2_embedding], dim=-1)))
elif self.feature_mode == 'subtract':
hidden = relu(self.mlp_hidden_layer(graph1_embedding - graph2_embedding))
else:
raise ValueError('unknown feature mode')
output = self.mlp_output_layer(hidden)
return output
def calculate_embedding(self, graph):
feature = graph.ndata['feature']
h = one_hot(feature, num_classes=self.tfeature_len)
h = torch.sum(h, dim=1, dtype=torch.float)
for layer in self.gnn_layers:
h = layer(graph, h)
if self.gnn == 'gat':
h = torch.reshape(h, [h.size()[0], -1])
if self.factor is None:
self.factor = math.sqrt(self.dim) / float(torch.mean(torch.linalg.norm(h, dim=1)))
h *= self.factor
graph_embedding = self.pooling_layer(graph, h)
return graph_embedding
def train(data,model,optimizer):
train_loader, val_loader, test_loader, tfeature_len = data
loss_fn = torch.nn.CrossEntropyLoss()
epoch = 23
model = model.to(device)
print('start training\n')
#evaluate(model, 'train', train_loader)
evaluate(model, 'val', val_loader)
evaluate(model, 'test', test_loader)
epoch_losses = []
for i in range(epoch):
print('epoch %d:' % i)
epoch_loss = 0
model.train()
for graph1, graph2, target in train_loader:
pred = torch.squeeze(model(graph1, graph2))
loss = loss_fn(pred, target)
optimizer.zero_grad()
loss.backward()
optimizer.step()
epoch_loss += loss.detach().item()
epoch_loss /= (iter + 1)
print('Epoch {}, loss {:.4f}'.format(epoch, epoch_loss))
epoch_losses.append(epoch_loss)
#evaluate(model, 'train', train_loader)
evaluate(model, 'val', val_loader)
evaluate(model, 'test', test_loader)
print()
def evaluate(model, mode, data):
pred_list = []
target_list = []
model.eval()
with torch.no_grad():
for graph1, graph2, target in data:
outputs = torch.softmax(model(graph1, graph2), 1)
_, predicted = torch.max(outputs.data, 1)
pred_list.append(predicted)
target_list.append(target)
#torch.sum(preds == targets).detach().cpu().numpy().
pred_list = torch.concat(pred_list)
target_list = torch.concat(target_list)
#print('%s Acc: %.4f' % (mode (sklearn.metrics.accuracy_score(target_list, pred_list, normalize=False)) / len(pred_list) * 100))
The accuracy is commented out at the moment because that too gave me an error. My first error however was the following:
start training
epoch 0:
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-84-9de6c6dbd2ee> in <module>
----> 1 train(data,model,optimizer)
3 frames
/usr/local/lib/python3.7/dist-packages/torch/nn/functional.py in cross_entropy(input, target, weight, size_average, ignore_index, reduce, reduction, label_smoothing)
3012 if size_average is not None or reduce is not None:
3013 reduction = _Reduction.legacy_get_string(size_average, reduce)
-> 3014 return torch._C._nn.cross_entropy_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index, label_smoothing)
3015
3016
RuntimeError: "nll_loss_forward_reduce_cuda_kernel_2d_index" not implemented for 'Float'
My targets are as follows:
targets = training_data['Class'].tolist()
targets = torch.Tensor(targets)
targets = targets.to(device)
And is just a list of 1s and 0s.
I call my model as follows:
model = GNN('sage', 3, tfeature_len, 2048, 100, 'subtract')
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
Anyone know how I can fix this? Real bummer