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,232 @@
1
+ import os
2
+ import json
3
+ import datetime
4
+ from typing import Dict, Tuple, Optional, List, Union
5
+ from huggingface_hub import hf_hub_download
6
+
7
+ def merge_task_configs(
8
+ task_id: str,
9
+ existing_config: Dict,
10
+ new_task_config: Dict,
11
+ num_params: int
12
+ ) -> Dict:
13
+ """Merge task-specific configuration and maintain version history.
14
+
15
+ Parameters
16
+ ----------
17
+ task_id : str
18
+ Task identifier (e.g., 'O2', 'N2')
19
+ existing_config : Dict
20
+ Existing configuration dictionary
21
+ new_task_config : Dict
22
+ New task configuration to merge
23
+ num_params : int
24
+ Number of model parameters
25
+
26
+ Returns
27
+ -------
28
+ Dict
29
+ Updated configuration with task history
30
+ """
31
+ merged = existing_config.copy()
32
+ tasks_config = merged.get("tasks", {})
33
+ task_config = tasks_config.get(task_id, {
34
+ "versions": [],
35
+ "current_version": "0.0.0",
36
+ "date_added": datetime.datetime.now().isoformat(),
37
+ })
38
+
39
+ # Update task version history
40
+ current_version = task_config["current_version"]
41
+ version_parts = current_version.split('.')
42
+ version_parts[-1] = str(int(version_parts[-1]) + 1)
43
+ new_version = '.'.join(version_parts)
44
+
45
+ # Archive current version if it exists
46
+ if task_config["versions"]:
47
+ task_config["versions"].append({
48
+ "version": current_version,
49
+ "date": datetime.datetime.now().isoformat(),
50
+ "config": task_config.copy()
51
+ })
52
+
53
+ # Update task config
54
+ task_config.update({
55
+ "current_version": new_version,
56
+ "last_updated": datetime.datetime.now().isoformat(),
57
+ "num_parameters": num_params,
58
+ **new_task_config
59
+ })
60
+
61
+ # Update tasks configuration
62
+ tasks_config[task_id] = task_config
63
+ merged["tasks"] = tasks_config
64
+ merged["last_updated"] = datetime.datetime.now().isoformat()
65
+
66
+ return merged
67
+
68
+ def get_existing_repo_data(repo_id: str, token: Optional[str] = None) -> Tuple[bool, Dict, str]:
69
+ """Get existing repository data from HuggingFace Hub.
70
+
71
+ Parameters
72
+ ----------
73
+ repo_id : str
74
+ Repository ID
75
+ token : Optional[str]
76
+ HuggingFace token
77
+
78
+ Returns
79
+ -------
80
+ Tuple[bool, Dict, str]
81
+ Tuple containing (repo_exists, existing_config, existing_readme)
82
+ """
83
+ repo_exists = False
84
+ existing_config = {}
85
+ existing_readme = ""
86
+
87
+ try:
88
+ config_path = hf_hub_download(
89
+ repo_id=repo_id,
90
+ filename="config.json",
91
+ token=token
92
+ )
93
+ with open(config_path, 'r') as f:
94
+ existing_config = json.load(f)
95
+ repo_exists = True
96
+
97
+ try:
98
+ readme_path = hf_hub_download(
99
+ repo_id=repo_id,
100
+ filename="README.md",
101
+ token=token
102
+ )
103
+ with open(readme_path, 'r') as f:
104
+ existing_readme = f.read()
105
+ except Exception:
106
+ pass
107
+
108
+ except Exception:
109
+ pass
110
+
111
+ return repo_exists, existing_config, existing_readme
112
+
113
+ def create_model_card(
114
+ model_class: str,
115
+ model_name: str,
116
+ tasks_config: Dict,
117
+ model_config: Dict,
118
+ repo_id: str,
119
+ existing_readme: str = ""
120
+ ) -> str:
121
+ """Create a model card for multiple tasks.
122
+
123
+ Parameters
124
+ ----------
125
+ model_class : str
126
+ Class name of the model
127
+ model_name : str
128
+ Name of the model
129
+ tasks_config : Dict
130
+ Configuration for all tasks
131
+ model_config : Dict
132
+ General model configuration
133
+ repo_id : str
134
+ Repository ID
135
+ existing_readme : str
136
+ Existing README content
137
+
138
+ Returns
139
+ -------
140
+ str
141
+ Generated model card content
142
+ """
143
+ # Create tasks summary table
144
+ tasks_table = "| Task | Version | Last Updated | Parameters | Metrics |\n"
145
+ tasks_table += "|------|---------|--------------|------------|----------|\n"
146
+
147
+ for task_id, task_info in sorted(tasks_config.items()):
148
+ metrics = task_info.get("metrics", {})
149
+ metrics_str = ", ".join([f"{k}: {v:.4f}" for k, v in metrics.items()])
150
+ tasks_table += (
151
+ f"| {task_id} | {task_info['current_version']} | "
152
+ f"{task_info['last_updated'][:10]} | "
153
+ f"{task_info['num_parameters']:,} | {metrics_str} |\n"
154
+ )
155
+
156
+ # - molecular-property-prediction
157
+ readme_content = f"""---
158
+ tags:
159
+ - torch_molecule
160
+ library_name: torch_molecule
161
+ ---
162
+
163
+ # {model_class} Model
164
+
165
+ ## Model Description
166
+ - **Model Type**: {model_class}
167
+ - **Framework**: torch_molecule
168
+ - **Last Updated**: {model_config.get('last_updated', datetime.datetime.now().isoformat())[:10]}
169
+
170
+ ## Task Summary
171
+ {tasks_table}
172
+
173
+ ## Usage
174
+
175
+ ```python
176
+ from torch_molecule import {model_class}
177
+
178
+ # Load model for specific task
179
+ model = {model_class}()
180
+ model.load(
181
+ "local_model_dir/{model_name}.pt",
182
+ repo="{repo_id}"
183
+ )
184
+
185
+ # For predictor: Make predictions
186
+ # predictions = model.predict(smiles_list)
187
+ # For generator: Make generations
188
+ # generations = model.generate(n_samples)
189
+ # For encoder: Make encodings
190
+ # encodings = model.encode(smiles_list)
191
+ ```
192
+
193
+ ## Tasks Details
194
+
195
+ """
196
+ # Add detailed task sections (latest version only, excluding fitting_loss)
197
+ for task_id, task_info in sorted(tasks_config.items()):
198
+ # Filter out fitting_loss from config
199
+ task_config = task_info.get('config', {}).copy()
200
+ if 'fitting_loss' in task_config:
201
+ del task_config['fitting_loss']
202
+
203
+ readme_content += f"""
204
+ ### {task_id} Task
205
+ - **Current Version**: {task_info['current_version']}
206
+ - **Last Updated**: {task_info['last_updated'][:10]}
207
+ - **Parameters**: {task_info['num_parameters']:,}
208
+ - **Configuration**:
209
+ ```python
210
+ {json.dumps(task_config, indent=2)}
211
+ ```
212
+ """
213
+
214
+ # Preserve custom sections from existing README
215
+ # if existing_readme:
216
+ # try:
217
+ # custom_sections = ""
218
+ # split_points = ["## Tasks Details", "## Usage"]
219
+ # for split_point in split_points:
220
+ # if split_point in existing_readme:
221
+ # parts = existing_readme.split(split_point)
222
+ # if len(parts) > 1 and "##" in parts[1]:
223
+ # custom_sections = parts[1].split("##", 1)[1]
224
+ # custom_sections = "##" + custom_sections
225
+ # break
226
+
227
+ # if custom_sections:
228
+ # readme_content += f"\n{custom_sections}"
229
+ # except Exception as e:
230
+ # print(f"Warning: Error preserving custom README sections: {e}")
231
+
232
+ return readme_content
@@ -0,0 +1,64 @@
1
+ from enum import Enum
2
+ from typing import Dict, Any, Union, List, Tuple, NamedTuple
3
+
4
+ class ParameterType(Enum):
5
+ """Enum defining types of hyperparameters for optimization.
6
+
7
+ Each type corresponds to a specific Optuna suggest method and parameter behavior.
8
+ """
9
+
10
+ CATEGORICAL = "categorical" # Uses suggest_categorical for discrete choices
11
+ INTEGER = "integer" # Uses suggest_int for whole numbers
12
+ FLOAT = "float" # Uses suggest_float for continuous values
13
+ LOG_FLOAT = "log_float" # Uses suggest_float with log=True for exponential scale
14
+
15
+ class ParameterSpec(NamedTuple):
16
+ """Specification for a hyperparameter including its type and valid range/options."""
17
+
18
+ param_type: ParameterType
19
+ value_range: Union[Tuple[Any, Any], List[Any]]
20
+
21
+ def suggest_parameter(trial: Any, param_name: str, param_spec: ParameterSpec) -> Any:
22
+ """Suggest a parameter value using the appropriate Optuna suggest method.
23
+
24
+ Parameters
25
+ ----------
26
+ trial : optuna.Trial
27
+ The Optuna trial object
28
+ param_name : str
29
+ Name of the parameter
30
+ param_spec : ParameterSpec
31
+ Specification of the parameter type and range
32
+
33
+ Returns
34
+ -------
35
+ Any
36
+ The suggested parameter value
37
+
38
+ Raises
39
+ ------
40
+ ValueError
41
+ If the parameter type is not recognized
42
+ """
43
+ if param_spec.param_type == ParameterType.CATEGORICAL:
44
+ return trial.suggest_categorical(param_name, param_spec.value_range)
45
+
46
+ elif param_spec.param_type == ParameterType.INTEGER:
47
+ min_val, max_val = param_spec.value_range
48
+ return trial.suggest_int(param_name, min_val, max_val)
49
+
50
+ elif param_spec.param_type == ParameterType.FLOAT:
51
+ min_val, max_val = param_spec.value_range
52
+ return trial.suggest_float(param_name, min_val, max_val)
53
+
54
+ elif param_spec.param_type == ParameterType.LOG_FLOAT:
55
+ min_val, max_val = param_spec.value_range
56
+ return trial.suggest_float(param_name, min_val, max_val, log=True)
57
+
58
+ else:
59
+ raise ValueError(f"Unknown parameter type: {param_spec.param_type}")
60
+
61
+ def parse_list_params(params_str):
62
+ if params_str is None:
63
+ return None
64
+ return params_str.split(',')
@@ -0,0 +1,243 @@
1
+ Metadata-Version: 2.4
2
+ Name: torch_molecule
3
+ Version: 0.1.0.dev2
4
+ Summary: Deep learning packages for molecular discovery with a simple sklearn-style interface
5
+ Author-email: Gang Liu <gliu7@nd.edu>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/liugangcode/torch-molecule
8
+ Project-URL: Bug Tracker, https://github.com/liugangcode/torch-molecule
9
+ Project-URL: Documentation, https://liugangcode.github.io/torch-molecule/
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.8
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: torch>=2.2.0
17
+ Requires-Dist: torch-geometric>=2.6.1
18
+ Requires-Dist: numpy
19
+ Requires-Dist: pandas>=2.2.3
20
+ Requires-Dist: click
21
+ Requires-Dist: huggingface_hub>=0.22.2
22
+ Requires-Dist: joblib>=1.3.2
23
+ Requires-Dist: networkx>=3.2.1
24
+ Requires-Dist: PyYAML>=6.0.2
25
+ Requires-Dist: rdkit>=2023.9.5
26
+ Requires-Dist: scikit_learn>=1.4.1.post1
27
+ Requires-Dist: scipy>=1.14.1
28
+ Requires-Dist: tqdm>=4.66.2
29
+ Requires-Dist: optuna>=4.0.0
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=7.0; extra == "dev"
32
+ Requires-Dist: black; extra == "dev"
33
+ Requires-Dist: isort; extra == "dev"
34
+ Requires-Dist: flake8; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ <p align="center">
38
+ <img src="assets/logo.png" alt="torch-molecule logo" width="600"/>
39
+ </p>
40
+
41
+ <p align="center">
42
+ <a href="https://github.com/liugangcode/torch-molecule">
43
+ <img src="https://img.shields.io/badge/GitHub-Repository-blue?logo=github" alt="GitHub Repository">
44
+ </a>
45
+ <a href="https://liugangcode.github.io/torch-molecule/">
46
+ <img src="https://img.shields.io/badge/Documentation-Online-brightgreen?logo=readthedocs" alt="Documentation">
47
+ </a>
48
+ </p>
49
+
50
+ <p align="center">
51
+ <b>Deep learning for molecular discovery with a simple sklearn-style interface</b>
52
+ </p>
53
+
54
+ ---
55
+
56
+ `torch-molecule` is a package under active development that facilitates molecular discovery through deep learning, featuring a user-friendly, `sklearn`-style interface. It includes model checkpoints for efficient deployment and benchmarking across a range of molecular tasks. Currently, the package focuses on three main components: **Predictive Models**, **Generative Models**, and **Representation Models**. See the [List of Supported Models](#list-of-supported-models) section for all available models.
57
+
58
+ > **Note**: This project is in active development, and features may change.
59
+
60
+ ## Installation
61
+
62
+ 1. **Create a Conda environment**:
63
+ ```bash
64
+ conda create --name torch_molecule python=3.11.7
65
+ conda activate torch_molecule
66
+ ```
67
+
68
+ 2. **Install `torch_molecule` from GitHub**:
69
+
70
+ Clone the repository:
71
+ ```bash
72
+ git clone https://github.com/liugangcode/torch-molecule
73
+ ```
74
+
75
+ Install the requirements:
76
+ ```bash
77
+ pip install -r requirements.txt
78
+ ```
79
+
80
+ Editable install:
81
+ ```bash
82
+ pip install -e .
83
+ ```
84
+
85
+ 3. **Install `torch_molecule` from PyPI** (Legacy):
86
+ ```bash
87
+ pip install -i https://test.pypi.org/simple/ torch-molecule
88
+ ```
89
+
90
+ ### Additional Packages
91
+
92
+ | Model | Required Packages |
93
+ |-------|-------------------|
94
+ | HFPretrainedMolecularEncoder | transformers |
95
+ | BFGNNMolecularPredictor | torch-scatter |
96
+ | GRINMolecularPredictor | torch-scatter |
97
+
98
+ ## Usage
99
+
100
+ Refer to the `tests` folder for more use cases.
101
+
102
+ ### Python API Example
103
+
104
+ The following example demonstrates how to use the `GREAMolecularPredictor` class from `torch_molecule`:
105
+
106
+ More examples could be found in the folders `examples` and `tests`.
107
+
108
+ ```python
109
+ from torch_molecule import GREAMolecularPredictor
110
+
111
+ # Train GREA model
112
+ grea_model = GREAMolecularPredictor(
113
+ num_task=num_task,
114
+ task_type="regression",
115
+ model_name="GREA_multitask",
116
+ evaluate_criterion='r2',
117
+ evaluate_higher_better=True,
118
+ verbose=True
119
+ )
120
+
121
+ # Fit the model
122
+ X_train = ['C1=CC=CC=C1', 'C1=CC=CC=C1']
123
+ y_train = [[0.5], [1.5]]
124
+ X_val = ['C1=CC=CC=C1', 'C1=CC=CC=C1']
125
+ y_val = [[0.5], [1.5]]
126
+ N_trial = 10
127
+
128
+ grea_model.autofit(
129
+ X_train=X_train.tolist(),
130
+ y_train=y_train,
131
+ X_val=X_val.tolist(),
132
+ y_val=y_val,
133
+ n_trials=N_trial,
134
+ )
135
+ ```
136
+
137
+ ### Checkpoints
138
+
139
+ `torch-molecule` provides checkpoint functions that can be interacted with on Hugging Face.
140
+
141
+ ```python
142
+ from torch_molecule import GREAMolecularPredictor
143
+ from sklearn.metrics import mean_absolute_error
144
+
145
+ # Define the repository ID for Hugging Face
146
+ repo_id = "user/repo_id"
147
+
148
+ # Initialize the GREAMolecularPredictor model
149
+ model = GREAMolecularPredictor()
150
+
151
+ # Train the model using autofit
152
+ model.autofit(
153
+ X_train=X.tolist(), # List of SMILES strings for training
154
+ y_train=y_train, # numpy array [n_samples, n_tasks] for training labels
155
+ X_val=X_val.tolist(),# List of SMILES strings for validation
156
+ y_val=y_val, # numpy array [n_samples, n_tasks] for validation labels
157
+ )
158
+
159
+ # Make predictions on the test set
160
+ output = model.predict(X_test.tolist()) # (n_sample, n_task)
161
+
162
+ # Calculate the mean absolute error
163
+ mae = mean_absolute_error(y_test, output['prediction'])
164
+ metrics = {'MAE': mae}
165
+
166
+ # Save the trained model to Hugging Face
167
+ model.save_to_hf(
168
+ repo_id=repo_id,
169
+ task_id=f"{task_name}",
170
+ metrics=metrics,
171
+ commit_message=f"Upload GREA_{task_name} model with metrics: {metrics}",
172
+ private=False
173
+ )
174
+
175
+ # Load a pretrained checkpoint from Hugging Face
176
+ model = GREAMolecularPredictor()
177
+ model.load_from_hf(repo_id=repo_id, local_cache=f"{model_dir}/GREA_{task_name}.pt")
178
+
179
+ # Set model parameters
180
+ model.set_params(verbose=True)
181
+
182
+ # Make predictions using the loaded model
183
+ predictions = model.predict(smiles_list)
184
+ ```
185
+
186
+ ## List of Supported Models
187
+
188
+ ### Predictive Models
189
+
190
+ | Model | Reference |
191
+ |----------------------|---------------------|
192
+ | GRIN | [Learning Repetition-Invariant Representations for Polymer Informatics. May 2025](https://arxiv.org/abs/2505.10726) |
193
+ | BFGNN | [Graph neural networks extrapolate out-of-distribution for shortest paths. March 2025](https://arxiv.org/abs/2503.19173) |
194
+ | SGIR | [Semi-Supervised Graph Imbalanced Regression. KDD 2023](https://dl.acm.org/doi/10.1145/3580305.3599497) |
195
+ | GREA | [Graph Rationalization with Environment-based Augmentations. KDD 2022](https://dl.acm.org/doi/abs/10.1145/3534678.3539347) |
196
+ | DIR | [Discovering Invariant Rationales for Graph Neural Networks. ICLR 2022](https://arxiv.org/abs/2201.12872) |
197
+ | SSR | [SizeShiftReg: a Regularization Method for Improving Size-Generalization in Graph Neural Networks. NeurIPS 2022](https://arxiv.org/abs/2206.07096) |
198
+ | IRM | [Invariant Risk Minimization (2019)](https://arxiv.org/abs/1907.02893) |
199
+ | RPGNN | [Relational Pooling for Graph Representations. ICML 2019](https://arxiv.org/abs/1903.02541) |
200
+ | GNNs | [Graph Convolutional Networks. ICLR 2017](https://arxiv.org/abs/1609.02907) and [Graph Isomorphism Network. ICLR 2019](https://arxiv.org/abs/1810.00826) |
201
+ | Transformer (SMILES) | [Transformer (Attention is All You Need. NeurIPS 2017)](https://arxiv.org/abs/1706.03762) based on SMILES strings |
202
+ | LSTM (SMILES) | [Long short-term memory (Neural Computation 1997)](https://ieeexplore.ieee.org/abstract/document/6795963) based on SMILES strings |
203
+
204
+ ### Generative Models
205
+
206
+ | Model | Reference |
207
+ |------------|---------------------|
208
+ | Graph DiT | [Graph Diffusion Transformers for Multi-Conditional Molecular Generation. NeurIPS 2024](https://openreview.net/forum?id=cfrDLD1wfO) |
209
+ | DiGress | [DiGress: Discrete Denoising Diffusion for Graph Generation. ICLR 2023](https://openreview.net/forum?id=UaAD-Nu86WX) |
210
+ | GDSS | [Score-based Generative Modeling of Graphs via the System of Stochastic Differential Equations. ICML 2022](https://proceedings.mlr.press/v162/jo22a/jo22a.pdf) |
211
+ | MolGPT | [MolGPT: Molecular Generation Using a Transformer-Decoder Model. Journal of Chemical Information and Modeling 2021](https://pubs.acs.org/doi/10.1021/acs.jcim.1c00600) |
212
+ | JTVAE | [Junction Tree Variational Autoencoder for Molecular Graph Generation. ICML 2018.](https://proceedings.mlr.press/v80/jin18a) |
213
+ | GraphGA | [A Graph-Based Genetic Algorithm and Its Application to the Multiobjective Evolution of Median Molecules. Journal of Chemical Information and Computer Sciences 2004](https://pubs.acs.org/doi/10.1021/ci034290p) |
214
+ | LSTM (SMILES) | [Long short-term memory (Neural Computation 1997)](https://ieeexplore.ieee.org/abstract/document/6795963) based on SMILES strings |
215
+
216
+ ### Representation Models
217
+
218
+ | Model | Reference |
219
+ |--------------|---------------------|
220
+ | MoAMa | [Motif-aware Attribute Masking for Molecular Graph Pre-training. LoG 2024](https://arxiv.org/abs/2309.04589) |
221
+ | GraphMAE | [GraphMAE: Self-Supervised Masked Graph Autoencoders. KDD 2022](https://arxiv.org/abs/2205.10803) |
222
+ | AttrMasking | [Strategies for Pre-training Graph Neural Networks. ICLR 2020](https://arxiv.org/abs/1905.12265) |
223
+ | ContextPred | [Strategies for Pre-training Graph Neural Networks. ICLR 2020](https://arxiv.org/abs/1905.12265) |
224
+ | EdgePred | [Strategies for Pre-training Graph Neural Networks. ICLR 2020](https://arxiv.org/abs/1905.12265) |
225
+ | InfoGraph | [InfoGraph: Unsupervised and Semi-supervised Graph-Level Representation Learning via Mutual Information Maximization. ICLR 2020](https://arxiv.org/abs/1908.01000) |
226
+ | Supervised | Supervised pretraining |
227
+ | Pretrained | More than ten pretrained models from [Hugging Face](https://huggingface.co) |
228
+
229
+ ## Project Structure
230
+
231
+ See the structure of `torch_molecule` with the command `tree -L 2 torch_molecule -I '__pycache__|*.pyc|*.pyo|.git|old*'`
232
+
233
+ ## Plan
234
+
235
+ 1. **Predictive Models**: Done: GREA, SGIR, IRM, GIN/GCN w/ virtual, DIR. SMILES-based LSTM/Transformers. TODO more
236
+ 2. **Generative Models**: Done: Graph DiT, GraphGA, DiGress, GDS, MolGPT TODO: more
237
+ 3. **Representation Models**: Done: MoAMa, AttrMasking, ContextPred, EdgePred. Many pretrained models from HF. TODO: checkpoints, more
238
+
239
+ ## Acknowledgements
240
+
241
+ This project is under active development, and some features may change over time.
242
+
243
+ The project template was adapted from [https://github.com/lwaekfjlk/python-project-template](https://github.com/lwaekfjlk/python-project-template). We thank the authors for their contribution to the open-source community.