title: Pytorch-lightning strange error: implemented method that does not override its parent's method
body: <p>I am trying to use the library Pytorch Lightning, but I am encountering a strange error that I am not able to solve. I cannot provide a minimal working implementation since my code is split across several modules and does not use many pre-built components. Furthermore, I cannot share the data I am using. However, I hope to find some help.</p>
  <p>Basically, I use a VGG network that implements the methods required by the pytorch-lightning library:</p>
  <pre><code>import pytorch_lightning as pl
  [...]
  
  class VGG(pl.LightningModule):
     [...]
  
     def forward(self, x):
         x = self.conv_layers(x)
         x = x.reshape(x.shape[0], -1)
         x = self.output(x)
         return x
  
     def configure_optimizers(self):
      # in the docs on the pytorch-lightning website, the self.parameters() 
      # below appears both with parentheses and without, 
      # i.e., both self.parameters() and self.paramters
      # I tried both with no changes
      optimizer = torch.optim.SGD(self.parameters(), lr=self.config[&quot;learning_rate&quot;], momentum=self.config[&quot;momentum&quot;])
      lr_scheduler = ReduceLROnPlateau(optimizer, 'min', factor=0.05, patience=5, cooldown=0, verbose=True)
      return optimizer, lr_scheduler
  
     def training_step(self, batch, batch_idx):
         x, y = batch
         y_hat = self.forward(x)
         loss =  F.cross_entropy(y_hat, y)
         return {'loss':loss}
  </code></pre>
  <p>I have a <code>DataModule</code> providing the training, validation and test data:</p>
  <pre><code>from pytorch_lightning import LightningDataModule
  
  class MyDataModule(LightningDataModule):
  def train_dataloader(self):
          if self.train_DL is None:
              self.train_DL = self._from_indexes_to_dataloader(&quot;train_i.tsv&quot;)
          return self.train_DL
      
      def val_dataloader(self):
          if self.valid_DL is None:
              self.valid_DL = self._from_indexes_to_dataloader(&quot;valid_i.tsv&quot;)
          return self.valid_DL
      
      def test_dataloader(self):
          if self.test_DL is None:
              self.test_DL = self._from_indexes_to_dataloader(&quot;test_i.tsv&quot;)
          return self.test_DL
  </code></pre>
  <p>An external script tries to train the model with:</p>
  <pre><code>import pytorch_lightning as pl
  [...]
  model = VGG(config)
  trainer = pl.Trainer(gpus=1, max_epochs=config[&quot;n_epochs&quot;], progress_bar_refresh_rate=5)
  datamodule = MyDataModule(config, logger=log)
  trainer.fit(model, datamodule)
  </code></pre>
  <p>But when I try and run it, <code>pytorch-lightning</code> tells me I forgot to implement the method <code>training_step</code>:</p>
  <pre><code>pytorch_lightning.utilities.exceptions.MisconfigurationException: 
  No `training_step()` method defined. 
  Lightning `Trainer` expects as minimum a `training_step()`, `train_dataloader()` and `configure_optimizers()` to be defined.
  </code></pre>
  <p>The error is caused by the fact that their checker <code>pytorch_lightning.utilities.model_helpers.py</code> does not consider my <code>VGG</code> to have overridden the <code>training_step</code> method. In its <code>is_overriden(.)</code> method:</p>
  <pre><code>def is_overridden(method_name: str, model: Union[LightningModule, LightningDataModule]) -&gt; bool:
      # if you pass DataModule instead of None or a LightningModule, we use LightningDataModule as super
      # TODO - refector this function to accept model_name, instance, parent so it makes more sense
      super_object = LightningModule if not isinstance(model, LightningDataModule) else LightningDataModule
  
      if not hasattr(model, method_name) or not hasattr(super_object, method_name):
          # in case of calling deprecated method
          return False
      instance_attr = getattr(model, method_name)
         
      if not instance_attr:
          return False
      super_attr = getattr(super_object, method_name)
  
      # when code pointers are different, it was implemented
      if hasattr(instance_attr, 'patch_loader_code'):
          # cannot pickle __code__ so cannot verify if PatchDataloader
          # exists which shows dataloader methods have been overwritten.
          # so, we hack it by using the string representation
          is_overridden = instance_attr.patch_loader_code != str(super_attr.__code__)
      else:
          is_overridden = instance_attr.__code__ is not super_attr.__code__
          print(method_name)
          print(instance_attr.__code__)
          print(super_attr.__code__)
          print(f'last is_overriden should be True, but it is {is_overridden}')
      return is_overridden
  </code></pre>
  <p>the last check fails. The output of the <code>print</code> I added is:</p>
  <pre><code>training_step
  &lt;code object training_step at 0x7f22e26cc870, file &quot;/opt/conda/lib/python3.8/site-packages/pytorch_lightning/core/lightning.py&quot;, line 531&gt;
  &lt;code object training_step at 0x7f22e26cc870, file &quot;/opt/conda/lib/python3.8/site-packages/pytorch_lightning/core/lightning.py&quot;, line 531&gt;
  last is_overriden should be True, but it is False
  </code></pre>
  <p>Basically the <code>training_step</code> in my <code>VGG</code> class &quot;poins to&quot; the same code of its superclass. Is there anyone who can tell me why it does not consider <code>VGG</code> to override the method of its parent?</p>
  <p>Is there anyone who can tell me what I should look at?
  I tried to ask on their support forum, but my question, as many others, remained unanswered.</p>
  <p>The <code>VGG</code>, the datasets and the <code>pytorch DataLoader</code> work correctly when used without <code>pytorch-lightning</code> with <code>pytorch</code> only.</p>