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.
- torch_molecule/__init__.py +70 -0
- torch_molecule/base/__init__.py +8 -0
- torch_molecule/base/base.py +396 -0
- torch_molecule/base/encoder.py +44 -0
- torch_molecule/base/generator.py +24 -0
- torch_molecule/base/old_encoder.py +322 -0
- torch_molecule/base/old_predictor.py +904 -0
- torch_molecule/base/old_predictor2.py +436 -0
- torch_molecule/base/predictor.py +112 -0
- torch_molecule/encoder/attrmask/__init__.py +3 -0
- torch_molecule/encoder/attrmask/model.py +113 -0
- torch_molecule/encoder/attrmask/modeling_attrmask.py +304 -0
- torch_molecule/encoder/constant.py +13 -0
- torch_molecule/encoder/contextpred/__init__.py +3 -0
- torch_molecule/encoder/contextpred/model.py +207 -0
- torch_molecule/encoder/contextpred/modeling_contextpred.py +299 -0
- torch_molecule/encoder/contextpred/utils.py +206 -0
- torch_molecule/encoder/edgepred/__init__.py +3 -0
- torch_molecule/encoder/edgepred/model.py +104 -0
- torch_molecule/encoder/edgepred/modeling_edgepred.py +285 -0
- torch_molecule/encoder/graphmae/__init__.py +3 -0
- torch_molecule/encoder/graphmae/dataloader.py +206 -0
- torch_molecule/encoder/graphmae/model.py +137 -0
- torch_molecule/encoder/graphmae/modeling_graphmae.py +323 -0
- torch_molecule/encoder/infograph/__init__.py +3 -0
- torch_molecule/encoder/infograph/loss_function.py +128 -0
- torch_molecule/encoder/infograph/model.py +92 -0
- torch_molecule/encoder/infograph/modeling_infograph.py +301 -0
- torch_molecule/encoder/infograph/module.py +31 -0
- torch_molecule/encoder/moama/__init__.py +3 -0
- torch_molecule/encoder/moama/model.py +131 -0
- torch_molecule/encoder/moama/modeling_moama.py +307 -0
- torch_molecule/encoder/moama/utils.py +143 -0
- torch_molecule/encoder/pretrained/__init__.py +3 -0
- torch_molecule/encoder/pretrained/modeling_pretrained.py +274 -0
- torch_molecule/encoder/supervised/__init__.py +3 -0
- torch_molecule/encoder/supervised/model.py +97 -0
- torch_molecule/encoder/supervised/modeling_supervised.py +354 -0
- torch_molecule/generator/digress/__init__.py +3 -0
- torch_molecule/generator/digress/diffusion.py +194 -0
- torch_molecule/generator/digress/modeling_digress.py +503 -0
- torch_molecule/generator/digress/transformer.py +360 -0
- torch_molecule/generator/digress/utils.py +196 -0
- torch_molecule/generator/gdss/__init__.py +3 -0
- torch_molecule/generator/gdss/layers.py +257 -0
- torch_molecule/generator/gdss/model.py +204 -0
- torch_molecule/generator/gdss/modeling_gdss.py +474 -0
- torch_molecule/generator/gdss/sde.py +334 -0
- torch_molecule/generator/gdss/solver.py +227 -0
- torch_molecule/generator/gdss/toremove/ScoreNetworkA.py +167 -0
- torch_molecule/generator/gdss/toremove/ScoreNetworkX.py +85 -0
- torch_molecule/generator/gdss/utils.py +240 -0
- torch_molecule/generator/graph_dit/__init__.py +3 -0
- torch_molecule/generator/graph_dit/diffusion.py +188 -0
- torch_molecule/generator/graph_dit/modeling_graph_dit.py +581 -0
- torch_molecule/generator/graph_dit/transformer.py +207 -0
- torch_molecule/generator/graph_dit/utils.py +220 -0
- torch_molecule/generator/graph_ga/__init__.py +3 -0
- torch_molecule/generator/graph_ga/crossover.py +182 -0
- torch_molecule/generator/graph_ga/modeling_graph_ga.py +310 -0
- torch_molecule/generator/graph_ga/mutate.py +136 -0
- torch_molecule/generator/graph_ga/oracle.py +95 -0
- torch_molecule/generator/jtvae/__init__.py +3 -0
- torch_molecule/generator/jtvae/jtnn/chemutils.py +450 -0
- torch_molecule/generator/jtvae/jtnn/datautils.py +127 -0
- torch_molecule/generator/jtvae/jtnn/jtmpn.py +140 -0
- torch_molecule/generator/jtvae/jtnn/jtnn_dec.py +350 -0
- torch_molecule/generator/jtvae/jtnn/jtnn_enc.py +131 -0
- torch_molecule/generator/jtvae/jtnn/mol_tree.py +111 -0
- torch_molecule/generator/jtvae/jtnn/mpn.py +129 -0
- torch_molecule/generator/jtvae/jtnn/nnutils.py +66 -0
- torch_molecule/generator/jtvae/jtnn/vocab.py +31 -0
- torch_molecule/generator/jtvae/jtnn_vae.py +246 -0
- torch_molecule/generator/jtvae/modeling_jtvae.py +247 -0
- torch_molecule/generator/lstm/__init__.py +3 -0
- torch_molecule/generator/lstm/action_sampler.py +91 -0
- torch_molecule/generator/lstm/lstm.py +59 -0
- torch_molecule/generator/lstm/modeling_lstm.py +263 -0
- torch_molecule/generator/lstm/smiles_char_dict.py +123 -0
- torch_molecule/generator/lstm/utils.py +62 -0
- torch_molecule/generator/molgpt/__init__.py +3 -0
- torch_molecule/generator/molgpt/dataset.py +87 -0
- torch_molecule/generator/molgpt/gpt.py +251 -0
- torch_molecule/generator/molgpt/modeling_molgpt.py +427 -0
- torch_molecule/generator/pretrained/modeling_pretrained.py +1 -0
- torch_molecule/nn/__init__.py +16 -0
- torch_molecule/nn/attention.py +63 -0
- torch_molecule/nn/embedder.py +183 -0
- torch_molecule/nn/gnn.py +631 -0
- torch_molecule/nn/mlp.py +34 -0
- torch_molecule/predictor/bfgnn/__init__.py +3 -0
- torch_molecule/predictor/bfgnn/model.py +116 -0
- torch_molecule/predictor/bfgnn/modeling_bfgnn.py +81 -0
- torch_molecule/predictor/dir/__init__.py +3 -0
- torch_molecule/predictor/dir/model.py +235 -0
- torch_molecule/predictor/dir/modeling_dir.py +161 -0
- torch_molecule/predictor/dir/utils.py +40 -0
- torch_molecule/predictor/gnn/__init__.py +3 -0
- torch_molecule/predictor/gnn/model.py +114 -0
- torch_molecule/predictor/gnn/modeling_gnn.py +706 -0
- torch_molecule/predictor/gnn/old_modeling_gnn.py +707 -0
- torch_molecule/predictor/grea/__init__.py +3 -0
- torch_molecule/predictor/grea/model.py +190 -0
- torch_molecule/predictor/grea/modeling_grea.py +107 -0
- torch_molecule/predictor/grea/old1_features.py +229 -0
- torch_molecule/predictor/grea/old1_modeling_grea.py +493 -0
- torch_molecule/predictor/grea/utils.py +97 -0
- torch_molecule/predictor/grin/__init__.py +3 -0
- torch_molecule/predictor/grin/model.py +116 -0
- torch_molecule/predictor/grin/modeling_grin.py +91 -0
- torch_molecule/predictor/irm/__init__.py +3 -0
- torch_molecule/predictor/irm/model.py +127 -0
- torch_molecule/predictor/irm/modeling_irm.py +179 -0
- torch_molecule/predictor/lstm/__init__.py +3 -0
- torch_molecule/predictor/lstm/model.py +145 -0
- torch_molecule/predictor/lstm/modeling_lstm.py +627 -0
- torch_molecule/predictor/lstm/token_from_smiles.py +85 -0
- torch_molecule/predictor/old_modeling_graph.py +650 -0
- torch_molecule/predictor/rpgnn/__init__.py +3 -0
- torch_molecule/predictor/rpgnn/model.py +185 -0
- torch_molecule/predictor/rpgnn/modeling_rpgnn.py +76 -0
- torch_molecule/predictor/sgir/__init__.py +3 -0
- torch_molecule/predictor/sgir/modeling_sgir.py +260 -0
- torch_molecule/predictor/sgir/strategy.py +266 -0
- torch_molecule/predictor/smiles_transformer/__init__.py +3 -0
- torch_molecule/predictor/smiles_transformer/model.py +424 -0
- torch_molecule/predictor/smiles_transformer/modeling_transformer.py +252 -0
- torch_molecule/predictor/ssr/__init__.py +3 -0
- torch_molecule/predictor/ssr/model.py +283 -0
- torch_molecule/predictor/ssr/modeling_ssr.py +267 -0
- torch_molecule/predictor/ssr/utils.py +185 -0
- torch_molecule/utils/__init__.py +31 -0
- torch_molecule/utils/checker.py +158 -0
- torch_molecule/utils/checkpoint.py +294 -0
- torch_molecule/utils/format.py +140 -0
- torch_molecule/utils/generic/metrics.py +530 -0
- torch_molecule/utils/generic/pseudo_tasks.py +11 -0
- torch_molecule/utils/generic/weights.py +30 -0
- torch_molecule/utils/graph/features.py +178 -0
- torch_molecule/utils/graph/graph_from_smiles.py +134 -0
- torch_molecule/utils/graph/graph_to_smiles.py +312 -0
- torch_molecule/utils/hf.py +232 -0
- torch_molecule/utils/search.py +64 -0
- torch_molecule-0.1.0.dev2.dist-info/METADATA +243 -0
- torch_molecule-0.1.0.dev2.dist-info/RECORD +148 -0
- torch_molecule-0.1.0.dev2.dist-info/WHEEL +5 -0
- torch_molecule-0.1.0.dev2.dist-info/licenses/LICENSE +21 -0
- 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.
|