Error 'object not callable'

username: Abhishek_Sood
cooked: <p>Hi so i was using gnn explainer in this GNN based model using OPENPOM model and pytorch’s GNNExplainer algorithm. But i was encountering error while generating explanation using the below code. Any help would be beneficial.</p>
<pre><code class="lang-auto">!wget https://raw.githubusercontent.com/ARY2260/openpom/main/openpom/data/curated_datasets/curated_GS_LF_merged_4983.csv

input_file = 'curated_GS_LF_merged_4983.csv' # or new downloaded file path
featurizer = GraphFeaturizer()
smiles_field = 'nonStereoSMILES' # column that contains SMILES
loader = dc.data.CSVLoader(tasks=TASKS,
feature_field=smiles_field,
featurizer=featurizer)
dataset = loader.create_dataset(inputs=[input_file])
n_tasks = len(dataset.tasks)
len(dataset)

randomstratifiedsplitter = dc.splits.RandomStratifiedSplitter()
train_dataset, test_dataset, valid_dataset = randomstratifiedsplitter.train_valid_test_split(dataset, frac_train = 0.8, frac_valid = 0.1, frac_test = 0.1, seed = 1)

print("train_dataset: ", len(train_dataset))
print("valid_dataset: ", len(valid_dataset))
print("test_dataset: ", len(test_dataset))
train_ratios = get_class_imbalance_ratio(train_dataset)
assert len(train_ratios) == n_tasks
learning_rate = dc.models.optimizers.ExponentialDecay(initial_rate=0.001, decay_rate=0.5, decay_steps=32*20, staircase=True)
model = MPNNPOMModel(n_tasks = n_tasks,
                            batch_size=128,
                            learning_rate=learning_rate,
                            class_imbalance_ratio = train_ratios,
                            loss_aggr_type = 'sum',
                            node_out_feats = 100,
                            edge_hidden_feats = 75,
                            edge_out_feats = 100,
                            num_step_message_passing = 5,
                            mpnn_residual = True,
                            message_aggregator_type = 'sum',
                            mode = 'classification',
                            number_atom_features = GraphConvConstants.ATOM_FDIM,
                            number_bond_features = GraphConvConstants.BOND_FDIM,
                            n_classes = 1,
                            readout_type = 'set2set',
                            num_step_set2set = 3,
                            num_layer_set2set = 2,
                            ffn_hidden_list= [392, 392],
                            ffn_embeddings = 256,
                            ffn_activation = 'relu',
                            ffn_dropout_p = 0.12,
                            ffn_dropout_at_input_no_act = False,
                            weight_decay = 1e-5,
                            self_loop = False,
                            optimizer_name = 'adam',
                            log_frequency = 32,
                            model_dir = './examples/experiments',
                            device_name='cuda')

explainer = Explainer(
    model=model,
    algorithm=GNNExplainer(epochs=200),
    explanation_type='model',
    node_mask_type='attributes',
    edge_mask_type='object',
    model_config=dict(
        mode='multiclass_classification',
        task_level='graph',
        return_type='log_probs',
    ),
)

batch = torch.zeros(data.x.size(0), dtype=torch.long)

with torch.no_grad():
    output = model(data.x, data.edge_index, batch)
print(f"Model output shape: {output.shape}")
print("Forward pass successful!")
print("Running explainer...")
exp = explainer(
    x=data.x,
    edge_index=data.edge_index,
    target=label_id,
    batch=batch
)
print(f"Explanation for '{TASKS[label_id]}' odor:")
print(f"Node importance: max={exp.node_mask.max().item():.3f}, min={exp.node_mask.min().item():.3f}")
print(f"Edge importance: max={exp.edge_mask.max().item():.3f}, min={exp.edge_mask.min().item():.3f}")
   
    # Optionally, if you need to visualize the results
print("Explanation generated successfully!") 

</code></pre>
<p>Outcome : <code>'MPNNPOMModel' object is not callable</code></p>
<p>while the explainer uses <code>mode='multiclass_classification',</code> and is set as multiclass, and the problem that OPENPOM solves is multi label, i was handling it already from extracting 571 smile strings that have only single label as their discriptor, so it sorts of represent multi class so considering that the dataset is already converted to PyG format , please anyone help how to resolve this error.</p>

