Taykhoom commited on
Commit
92876c2
·
verified ·
1 Parent(s): 24c9656

Upload folder using huggingface_hub

Browse files
README.md ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - rna
4
+ library_name: transformers
5
+ tags:
6
+ - RNA
7
+ - language-model
8
+ - bert
9
+ license: mit
10
+ ---
11
+
12
+ # RNABERT
13
+
14
+ A small BERT-style RNA language model pretrained on non-coding RNA sequences from Rfam 14.3, using
15
+ Masked Language Modeling (MLM) and Structural Alignment Learning (SAL). Designed for RNA clustering
16
+ and structural alignment tasks.
17
+
18
+ ## Architecture
19
+
20
+ | Parameter | Value |
21
+ |---|---|
22
+ | Layers | 6 |
23
+ | Attention heads | 12 |
24
+ | Embedding dimension | 120 |
25
+ | FFN intermediate size | 40 |
26
+ | Vocabulary size | 6 (PAD, MASK, A, U, G, C) |
27
+ | Positional encoding | Learned absolute |
28
+ | Architecture | Post-LN BERT encoder |
29
+ | Max sequence length | 440 |
30
+
31
+ **Vocabulary:**
32
+
33
+ | Token | ID |
34
+ |---|---|
35
+ | `<pad>` | 0 |
36
+ | `<mask>` | 1 |
37
+ | A | 2 |
38
+ | U | 3 |
39
+ | G | 4 |
40
+ | C | 5 |
41
+
42
+ No CLS or EOS tokens are added. Sequences are tokenized character-by-character; T is silently converted to U.
43
+
44
+ ## Pretraining
45
+
46
+ - **Objective:** Masked Language Modeling (MLM) + Structural Alignment Learning (SAL, a pairwise
47
+ structural alignment contrastive objective)
48
+ - **Data:** Rfam 14.3 (~440 nt max length sequences)
49
+ - **Source checkpoint:** `bert_mul_2.pth` (distributed inside `RNABERT_pretrained.pth` zip)
50
+
51
+ ### Checkpoint selection
52
+
53
+ There is one published pretrained checkpoint from the original repository. This is it.
54
+
55
+ ## Parity Verification
56
+
57
+ Hidden-state representations verified identical (max abs diff = 2.2e-6) to the original
58
+ implementation at all 7 representation levels (embedding + 6 transformer layers), with and
59
+ without padding. Verified on CPU with PyTorch 2.7 / transformers 4.57.6.
60
+
61
+ ## Related Models
62
+
63
+ See the full [RNABERT collection](https://huggingface.co/collections/Taykhoom/rnabert-PLACEHOLDER).
64
+
65
+ | Model | Notes |
66
+ |---|---|
67
+ | **[Taykhoom/RNABERT](https://huggingface.co/Taykhoom/RNABERT)** | This model |
68
+
69
+ ## Usage
70
+
71
+ ### Embedding generation
72
+
73
+ ```python
74
+ import torch
75
+ from transformers import AutoTokenizer, AutoModel
76
+
77
+ tokenizer = AutoTokenizer.from_pretrained("Taykhoom/RNABERT", trust_remote_code=True)
78
+ model = AutoModel.from_pretrained("Taykhoom/RNABERT")
79
+ model.eval()
80
+
81
+ sequences = ["AUGCAUGCAUGC", "GCUAGCUAGCUA"]
82
+ enc = tokenizer(sequences, return_tensors="pt", padding=True)
83
+
84
+ with torch.no_grad():
85
+ out = model(**enc)
86
+
87
+ # Token-level embeddings
88
+ token_emb = out.last_hidden_state # (batch, seq_len, 120)
89
+
90
+ # Mean-pool over non-padding positions
91
+ mask = enc["attention_mask"].unsqueeze(-1).float()
92
+ mean_emb = (token_emb * mask).sum(1) / mask.sum(1) # (batch, 120)
93
+
94
+ # Intermediate layers
95
+ out_all = model(**enc, output_hidden_states=True)
96
+ layer3_emb = out_all.hidden_states[3] # (batch, seq_len, 120)
97
+ ```
98
+
99
+ ### Fine-tuning
100
+
101
+ Standard HF conventions. The model has no CLS token, so use mean pooling over non-padding
102
+ positions for sequence-level tasks.
103
+
104
+ ## Implementation Notes
105
+
106
+ This model uses the standard HuggingFace `BertModel` (`model_type: "bert"`) with custom
107
+ hyperparameters matching the original RNABERT architecture. No custom modeling code is required;
108
+ `trust_remote_code=True` is only needed for the tokenizer.
109
+
110
+ The original implementation uses standard scaled dot-product attention (post-LN BERT). This HF
111
+ port adds `attn_implementation="sdpa"` and `attn_implementation="flash_attention_2"` support via
112
+ the standard HF dispatch mechanism, which were not part of the original codebase.
113
+
114
+ ## Citation
115
+
116
+ ```bibtex
117
+ @article{akiyama2022informative,
118
+ title={Informative {RNA}-base embedding for functional {RNA} clustering and structural alignment},
119
+ author={Akiyama, Manato and Hamada, Michiaki},
120
+ journal={NAR Genomics and Bioinformatics},
121
+ volume={4},
122
+ number={1},
123
+ pages={lqac012},
124
+ year={2022},
125
+ publisher={Oxford University Press}
126
+ }
127
+ ```
128
+
129
+ ## Credits
130
+
131
+ Original model and code by Akiyama and Hamada. Source: [GitHub](https://github.com/mana438/RNABERT).
132
+ The HF conversion code was authored primarily by [Claude Code](https://claude.ai/code)
133
+ and reviewed manually by Taykhoom Dalal.
134
+
135
+ ## License
136
+
137
+ MIT, following the original repository.
config.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "BertModel"
4
+ ],
5
+ "attention_probs_dropout_prob": 0.0,
6
+ "classifier_dropout": null,
7
+ "dtype": "float32",
8
+ "hidden_act": "gelu",
9
+ "hidden_dropout_prob": 0.0,
10
+ "hidden_size": 120,
11
+ "initializer_range": 0.02,
12
+ "intermediate_size": 40,
13
+ "layer_norm_eps": 1e-12,
14
+ "max_position_embeddings": 440,
15
+ "model_type": "bert",
16
+ "num_attention_heads": 12,
17
+ "num_hidden_layers": 6,
18
+ "pad_token_id": 0,
19
+ "position_embedding_type": "absolute",
20
+ "transformers_version": "4.57.6",
21
+ "type_vocab_size": 2,
22
+ "use_cache": true,
23
+ "vocab_size": 6
24
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3f2e501e6923a5d0aeb67ea4709d2a796b583e81057602b719689a8a533743da
3
+ size 1924760
special_tokens_map.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ {
2
+ "pad_token": "<pad>",
3
+ "mask_token": "<mask>",
4
+ "unk_token": "<pad>"
5
+ }
tokenization_rnabert.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ from transformers import PreTrainedTokenizer
4
+
5
+ VOCAB = {"<pad>": 0, "<mask>": 1, "A": 2, "U": 3, "G": 4, "C": 5}
6
+
7
+
8
+ class RNABertTokenizer(PreTrainedTokenizer):
9
+ vocab_files_names = {"vocab_file": "vocab.json"}
10
+ model_input_names = ["input_ids", "attention_mask"]
11
+
12
+ def __init__(
13
+ self,
14
+ vocab_file=None,
15
+ pad_token="<pad>",
16
+ mask_token="<mask>",
17
+ unk_token="<pad>",
18
+ **kwargs,
19
+ ):
20
+ self._vocab = dict(VOCAB)
21
+ if vocab_file and os.path.isfile(vocab_file):
22
+ with open(vocab_file) as f:
23
+ self._vocab = json.load(f)
24
+ self._ids_to_tokens = {v: k for k, v in self._vocab.items()}
25
+ super().__init__(
26
+ pad_token=pad_token,
27
+ mask_token=mask_token,
28
+ unk_token=unk_token,
29
+ **kwargs,
30
+ )
31
+
32
+ @property
33
+ def vocab_size(self):
34
+ return len(self._vocab)
35
+
36
+ def get_vocab(self):
37
+ return dict(self._vocab)
38
+
39
+ def _tokenize(self, text):
40
+ return list(text.upper().replace("T", "U"))
41
+
42
+ def _convert_token_to_id(self, token):
43
+ return self._vocab.get(token, 0)
44
+
45
+ def _convert_id_to_token(self, index):
46
+ return self._ids_to_tokens.get(index, "<pad>")
47
+
48
+ def save_vocabulary(self, save_directory, filename_prefix=None):
49
+ os.makedirs(save_directory, exist_ok=True)
50
+ fname = (filename_prefix + "-" if filename_prefix else "") + "vocab.json"
51
+ path = os.path.join(save_directory, fname)
52
+ with open(path, "w") as f:
53
+ json.dump(self._vocab, f, indent=2)
54
+ return (path,)
55
+
56
+ def build_inputs_with_special_tokens(self, token_ids_0, token_ids_1=None):
57
+ if token_ids_1 is None:
58
+ return token_ids_0
59
+ return token_ids_0 + token_ids_1
60
+
61
+ def get_special_tokens_mask(self, token_ids_0, token_ids_1=None, already_has_special_tokens=False):
62
+ if already_has_special_tokens:
63
+ return super().get_special_tokens_mask(token_ids_0, token_ids_1, True)
64
+ return [0] * len(token_ids_0) + ([0] * len(token_ids_1) if token_ids_1 else [])
65
+
66
+ def create_token_type_ids_from_sequences(self, token_ids_0, token_ids_1=None):
67
+ if token_ids_1 is None:
68
+ return [0] * len(token_ids_0)
69
+ return [0] * len(token_ids_0) + [0] * len(token_ids_1)
tokenizer_config.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "auto_map": {
3
+ "AutoTokenizer": ["tokenization_rnabert.RNABertTokenizer", null]
4
+ },
5
+ "model_max_length": 440,
6
+ "tokenizer_class": "RNABertTokenizer",
7
+ "pad_token": "<pad>",
8
+ "mask_token": "<mask>",
9
+ "unk_token": "<pad>",
10
+ "vocab_file": "vocab.json"
11
+ }
vocab.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "<pad>": 0,
3
+ "<mask>": 1,
4
+ "A": 2,
5
+ "U": 3,
6
+ "G": 4,
7
+ "C": 5
8
+ }