torch-molecule 0.1.0.dev2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. torch_molecule/__init__.py +70 -0
  2. torch_molecule/base/__init__.py +8 -0
  3. torch_molecule/base/base.py +396 -0
  4. torch_molecule/base/encoder.py +44 -0
  5. torch_molecule/base/generator.py +24 -0
  6. torch_molecule/base/old_encoder.py +322 -0
  7. torch_molecule/base/old_predictor.py +904 -0
  8. torch_molecule/base/old_predictor2.py +436 -0
  9. torch_molecule/base/predictor.py +112 -0
  10. torch_molecule/encoder/attrmask/__init__.py +3 -0
  11. torch_molecule/encoder/attrmask/model.py +113 -0
  12. torch_molecule/encoder/attrmask/modeling_attrmask.py +304 -0
  13. torch_molecule/encoder/constant.py +13 -0
  14. torch_molecule/encoder/contextpred/__init__.py +3 -0
  15. torch_molecule/encoder/contextpred/model.py +207 -0
  16. torch_molecule/encoder/contextpred/modeling_contextpred.py +299 -0
  17. torch_molecule/encoder/contextpred/utils.py +206 -0
  18. torch_molecule/encoder/edgepred/__init__.py +3 -0
  19. torch_molecule/encoder/edgepred/model.py +104 -0
  20. torch_molecule/encoder/edgepred/modeling_edgepred.py +285 -0
  21. torch_molecule/encoder/graphmae/__init__.py +3 -0
  22. torch_molecule/encoder/graphmae/dataloader.py +206 -0
  23. torch_molecule/encoder/graphmae/model.py +137 -0
  24. torch_molecule/encoder/graphmae/modeling_graphmae.py +323 -0
  25. torch_molecule/encoder/infograph/__init__.py +3 -0
  26. torch_molecule/encoder/infograph/loss_function.py +128 -0
  27. torch_molecule/encoder/infograph/model.py +92 -0
  28. torch_molecule/encoder/infograph/modeling_infograph.py +301 -0
  29. torch_molecule/encoder/infograph/module.py +31 -0
  30. torch_molecule/encoder/moama/__init__.py +3 -0
  31. torch_molecule/encoder/moama/model.py +131 -0
  32. torch_molecule/encoder/moama/modeling_moama.py +307 -0
  33. torch_molecule/encoder/moama/utils.py +143 -0
  34. torch_molecule/encoder/pretrained/__init__.py +3 -0
  35. torch_molecule/encoder/pretrained/modeling_pretrained.py +274 -0
  36. torch_molecule/encoder/supervised/__init__.py +3 -0
  37. torch_molecule/encoder/supervised/model.py +97 -0
  38. torch_molecule/encoder/supervised/modeling_supervised.py +354 -0
  39. torch_molecule/generator/digress/__init__.py +3 -0
  40. torch_molecule/generator/digress/diffusion.py +194 -0
  41. torch_molecule/generator/digress/modeling_digress.py +503 -0
  42. torch_molecule/generator/digress/transformer.py +360 -0
  43. torch_molecule/generator/digress/utils.py +196 -0
  44. torch_molecule/generator/gdss/__init__.py +3 -0
  45. torch_molecule/generator/gdss/layers.py +257 -0
  46. torch_molecule/generator/gdss/model.py +204 -0
  47. torch_molecule/generator/gdss/modeling_gdss.py +474 -0
  48. torch_molecule/generator/gdss/sde.py +334 -0
  49. torch_molecule/generator/gdss/solver.py +227 -0
  50. torch_molecule/generator/gdss/toremove/ScoreNetworkA.py +167 -0
  51. torch_molecule/generator/gdss/toremove/ScoreNetworkX.py +85 -0
  52. torch_molecule/generator/gdss/utils.py +240 -0
  53. torch_molecule/generator/graph_dit/__init__.py +3 -0
  54. torch_molecule/generator/graph_dit/diffusion.py +188 -0
  55. torch_molecule/generator/graph_dit/modeling_graph_dit.py +581 -0
  56. torch_molecule/generator/graph_dit/transformer.py +207 -0
  57. torch_molecule/generator/graph_dit/utils.py +220 -0
  58. torch_molecule/generator/graph_ga/__init__.py +3 -0
  59. torch_molecule/generator/graph_ga/crossover.py +182 -0
  60. torch_molecule/generator/graph_ga/modeling_graph_ga.py +310 -0
  61. torch_molecule/generator/graph_ga/mutate.py +136 -0
  62. torch_molecule/generator/graph_ga/oracle.py +95 -0
  63. torch_molecule/generator/jtvae/__init__.py +3 -0
  64. torch_molecule/generator/jtvae/jtnn/chemutils.py +450 -0
  65. torch_molecule/generator/jtvae/jtnn/datautils.py +127 -0
  66. torch_molecule/generator/jtvae/jtnn/jtmpn.py +140 -0
  67. torch_molecule/generator/jtvae/jtnn/jtnn_dec.py +350 -0
  68. torch_molecule/generator/jtvae/jtnn/jtnn_enc.py +131 -0
  69. torch_molecule/generator/jtvae/jtnn/mol_tree.py +111 -0
  70. torch_molecule/generator/jtvae/jtnn/mpn.py +129 -0
  71. torch_molecule/generator/jtvae/jtnn/nnutils.py +66 -0
  72. torch_molecule/generator/jtvae/jtnn/vocab.py +31 -0
  73. torch_molecule/generator/jtvae/jtnn_vae.py +246 -0
  74. torch_molecule/generator/jtvae/modeling_jtvae.py +247 -0
  75. torch_molecule/generator/lstm/__init__.py +3 -0
  76. torch_molecule/generator/lstm/action_sampler.py +91 -0
  77. torch_molecule/generator/lstm/lstm.py +59 -0
  78. torch_molecule/generator/lstm/modeling_lstm.py +263 -0
  79. torch_molecule/generator/lstm/smiles_char_dict.py +123 -0
  80. torch_molecule/generator/lstm/utils.py +62 -0
  81. torch_molecule/generator/molgpt/__init__.py +3 -0
  82. torch_molecule/generator/molgpt/dataset.py +87 -0
  83. torch_molecule/generator/molgpt/gpt.py +251 -0
  84. torch_molecule/generator/molgpt/modeling_molgpt.py +427 -0
  85. torch_molecule/generator/pretrained/modeling_pretrained.py +1 -0
  86. torch_molecule/nn/__init__.py +16 -0
  87. torch_molecule/nn/attention.py +63 -0
  88. torch_molecule/nn/embedder.py +183 -0
  89. torch_molecule/nn/gnn.py +631 -0
  90. torch_molecule/nn/mlp.py +34 -0
  91. torch_molecule/predictor/bfgnn/__init__.py +3 -0
  92. torch_molecule/predictor/bfgnn/model.py +116 -0
  93. torch_molecule/predictor/bfgnn/modeling_bfgnn.py +81 -0
  94. torch_molecule/predictor/dir/__init__.py +3 -0
  95. torch_molecule/predictor/dir/model.py +235 -0
  96. torch_molecule/predictor/dir/modeling_dir.py +161 -0
  97. torch_molecule/predictor/dir/utils.py +40 -0
  98. torch_molecule/predictor/gnn/__init__.py +3 -0
  99. torch_molecule/predictor/gnn/model.py +114 -0
  100. torch_molecule/predictor/gnn/modeling_gnn.py +706 -0
  101. torch_molecule/predictor/gnn/old_modeling_gnn.py +707 -0
  102. torch_molecule/predictor/grea/__init__.py +3 -0
  103. torch_molecule/predictor/grea/model.py +190 -0
  104. torch_molecule/predictor/grea/modeling_grea.py +107 -0
  105. torch_molecule/predictor/grea/old1_features.py +229 -0
  106. torch_molecule/predictor/grea/old1_modeling_grea.py +493 -0
  107. torch_molecule/predictor/grea/utils.py +97 -0
  108. torch_molecule/predictor/grin/__init__.py +3 -0
  109. torch_molecule/predictor/grin/model.py +116 -0
  110. torch_molecule/predictor/grin/modeling_grin.py +91 -0
  111. torch_molecule/predictor/irm/__init__.py +3 -0
  112. torch_molecule/predictor/irm/model.py +127 -0
  113. torch_molecule/predictor/irm/modeling_irm.py +179 -0
  114. torch_molecule/predictor/lstm/__init__.py +3 -0
  115. torch_molecule/predictor/lstm/model.py +145 -0
  116. torch_molecule/predictor/lstm/modeling_lstm.py +627 -0
  117. torch_molecule/predictor/lstm/token_from_smiles.py +85 -0
  118. torch_molecule/predictor/old_modeling_graph.py +650 -0
  119. torch_molecule/predictor/rpgnn/__init__.py +3 -0
  120. torch_molecule/predictor/rpgnn/model.py +185 -0
  121. torch_molecule/predictor/rpgnn/modeling_rpgnn.py +76 -0
  122. torch_molecule/predictor/sgir/__init__.py +3 -0
  123. torch_molecule/predictor/sgir/modeling_sgir.py +260 -0
  124. torch_molecule/predictor/sgir/strategy.py +266 -0
  125. torch_molecule/predictor/smiles_transformer/__init__.py +3 -0
  126. torch_molecule/predictor/smiles_transformer/model.py +424 -0
  127. torch_molecule/predictor/smiles_transformer/modeling_transformer.py +252 -0
  128. torch_molecule/predictor/ssr/__init__.py +3 -0
  129. torch_molecule/predictor/ssr/model.py +283 -0
  130. torch_molecule/predictor/ssr/modeling_ssr.py +267 -0
  131. torch_molecule/predictor/ssr/utils.py +185 -0
  132. torch_molecule/utils/__init__.py +31 -0
  133. torch_molecule/utils/checker.py +158 -0
  134. torch_molecule/utils/checkpoint.py +294 -0
  135. torch_molecule/utils/format.py +140 -0
  136. torch_molecule/utils/generic/metrics.py +530 -0
  137. torch_molecule/utils/generic/pseudo_tasks.py +11 -0
  138. torch_molecule/utils/generic/weights.py +30 -0
  139. torch_molecule/utils/graph/features.py +178 -0
  140. torch_molecule/utils/graph/graph_from_smiles.py +134 -0
  141. torch_molecule/utils/graph/graph_to_smiles.py +312 -0
  142. torch_molecule/utils/hf.py +232 -0
  143. torch_molecule/utils/search.py +64 -0
  144. torch_molecule-0.1.0.dev2.dist-info/METADATA +243 -0
  145. torch_molecule-0.1.0.dev2.dist-info/RECORD +148 -0
  146. torch_molecule-0.1.0.dev2.dist-info/WHEEL +5 -0
  147. torch_molecule-0.1.0.dev2.dist-info/licenses/LICENSE +21 -0
  148. torch_molecule-0.1.0.dev2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,274 @@
