Skip to content

Commit 7a006ff

Browse files
Setup for final runs on GlyPP data
1 parent 657cbda commit 7a006ff

8 files changed

Lines changed: 148 additions & 155 deletions

File tree

configs/downstream/final.yaml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
seed: [42, 1234, 1337]
2+
root_dir: /scratch/SCRATCH_SAS/roman/Gothenburg/GIFFLAR/data_final
3+
logs_dir: /scratch/SCRATCH_SAS/roman/Gothenburg/GIFFLAR/logs_final
4+
datasets:
5+
- name: Taxonomy_Kingdom
6+
task: multilabel
7+
- name: Tissue
8+
task: multilabel
9+
- name: Glycosylation
10+
task: classification
11+
- name: Spectrum
12+
task: spectrum
13+
pre-transforms:
14+
GIFFLARTransform:
15+
GNNGLYTransform:
16+
ECFPTransform:
17+
SweetNetTransform:
18+
RGCNTransform:
19+
RandomWalkPE:
20+
dim: 20
21+
individual: False
22+
LaplacianPE:
23+
dim: 20
24+
individual: False
25+
model:
26+
- name: rf
27+
n_estimators: 500
28+
n_jobs: -1
29+
random_state: 42
30+
- name: svm
31+
random_state: 42
32+
- name: xgb
33+
random_state: 42
34+
- name: mlp
35+
feat_dim: 1024
36+
hidden_dim: 1024
37+
batch_size: 256
38+
num_layers: 3
39+
epochs: 100
40+
patience: 30
41+
learning_rate: 0.001
42+
optimizer: Adam
43+
- name: sweetnet
44+
feat_dim: 128
45+
hidden_dim: 1024
46+
batch_size: 512
47+
num_layers: 16
48+
epochs: 100
49+
patience: 30
50+
learning_rate: 0.001
51+
optimizer: Adam
52+
suffix:
53+
- name: gnngly
54+
feat_dim: 128
55+
hidden_dim: 1024
56+
batch_size: 512
57+
num_layers: 8
58+
epochs: 100
59+
patience: 30
60+
learning_rate: 0.001
61+
optimizer: Adam
62+
suffix:
63+
- name: rgcn
64+
feat_dim: 128
65+
hidden_dim: 1024
66+
batch_size: 256
67+
num_layers: 8
68+
epochs: 100
69+
learning_rate: 0.001
70+
optimizer: Adam
71+
suffix:
72+
- name: gifflar
73+
feat_dim: 128
74+
hidden_dim: 1024
75+
batch_size: 256
76+
num_layers: 8
77+
epochs: 100
78+
learning_rate: 0.001
79+
optimizer: Adam
80+
pooling: global_mean
81+
suffix:

configs/downstream/spec.yaml

Lines changed: 13 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
seed: 42
22
root_dir: /scratch/SCRATCH_SAS/roman/Gothenburg/GIFFLAR/data
3-
logs_dir: /scratch/SCRATCH_SAS/roman/Gothenburg/GIFFLAR/logs_spec_mse
3+
logs_dir: /scratch/SCRATCH_SAS/roman/Gothenburg/GIFFLAR/logs_spec
44
datasets:
55
- name: Spectrum
66
task: spectrum
@@ -11,69 +11,22 @@ pre-transforms:
1111
SweetNetTransform:
1212
RGCNTransform:
1313
model:
14-
# - name: rf
15-
# n_estimators: 500
16-
# n_jobs: -1
17-
# random_state: 42
18-
# - name: svm
19-
# random_state: 42
20-
# - name: xgb
21-
# random_state: 42
2214
- name: mlp
2315
feat_dim: 1024
2416
hidden_dim: 1024
25-
batch_size: 256
17+
batch_size: 16
2618
num_layers: 3
27-
epochs: 3
19+
epochs: 100
2820
patience: 30
2921
learning_rate: 0.001
3022
optimizer: Adam
31-
# - name: sweetnet
32-
# feat_dim: 128
33-
# hidden_dim: 1024
34-
# batch_size: 512
35-
# num_layers: 16
36-
# epochs: 100
37-
# patience: 30
38-
# learning_rate: 0.001
39-
# optimizer: Adam
40-
# suffix:
41-
# - name: gnngly
42-
# feat_dim: 128
43-
# hidden_dim: 1024
44-
# batch_size: 512
45-
# num_layers: 8
46-
# epochs: 100
47-
# patience: 30
48-
# learning_rate: 0.001
49-
# optimizer: Adam
50-
# suffix:
51-
# - name: rgcn
52-
# feat_dim: 128
53-
# hidden_dim: 1024
54-
# batch_size: 256
55-
# num_layers: 8
56-
# epochs: 100
57-
# learning_rate: 0.001
58-
# optimizer: Adam
59-
# suffix:
60-
# - name: gifflar
61-
# feat_dim: 128
62-
# hidden_dim: 1024
63-
# batch_size: 256
64-
# num_layers: 8
65-
# epochs: 100
66-
# learning_rate: 0.001
67-
# optimizer: Adam
68-
# pooling: global_mean
69-
# suffix: _128_8_gp
70-
# - name: glylm
71-
# token_file: /scratch/SCRATCH_SAS/roman/Gothenburg/GIFFLAR/unique/GlyLM/bpe_lib_2500.pkl
72-
# model_dir: /scratch/SCRATCH_SAS/roman/Gothenburg/GIFFLAR/unique/GlyLM/bpe_lib_2500_t6/checkpoint-5927260
73-
# pre_tokenizer: lib
74-
# hidden_dim: 320
75-
# epochs: 100
76-
# learning_rate: 0.001
77-
# batch_size: 256
78-
# optimizer: Adam
79-
# suffix: _bpe_lib_25_t6_20
23+
- name: gifflar
24+
feat_dim: 128
25+
hidden_dim: 1024
26+
batch_size: 16
27+
num_layers: 8
28+
epochs: 100
29+
learning_rate: 0.001
30+
optimizer: Adam
31+
pooling: global_mean
32+
suffix: _128_8_gp

