Repository: pykeen/pykeen
Issue: Issue with requires_grad in CompGCN?
Root cause: Algorithmic Error

Upon trying to run this bit of code I received an error
`RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn`

```python
tf = TriplesFactory.from_path('graph.tsv',create_inverse_triples=True)
training, validation, testing = tf.split([.8, .1, .1])

result = pipeline(
    training=training,
    testing=testing,
    validation=validation,
    stopper='early',
    model_kwargs = dict(embedding_dim=512),
    training_kwargs = dict(num_epochs=1000),
    device='gpu',
    model='CompGCN'
)
```

Could, somebody, please, help me with this?

Could you please paste the output from `pykeen.env()` and the full stack trace?

```python-traceback
WARNING:pykeen.utils:using automatically assigned random_state=593265551
INFO:pykeen.triples.splitting:done splitting triples to groups of sizes [16669, 2374, 2375]
WARNING:pykeen.pipeline.api:No random seed is specified. Setting to 835068086.
INFO:pykeen.triples.triples_factory:Creating inverse triples.
INFO:pykeen.training.training_loop:Dropping last (incomplete) batch each epoch (1/37984 (0.00%) batches).
Training epochs on cuda: 1%
10/1000 [00:47<1:27:49, 5.32s/epoch, loss=0.00436, prev_loss=0.00296]
INFO:pykeen.evaluation.evaluator:Starting batch_size search for evaluation now...
INFO:pykeen.evaluation.evaluator:Concluded batch_size search with batch_size=4096.
INFO:pykeen.evaluation.evaluator:Evaluation took 0.67s seconds
INFO:pykeen.training.training_loop:=> Saved checkpoint after having finished epoch 10.
Training batches on cuda: 0%
0/148 [00:00<?, ?batch/s]
WARNING:pykeen.training.training_loop:The training loop just failed during epoch 11 due to error element 0 of tensors does not require grad and does not have a grad_fn.

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
/tmp/ipykernel_363/2471489407.py in <module>
     10     training_kwargs = dict(num_epochs=1000),
     11     device='gpu',
---> 12     model='CompGCN'
     13 )

/home/user/conda/lib/python3.7/site-packages/pykeen/pipeline/api.py in pipeline(dataset, dataset_kwargs, training, testing, validation, evaluation_entity_whitelist, evaluation_relation_whitelist, model, model_kwargs, interaction, interaction_kwargs, dimensions, loss, loss_kwargs, regularizer, regularizer_kwargs, optimizer, optimizer_kwargs, clear_optimizer, training_loop, training_loop_kwargs, negative_sampler, negative_sampler_kwargs, training_kwargs, stopper, stopper_kwargs, evaluator, evaluator_kwargs, evaluation_kwargs, result_tracker, result_tracker_kwargs, metadata, device, random_seed, use_testing_data, evaluation_fallback, filter_validation_when_testing)
   1019         result_tracker=_result_tracker,
   1020         clear_optimizer=clear_optimizer,
-> 1021         **training_kwargs,
   1022     )
   1023     assert losses is not None  # losses is only none if it's doing search mode

/home/user/conda/lib/python3.7/site-packages/pykeen/training/training_loop.py in train(self, triples_factory, num_epochs, batch_size, slice_size, label_smoothing, sampler, continue_training, only_size_probing, use_tqdm, use_tqdm_batch, tqdm_kwargs, stopper, result_tracker, sub_batch_size, num_workers, clear_optimizer, checkpoint_directory, checkpoint_name, checkpoint_frequency, checkpoint_on_failure, drop_last, callbacks)
    323                 callbacks=callbacks,
    324                 triples_factory=triples_factory,
--> 325                 training_instances=training_instances,
    326             )
    327 

/home/user/conda/lib/python3.7/site-packages/pykeen/training/training_loop.py in _train(self, triples_factory, training_instances, num_epochs, batch_size, slice_size, label_smoothing, sampler, continue_training, only_size_probing, use_tqdm, use_tqdm_batch, tqdm_kwargs, stopper, result_tracker, sub_batch_size, num_workers, save_checkpoints, checkpoint_path, checkpoint_frequency, checkpoint_on_failure_file_path, best_epoch_model_file_path, last_best_epoch, drop_last, callbacks)
    687                 if best_epoch_model_file_path is not None and best_epoch_model_file_path.is_file():
    688                     os.remove(best_epoch_model_file_path)
--> 689                 raise e
    690 
    691             # Includes a call to result_tracker.log_metrics

/home/user/conda/lib/python3.7/site-packages/pykeen/training/training_loop.py in _train(self, triples_factory, training_instances, num_epochs, batch_size, slice_size, label_smoothing, sampler, continue_training, only_size_probing, use_tqdm, use_tqdm_batch, tqdm_kwargs, stopper, result_tracker, sub_batch_size, num_workers, save_checkpoints, checkpoint_path, checkpoint_frequency, checkpoint_on_failure_file_path, best_epoch_model_file_path, last_best_epoch, drop_last, callbacks)
    602                             current_batch_size,
    603                             label_smoothing,
--> 604                             slice_size,
    605                         )
    606                         current_epoch_loss += batch_loss

/home/user/conda/lib/python3.7/site-packages/pykeen/training/training_loop.py in _forward_pass(self, batch, start, stop, current_batch_size, label_smoothing, slice_size)
    758 
    759         # backward pass
--> 760         loss.backward()
    761         current_epoch_loss = loss.item()
    762 

/home/user/conda/lib/python3.7/site-packages/torch/tensor.py in backward(self, gradient, retain_graph, create_graph)
    183                 products. Defaults to ``False``.
    184         """
--> 185         torch.autograd.backward(self, gradient, retain_graph, create_graph)
    186 
    187     def register_hook(self, hook):

/home/user/conda/lib/python3.7/site-packages/torch/autograd/__init__.py in backward(tensors, grad_tensors, retain_graph, create_graph, grad_variables)
    125     Variable._execution_engine.run_backward(
    126         tensors, grad_tensors, retain_graph, create_graph,
--> 127         allow_unreachable=True)  # allow_unreachable flag
    128 
    129 

RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
```

