Views
No views yet
facebook/esm2_t6_8M_UR50D, for the same task. For more information
on training a sequence classifier langauge model with LoRA see here.
Note, this is for natural language processing and must be adapted to our use case using a protein language model like ESM-2.train_sequences.fasta file of protein sequences, with the train_terms.tsv file serving as the labels.
The gene ontology used is a hierarchy, and so the labels lower in the hierchay should be weighted more, or the
graph structure should be taken into account. The model achieved the following metrics:Epoch: 3,
Validation Loss: 0.0031,
Validation Micro F1: 0.3752,
Validation Macro F1: 0.9968,
Validation Micro Precision: 0.5287,
Validation Macro Precision: 0.9992,
Validation Micro Recall: 0.2911,
Validation Macro Recall: 0.99681import os
2import numpy as np
3import torch
4from transformers import AutoTokenizer, EsmForSequenceClassification, AdamW
5from torch.nn.functional import binary_cross_entropy_with_logits
6from sklearn.model_selection import train_test_split
7from sklearn.metrics import f1_score, precision_score, recall_score
8from accelerate import Accelerator
9from Bio import SeqIO
10
11# Step 1: Data Preprocessing
12fasta_file = "data/Train/train_sequences.fasta"
13tsv_file = "data/Train/train_terms.tsv"
14
15fasta_data = {}
16tsv_data = {}
17
18for record in SeqIO.parse(fasta_file, "fasta"):
19 fasta_data[record.id] = str(record.seq)
20
21with open(tsv_file, 'r') as f:
22 for line in f:
23 parts = line.strip().split("\t")
24 tsv_data[parts[0]] = parts[1:]
25
26unique_terms = list(set(term for terms in tsv_data.values() for term in terms))
27
28def parse_fasta(file_path):
29 """
30 Parses a FASTA file and returns a list of sequences.
31 """
32 with open(file_path, 'r') as f:
33 content = f.readlines()
34
35 sequences = []
36 current_sequence = ""
37
38 for line in content:
39 if line.startswith(">"):
40 if current_sequence:
41 sequences.append(current_sequence)
42 current_sequence = ""
43 else:
44 current_sequence += line.strip()
45
46 if current_sequence:
47 sequences.append(current_sequence)
48
49 return sequences
50
51# Parse the provided FASTA file
52fasta_file_path = "data/Test/testsuperset.fasta"
53protein_sequences = parse_fasta(fasta_file_path)
54# protein_sequences[:3] # Displaying the first 3 sequences for verification
55
56import torch
57from transformers import AutoTokenizer, EsmForSequenceClassification
58from sklearn.metrics import precision_recall_fscore_support
59
60# 1. Parsing the go-basic.obo file (Assuming this is still needed)
61def parse_obo_file(file_path):
62 with open(file_path, 'r') as f:
63 data = f.read().split("[Term]")
64
65 terms = []
66 for entry in data[1:]:
67 lines = entry.strip().split("\n")
68 term = {}
69 for line in lines:
70 if line.startswith("id:"):
71 term["id"] = line.split("id:")[1].strip()
72 elif line.startswith("name:"):
73 term["name"] = line.split("name:")[1].strip()
74 elif line.startswith("namespace:"):
75 term["namespace"] = line.split("namespace:")[1].strip()
76 elif line.startswith("def:"):
77 term["definition"] = line.split("def:")[1].split('"')[1]
78 terms.append(term)
79 return terms
80
81# Let's assume the path to go-basic.obo is as follows (please modify if different)
82obo_file_path = "data/Train/go-basic.obo"
83parsed_terms = parse_obo_file("data/Train/go-basic.obo") # Replace with your path
84
85# 2. Load the saved model and tokenizer
86# Assuming the model path provided is correct
87from transformers import AutoTokenizer, AutoModelForSequenceClassification
88from peft import PeftModel, PeftConfig
89
90# Load the tokenizer and model
91model_id = "AmelieSchreiber/esm2_t6_8M_UR50D_cafa5_lora" # Replace with your Hugging Face hub model name
92tokenizer = AutoTokenizer.from_pretrained(model_id)
93
94# First, we load the underlying base model
95base_model = AutoModelForSequenceClassification.from_pretrained(model_id)
96
97# Then, we load the model with PEFT
98model = PeftModel.from_pretrained(base_model, model_id)
99loaded_model = model
100loaded_tokenizer = AutoTokenizer.from_pretrained(model_id)
101
102# 3. The predict_protein_function function
103def predict_protein_function(sequence, model, tokenizer, go_terms):
104 inputs = tokenizer(sequence, return_tensors="pt", padding=True, truncation=True, max_length=1022)
105 model.eval()
106 with torch.no_grad():
107 outputs = model(**inputs)
108 predictions = torch.sigmoid(outputs.logits)
109 predicted_indices = torch.where(predictions > 0.05)[1].tolist()
110
111 functions = []
112 for idx in predicted_indices:
113 term_id = unique_terms[idx] # Use the unique_terms list from your training script
114 for term in go_terms:
115 if term["id"] == term_id:
116 functions.append(term["name"])
117 break
118
119 return functions
120
121# 4. Predicting protein function for the sequences in the FASTA file
122protein_functions = {}
123for seq in protein_sequences[:20]: # Using only the first 3 sequences for demonstration
124 predicted_functions = predict_protein_function(seq, loaded_model, loaded_tokenizer, parsed_terms)
125 protein_functions[seq[:20] + "..."] = predicted_functions # Using first 20 characters as key
126
127protein_functions