gifflar/benchmarks.py

Lines changed: 18 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,12 @@
44

55
import numpy as np
66
import pandas as pd
7-
from glycowork.glycan_data.loader import df_species as taxonomy
7+
from glycowork.glycan_data.loader import df_species, df_glycan, build_custom_df
88
from tqdm import tqdm
99

1010
from gifflar.utils import iupac2smiles
1111

1212

13-
def get_taxonomy(root: Path | str) -> pd.DataFrame:
14-
"""
15-
Download full taxonomy data, process it, and save it as a tsv file.
16-
17-
Args:
18-
root: The root directory to save the data to.
19-
20-
Returns:
21-
The processed taxonomy data.
22-
"""
23-
if not (p := (root / Path("taxonomy.tsv"))).exists():
24-
mask = []
25-
# convert to IUPAC to SMILES and build a mask to remove not-convertable molecules.
26-
for i in tqdm(taxonomy["glycan"]):
27-
smiles = iupac2smiles(i)
28-
mask.append(smiles is not None)
29-
tax = taxonomy[mask]
30-
tax.to_csv(p, sep="\t", index=False)
31-
return pd.read_csv(p, sep="\t")
32-
33-
3413
def get_taxonomic_level(
3514
root: Path | str,
3615
level: Literal["Domain", "Kingdom", "Phylum", "Class", "Order", "Family", "Genus", "Species"]
@@ -47,7 +26,7 @@ def get_taxonomic_level(
4726
"""
4827
if not (p := (root / Path(f"taxonomy_{level}.tsv"))).exists():
4928
# Chop to taxonomic level of interest and remove invalid rows
50-
tax = get_taxonomy(root)[["glycan", level]]
29+
tax = df_species[["glycan", level]]
5130
tax.rename(columns={"glycan": "IUPAC"}, inplace=True)
5231
tax[tax[level] == "undetermined"] = np.nan
5332
tax.dropna(inplace=True)
@@ -83,45 +62,17 @@ def get_tissue(root: Path | str) -> Path:
8362
"""
8463
if not (p := (root / Path("tissue.tsv"))).exists():
8564
# Process the data and remove unnecessary columns
86-
df = pd.read_csv("datasets/tissue_multilabel_df.csv")
87-
df.rename(columns={"glycan": "IUPAC"}, inplace=True)
88-
df.dropna(inplace=True)
89-
90-
df["split"] = np.random.choice(["train", "val", "test"], df.shape[0], p=[0.7, 0.2, 0.1])
91-
df.to_csv(p, sep="\t", index=False)
92-
return p
93-
94-
95-
def get_immunogenicity(root: Path | str) -> Path:
96-
"""
97-
Download immunogenicity data, process it, and save it as a tsv file.
98-
99-
Args:
100-
root: The root directory to save the data to.
101-
102-
Returns:
103-
The filepath of the processed immunogenicity data.
104-
"""
105-
root = Path(root)
106-
if not (p := (root / "immunogenicity.tsv")).exists():
107-
# Download the data
108-
urllib.request.urlretrieve("https://torchglycan.s3.us-east-2.amazonaws.com/downstream/glycan_immunogenicity.csv", p.with_suffix(".csv"))
109-
110-
# Process the data and remove unnecessary columns
111-
df = pd.read_csv(p.with_suffix(".csv"))[["glycan", "immunogenicity"]]
65+
df = build_custom_df(df_glycan, "df_tissue")[["glycan", "tissue_sample"]]
11266
df.rename(columns={"glycan": "IUPAC"}, inplace=True)
67+
df.drop_duplicates(inplace=True)
11368
df.dropna(inplace=True)
11469

11570
# One-hot encode the individual classes and collate them for glycans that are the same
116-
classes = {n: i for i, n in enumerate(df["immunogenicity"].unique())}
117-
df["label"] = df["immunogenicity"].map(classes)
118-
df["split"] = np.random.choice(["train", "val", "test"], df.shape[0], p=[0.7, 0.2, 0.1])
71+
df = pd.concat([df["IUPAC"], pd.get_dummies(df["tissue_sample"])], axis=1)
72+
df = df.groupby('IUPAC').agg("sum").reset_index()
11973

120-
df.drop("immunogenicity", axis=1, inplace=True)
74+
df["split"] = np.random.choice(["train", "val", "test"], df.shape[0], p=[0.7, 0.2, 0.1])
12175
df.to_csv(p, sep="\t", index=False)
122-
with open(root / "immunogenicity_classes.tsv", "w") as f:
123-
for n, i in classes.items():
124-
print(n, i, sep="\t", file=f)
12576
return p
12677

12778

@@ -137,16 +88,15 @@ def get_glycosylation(root: Path | str) -> Path:
13788
"""
13889
root = Path(root)
13990
if not (p := root / "glycosylation.tsv").exists():
140-
urllib.request.urlretrieve("https://torchglycan.s3.us-east-2.amazonaws.com/downstream/glycan_properties.csv", p.with_suffix(".csv"))
141-
df = pd.read_csv(p.with_suffix(".csv"))[["glycan", "link"]]
91+
df = df_glycan[["glycan", "glycan_type"]]
14292
df.rename(columns={"glycan": "IUPAC"}, inplace=True)
14393
df.dropna(inplace=True)
14494

145-
classes = {n: i for i, n in enumerate(df["link"].unique())}
146-
df["label"] = df["link"].map(classes)
95+
classes = {n: i for i, n in enumerate(df["glycan_type"].unique())}
96+
df["label"] = df["glycan_type"].map(classes)
14797
df["split"] = np.random.choice(["train", "val", "test"], df.shape[0], p=[0.7, 0.2, 0.1])
14898

149-
df.drop("link", axis=1, inplace=True)
99+
df.drop("glycan_type", axis=1, inplace=True)
150100
df.to_csv(p, sep="\t", index=False)
151101
with open(root / "glycosylation_classes.tsv", "w") as f:
152102
for n, i in classes.items():
@@ -164,12 +114,12 @@ def get_spectrum(root: Path | str) -> Path:
164114
Returns:
165115
The filepath of the processed spectrum data.
166116
"""
167-
root = Path(root)
168-
#if not (p := root / "spectrum.tsv").exists():
169-
p = root / "spectrum.tsv"
170-
df = pd.read_csv(Path("/") / "scratch" / "SCRATCH_SAS" / "roman" / "Gothenburg" / "GIFFLAR" / "spectrum_pred_512_small.tsv", sep="\t")
171-
df.to_csv(p, sep="\t", index=False)
172-
return p
117+
# root = Path(root)
118+
# if not (p := root / "spectrum.tsv").exists():
119+
# p = root / "spectrum.tsv"
120+
# df = pd.read_csv(Path("/") / "scratch" / "SCRATCH_SAS" / "roman" / "Gothenburg" / "GIFFLAR" / "spectrum_pred_2048.tsv", sep="\t")
121+
# df.to_csv(p, sep="\t", index=False)
122+
return Path("/") / "scratch" / "SCRATCH_SAS" / "roman" / "Gothenburg" / "GIFFLAR" / "spectrum_pred_2048.tsv"
173123

174124

175125
def get_dataset(data_config: dict, root: Path | str) -> dict:
@@ -190,9 +140,7 @@ def get_dataset(data_config: dict, root: Path | str) -> dict:
190140
path = get_taxonomic_level(root, name_fracs[1])
191141
case "Tissue":
192142
path = get_tissue(root)
193-
case "Immunogenicity":
194-
path = get_immunogenicity(root)
195-
case "Glycosylation":
143+
case "Glycosylation" | "Linkage":
196144
path = get_glycosylation(root)
197145
case "Spectrum":
198146
path = get_spectrum(root)

gifflar/metrics.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ class ModifiedCosineSimilarity(Metric):
2020
Args:
2121
tolerance: The tolerance value for the modified cosine similarity.
2222
"""
23-
def __init__(self, num_bins, tolerance: float = 0.2):
23+
def __init__(self, num_bins: Optional[int] = None, tolerance: float = 0.2):
2424
super(ModifiedCosineSimilarity, self).__init__()
2525
self.mod_cos = matchms.similarity.ModifiedCosine(tolerance=tolerance)
26-
self.mz = np.arange(MIN, MAX, (MAX - MIN) / num_bins)
26+
self.mz = None if num_bins is None else np.arange(MIN, MAX, (MAX - MIN) / num_bins)
2727
self.add_state("mod_cos_sim", default=[], dist_reduce_fx="cat")
2828

2929
def update(self, pred: torch.Tensor, true: torch.Tensor, precursor_masses: list[float]) -> torch.Tensor:
@@ -32,9 +32,11 @@ def update(self, pred: torch.Tensor, true: torch.Tensor, precursor_masses: list[
3232
assert len(true.shape) == 2, "The true values must have dimensions (batch_size, num_predictions)"
3333
assert pred.shape[0] == len(precursor_masses), "The batch size the precursor masses must match those of predictions, and true values"
3434

35+
if self.mz is None:
36+
self.mz = np.arange(MIN, MAX, (MAX - MIN) / pred.shape[1])
3537
self.mod_cos_sim += [float(self.mod_cos.pair(
36-
matchms.Spectrum(mz=self.mz, intensities=pred[i].cpu().numpy(), metadata={"precursor_mz": precursor_masses[i]}),
37-
matchms.Spectrum(mz=self.mz, intensities=true[i].cpu().numpy(), metadata={"precursor_mz": precursor_masses[i]})
38+
matchms.Spectrum(mz=self.mz, intensities=pred[i].cpu().numpy().astype(float), metadata={"precursor_mz": precursor_masses[i]}),
39+
matchms.Spectrum(mz=self.mz, intensities=true[i].cpu().numpy().astype(float), metadata={"precursor_mz": precursor_masses[i]})
3840
)["score"]) for i in range(pred.shape[0])]
3941

4042
def compute(self) -> torch.Tensor:

gifflar/model/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from typing import Literal, Optional, Any
22

33
import torch
4+
import matplotlib
5+
matplotlib.use('TkAgg',force=True)
46
from glycowork.glycan_data.loader import lib
57
from pytorch_lightning import LightningModule
68
from torch import nn

gifflar/model/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def get_spectrum_prediction_head(
177177
m = MetricCollection([
178178
CosineSimilarity(reduction="mean"),
179179
KLDivergence(reduction="mean", log_prob=True),
180-
ModifiedCosineSimilarity(num_bins=512, tolerance=0.2),
180+
ModifiedCosineSimilarity(num_bins=2048, tolerance=0.2),
181181
])
182182
metrics = {
183183
"train": m.clone(prefix="train/" + metric_prefix),

gifflar/train.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import os
2-
# os.environ["CUDA_VISIBLE_DEVICES"] = "1"
3-
41
from pathlib import Path
52
from typing import Any
63
import time
@@ -143,15 +140,16 @@ def train(**kwargs: Any) -> None:
143140
data_config, datamodule, logger, _ = setup(3, **kwargs)
144141
model = MODELS[kwargs["model"]["name"]](output_dim=data_config["num_classes"], task=data_config["task"],
145142
pre_transform_args=kwargs.get("pre-transforms", {}), **kwargs["model"])
143+
print("Using device", "CUDA" if torch.cuda.is_available() else "CPU")
146144
trainer = Trainer(
147145
callbacks=[
148146
RichModelSummary(),
149147
RichProgressBar(),
150148
],
151149
max_epochs=kwargs["model"]["epochs"],
152150
logger=logger,
153-
limit_train_batches=3,
154-
limit_val_batches=3,
151+
# limit_train_batches=3,
152+
# limit_val_batches=3,
155153
# accelerator="cpu",
156154
)
157155
start = time.time()

0 commit comments

Comments
 (0)