@nahisaho/satori 0.12.0 → 0.14.0
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.
- package/README.md +150 -54
- package/package.json +1 -1
- package/src/.github/skills/scientific-biomedical-pubtator/SKILL.md +331 -0
- package/src/.github/skills/scientific-biothings-idmapping/SKILL.md +298 -0
- package/src/.github/skills/scientific-cell-line-resources/SKILL.md +258 -0
- package/src/.github/skills/scientific-compound-screening/SKILL.md +245 -0
- package/src/.github/skills/scientific-ebi-databases/SKILL.md +280 -0
- package/src/.github/skills/scientific-genome-sequence-tools/SKILL.md +304 -0
- package/src/.github/skills/scientific-healthcare-ai/SKILL.md +273 -0
- package/src/.github/skills/scientific-human-protein-atlas/SKILL.md +244 -0
- package/src/.github/skills/scientific-metabolic-modeling/SKILL.md +288 -0
- package/src/.github/skills/scientific-noncoding-rna/SKILL.md +262 -0
- package/src/.github/skills/scientific-ontology-enrichment/SKILL.md +340 -0
- package/src/.github/skills/scientific-pharmacology-targets/SKILL.md +323 -0
- package/src/.github/skills/scientific-phylogenetics/SKILL.md +297 -0
- package/src/.github/skills/scientific-preprint-archive/SKILL.md +476 -0
- package/src/.github/skills/scientific-public-health-data/SKILL.md +322 -0
- package/src/.github/skills/scientific-rare-disease-genetics/SKILL.md +327 -0
- package/src/.github/skills/scientific-regulatory-genomics/SKILL.md +274 -0
- package/src/.github/skills/scientific-reinforcement-learning/SKILL.md +280 -0
- package/src/.github/skills/scientific-structural-proteomics/SKILL.md +317 -0
- package/src/.github/skills/scientific-symbolic-mathematics/SKILL.md +277 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scientific-regulatory-genomics
|
|
3
|
+
description: |
|
|
4
|
+
レギュラトリーゲノミクススキル。RegulomeDB バリアント制御機能スコア、
|
|
5
|
+
ReMap 転写因子結合マッピング、4D Nucleome (4DN) 三次元ゲノム構造
|
|
6
|
+
解析の統合パイプライン。
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Scientific Regulatory Genomics
|
|
10
|
+
|
|
11
|
+
RegulomeDB / ReMap / 4D Nucleome を統合した
|
|
12
|
+
レギュラトリーゲノミクス (制御領域バリアント解析) パイプラインを提供する。
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
- 非コード領域バリアントの制御機能を評価するとき
|
|
17
|
+
- RegulomeDB で SNP の調節的影響をスコアリングするとき
|
|
18
|
+
- ReMap で転写因子結合部位のマッピングを確認するとき
|
|
19
|
+
- 4DN データから三次元ゲノム構造 (TAD/ループ) を解析するとき
|
|
20
|
+
- GWAS ヒットの制御メカニズムを解明するとき
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
## 1. RegulomeDB バリアント制御スコア
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
import requests
|
|
30
|
+
import pandas as pd
|
|
31
|
+
|
|
32
|
+
REGULOMEDB_API = "https://regulomedb.org/regulome-search"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def score_regulome_variants(variants):
|
|
36
|
+
"""
|
|
37
|
+
RegulomeDB — 非コード領域バリアントの制御機能スコアリング。
|
|
38
|
+
|
|
39
|
+
Parameters:
|
|
40
|
+
variants: list — バリアントリスト (rsID or chr:pos 形式)
|
|
41
|
+
e.g., ["rs12345", "chr1:109274570"]
|
|
42
|
+
|
|
43
|
+
ToolUniverse:
|
|
44
|
+
RegulomeDB_score_variant(variant=variant)
|
|
45
|
+
"""
|
|
46
|
+
results = []
|
|
47
|
+
for variant in variants:
|
|
48
|
+
params = {"regions": variant, "genome": "GRCh38", "format": "json"}
|
|
49
|
+
resp = requests.get(REGULOMEDB_API, params=params)
|
|
50
|
+
if resp.status_code != 200:
|
|
51
|
+
results.append({"variant": variant, "score": None, "error": True})
|
|
52
|
+
continue
|
|
53
|
+
|
|
54
|
+
data = resp.json()
|
|
55
|
+
for hit in data.get("@graph", []):
|
|
56
|
+
results.append({
|
|
57
|
+
"variant": variant,
|
|
58
|
+
"regulome_score": hit.get("regulome_score", {}).get("ranking", ""),
|
|
59
|
+
"probability": hit.get("regulome_score", {}).get("probability", ""),
|
|
60
|
+
"chrom": hit.get("chrom", ""),
|
|
61
|
+
"start": hit.get("start", ""),
|
|
62
|
+
"end": hit.get("end", ""),
|
|
63
|
+
"dnase": hit.get("dnase", ""),
|
|
64
|
+
"proteins_binding": hit.get("proteins_binding", []),
|
|
65
|
+
"motifs": hit.get("motifs", []),
|
|
66
|
+
"eqtls": hit.get("eqtls", []),
|
|
67
|
+
"chromatin_state": hit.get("chromatin_state", {}),
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
df = pd.DataFrame(results)
|
|
71
|
+
if not df.empty and "regulome_score" in df.columns:
|
|
72
|
+
high_func = (df["regulome_score"].astype(str).str.match(r"^[12]")).sum()
|
|
73
|
+
print(f"RegulomeDB: {len(variants)} variants scored, "
|
|
74
|
+
f"{high_func} with high regulatory function (score 1-2)")
|
|
75
|
+
return df
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 2. ReMap 転写因子結合マッピング
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
REMAP_API = "https://remap.univ-amu.fr/api/v1"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def search_remap_binding(chrom, start, end, genome="hg38"):
|
|
85
|
+
"""
|
|
86
|
+
ReMap — ゲノム領域の転写因子/コレギュレーター結合マッピング。
|
|
87
|
+
|
|
88
|
+
Parameters:
|
|
89
|
+
chrom: str — 染色体 (e.g., "chr1")
|
|
90
|
+
start: int — 開始座標
|
|
91
|
+
end: int — 終了座標
|
|
92
|
+
genome: str — ゲノムアセンブリ ("hg38", "hg19", "mm10")
|
|
93
|
+
|
|
94
|
+
ToolUniverse:
|
|
95
|
+
ReMap_search_peaks(chrom=chrom, start=start, end=end)
|
|
96
|
+
ReMap_get_tf_targets(tf_name=tf_name)
|
|
97
|
+
"""
|
|
98
|
+
params = {
|
|
99
|
+
"chrom": chrom,
|
|
100
|
+
"start": start,
|
|
101
|
+
"end": end,
|
|
102
|
+
"genome": genome,
|
|
103
|
+
}
|
|
104
|
+
resp = requests.get(f"{REMAP_API}/peaks/search", params=params)
|
|
105
|
+
resp.raise_for_status()
|
|
106
|
+
data = resp.json()
|
|
107
|
+
|
|
108
|
+
results = []
|
|
109
|
+
for peak in data.get("peaks", []):
|
|
110
|
+
results.append({
|
|
111
|
+
"tf_name": peak.get("tf_name", ""),
|
|
112
|
+
"biotype": peak.get("biotype", ""),
|
|
113
|
+
"cell_type": peak.get("cell_type", ""),
|
|
114
|
+
"experiment": peak.get("experiment_accession", ""),
|
|
115
|
+
"peak_start": peak.get("start", ""),
|
|
116
|
+
"peak_end": peak.get("end", ""),
|
|
117
|
+
"score": peak.get("score", ""),
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
df = pd.DataFrame(results)
|
|
121
|
+
unique_tfs = df["tf_name"].nunique() if not df.empty else 0
|
|
122
|
+
print(f"ReMap {chrom}:{start}-{end}: {len(df)} peaks, {unique_tfs} unique TFs")
|
|
123
|
+
return df
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def get_remap_tf_targets(tf_name, genome="hg38"):
|
|
127
|
+
"""
|
|
128
|
+
ReMap — 特定転写因子の全結合部位取得。
|
|
129
|
+
|
|
130
|
+
Parameters:
|
|
131
|
+
tf_name: str — 転写因子名 (e.g., "TP53", "CTCF", "STAT3")
|
|
132
|
+
"""
|
|
133
|
+
params = {"tf": tf_name, "genome": genome}
|
|
134
|
+
resp = requests.get(f"{REMAP_API}/peaks/tf", params=params)
|
|
135
|
+
resp.raise_for_status()
|
|
136
|
+
data = resp.json()
|
|
137
|
+
|
|
138
|
+
results = []
|
|
139
|
+
for peak in data.get("peaks", [])[:1000]: # Limit for large TFs
|
|
140
|
+
results.append({
|
|
141
|
+
"chrom": peak.get("chrom", ""),
|
|
142
|
+
"start": peak.get("start", ""),
|
|
143
|
+
"end": peak.get("end", ""),
|
|
144
|
+
"cell_type": peak.get("cell_type", ""),
|
|
145
|
+
"score": peak.get("score", ""),
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
df = pd.DataFrame(results)
|
|
149
|
+
print(f"ReMap TF '{tf_name}': {len(df)} binding sites")
|
|
150
|
+
return df
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## 3. 4D Nucleome (4DN) 三次元ゲノム構造
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
FOURDN_API = "https://data.4dnucleome.org"
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def search_4dn_experiments(query, experiment_type=None):
|
|
160
|
+
"""
|
|
161
|
+
4D Nucleome ポータル — 三次元ゲノム実験データ検索。
|
|
162
|
+
|
|
163
|
+
Parameters:
|
|
164
|
+
query: str — 検索クエリ (細胞株名、タンパク質名等)
|
|
165
|
+
experiment_type: str — 実験タイプ ("in situ Hi-C", "SPRITE", "GAM")
|
|
166
|
+
|
|
167
|
+
ToolUniverse:
|
|
168
|
+
FourDN_search_experiments(query=query)
|
|
169
|
+
"""
|
|
170
|
+
params = {
|
|
171
|
+
"searchTerm": query,
|
|
172
|
+
"type": "ExperimentSetReplicate",
|
|
173
|
+
"format": "json",
|
|
174
|
+
}
|
|
175
|
+
if experiment_type:
|
|
176
|
+
params["experiment_type.display_title"] = experiment_type
|
|
177
|
+
|
|
178
|
+
resp = requests.get(f"{FOURDN_API}/search/", params=params)
|
|
179
|
+
resp.raise_for_status()
|
|
180
|
+
data = resp.json()
|
|
181
|
+
|
|
182
|
+
results = []
|
|
183
|
+
for item in data.get("@graph", []):
|
|
184
|
+
results.append({
|
|
185
|
+
"accession": item.get("accession", ""),
|
|
186
|
+
"title": item.get("display_title", ""),
|
|
187
|
+
"experiment_type": item.get("experiment_type", {}).get("display_title", ""),
|
|
188
|
+
"biosource": item.get("biosource_summary", ""),
|
|
189
|
+
"lab": item.get("lab", {}).get("display_title", ""),
|
|
190
|
+
"status": item.get("status", ""),
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
df = pd.DataFrame(results)
|
|
194
|
+
print(f"4DN search '{query}': {len(df)} experiment sets")
|
|
195
|
+
return df
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## 4. 制御バリアント統合解析パイプライン
|
|
199
|
+
|
|
200
|
+
```python
|
|
201
|
+
def regulatory_variant_pipeline(variants, genome="hg38"):
|
|
202
|
+
"""
|
|
203
|
+
制御領域バリアント統合解析。
|
|
204
|
+
|
|
205
|
+
Parameters:
|
|
206
|
+
variants: list — バリアントリスト (rsID or chr:pos)
|
|
207
|
+
"""
|
|
208
|
+
print("=" * 60)
|
|
209
|
+
print("Regulatory Variant Analysis Pipeline")
|
|
210
|
+
print("=" * 60)
|
|
211
|
+
|
|
212
|
+
# Step 1: RegulomeDB scoring
|
|
213
|
+
print("\n[1/3] RegulomeDB scoring...")
|
|
214
|
+
regulome_df = score_regulome_variants(variants)
|
|
215
|
+
|
|
216
|
+
# Step 2: ReMap TF binding for high-scoring variants
|
|
217
|
+
print("\n[2/3] ReMap TF binding analysis...")
|
|
218
|
+
remap_results = {}
|
|
219
|
+
for _, row in regulome_df.iterrows():
|
|
220
|
+
if row.get("chrom") and row.get("start"):
|
|
221
|
+
chrom = row["chrom"]
|
|
222
|
+
start = int(row["start"]) - 500
|
|
223
|
+
end = int(row["end"]) + 500
|
|
224
|
+
try:
|
|
225
|
+
remap_df = search_remap_binding(chrom, start, end, genome)
|
|
226
|
+
remap_results[row["variant"]] = remap_df
|
|
227
|
+
except Exception as e:
|
|
228
|
+
print(f" ReMap error for {row['variant']}: {e}")
|
|
229
|
+
|
|
230
|
+
# Step 3: Summary
|
|
231
|
+
print("\n[3/3] Summary")
|
|
232
|
+
summary = {
|
|
233
|
+
"total_variants": len(variants),
|
|
234
|
+
"regulome_scored": len(regulome_df),
|
|
235
|
+
"high_regulatory": (
|
|
236
|
+
regulome_df["regulome_score"].astype(str).str.match(r"^[12]")
|
|
237
|
+
).sum() if "regulome_score" in regulome_df.columns else 0,
|
|
238
|
+
"remap_annotated": len(remap_results),
|
|
239
|
+
}
|
|
240
|
+
print(f" Total: {summary['total_variants']}, "
|
|
241
|
+
f"High regulatory: {summary['high_regulatory']}, "
|
|
242
|
+
f"ReMap annotated: {summary['remap_annotated']}")
|
|
243
|
+
|
|
244
|
+
return {"regulome": regulome_df, "remap": remap_results, "summary": summary}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## 利用可能ツール
|
|
250
|
+
|
|
251
|
+
| ToolUniverse カテゴリ | 主なツール |
|
|
252
|
+
|---|---|
|
|
253
|
+
| `regulomedb` | `RegulomeDB_score_variant` |
|
|
254
|
+
| `remap` | `ReMap_search_peaks`, `ReMap_get_tf_targets` |
|
|
255
|
+
| `fourdn_portal` | `FourDN_search_experiments` |
|
|
256
|
+
|
|
257
|
+
## パイプライン出力
|
|
258
|
+
|
|
259
|
+
| 出力ファイル | 説明 | 連携先スキル |
|
|
260
|
+
|---|---|---|
|
|
261
|
+
| `results/regulome_scores.csv` | バリアント制御スコア | → variant-interpretation, variant-effect-prediction |
|
|
262
|
+
| `results/remap_binding.csv` | TF 結合マッピング | → epigenomics-chromatin, disease-research |
|
|
263
|
+
| `results/4dn_contacts.json` | 3D ゲノム構造データ | → single-cell-genomics, epigenomics-chromatin |
|
|
264
|
+
|
|
265
|
+
## パイプライン統合
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
variant-interpretation ──→ regulatory-genomics ──→ epigenomics-chromatin
|
|
269
|
+
(ACMG/AMP) (RegulomeDB/ReMap/4DN) (ChIP-seq/ATAC)
|
|
270
|
+
│
|
|
271
|
+
├──→ disease-research (GWAS enhancer)
|
|
272
|
+
├──→ gene-expression (eQTL/制御)
|
|
273
|
+
└──→ noncoding-rna (ncRNA 制御)
|
|
274
|
+
```
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scientific-reinforcement-learning
|
|
3
|
+
description: |
|
|
4
|
+
強化学習スキル。Stable-Baselines3 による RL エージェント訓練、
|
|
5
|
+
Gymnasium 環境構築、PufferLib 大規模マルチエージェント、
|
|
6
|
+
科学応用 (分子生成・実験最適化・ロボット制御) パイプライン。
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Scientific Reinforcement Learning
|
|
10
|
+
|
|
11
|
+
Stable-Baselines3 / PufferLib / Gymnasium を活用した
|
|
12
|
+
強化学習パイプラインを提供する。
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
- RL エージェントを訓練・評価するとき
|
|
17
|
+
- カスタム Gymnasium 環境を構築するとき
|
|
18
|
+
- 分子設計・創薬に RL を適用するとき
|
|
19
|
+
- 実験パラメータの逐次最適化に RL を使うとき
|
|
20
|
+
- マルチエージェント強化学習を実行するとき
|
|
21
|
+
- ロボティクス・ラボオートメーションの制御方策を学習するとき
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
## 1. Stable-Baselines3 基本訓練
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
import numpy as np
|
|
31
|
+
import gymnasium as gym
|
|
32
|
+
from stable_baselines3 import PPO, SAC, A2C, DQN
|
|
33
|
+
from stable_baselines3.common.evaluation import evaluate_policy
|
|
34
|
+
from stable_baselines3.common.vec_env import DummyVecEnv, SubprocVecEnv
|
|
35
|
+
from stable_baselines3.common.callbacks import EvalCallback, CheckpointCallback
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def train_rl_agent(env_id, algorithm="PPO", total_timesteps=100_000,
|
|
39
|
+
n_envs=4, hyperparams=None):
|
|
40
|
+
"""
|
|
41
|
+
Stable-Baselines3 RL エージェント訓練。
|
|
42
|
+
|
|
43
|
+
Parameters:
|
|
44
|
+
env_id: str — Gymnasium 環境 ID (e.g., "CartPole-v1", "LunarLander-v3")
|
|
45
|
+
algorithm: str — "PPO", "SAC", "A2C", "DQN"
|
|
46
|
+
total_timesteps: int — 総訓練ステップ数
|
|
47
|
+
n_envs: int — 並列環境数
|
|
48
|
+
hyperparams: dict — ハイパーパラメータ override
|
|
49
|
+
|
|
50
|
+
K-Dense: stable-baselines3 — RL training framework
|
|
51
|
+
"""
|
|
52
|
+
algo_map = {"PPO": PPO, "SAC": SAC, "A2C": A2C, "DQN": DQN}
|
|
53
|
+
AlgoClass = algo_map.get(algorithm, PPO)
|
|
54
|
+
|
|
55
|
+
# Vectorized environments
|
|
56
|
+
env = DummyVecEnv([lambda: gym.make(env_id) for _ in range(n_envs)])
|
|
57
|
+
|
|
58
|
+
# Default hyperparams per algorithm
|
|
59
|
+
default_params = {
|
|
60
|
+
"PPO": {"learning_rate": 3e-4, "n_steps": 2048, "batch_size": 64},
|
|
61
|
+
"SAC": {"learning_rate": 3e-4, "buffer_size": 1_000_000},
|
|
62
|
+
"A2C": {"learning_rate": 7e-4, "n_steps": 5},
|
|
63
|
+
"DQN": {"learning_rate": 1e-4, "buffer_size": 100_000},
|
|
64
|
+
}
|
|
65
|
+
params = default_params.get(algorithm, {})
|
|
66
|
+
if hyperparams:
|
|
67
|
+
params.update(hyperparams)
|
|
68
|
+
|
|
69
|
+
model = AlgoClass("MlpPolicy", env, verbose=1, **params)
|
|
70
|
+
|
|
71
|
+
# Callbacks
|
|
72
|
+
eval_env = gym.make(env_id)
|
|
73
|
+
eval_callback = EvalCallback(
|
|
74
|
+
eval_env, best_model_save_path="./models/best/",
|
|
75
|
+
log_path="./logs/", eval_freq=10_000,
|
|
76
|
+
)
|
|
77
|
+
checkpoint_callback = CheckpointCallback(
|
|
78
|
+
save_freq=25_000, save_path="./models/checkpoints/",
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
model.learn(
|
|
82
|
+
total_timesteps=total_timesteps,
|
|
83
|
+
callback=[eval_callback, checkpoint_callback],
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Evaluation
|
|
87
|
+
mean_reward, std_reward = evaluate_policy(model, eval_env, n_eval_episodes=20)
|
|
88
|
+
print(f"RL Training ({algorithm} on {env_id}): "
|
|
89
|
+
f"reward = {mean_reward:.2f} ± {std_reward:.2f}")
|
|
90
|
+
|
|
91
|
+
return model, {"mean_reward": mean_reward, "std_reward": std_reward}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## 2. カスタム Gymnasium 環境
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
class MoleculeDesignEnv(gym.Env):
|
|
98
|
+
"""
|
|
99
|
+
分子設計用カスタム RL 環境。
|
|
100
|
+
|
|
101
|
+
状態: 分子フィンガープリント (Morgan FP)
|
|
102
|
+
行動: 原子/結合の追加・削除・変更
|
|
103
|
+
報酬: 薬物らしさスコア (QED) + 結合親和性予測
|
|
104
|
+
"""
|
|
105
|
+
metadata = {"render_modes": ["human"]}
|
|
106
|
+
|
|
107
|
+
def __init__(self, max_atoms=50, target_property="qed"):
|
|
108
|
+
super().__init__()
|
|
109
|
+
self.max_atoms = max_atoms
|
|
110
|
+
self.target_property = target_property
|
|
111
|
+
|
|
112
|
+
# Action space: discrete (add atom types, add bonds, remove)
|
|
113
|
+
self.action_space = gym.spaces.Discrete(10)
|
|
114
|
+
|
|
115
|
+
# Observation space: molecular fingerprint
|
|
116
|
+
self.observation_space = gym.spaces.Box(
|
|
117
|
+
low=0, high=1, shape=(2048,), dtype=np.float32,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
self.current_mol = None
|
|
121
|
+
self.step_count = 0
|
|
122
|
+
|
|
123
|
+
def reset(self, seed=None, options=None):
|
|
124
|
+
super().reset(seed=seed)
|
|
125
|
+
self.current_mol = None # Start from scratch
|
|
126
|
+
self.step_count = 0
|
|
127
|
+
obs = np.zeros(2048, dtype=np.float32)
|
|
128
|
+
return obs, {}
|
|
129
|
+
|
|
130
|
+
def step(self, action):
|
|
131
|
+
self.step_count += 1
|
|
132
|
+
|
|
133
|
+
# Apply action to modify molecule
|
|
134
|
+
reward = self._calculate_reward()
|
|
135
|
+
terminated = self.step_count >= self.max_atoms
|
|
136
|
+
truncated = False
|
|
137
|
+
obs = self._get_observation()
|
|
138
|
+
|
|
139
|
+
return obs, reward, terminated, truncated, {}
|
|
140
|
+
|
|
141
|
+
def _calculate_reward(self):
|
|
142
|
+
"""Calculate reward based on molecular properties."""
|
|
143
|
+
if self.current_mol is None:
|
|
144
|
+
return 0.0
|
|
145
|
+
# Placeholder: QED score
|
|
146
|
+
return np.random.uniform(0, 1)
|
|
147
|
+
|
|
148
|
+
def _get_observation(self):
|
|
149
|
+
return np.zeros(2048, dtype=np.float32)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def train_molecule_designer(total_timesteps=50_000):
|
|
153
|
+
"""分子設計 RL エージェント訓練。"""
|
|
154
|
+
env = MoleculeDesignEnv()
|
|
155
|
+
model = PPO("MlpPolicy", env, verbose=1, learning_rate=1e-4)
|
|
156
|
+
model.learn(total_timesteps=total_timesteps)
|
|
157
|
+
|
|
158
|
+
mean_reward, std_reward = evaluate_policy(model, env, n_eval_episodes=10)
|
|
159
|
+
print(f"Molecule Designer: reward = {mean_reward:.2f} ± {std_reward:.2f}")
|
|
160
|
+
return model
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## 3. PufferLib 大規模マルチエージェント
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
def setup_pufferlib_training(env_name, num_agents=8, algorithm="PPO"):
|
|
167
|
+
"""
|
|
168
|
+
PufferLib マルチエージェント RL 設定。
|
|
169
|
+
|
|
170
|
+
Parameters:
|
|
171
|
+
env_name: str — PufferLib 対応環境
|
|
172
|
+
num_agents: int — エージェント数
|
|
173
|
+
algorithm: str — "PPO", "IMPALA"
|
|
174
|
+
|
|
175
|
+
K-Dense: pufferlib — Scalable multi-agent RL
|
|
176
|
+
"""
|
|
177
|
+
try:
|
|
178
|
+
import pufferlib
|
|
179
|
+
import pufferlib.environments
|
|
180
|
+
|
|
181
|
+
config = {
|
|
182
|
+
"env": env_name,
|
|
183
|
+
"num_agents": num_agents,
|
|
184
|
+
"algorithm": algorithm,
|
|
185
|
+
"total_timesteps": 1_000_000,
|
|
186
|
+
"batch_size": 256,
|
|
187
|
+
"learning_rate": 2.5e-4,
|
|
188
|
+
"num_envs": 16,
|
|
189
|
+
"num_steps": 128,
|
|
190
|
+
}
|
|
191
|
+
print(f"PufferLib config: {config}")
|
|
192
|
+
return config
|
|
193
|
+
|
|
194
|
+
except ImportError:
|
|
195
|
+
print("PufferLib not installed. Install with: pip install pufferlib")
|
|
196
|
+
return None
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## 4. 実験パラメータ逐次最適化
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
def rl_experiment_optimizer(parameter_ranges, objective_fn,
|
|
203
|
+
total_episodes=100, algorithm="PPO"):
|
|
204
|
+
"""
|
|
205
|
+
RL による実験パラメータ逐次最適化。
|
|
206
|
+
|
|
207
|
+
Parameters:
|
|
208
|
+
parameter_ranges: dict — {param_name: (min, max)}
|
|
209
|
+
objective_fn: callable — 目的関数 (params → score)
|
|
210
|
+
total_episodes: int — 最適化エピソード数
|
|
211
|
+
"""
|
|
212
|
+
n_params = len(parameter_ranges)
|
|
213
|
+
param_names = list(parameter_ranges.keys())
|
|
214
|
+
|
|
215
|
+
class ExperimentEnv(gym.Env):
|
|
216
|
+
def __init__(self):
|
|
217
|
+
super().__init__()
|
|
218
|
+
self.action_space = gym.spaces.Box(
|
|
219
|
+
low=-1, high=1, shape=(n_params,), dtype=np.float32,
|
|
220
|
+
)
|
|
221
|
+
self.observation_space = gym.spaces.Box(
|
|
222
|
+
low=-np.inf, high=np.inf,
|
|
223
|
+
shape=(n_params + 1,), dtype=np.float32,
|
|
224
|
+
)
|
|
225
|
+
self.best_score = -np.inf
|
|
226
|
+
self.history = []
|
|
227
|
+
|
|
228
|
+
def reset(self, seed=None, options=None):
|
|
229
|
+
super().reset(seed=seed)
|
|
230
|
+
self.current_params = np.zeros(n_params, dtype=np.float32)
|
|
231
|
+
return np.zeros(n_params + 1, dtype=np.float32), {}
|
|
232
|
+
|
|
233
|
+
def step(self, action):
|
|
234
|
+
# Scale action to parameter ranges
|
|
235
|
+
params = {}
|
|
236
|
+
for i, name in enumerate(param_names):
|
|
237
|
+
lo, hi = parameter_ranges[name]
|
|
238
|
+
params[name] = lo + (action[i] + 1) / 2 * (hi - lo)
|
|
239
|
+
|
|
240
|
+
score = objective_fn(params)
|
|
241
|
+
self.history.append({"params": params, "score": score})
|
|
242
|
+
|
|
243
|
+
if score > self.best_score:
|
|
244
|
+
self.best_score = score
|
|
245
|
+
|
|
246
|
+
obs = np.append(action, [score]).astype(np.float32)
|
|
247
|
+
return obs, score, False, False, {}
|
|
248
|
+
|
|
249
|
+
env = ExperimentEnv()
|
|
250
|
+
model = SAC("MlpPolicy", env, verbose=0) if algorithm == "SAC" else PPO("MlpPolicy", env, verbose=0)
|
|
251
|
+
model.learn(total_timesteps=total_episodes)
|
|
252
|
+
|
|
253
|
+
best_idx = max(range(len(env.history)), key=lambda i: env.history[i]["score"])
|
|
254
|
+
best = env.history[best_idx]
|
|
255
|
+
print(f"RL Optimization: best score = {best['score']:.4f}")
|
|
256
|
+
print(f" Best params: {best['params']}")
|
|
257
|
+
return best, env.history
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## パイプライン出力
|
|
263
|
+
|
|
264
|
+
| 出力ファイル | 説明 | 連携先スキル |
|
|
265
|
+
|---|---|---|
|
|
266
|
+
| `models/rl_model.zip` | 訓練済み RL モデル | → deep-learning (モデル統合) |
|
|
267
|
+
| `results/rl_training_log.json` | 訓練曲線・メトリクス | → publication-figures |
|
|
268
|
+
| `results/rl_optimization.json` | 最適化パラメータ | → doe, process-optimization |
|
|
269
|
+
| `figures/rl_reward_curve.png` | 報酬曲線 | → presentation-design |
|
|
270
|
+
|
|
271
|
+
## パイプライン統合
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
doe ──→ reinforcement-learning ──→ lab-automation
|
|
275
|
+
(実験計画) (逐次最適化) (ロボット制御)
|
|
276
|
+
│
|
|
277
|
+
├──→ drug-target-profiling (分子設計 RL)
|
|
278
|
+
├──→ protein-design (構造最適化 RL)
|
|
279
|
+
└──→ deep-learning (DRL パイプライン)
|
|
280
|
+
```
|