File size: 27,938 Bytes
ed2beb0
 
 
 
9f72e51
ed2beb0
 
 
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
 
 
 
 
 
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
 
 
 
 
 
 
 
 
 
 
ed2beb0
9f72e51
ed2beb0
9f72e51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dc84b2b
9f72e51
dc84b2b
9f72e51
 
dc84b2b
 
9f72e51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9084b3e
9f72e51
 
 
 
 
 
 
 
 
 
 
 
ed2beb0
9f72e51
ed2beb0
9f72e51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9084b3e
9f72e51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
 
ed2beb0
9f72e51
 
ed2beb0
9f72e51
 
ed2beb0
9f72e51
 
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
 
ed2beb0
9f72e51
 
ed2beb0
9f72e51
 
 
ed2beb0
9f72e51
 
 
ed2beb0
9f72e51
ed2beb0
9f72e51
 
 
 
ed2beb0
9f72e51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed2beb0
9f72e51
ed2beb0
9f72e51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
 
 
 
 
 
 
ed2beb0
9f72e51
ed2beb0
9f72e51
 
 
 
 
 
 
ed2beb0
9f72e51
ed2beb0
9f72e51
 
 
 
 
 
 
 
ed2beb0
9f72e51
ed2beb0
9f72e51
 
 
 
 
 
ed2beb0
9f72e51
ed2beb0
9f72e51
 
 
 
 
 
 
 
 
 
 
 
 
 
ed2beb0
9f72e51
ed2beb0
9f72e51
ed2beb0
9f72e51
 
 
 
 
ed2beb0
9f72e51
ed2beb0
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
---
license: mit
metrics:
- accuracy
pipeline_tag: image-to-text
tags:
- chemistry
---
# MS²-SMILES AlignNet 模型文档

## 📋 目录