1
+ import warnings
2
+ from tqdm import tqdm
3
+ from typing import Optional, Union, Dict, Any, Tuple, List, Literal
4
+ from dataclasses import dataclass, field
5
+
6
+ import torch
7
+ import numpy as np
8
+
9
+ from ...base import BaseMolecularEncoder
10
+
11
+ known_repos = [
12
+ "entropy/gpt2_zinc_87m",
13
+ "entropy/roberta_zinc_480m",
14
+ "ncfrey/ChemGPT-1.2B",
15
+ "ncfrey/ChemGPT-19M",
16
+ "ncfrey/ChemGPT-4.7M",
17
+ "DeepChem/ChemBERTa-77M-MTR",
18
+ "DeepChem/ChemBERTa-77M-MLM",
19
+ "DeepChem/ChemBERTa-10M-MTR",
20
+ "DeepChem/ChemBERTa-10M-MLM",
21
+ "DeepChem/ChemBERTa-5M-MLM",
22
+ "DeepChem/ChemBERTa-5M-MTR",
23
+ "unikei/bert-base-smiles",
24
+ 'seyonec/ChemBERTa-zinc-base-v1'
25
+ ]
26
+
27
+ known_add_bos_eos_list = ["entropy/gpt2_zinc_87m"]
28
+
29
+ @dataclass(init=False)
30
+ class HFPretrainedMolecularEncoder(BaseMolecularEncoder):
31
+ """Implements Hugging Face pretrained transformer models as molecular encoders.
32
+
33
+ This class provides an interface to use pretrained transformer models from Hugging Face
34
+ as molecular encoders. It handles tokenization and encoding of molecular representations.
35
+
36
+ Tested models include:
37
+
38
+ - ChemGPT series (1.2B/19M/4.7M): GPT-Neo based models pretrained on PubChem10M dataset with SELFIES strings.
39
+ Output dimension: 2048.
40
+
41
+ repo_id: "ncfrey/ChemGPT-1.2B" (https://huggingface.co/ncfrey/ChemGPT-1.2B)
42
+
43
+ repo_id: "ncfrey/ChemGPT-19M" (https://huggingface.co/ncfrey/ChemGPT-19M)
44
+
45
+ repo_id: "ncfrey/ChemGPT-4.7M" (https://huggingface.co/ncfrey/ChemGPT-4.7M)
46
+
47
+ - GPT2-ZINC-87M: GPT-2 based model (87M parameters) pretrained on ZINC dataset with ~480M SMILES strings.
48
+ Output dimension: 768.
49
+
50
+ repo_id: "entropy/gpt2_zinc_87m" (https://huggingface.co/entropy/gpt2_zinc_87m)
51
+
52
+ - RoBERTa-ZINC-480M: RoBERTa based model (102M parameters) pretrained on ZINC dataset with ~480M SMILES strings.
53
+ Output dimension: 768.
54
+
55
+ repo_id: "entropy/roberta_zinc_480m" (https://huggingface.co/entropy/roberta_zinc_480m)
56
+
57
+ - ChemBERTa series: Available in multiple sizes (77M/10M/5M) and training objectives (MTR/MLM).
58
+ Output dimension: 384.
59
+
60
+ repo_id: "DeepChem/ChemBERTa-77M-MTR" (https://huggingface.co/DeepChem/ChemBERTa-77M-MTR)
61
+
62
+ repo_id: "DeepChem/ChemBERTa-77M-MLM" (https://huggingface.co/DeepChem/ChemBERTa-77M-MLM)
63
+
64
+ repo_id: "DeepChem/ChemBERTa-10M-MTR" (https://huggingface.co/DeepChem/ChemBERTa-10M-MTR)
65
+
66
+ repo_id: "DeepChem/ChemBERTa-10M-MLM" (https://huggingface.co/DeepChem/ChemBERTa-10M-MLM)
67
+
68
+ repo_id: "DeepChem/ChemBERTa-5M-MLM" (https://huggingface.co/DeepChem/ChemBERTa-5M-MLM)
69
+
70
+ repo_id: "DeepChem/ChemBERTa-5M-MTR" (https://huggingface.co/DeepChem/ChemBERTa-5M-MTR)
71
+
72
+ - UniKi/bert-base-smiles: BERT model pretrained on SMILES strings.
73
+ Output dimension: 768.
74
+
75
+ repo_id: "unikei/bert-base-smiles" (https://huggingface.co/unikei/bert-base-smiles)
76
+
77
+ - ChemBERTa-zinc-base-v1: RoBERTa model pretrained on ZINC dataset with ~100k SMILES strings.
78
+ Output dimension: 384.
79
+
80
+ repo_id: "seyonec/ChemBERTa-zinc-base-v1" (https://huggingface.co/seyonec/ChemBERTa-zinc-base-v1)
81
+
82
+ Other models accessible through the transformers library have not been explicitly tested but may still be compatible with this interface.
83
+
84
+ Parameters
85
+ ----------
86
+ repo_id : str
87
+ The Hugging Face repository ID of the pretrained model.
88
+ max_length : int, default=128
89
+ Maximum sequence length for tokenization. Longer sequences will be truncated.
90
+ batch_size : int, default=128
91
+ Batch size used when encoding multiple molecules.
92
+ add_bos_eos : Optional[bool], default=None
93
+ Whether to add beginning/end of sequence tokens. If None, models in known_add_bos_eos_list will be set to True.
94
+ The current known_add_bos_eos_list includes: ["entropy/gpt2_zinc_87m"].
95
+ model_name : str, default="PretrainedMolecularEncoder"
96
+ Name identifier for the model instance.
97
+ verbose : bool, default=False
98
+ Whether to display progress information during encoding.
99
+ """
100
+
101
+ repo_id: str
102
+
103
+ # Default arguments
104
+ max_length: int = 128
105
+ batch_size: int = 128
106
+ add_bos_eos: Optional[bool] = None
107
+ model_name: str = "PretrainedMolecularEncoder"
108
+ verbose: bool = False
109
+
110
+ def __init__(self, repo_id: str, max_length: int = 128, batch_size: int = 128, add_bos_eos: Optional[bool] = None,
111
+ model_name: str = "PretrainedMolecularEncoder", verbose: bool = False, **kwargs):
112
+ self.repo_id = repo_id
113
+ self.max_length = max_length
114
+ self.batch_size = batch_size
115
+ self.add_bos_eos = add_bos_eos
116
+ self.model_name = model_name
117
+ self.verbose = verbose
118
+ super().__init__(**kwargs)
119
+
120
+ def __post_init__(self):
121
+ super().__post_init__()
122
+ self._require_transformers()
123
+ self.fitting_epoch = -1
124
+ self.fitting_loss = -1
125
+
126
+ if self.repo_id not in known_repos:
127
+ warnings.warn(f"Unknown repo_id: {self.repo_id}. The class will try to load the model from HuggingFace, but it might fail.")
128
+
129
+ @staticmethod
130
+ def _get_param_names() -> List[str]:
131
+ """Get parameter names for the estimator.
132
+
133
+ Returns
134
+ -------
135
+ List[str]
136
+ List of parameter names that can be used for model configuration.
137
+ """
138
+ return ["repo_id", "max_length", "model_name", "add_bos_eos"]
139
+
140
+ def _get_model_params(self) -> Dict[str, Any]:
141
+ raise NotImplementedError("PretrainedMolecularEncoder does not support model parameters.")
142
+
143
+ def _setup_optimizers(self) -> None:
144
+ raise NotImplementedError("PretrainedMolecularEncoder does not support training.")
145
+
146
+ def _train_epoch(self) -> None:
147
+ raise NotImplementedError("PretrainedMolecularEncoder does not support training.")
148
+
149
+ def save_to_local(self) -> None:
150
+ raise NotImplementedError("PretrainedMolecularEncoder does not support saving to local.")
151
+
152
+ def load_from_local(self) -> None:
153
+ raise NotImplementedError("PretrainedMolecularEncoder does not support loading from local.")
154
+
155
+ def save_to_hf(self) -> None:
156
+ raise NotImplementedError("PretrainedMolecularEncoder does not support saving to huggingface.")
157
+
158
+ def load_from_hf(self) -> None:
159
+ """The same as fit()"""
160
+ self.fit()
161
+
162
+ def load(self) -> None:
163
+ """The same as fit()"""
164
+ self.fit()
165
+
166
+ def fit(self) -> "HFPretrainedMolecularEncoder":
167
+ """Load the pretrained model from HuggingFace."""
168
+ assert self.repo_id is not None, "repo_id is not set"
169
+ self._require_transformers()
170
+ import transformers
171
+
172
+ self.tokenizer = transformers.AutoTokenizer.from_pretrained(self.repo_id, max_length=self.max_length)
173
+ self.model = transformers.AutoModel.from_pretrained(self.repo_id)
174
+ self.model.to(self.device)
175
+
176
+ model_config = self.model.config
177
+ model_type = model_config.model_type
178
+
179
+ if self.add_bos_eos is None:
180
+ self.add_bos_eos = self.repo_id in known_add_bos_eos_list
181
+
182
+ if self.tokenizer.pad_token is None:
183
+ if self.tokenizer.eos_token is not None:
184
+ self.tokenizer.pad_token = self.tokenizer.eos_token
185
+ else:
186
+ self.tokenizer.add_special_tokens({'pad_token': '[PAD]'})
187
+ self.model.resize_token_embeddings(len(self.tokenizer))
188
+
189
+ if self.add_bos_eos:
190
+ if self.tokenizer.bos_token is None:
191
+ self.tokenizer.add_special_tokens({'bos_token': '[BOS]'})
192
+ if self.tokenizer.eos_token is None:
193
+ self.tokenizer.add_special_tokens({'eos_token': '[EOS]'})
194
+ self.model.resize_token_embeddings(len(self.tokenizer))
195
+
196
+ warnings.warn("BOS and EOS tokens are not found in the tokenizer. They are added to the tokenizer since add_bos_eos is set to True.")
197
+
198
+ self.collator = transformers.DataCollatorWithPadding(self.tokenizer, padding=True, return_tensors='pt')
199
+ self.is_fitted_ = True
200
+ return self
201
+
202
+ def encode(self, X: List[str], return_type: Literal["np", "pt"] = "pt") -> Union[np.ndarray, torch.Tensor]:
203
+ """Encode molecules into vector representations.
204
+
205
+ Parameters
206
+ ----------
207
+ X : List[str]
208
+ List of SMILES strings
209
+ return_type : Literal["np", "pt"], default="pt"
210
+ Return type of the representations
211
+
212
+ Returns
213
+ -------
214
+ representations : ndarray or torch.Tensor
215
+ Molecular representations
216
+ """
217
+ self._require_transformers()
218
+ self._check_is_fitted()
219
+ X, _ = self._validate_inputs(X, return_rdkit_mol=False)
220
+
221
+ # Process in batches
222
+ all_embeddings = []
223
+ iterator = tqdm(range(0, len(X), self.batch_size), desc="Encoding molecules", total=len(X) // self.batch_size, disable=not self.verbose)
224
+ for i in iterator:
225
+ batch_X = X[i:i + self.batch_size]
226
+
227
+ if self.add_bos_eos:
228
+ # For decoding models (e.g. GPT2), manually add BOS and EOS tokens
229
+ processed_batch = [self.tokenizer.bos_token + x + self.tokenizer.eos_token for x in batch_X]
230
+ inputs = self.collator(self.tokenizer(processed_batch))
231
+ else:
232
+ inputs = self.collator(self.tokenizer(batch_X))
233
+
234
+ # Move inputs to the same device as the model
235
+ inputs = {k: v.to(self.device) for k, v in inputs.items()}
236
+
237
+ # Get model outputs
238
+ with torch.no_grad():
239
+ outputs = self.model(**inputs, output_hidden_states=True)
240
+
241
+ # get all attributes of outputs
242
+ print('outputs', outputs.keys())
243
+ # Extract embeddings based on model type
244
+ if hasattr(outputs, 'hidden_states'):
245
+ # For models that return a named tuple
246
+ full_embeddings = outputs.hidden_states[-1]
247
+ elif isinstance(outputs, tuple) and len(outputs) > 1:
248
+ # For models that return a tuple with hidden states
249
+ full_embeddings = outputs[-1][-1]
250
+ else:
251
+ # For models that return last_hidden_state directly
252
+ full_embeddings = outputs.last_hidden_state
253
+
254
+ # Apply attention mask to get meaningful embeddings
255
+ mask = inputs['attention_mask']
256
+ batch_embeddings = ((full_embeddings * mask.unsqueeze(-1)).sum(1) /
257
+ mask.sum(-1).unsqueeze(-1))
258
+
259
+ all_embeddings.append(batch_embeddings)
260
+
261
+ # Concatenate all batch embeddings
262
+ embeddings = torch.cat(all_embeddings, dim=0)
263
+
264
+ return embeddings if return_type == "pt" else embeddings.cpu().numpy()
265
+
266
+ @staticmethod
267
+ def _require_transformers():
268
+ try:
269
+ import transformers # noqa: F401
270
+ except ImportError:
271
+ raise ImportError(
272
+ "The 'transformers' package is required for PretrainedMolecularEncoder. "
273
+ "Please install it using `pip install transformers`."
274
+ )
@@ -0,0 +1,3 @@
1
+ from .modeling_supervised import SupervisedMolecularEncoder
2
+
3
+ __all__ = ['SupervisedMolecularEncoder']
@@ -0,0 +1,97 @@
1
+ import torch
2
+ import torch.nn as nn
3
+ from torch_geometric.nn import global_add_pool, global_mean_pool, global_max_pool
4
+
5
+ from ...nn import GNN_node, GNN_node_Virtualnode, MLP
6
+ from ...utils import init_weights
7
+
8
+ reg_criterion = torch.nn.L1Loss()
9
+ class_criterion = torch.nn.BCEWithLogitsLoss()
10
+
11
+ class GNN(nn.Module):
12
+ def __init__(
13
+ self,
14
+ num_layer,
15
+ hidden_size,
16
+ num_task,
17
+ drop_ratio=0.5,
18
+ norm_layer="batch_norm",
19
+ encoder_type="gin-virtual",
20
+ readout="max",
21
+ ):
22
+ super(GNN, self).__init__()
23
+ gnn_name = encoder_type.split("-")[0]
24
+ self.num_task = num_task
25
+ self.hidden_size = hidden_size
26
+
27
+ encoder_params = {
28
+ "num_layer": num_layer,
29
+ "hidden_size": hidden_size,
30
+ "JK": "last",
31
+ "drop_ratio": drop_ratio,
32
+ "residual": True,
33
+ "gnn_name": gnn_name,
34
+ "norm_layer": norm_layer
35
+ }
36
+
37
+ # Choose encoder type based on encoder
38
+ encoder_class = GNN_node_Virtualnode if "virtual" in encoder_type else GNN_node
39
+ self.graph_encoder = encoder_class(**encoder_params)
40
+ pooling_funcs = {
41
+ "sum": global_add_pool,
42
+ "mean": global_mean_pool,
43
+ "max": global_max_pool
44
+ }
45
+ self.readout = pooling_funcs.get(readout)
46
+ if self.readout is None:
47
+ raise ValueError(f"Invalid graph pooling type {readout}.")
48
+
49
+ self.predictor = MLP(hidden_size, hidden_features=2 * hidden_size, out_features=num_task)
50
+
51
+ def initialize_parameters(self, seed=None):
52
+ """
53
+ Randomly initialize all model parameters using the init_weights function.
54
+
55
+ Args:
56
+ seed (int, optional): Random seed for reproducibility. Defaults to None.
57
+ """
58
+ if seed is not None:
59
+ torch.manual_seed(seed)
60
+
61
+ # Initialize the main components
62
+ init_weights(self.graph_encoder)
63
+ init_weights(self.predictor)
64
+
65
+ # Reset all parameters using PyTorch Geometric's reset function
66
+ def reset_parameters(module):
67
+ if hasattr(module, 'reset_parameters'):
68
+ module.reset_parameters()
69
+ elif hasattr(module, 'weight') and hasattr(module.weight, 'data'):
70
+ init_weights(module)
71
+
72
+ self.apply(reset_parameters)
73
+
74
+ def compute_loss(self, batched_data, is_class):
75
+ h_node, _ = self.graph_encoder(batched_data)
76
+ h_rep = self.readout(h_node, batched_data.batch)
77
+ prediction = self.predictor(h_rep)
78
+
79
+ target = batched_data.y.to(torch.float32)
80
+ is_labeled = ~torch.isnan(target)
81
+ is_labeled_class = is_labeled[:, is_class]
82
+ is_labeled_reg = is_labeled[:, ~is_class]
83
+
84
+ target_class = target[:, is_class]
85
+ target_reg = target[:, ~is_class]
86
+ prediction_class = prediction[:, is_class]
87
+ prediction_reg = prediction[:, ~is_class]
88
+
89
+ loss_class = class_criterion(prediction_class.to(torch.float32)[is_labeled_class], target_class[is_labeled_class])
90
+ loss_reg = reg_criterion(prediction_reg.to(torch.float32)[is_labeled_reg], target_reg[is_labeled_reg])
91
+ loss = loss_class + loss_reg
92
+ return loss
93
+
94
+ def forward(self, batched_data):
95
+ h_node, _ = self.graph_encoder(batched_data)
96
+ h_rep = self.readout(h_node, batched_data.batch)
97
+ return {"graph": h_rep, "node": h_node}