Module is not an instance of function

If I pip install fastai from github source on Debian/Bullseye using the --no-deps option (ensuring all requirements listed in settings.ini are met using Debian packages - pytorch version 1.7.0) then an import statement such import fastai.data.external leads to an error module is not an instance of function as below. If I remove the --no-deps option the only additional packages that pip installs is torch (version 1.10.1) torchvision (version 0.11.2), and there is no error on using the import statement. I am a bit surprised since setup.ini specifies that torch version >=1.7.0 should be suffecient. I would be grateful if you could point me in the right direction regarding what could be causing this problem.

$ python
Python 3.9.2 (default, Feb 28 2021, 17:03:44) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import fastai.data.external
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/fastai/data/external.py", line 6, in <module>
    from ..torch_basics import *
  File "/usr/lib/python3/dist-packages/fastai/torch_basics.py", line 12, in <module>
    from .layers import *
  File "/usr/lib/python3/dist-packages/fastai/layers.py", line 551, in <module>
    def _swish_jit_fwd(x): return x.mul(torch.sigmoid(x))
  File "/usr/lib/python3/dist-packages/torch/jit/_script.py", line 939, in script
    fn = torch._C._jit_script_compile(
TypeError: Object of type 'module' is not an instance of 'function'

On further investigation this does not seem to be a problem with Debian’s Python torch package given that the following test script works as expected (shown below).

# test.py
import torch

@torch.jit.script
def foo(x, y):
    if x.max() > y.max():
        r = x
    else:
        r = y
    return r

print(type(foo))  # torch.jit.ScriptFunction

# See the compiled graph as Python code
print(foo.code)

# Call the function using the TorchScript interpreter
foo(torch.ones(2, 2), torch.ones(2, 2))
$ python test.py 
<class 'torch.jit.ScriptFunction'>
def foo(x: Tensor,
    y: Tensor) -> Tensor:
  _0 = bool(torch.gt(torch.max(x), torch.max(y)))
  if _0:
    r = x
  else:
    r = y
  return r

I was able to eliminate the error by explicitly importing the sigmoid function from torch as shown below

from torch.jit import script
from torch import sigmoid

@script
def _swish_jit_fwd(x):
    return x.mul(sigmoid(x))

instead of invoking sigmoid as a module attribute as is the case in the fastai codebase, as shown below

import torch
from torch.jit import script

@script
def _swish_jit_fwd(x):
    return x.mul(torch.sigmoid(x))

If FastAI developers have no objection I can create a pull request/patch with all similar changes to support backward compatibility with pytorch 1.7.

The included patch (could not attach since txt extension upload is not supported) fixed the issue for me on Debian/Bullseye with Pytorch version 1.7.0. I am still in the process of testing if there are any other issues.

--- a/fastai/layers.py
+++ b/fastai/layers.py
@@ -545,14 +545,15 @@
 
 # Cell
 from torch.jit import script
+from torch import sigmoid, tanh
 
 # Cell
 @script
-def _swish_jit_fwd(x): return x.mul(torch.sigmoid(x))
+def _swish_jit_fwd(x): return x.mul(sigmoid(x))
 
 @script
 def _swish_jit_bwd(x, grad_output):
-    x_sigmoid = torch.sigmoid(x)
+    x_sigmoid = sigmoid(x)
     return grad_output * (x_sigmoid * (1 + x * (1 - x_sigmoid)))
 
 class _SwishJitAutoFn(torch.autograd.Function):
@@ -573,14 +574,15 @@
 class Swish(Module):
     def forward(self, x): return _SwishJitAutoFn.apply(x)
 
+from torch.nn.functional import softplus
 # Cell
 @script
-def _mish_jit_fwd(x): return x.mul(torch.tanh(F.softplus(x)))
+def _mish_jit_fwd(x): return x.mul(tanh(softplus(x)))
 
 @script
 def _mish_jit_bwd(x, grad_output):
-    x_sigmoid = torch.sigmoid(x)
-    x_tanh_sp = F.softplus(x).tanh()
+    x_sigmoid = sigmoid(x)
+    x_tanh_sp = softplus(x).tanh()
     return grad_output.mul(x_tanh_sp + x * x_sigmoid * (1 - x_tanh_sp * x_tanh_sp))
 
 class MishJitAutoFn(torch.autograd.Function):
@@ -654,4 +656,4 @@
     for l in flatten_model(m):
         if getattr(l, 'weight', None) is not None and l.weight.ndim==4:
             return l.weight.shape[1]
-    raise Exception('No weight layer')
\ No newline at end of file
+    raise Exception('No weight layer')