Key	Value
OS	posix
Platform	Linux
Release	4.15.0-124-generic
User	jovyan
Time	Thu Aug 19 07:36:57 2021
Python	3.7.10
PyKEEN	1.5.0
PyKEEN Hash	UNHASHED
PyKEEN Branch	
PyTorch	1.6.0+cu101
CUDA Available?	true
CUDA Version	10.1
cuDNN Version	7603


I could reproduce the behaviour with this smaller snippet on the current `master` branch (8405d82db33e6a6cda2d237ed8d2b719c578483e)
```python
from pykeen.pipeline import pipeline

result = pipeline(
    dataset="nations",
    dataset_kwargs=dict(create_inverse_triples=True),
    stopper="early",
    stopper_kwargs=dict(frequency=1),
    training_kwargs=dict(num_epochs=2),
    model="CompGCN"
)
```

When I disable early stopping, the error does not occur anymore. The same holds for changing to other models, e.g., `"DistMult"` or `"RGCN"`.

I think the error originates from the buffering here:
https://github.com/pykeen/pykeen/blob/8405d82db33e6a6cda2d237ed8d2b719c578483e/src/pykeen/nn/emb.py#L942

After evaluation via the early stopper, post_parameter_update is not called, and thus `self.enriched_representations` still contains the evaluation representations which do not require a gradient since they were computed in evaluation mode.

Oh, thanks, I'll disable the early stopper then, hope this won't be the case in the future :) 

> Oh, thanks, I'll disable the early stopper then, hope this won't be the case in the future :)

This may be a work-around until we have fixed this issue.

Thanks for reporting the bug :+1: 

@tatiana-iazykova the issue should now be resolved with #573 being merged to master. You can install this version via
```console
$ pip install git+https://github.com/pykeen/pykeen.git
```

The change will also become available via 
```console
$ pip install -U pykeen
```
once we make the next release.