[Bug] Sigmoid function node detected as method instead of function

username: nscotto
cooked: <p>Hi,</p>
<p>it seems that I am encountering a bug from <code>torch.fx</code>.<br>
It is wrongly detecting a sigmoid function call as a method call:</p>
<pre><code class="lang-auto">class ConvAutoencoder(nn.Module):
    def __init__(self):
        super(ConvAutoencoder, self).__init__()

        #Encoder
        self.conv1 = nn.Conv2d(3, 16, 3, padding=1)
        self.conv2 = nn.Conv2d(16, 4, 3, padding=1)
        self.pool = nn.MaxPool2d(2, 2)

        #Decoder
        self.t_conv1 = nn.ConvTranspose2d(4, 16, 2, stride=2)
        self.t_conv2 = nn.ConvTranspose2d(16, 3, 2, stride=2)
        self.sigmoid = nn.Sigmoid


    def forward(self, x):
        feat1 = F.relu(self.conv1(x))
        x = self.pool(feat1)
        x = F.relu(self.conv2(x))
        x = self.pool(x)
        x = F.relu(self.t_conv1(x))
        x = F.sigmoid(torch.cat([self.t_conv2(x), feat1], 1))

        return x

model = torch.fx.symbolic_trace(ConvAutoencoder())

for node in model.graph.nodes:
    print(f'{node.op} name: {node.name} target: {node.target} ({type(node.target)}) args: {node.args} kwargs: {node.kwargs}')
</code></pre>
<p>output:</p>
<pre><code class="lang-auto">placeholder name: x target: x (&lt;class 'str'&gt;) args: () kwargs: {}
call_module name: conv1 target: conv1 (&lt;class 'str'&gt;) args: (x,) kwargs: {}
call_function name: relu_1 target: &lt;function relu at 0x7f3ccc0104d0&gt; (&lt;class 'function'&gt;) args: (conv1,) kwargs: {'inplace': False}
call_module name: pool target: pool (&lt;class 'str'&gt;) args: (relu_1,) kwargs: {}
call_module name: conv2 target: conv2 (&lt;class 'str'&gt;) args: (pool,) kwargs: {}
call_function name: relu_2 target: &lt;function relu at 0x7f3ccc0104d0&gt; (&lt;class 'function'&gt;) args: (conv2,) kwargs: {'inplace': False}
call_module name: pool_1 target: pool (&lt;class 'str'&gt;) args: (relu_2,) kwargs: {}
call_module name: t_conv1 target: t_conv1 (&lt;class 'str'&gt;) args: (pool_1,) kwargs: {}
call_function name: relu_3 target: &lt;function relu at 0x7f3ccc0104d0&gt; (&lt;class 'function'&gt;) args: (t_conv1,) kwargs: {'inplace': False}
call_module name: t_conv2 target: t_conv2 (&lt;class 'str'&gt;) args: (relu_3,) kwargs: {}
call_function name: cat_1 target: &lt;built-in method cat of type object at 0x7f3ce1503640&gt; (&lt;class 'builtin_function_or_method'&gt;) args: ([t_conv2, relu_1], 1) kwargs: {}
call_method name: sigmoid_1 target: sigmoid (&lt;class 'str'&gt;) args: (cat_1,) kwargs: {}
output name: output target: output (&lt;class 'str'&gt;) args: (sigmoid_1,) kwargs: {}
</code></pre>
<p>What is happening?<br>
Is this really a bug?</p>
<p>It is currently a problem for me as I am trying to rebuild a full model with some variations using proxy calls, following <a href="https://discuss.pytorch.org/t/fx-insert-a-graph-instead-of-a-node/119694/4">this discussion</a>.<br>
While I can provide a quick fix special to the sigmoid case here, I am not sure if this is only related to sigmoid or other functions and if this behaviour is constant.</p>
<p>Thank you in advance for your interest.</p>

username: nscotto
cooked: <p>I understand it now, the first argument of the since the call_method argument includes <code>self</code>, and in this example the first argument is <code>cat_1</code>, the sigmoid is called on the <code>cat_1</code> tensor (it’s a tensor method).<br>
So not a bug!.</p>