PypCoder commited on
Commit
0ba1a8e
·
verified ·
1 Parent(s): e5a3a7b

Create appy.py

Browse files
Files changed (1) hide show
  1. app.py +71 -0
app.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import torch.nn as nn
4
+ from huggingface_hub import hf_hub_download
5
+ from transformers import EsmModel, EsmTokenizer
6
+
7
+ HF_REPO_ID = "PypCoder/SERAPH"
8
+ WEIGHTS_FILE = "SERAPH.pth"
9
+ ESM_MODEL_ID = "facebook/esm2_t6_8M_UR50D"
10
+ IDX_TO_LABEL = {0: 'H', 1: 'E', 2: 'C'}
11
+
12
+ class SERAPH(nn.Module):
13
+ def __init__(self, esm_model, conv_channels=256, kernel_size=7,
14
+ lstm_hidden=256, num_classes=3, dropout=0.3, freeze_esm=True):
15
+ super().__init__()
16
+ self.esm = esm_model
17
+ if freeze_esm:
18
+ for param in self.esm.encoder.layer[:-2].parameters():
19
+ param.requires_grad = False
20
+ esm_embed_dim = self.esm.config.hidden_size
21
+ self.conv = nn.Conv1d(esm_embed_dim, conv_channels, kernel_size=kernel_size, padding=kernel_size//2)
22
+ self.bn = nn.BatchNorm1d(conv_channels)
23
+ self.dropout = nn.Dropout(dropout)
24
+ self.bilstm = nn.LSTM(conv_channels, lstm_hidden, num_layers=2, batch_first=True, bidirectional=True)
25
+ self.fc = nn.Linear(lstm_hidden * 2, num_classes)
26
+
27
+ def forward(self, input_ids, attention_mask=None):
28
+ x = self.esm(input_ids=input_ids, attention_mask=attention_mask).last_hidden_state
29
+ x = x.transpose(1, 2)
30
+ x = torch.relu(self.bn(self.conv(x)))
31
+ x = self.dropout(x)
32
+ x = x.transpose(1, 2)
33
+ x, _ = self.bilstm(x)
34
+ x = self.dropout(x)
35
+ return self.fc(x)
36
+
37
+ print("Loading ESM2 backbone...")
38
+ esm = EsmModel.from_pretrained(ESM_MODEL_ID)
39
+ tokenizer = EsmTokenizer.from_pretrained(ESM_MODEL_ID)
40
+
41
+ print("Downloading SERAPH weights...")
42
+ weights_path = hf_hub_download(repo_id=HF_REPO_ID, filename=WEIGHTS_FILE)
43
+ checkpoint = torch.load(weights_path, map_location="cpu")
44
+
45
+ model = SERAPH(esm_model=esm)
46
+ model.load_state_dict(checkpoint["model_state_dict"])
47
+ model.eval()
48
+ print("SERAPH ready.")
49
+
50
+ def predict(sequence: str) -> dict:
51
+ sequence = sequence.upper().strip()
52
+ tokens = tokenizer(sequence, return_tensors="pt", truncation=True, max_length=512)
53
+ with torch.no_grad():
54
+ output = model(input_ids=tokens["input_ids"], attention_mask=tokens["attention_mask"])
55
+ preds = output.argmax(dim=-1)[0]
56
+ labels = [IDX_TO_LABEL[p.item()] for p in preds[1:-1]]
57
+ return {
58
+ "sequence": sequence,
59
+ "prediction": "".join(labels),
60
+ "length": len(sequence),
61
+ "composition": {"H": labels.count("H"), "E": labels.count("E"), "C": labels.count("C")},
62
+ }
63
+
64
+ demo = gr.Interface(
65
+ fn=predict,
66
+ inputs=gr.Textbox(label="Amino Acid Sequence"),
67
+ outputs=gr.JSON(label="SERAPH Prediction"),
68
+ title="SERAPH — Protein Secondary Structure Prediction",
69
+ )
70
+
71
+ demo.launch()