1. [概述](#概述)
2. [数据处理流程](#数据处理流程)
3. [模型架构](#模型架构)
4. [损失函数设计](#损失函数设计)
5. [训练流程](#训练流程)
6. [配置参数](#配置参数)

---

## 概述

MS²-SMILES AlignNet 是一个基于**对比学习**的跨模态对齐模型,旨在学习质谱(MS²)数据与分子结构(SMILES)之间的语义对齐表示。该模型采用双分支架构,分别编码 MS 谱图和分子结构,并通过对比学习使得匹配的 MS-分子对在嵌入空间中靠近。

### 核心思想

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                        MS²-SMILES AlignNet 架构                              │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│   SMILES ──→ [分子编码分支] ──→ 256维向量 ─┐                                 │
│                                            ├──→ 对比学习 ──→ 对齐损失        │
│   MS谱图 ──→ [MS编码分支]  ──→ 256维向量 ──┘                                 │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
```

---

## 数据处理流程

### 2.1 数据加载入口

**文件**: `train.py` (第174-175行)

```python
train_loader = build_loaders(train_set, "train", cfg, 10)
valid_loader = build_loaders(valid_set, "valid", cfg, 10)
```

数据支持两种输入格式:
- **JSON/MGF 文件列表**: 使用 `PathDataset`- **预处理字典列表**: 使用 `Dataset`### 2.2 原始数据获取

**文件**: `dataset.py` (第103-128行)

```
PathDataset
    ├── proc_data(): 解析 JSON/MGF 文件
    │   └── 提取: ms (质谱峰列表), smiles (分子结构)

    └── __getitem__(): 调用 calc_feats() 计算特征
```

**数据格式**:
- `ms`: List of (m/z, intensity) 元组
- `smiles`: 分子 SMILES 字符串

### 2.3 特征预处理

**文件**: `dataset.py` (第7-41行) - `calc_feats()` 函数

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                           特征计算流程                                       │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  输入: smi (SMILES), ms (质谱), nls (中性丢失)                               │
│                                                                              │
│  ┌────────────────────────┐  ┌────────────────────────────┐                 │
│  │   MS 特征处理          │  │   分子特征处理              │                 │
│  ├────────────────────────┤  ├────────────────────────────┤                 │
│  │ 1. ms_binner()         │  │ 1. mol_fp_encoder()        │                 │
│  │    → ms_bins           │  │    → mol_fps (指纹)        │                 │
│  │    (39600维稀疏向量)    │  │    (2048维)                │                 │
│  │                        │  │                            │                 │
│  │ 2. ms_feature_processor│  │ 2. mol_graph_featurizer()  │                 │
│  │    → ms_bins1 (100,29) │  │    → V (节点特征)          │                 │
│  │    → ms_bins2 (100,)   │  │    → A (邻接矩阵)          │                 │
│  │    (峰特征 + m/z值)     │  │    → mol_size             │                 │
│  └────────────────────────┘  └────────────────────────────┘                 │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
```

#### 2.3.1 MS 特征处理详解

**方法一: `ms_binner()` - 稀疏分桶表示**

```python
# 参数配置
min_mz = 20, max_mz = 2000, bin_size = 0.05
# 计算: (2000-20)/0.05 = 39600 bins

# 流程:
1. 过滤 m/z 范围外的峰
2. 归一化强度 (0-1)
3. 分桶 (bin_idx = (m/z - min_mz) / bin_size)
4. 可选: 添加中性丢失特征 (额外 4000 bins)
```

**方法二: `ms_feature_processor()` - 序列化峰表示**

```python
输入: ms, precursor_mz, metadata_vec(135维)
输出: 
  - ms_bins1: (100,135) 峰特征矩阵
  - ms_bins2: (100,) m/z 值序列

## 135 维全局特征 = 仪器(20) + 加合物(21) + 碰撞能量(5) + 电荷电离(4) + 诊断离子(46) + 中性丢失(39)
线性变换 → 256 维模型输
```

#### 2.3.2 分子特征处理详解

**Morgan 指纹编码**:
```python
mol_fp_encoder(smiles, tp='morgan', nbits=2048)
# → 2048 维二进制向量
```

**分子图特征化**:
```python
mol_graph_featurizer(smiles)
# → V: 节点特征矩阵 (N_atoms, 74)
# → A: 邻接张量 (N_atoms, 6, N_atoms)
#      6 通道 = 4 键类型 + 环内 + 共轭
# → mol_size: 原子数量
```

**原子节点特征 (74维)**:
| 特征类型 | 维度 | 说明 |
|---------|------|------|
| 原子类型 | 12 | One-hot: H,C,N,O,S,F,Si,P,Cl,Br,I,B |
| 显式价态 | 7 | One-hot: 0-6 |
| 隐式价态 | 7 | One-hot: 0-6 |
| 氢原子数 | 5 | One-hot: 0-4 |
| 自由基电子 | 5 | One-hot: 0-4 |
| 总度数 | 7 | One-hot: 0-6 |
| 形式电荷 | 5 | One-hot: -2 to 2 |
| 杂化类型 | 5 | SP,SP2,SP3,SP3D,SP3D2 |
| 芳香性 | 2 | True/False |
| 环内原子 | 2 | True/False |
| 手性 | 4 | 4种类型 |
| CIP编码 | 2 | R/S |
| 范德华半径 | 1 | 连续值 |
| 手性可能性 | 1 | True/False |
| 原子序数 | 1 | 连续值 |
| 原子质量 | 1 | 连续值 × 0.01 |
| 度数 | 1 | 连续值 |
| 特征不变量 | 6 | 6位二进制编码 |

### 2.4 数据批处理聚合

**文件**: `train.py` (第36-83行) - `my_collate()` 函数

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                         Batch 聚合流程                                       │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  输入: [sample_1, sample_2, ..., sample_B]  (B = batch_size)                │
│                                                                              │
│  1. 过滤 None 样本                                                           │
│                                                                              │
│  2. 堆叠各特征:                                                              │
│     ├── ms_bins:  stack → (B, 39600+4000)                                   │
│     ├── ms_bins1: stack → (B, 100, 135)                                      │
│     ├── ms_bins2: stack → (B, 100)                                          │
│     ├── mol_fps:  stack → (B, 2048)                                         │
│     └── mol_fmvec: stack → (B, 10)  [可选: 分子式向量]                       │
│                                                                              │
│  3. 图数据 Padding:                                                          │
│     ├── 计算 max_n = max(所有分子的原子数)                                   │
│     ├── V: pad → (B, max_n, 74)                                             │
│     ├── A: pad → (B, max_n, 6, max_n)                                       │
│     └── mol_size: concat → (B,)                                             │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
```

---

## 模型架构

**文件**: `modules.py` (第298-457行) - `FragSimiModelNew` 类

### 3.1 整体架构图

```
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                              FragSimiModelNew 双分支架构                                 │
├─────────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                          │
│  ┌──────────────────────────────────┐    ┌──────────────────────────────────────────┐   │
│  │     分子编码分支 (LEFT)          │    │        MS 编码分支 (RIGHT)                │   │
│  ├──────────────────────────────────┤    ├──────────────────────────────────────────┤   │
│  │                                  │    │                                          │   │
│  │  SMILES                          │    │  MS 谱图                                 │   │
│  │     │                            │    │     │                                    │   │
│  │     ▼                            │    │     ▼                                    │   │
│  │  ┌─────────────┐                 │    │  ┌─────────────────────────────────────┐│   │
│  │  │ RDKit 解析   │                 │    │  │ 分支A: ms_bins (稀疏分桶)           ││   │
│  │  └──────┬──────┘                 │    │  │   │                                 ││   │
│  │         │                        │    │  │   ▼ ms_input_proj (Linear)          ││   │
│  │    ┌────┴────┐                   │    │  │   │                                 ││   │
│  │    ▼         ▼                   │    │  │   ▼ 6层 Transformer                 ││   │
│  │ ┌──────┐ ┌───────┐               │    │  │   │                                 ││   │
│  │ │ 分子图 │ │ Morgan│               │    │  │   ▼ Mean Pooling                   ││   │
│  │ │构建   │ │ 指纹  │               │    │  │   │                                 ││   │
│  │ └──┬───┘ └───┬───┘               │    │  │   ▼ ms_final_proj                   ││   │
│  │    │         │                   │    │  │   └───→ 256维                       ││   │
│  │    ▼         │                   │    │  └─────────────────────────────────────┘│   │
│  │ ┌──────────┐ │                   │    │                     │                    │   │
│  │ │MolGNN    │ │                   │    │                     ▼                    │   │
│  │ │Encoder   │ │                   │    │  ┌─────────────────────────────────────┐│   │
│  │ │(3层GCN   │ │                   │    │  │ 分支B: ms_bins1/2 (峰序列)          ││   │
│  │ │+Attention│ │                   │    │  │   │                                 ││   │
│  │ │+Readout) │ │                   │    │  │   ▼ SinusoidalMzEmbedding           ││   │
│  │ └────┬─────┘ │                   │    │  │   + feature_proj (135→256)           ││   │
│  │      │       │                   │    │  │   │                                 ││   │
│  │      ▼       ▼                   │    │  │   ▼ 6层 Transformer                 ││   │
│  │ ┌──────────────────┐             │    │  │   │                                 ││   │
│  │ │  MolFusionHead   │             │    │  │   ▼ Mean Pooling                   ││   │
│  │ │ (GNN→128, FP→256)│             │    │  │   │                                 ││   │
│  │ │ → Concat → 256   │             │    │  │   ▼ final_proj                      ││   │
│  │ └────────┬─────────┘             │    │  │   └───→ 256维                       ││   │
│  │          │                       │    │  └─────────────────────────────────────┘│   │
│  │          ▼                       │    │                     │                    │   │
│  │     256维向量                    │    │                     ▼                    │   │
│  │                                  │    │  ┌─────────────────────────────────────┐│   │
│  │                                  │    │  │    Concat (256+256=512)             ││   │
│  │                                  │    │  │           │                         ││   │
│  │                                  │    │  │           ▼                         ││   │
│  │                                  │    │  │    all_final_proj → 256维           ││   │
│  │                                  │    │  └─────────────────────────────────────┘│   │
│  └──────────────────────────────────┘    └──────────────────────────────────────────┘   │
│                  │                                           │                          │
│                  ▼                                           ▼                          │
│          mol_embeddings (256)                        ms_embeddings (256)                │
│                  │                                           │                          │
│                  └───────────────────┬───────────────────────┘                          │
│                                      ▼                                                  │
│                          ┌───────────────────────┐                                      │
│                          │    L2 Normalize       │                                      │
│                          └───────────┬───────────┘                                      │
│                                      ▼                                                  │
│                          ┌───────────────────────┐                                      │
│                          │   HybridAlignLoss     │                                      │
│                          │ (InfoNCE + Tanimoto)  │                                      │
│                          └───────────────────────┘                                      │
│                                                                                          │
└─────────────────────────────────────────────────────────────────────────────────────────┘
```

### 3.2 分子编码分支

#### 3.2.1 MolGNNEncoder

```python
class MolGNNEncoder(nn.Module):
    # 输入: V (B, N, 74), A (B, N, 6, N), mol_size (B,)
    # 输出: (B, mol_embedding_dim)
    
    结构:
    ├── block_layers: 3 × GConvBlockNoGF
    │   └── GraphCNNLayer: 图卷积 + BatchNorm + ReLU
    │       [74 → 256 → 256 → 256]

    ├── attention_layer: MultiHeadGlobalAttention (4 heads)
    │   └── 对节点进行加权聚合,去除 padding 影响
    │       [256 → 256×4 = 1024]

    └── readout_layers: 2 × Linear + GELU
        └── [1024 → 2048 → 2048]
```

#### 3.2.2 MolFusionHead

```python
class MolFusionHead(nn.Module):
    # 输入: gnn_feat (B, 2048), fps (B, 2048)
    # 输出: (B, 256)
    
    结构:
    ├── gnn_proj: Linear(2048 → 128)

    ├── fp_proj: Linear(2048 → 256) + LayerNorm + GELU

    └── fusion_layer: 
        ├── Concat: [128, 256] → 384
        └── Linear(384 → 256) + LayerNorm + Dropout + GELU
```

### 3.3 MS 编码分支

#### 3.3.1 分支A: 稀疏分桶编码

```python
# 输入: ms_bins (B, 43600)
# 输出: 256维

流程:
1. ms_input_proj: Linear(43600 → 256)
2. unsqueeze → (B, 1, 256) [假序列]
3. ms_transformer: 6层 Transformer (width=256, heads=8)
4. mean(dim=1) → (B, 256)
5. ms_final_proj: Linear + LayerNorm + Dropout → 256维
```

#### 3.3.2 分支B: 峰序列编码

```python
# 输入: ms_bins1 (B, 100, 29), ms_bins2 (B, 100)
# 输出: 256维

流程:
1. mz_embedder(ms_bins2) → (B, 100, 256)  # 正弦位置编码
2. feature_proj(ms_bins1) → (B, 100, 256)  # 峰特征投影
3. 相加融合 → (B, 100, 256)
4. transformer: 6层 Transformer
5. mean(dim=1) → (B, 256)
6. final_proj: Linear + LayerNorm + Dropout → 256维
```

#### 3.3.3 正弦 m/z 嵌入

```python
class SinusoidalMzEmbedding(nn.Module):
    # 将 m/z 值编码为 256 维向量
    # 类似 Transformer 的位置编码
    
    PE[pos, 2i]   = sin(pos / 10000^(2i/256))
    PE[pos, 2i+1] = cos(pos / 10000^(2i/256))
```

#### 3.3.4 双分支融合

```python
# 两个 MS 分支的输出融合
out1 = torch.cat([ms_embeddings_A, ms_embeddings_B], dim=-1)  # (B, 512)
ms_embeddings = all_final_proj(out1)  # Linear(512→256) + LayerNorm + Dropout
```

### 3.4 Transformer 结构

**文件**: `cliplayers.py` - 采用 CLIP 风格的 Transformer

```python
class ResidualAttentionBlock(nn.Module):
    # 单个 Transformer Block
    
    结构:
    ├── ln_1 → MultiheadAttention → 残差连接

    └── ln_2 → MLP (Linear→QuickGELU→Linear) → 残差连接
    
    # QuickGELU: x * sigmoid(1.702 * x)
    # 比标准 GELU 更快
```

---

## 损失函数设计

**文件**: `modules.py` (第196-233行) - `HybridAlignLoss` 类

### 4.1 联合损失公式

$$\mathcal{L}_{total} = \beta \cdot \mathcal{L}_{InfoNCE} + \alpha \cdot \mathcal{L}_{Tanimoto-MSE}$$

**默认参数**: α = 0.5, β = 1.0

### 4.2 InfoNCE 对比损失

```python
# 目标: 让匹配的 MS-分子对相似度高,不匹配的对相似度低

logits = (ms_emb @ mol_emb.T) / temperature  # 相似度矩阵
labels = torch.arange(batch_size)            # 对角线为正样本

loss_i2t = CrossEntropy(logits, labels)      # MS → Mol
loss_t2i = CrossEntropy(logits.T, labels)    # Mol → MS

L_InfoNCE = (loss_i2t + loss_t2i) / 2
```

**温度参数**: τ = 0.07

### 4.3 Tanimoto MSE 损失

```python
# 目标: 让嵌入空间的相似度矩阵逼近真实的分子结构相似度

# 1. 预测的相似度矩阵 (余弦相似度)
pred_sim = ms_emb @ mol_emb.T  # 因为已 L2 normalize

# 2. 真实的结构相似度 (Tanimoto 系数)
#    Tanimoto(A,B) = (A·B) / (|A|² + |B|² - A·B)
target_sim = batch_tanimoto_sim(mol_fps, mol_fps)

# 3. MSE 损失
L_MSE = MSELoss(pred_sim, target_sim)
```

### 4.4 损失设计的意义

| 损失组件 | 作用 | 特点 |
|---------|------|------|
| InfoNCE | 跨模态对齐 | 区分正负样本对,对比学习核心 |
| Tanimoto MSE | 结构约束 | 保持分子结构相似性关系 |

```
┌─────────────────────────────────────────────────────────────────┐
│                    联合损失的几何意义                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   InfoNCE: "匹配的 MS-Mol 对要靠近"                             │
│                                                                  │
│       MS₁ ←──── 拉近 ────→ Mol₁                                 │
│       MS₂ ←──── 拉近 ────→ Mol₂                                 │
│        ↑                    ↑                                    │
│     推远                  推远                                   │
│        ↓                    ↓                                    │
│       MS₃ ←──── 拉近 ────→ Mol₃                                 │
│                                                                  │
│   Tanimoto MSE: "结构相似的分子在嵌入空间也要相似"               │
│                                                                  │
│     如果 Tanimoto(Mol₁, Mol₂) = 0.8                             │
│     则希望 CosSim(Emb₁, Emb₂) ≈ 0.8                             │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

---

## 训练流程

**文件**: `train.py`

### 5.1 训练入口

```python
# main() 函数

1. 数据划分: make_train_valid(data, valid_ratio=0.1)
2. 构建 DataLoader: build_loaders()
3. 初始化模型: FragSimiModelNew(cfg).to(device)
4. 优化器: AdamW(lr=1e-3, weight_decay=1e-3)
5. 学习率调度: ReduceLROnPlateau(patience=2, factor=0.5)
6. 训练循环: epochs=50
```

### 5.2 训练周期

```python
def train_epoch(model, train_loader, optimizer, lr_scheduler, step):
    for batch in train_loader:
        # 1. 数据移到 GPU
        batch = {k: v.to(device) for k, v in batch.items()}
        
        # 2. 前向传播
        loss = model(batch)  # 返回总损失
        
        # 3. 反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
```

### 5.3 模型保存策略

```python
# 保存最佳模型 (基于验证集损失)
if valid_loss < best_loss:
    checkpoint = {
        'state_dict': model.state_dict(),
        'optimizer': optimizer.state_dict(),
        'config': dict(CFG)
    }
    torch.save(checkpoint, best_model_fn)

# 只保留最新的 3 个最佳模型
keep_best_models_num = 3
```

---

## 配置参数

**文件**: `config.py`

### 6.1 核心参数

| 参数 | 默认值 | 说明 |
|------|-------|------|
| `batch_size` | 64 | 批次大小 |
| `lr` | 1e-3 | 学习率 |
| `epochs` | 50 | 训练轮数 |
| `dropout` | 0.1 | Dropout 比例 |
| `projection_dim` | 256 | 最终嵌入维度 |

### 6.2 MS 相关参数

| 参数 | 默认值 | 说明 |
|------|-------|------|
| `min_mz` | 20 | 最小 m/z |
| `max_mz` | 2000 | 最大 m/z |
| `bin_size` | 0.05 | 分桶大小 |
| `add_nl` | True | 是否添加中性丢失特征 |
| `binary_intn` | False | 是否二值化强度 |

### 6.3 分子编码参数

| 参数 | 默认值 | 说明 |
|------|-------|------|
| `mol_encoder` | 'gnn+fp' | 编码方式 (fp/gnn/gnn+fp) |
| `mol_embedding_dim` | 2048 | Morgan 指纹维度 |
| `fptype` | 'morgan' | 指纹类型 |
| `molgnn_n_filters_list` | [256,256,256] | GNN 各层维度 |
| `molgnn_nhead` | 4 | 注意力头数 |
| `molgnn_readout_layers` | 2 | Readout 层数 |

### 6.4 Transformer 参数

| 参数 | 默认值 | 说明 |
|------|-------|------|
| `tsfm_layers` | 6 | Transformer 层数 |
| `tsfm_heads` | 8 | 注意力头数 |
| `tsfm_in_ms` | True | MS 分支使用 Transformer |
| `tsfm_in_mol` | False | 分子分支使用 Transformer |

---

## 附录: 文件结构

```
train-001/
├── train.py          # 训练入口
├── dataset.py        # 数据集定义
├── modules.py        # 模型定义 (FragSimiModelNew)
├── config.py         # 配置参数
├── utils.py          # 工具函数 (特征处理等)
├── cliplayers.py     # CLIP 风格的 Transformer
└── GNN/
    ├── layers.py     # 图卷积层
    └── featurizer.py # 分子图特征化
```

---

## 参考

本模型设计参考了以下工作:
- CLIP (Contrastive Language-Image Pre-training)
- Graph Attention Networks (GAT)
- Morgan Fingerprints (Extended Connectivity Fingerprints)
- Tanimoto Coefficient for molecular similarity

---