username: KFrank
cooked: <p>Hi Abhishek!</p>
<aside class="quote no-group quote-modified" data-username="Abhishek_Sood" data-post="1" data-topic="219729" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/abhishek_sood/48/76903_2.png" class="avatar"> Abhishek_Sood:</div>
<blockquote>
<pre><code class="lang-auto">model = MPNNPOMModel(n_tasks = n_tasks,
...
with torch.no_grad():
    output = model(data.x, data.edge_index, batch)
</code></pre>
<p>Outcome : <code>'MPNNPOMModel' object is not callable</code></p>
</blockquote>
</aside>
<p>Perhaps ‘model’ isn’t a proper pytorch “model” derived from <code>Module</code> and doesn’t have<br>
a proper <code>forward()</code> method.</p>
<p>Try printing out <code>type (model).mro()</code> to see what class <code>model</code> is and what classes it is<br>
derived from.  Try printing out <code>dir (model)</code> to see whether <code>model</code> has a <code>forward</code> method.<br>
Try evaluating <code>model.forward</code> (without parentheses or function call) to see whether it’s<br>
a “bound method.”</p>
<p>Consider:</p>
<pre><code class="lang-plaintext">&gt;&gt;&gt; import torch
&gt;&gt;&gt; torch.__version__
'2.7.0+cu128'
&gt;&gt;&gt; lin = torch.nn.Linear (2, 3)
&gt;&gt;&gt; type (lin).mro()
[&lt;class 'torch.nn.modules.linear.Linear'&gt;, &lt;class 'torch.nn.modules.module.Module'&gt;, &lt;class 'object'&gt;]
&gt;&gt;&gt; 'forward' in dir (lin)
True
&gt;&gt;&gt; lin ('incorrect_input_to_a_Linear')
Traceback (most recent call last):
...
    return F.linear(input, self.weight, self.bias)
           ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: linear(): argument 'input' (position 1) must be Tensor, not str
</code></pre>
<p>Best.</p>
<p>K. Frank</p>

username: Abhishek_Sood
cooked: <p>hi thanks,<br>
so for resolving the proper forward method i used a custom wrapper and then passed in the explainer</p>
<pre><code class="lang-auto">class MPNNPOMWrapper(Module):
    def __init__(self, dc_model, pyg_graphs, featurizer):
        super().__init__()
        self.dc_model = dc_model
        self.pyg_graphs = pyg_graphs
        self.featurizer = featurizer

    def forward(self, x, edge_index, batch):
        unique_graphs = batch.unique()
        selected_graphs = [self.pyg_graphs[i] for i in unique_graphs.tolist()]

        dc_graphs = []
        for g in selected_graphs:
            mol = Chem.MolFromSmiles(g.smiles)
            if mol is None:
                continue
            try:
                feats = self.featurizer.featurize([mol])
                if isinstance(feats, list) and len(feats) &gt; 0 and feats[0] is not None:
                    dc_graphs.append(feats[0])
                else:
                    print(f"Warning: Featurization failed for SMILES: {g.smiles}, check featurization method")
                    from deepchem.feat.graph_data import GraphData
                    dc_graphs.append(GraphData(node_features=np.array([[0]]),  
                                             edge_index=np.array([[], []], dtype=np.int64),
                                             edge_features=np.empty((0, 1))))

            except Exception as e:
                print(f"Featurization failed for SMILES: {g.smiles} — {e}")
                from deepchem.feat.graph_data import GraphData
                dc_graphs.append(GraphData(node_features=np.array([[0]]), 
                                         edge_index=np.array([[], []], dtype=np.int64),
                                         edge_features=np.empty((0, 1))))
        if not dc_graphs:
            return torch.empty((0, self.dc_model.n_tasks), dtype=torch.float32) 

        batch_graph = BatchGraphData(dc_graphs)
        preds = self.dc_model.predict_on_batch(batch_graph)
        return torch.tensor(preds, dtype=torch.float32)
</code></pre>
<p>and when i used this and tried to generate the explanation</p>
<pre><code class="lang-auto">wrapper = MPNNPOMWrapper(dc_model=model, pyg_graphs=pyg_ds,featurizer=featurizer)

with torch.no_grad():
   output = wrapper(data.x, data.edge_index, batch)
   print(f"Model output shape: {output.shape}")
</code></pre>
<p>outcome was:</p>
<pre><code class="lang-auto">Warning: Featurization failed for SMILES: CCO, check featurization method
IndexError: tuple index out of range
</code></pre>
<p>maybe the fault is that when i converted the deepchem dataset to PyG format the featurisation<br>
stopped working because the featuriser worked exclusively for DeepChem format. Maybe this is the issue now but idk how to handle this.<br>
The featuriser that i am using is <code>from openpom.feat.graph_featurizer import GraphFeaturizer</code><br>
Can you please help resolving this <a class="mention" href="/u/kfrank">@KFrank</a> Thank you.</p>