Taykhoom commited on
Commit
933cd85
·
0 Parent(s):

Initial structRFM HF port

Browse files
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: transformers
3
+ tags:
4
+ - biology
5
+ - RNA
6
+ - language-model
7
+ - bert
8
+ license: mit
9
+ ---
10
+
11
+ # structRFM
12
+
13
+ Minimal HuggingFace port of [structRFM](https://huggingface.co/heqin-zhu/structRFM)
14
+ -- a structure-guided RNA foundation model: a BERT encoder pretrained with
15
+ structure-guided masked language modeling on ~21M RNAcentral sequences paired
16
+ with ensemble-predicted secondary structures.
17
+
18
+ ## Why this port?
19
+
20
+ [heqin-zhu/structRFM](https://huggingface.co/heqin-zhu/structRFM) ships the
21
+ weights as a stock `BertForMaskedLM`, but its tokenizer has no post-processing
22
+ template or normalizer. Upstream code builds the model input by hand
23
+ (`"[CLS]" + seq.upper().replace("T", "U") + "[SEP]"`); calling its
24
+ `AutoTokenizer` directly on a sequence silently:
25
+
26
+ 1. adds **no** `[CLS]` / `[SEP]` tokens, and
27
+ 2. maps `T` and every lowercase base to `[UNK]`.
28
+
29
+ This repo's tokenizer applies the upstream preprocessing itself (uppercase,
30
+ T->U, `[CLS] ... [SEP]`), so `tokenizer(seq)` produces exactly the token ids the
31
+ model was pretrained on. It also adds `flash_attention_2` support. The weights
32
+ are unchanged and bit-exact with the upstream release (see
33
+ [Parity Verification](#parity-verification)).
34
+
35
+ ## Architecture
36
+
37
+ | Parameter | Value |
38
+ |---|---|
39
+ | Layers | 12 |
40
+ | Attention heads | 12 |
41
+ | Embedding dimension | 768 |
42
+ | FFN hidden dimension | 3072 (GELU) |
43
+ | Vocabulary size | 10 |
44
+ | Positional encoding | Learned absolute |
45
+ | Normalization | LayerNorm (post-residual, eps=1e-12) |
46
+ | Architecture | Post-LN BERT encoder |
47
+ | Max sequence length | 512 nt (514 tokens with [CLS] and [SEP]) |
48
+ | Parameters | 85.5M (encoder) + 0.6M (MLM head) |
49
+
50
+ **Vocabulary:** `[UNK]`=0, `[CLS]`=1, `[SEP]`=2, `[PAD]`=3, `[MASK]`=4,
51
+ `A`=5, `U`=6, `C`=7, `G`=8, `N`=9. Input is uppercased and `T` is read as `U`;
52
+ any other character (including whitespace) maps to `[UNK]`, as upstream.
53
+
54
+ ## Pretraining
55
+
56
+ - **Objective:** Structure-guided masked language modeling (SgMLM): each batch
57
+ uses either standard 15% token masking or structure masking, where masking a
58
+ paired base also masks its partner; the share of structure-masked batches is
59
+ scheduled over training
60
+ - **Data:** ~21M RNAcentral sequences (<= 512 nt) with secondary structures from
61
+ MUSES, a multi-source ensemble of thermodynamic, probabilistic and
62
+ deep-learning predictors
63
+ - **Source checkpoint:** `structRFM_checkpoint.tar.gz` from the upstream
64
+ [v0.0.8 release](https://github.com/heqin-zhu/structRFM/releases/tag/v0.0.8)
65
+ (identical to [`heqin-zhu/structRFM`](https://huggingface.co/heqin-zhu/structRFM))
66
+
67
+ ### Checkpoint selection
68
+
69
+ Upstream released two pretrained models: v0.0.3, pretrained on single-predictor
70
+ (BPfold) structures, and v0.0.8, re-pretrained on MUSES ensemble structures.
71
+ v0.0.8 replaced v0.0.3 on the Hub and is the base of every released downstream
72
+ checkpoint, so it is the one ported here.
73
+
74
+ The released secondary-structure (`structRFM_SSP_bpRNA1m.pt`,
75
+ `structRFM_SSP_RNAStrAlign.pt`), tertiary-structure and IRES checkpoints train a
76
+ task head on detached encoder features, so their encoder weights are
77
+ bit-identical to this model; use this repo for their embeddings.
78
+
79
+ ## Parity Verification
80
+
81
+ All 13 representation levels (embedding + 12 transformer blocks) and the MLM
82
+ logits verified to be bit-exact (max abs diff = 0.00) against the original
83
+ v0.0.8 weights run through the upstream `structRFM` code, with `eager` and `sdpa`
84
+ attention, on padded and unpadded batches. The tokenizer reproduces the upstream
85
+ token ids exactly. Verified on an NVIDIA H100 with PyTorch 2.7 / CUDA 12.9.
86
+
87
+ ## Related Models
88
+
89
+ See the full [structRFM collection](https://huggingface.co/collections/Taykhoom/structrfm-6aebd71d994e3b036c62ed23).
90
+
91
+ | Model | Parameters | Notes |
92
+ |---|---:|---|
93
+ | **[structRFM](https://huggingface.co/Taykhoom/structRFM)** | 86M | This model |
94
+
95
+ ## Usage
96
+
97
+ ### Embedding generation
98
+
99
+ ```python
100
+ import torch
101
+ from transformers import AutoTokenizer, AutoModel
102
+
103
+ tokenizer = AutoTokenizer.from_pretrained("Taykhoom/structRFM", trust_remote_code=True)
104
+ model = AutoModel.from_pretrained("Taykhoom/structRFM", trust_remote_code=True)
105
+ model.eval()
106
+
107
+ sequences = ["GUCCCAACUCUUGCGGGGAGGGAU", "ATGGCTACGTAG"] # T is read as U
108
+ enc = tokenizer(sequences, return_tensors="pt", padding=True)
109
+
110
+ with torch.no_grad():
111
+ out = model(**enc)
112
+
113
+ cls_emb = out.last_hidden_state[:, 0, :] # (batch, 768) -- CLS token
114
+ token_emb = out.last_hidden_state # (batch, seq_len, 768)
115
+
116
+ # Mean over nucleotides only (drop [CLS], [SEP] and padding)
117
+ special = torch.isin(enc.input_ids, torch.tensor([tokenizer.cls_token_id, tokenizer.sep_token_id]))
118
+ mask = (enc.attention_mask.bool() & ~special).unsqueeze(-1)
119
+ mean_emb = (token_emb * mask).sum(1) / mask.sum(1) # (batch, 768)
120
+
121
+ # Intermediate layers: hidden_states[0] is the embedding, [i] block i
122
+ out_all = model(**enc, output_hidden_states=True)
123
+ layer6_emb = out_all.hidden_states[6]
124
+ ```
125
+
126
+ Sequences longer than 512 nt must be split into windows (e.g. 512 nt chunks)
127
+ and the per-window embeddings pooled.
128
+
129
+ ### MLM logits
130
+
131
+ ```python
132
+ import torch
133
+ from transformers import AutoTokenizer, AutoModelForMaskedLM
134
+
135
+ tokenizer = AutoTokenizer.from_pretrained("Taykhoom/structRFM", trust_remote_code=True)
136
+ model = AutoModelForMaskedLM.from_pretrained("Taykhoom/structRFM", trust_remote_code=True)
137
+ model.eval()
138
+
139
+ enc = tokenizer(["GUCCCAAC[MASK]CUUGCGG"], return_tensors="pt")
140
+ with torch.no_grad():
141
+ logits = model(**enc).logits # (1, seq_len, 10)
142
+ ```
143
+
144
+ ### Faster attention backends
145
+
146
+ ```python
147
+ # SDPA (PyTorch 2.0+) -- recommended for production
148
+ model = AutoModel.from_pretrained("Taykhoom/structRFM", trust_remote_code=True,
149
+ attn_implementation="sdpa")
150
+
151
+ # Flash Attention 2 (requires flash-attn) -- fastest on long sequences
152
+ model = AutoModel.from_pretrained("Taykhoom/structRFM", trust_remote_code=True,
153
+ attn_implementation="flash_attention_2",
154
+ dtype=torch.bfloat16)
155
+ ```
156
+
157
+ | Backend | Status |
158
+ |---|---|
159
+ | `eager` | Supported; bit-exact with upstream eager |
160
+ | `sdpa` | Supported; bit-exact with upstream (the upstream default backend) |
161
+ | `flash_attention_2` | Supported (added by this port); requires fp16/bf16 weights |
162
+
163
+ `output_attentions=True` falls back to eager under `sdpa` and
164
+ `flash_attention_2` and returns post-softmax attention probabilities
165
+ `(batch, heads, seq_len, seq_len)`.
166
+
167
+ ### Fine-tuning
168
+
169
+ Standard HF conventions. For sequence-level tasks, use the CLS embedding or a
170
+ masked mean over nucleotide positions as input to a prediction head; for
171
+ nucleotide- or pair-level tasks use `last_hidden_state` directly.
172
+ `gradient_checkpointing_enable()` is supported.
173
+
174
+ ## Implementation Notes
175
+
176
+ This port reuses the shared [BERT-updated](https://huggingface.co/Taykhoom/BERT-updated)
177
+ runtime (identical to the stock `transformers` BERT architecture), which adds
178
+ `flash_attention_2` alongside `eager` and `sdpa`. The MLM decoder is tied to the
179
+ input embeddings, as in the upstream checkpoint.
180
+
181
+ `config.pad_token_id` is 0 (`[UNK]`), the value in the upstream config, while
182
+ the tokenizer pads with `[PAD]`=3. The config value only sets the embedding's
183
+ `padding_idx` (no gradient into that row during fine-tuning) and is kept for
184
+ fidelity; padding is controlled by `attention_mask`.
185
+
186
+ The pooler (`pooler_output`) is not part of the pretrained checkpoint and is
187
+ randomly initialized; do not use it without fine-tuning.
188
+
189
+ ## Citation
190
+
191
+ ```bibtex
192
+ @article{zhu2026_structrfm,
193
+ title = {An open structure-guided {RNA} foundation model for generalizable prediction},
194
+ author = {Zhu, Heqin and Li, Ruifeng and Chang, Ao and Chen, Haobin and Zhang, Feng and Tang, Fenghe and Ye, Tong and Li, Xin and Gu, Yunjie and Xiong, Peng and Zhou, S. Kevin},
195
+ journal = {Nature},
196
+ year = {2026},
197
+ doi = {10.1038/s41586-026-11210-2}
198
+ }
199
+ ```
200
+
201
+ ## Credits
202
+
203
+ Original model and code by Zhu et al. Source:
204
+ [GitHub](https://github.com/heqin-zhu/structRFM),
205
+ [`heqin-zhu/structRFM` on the Hub](https://huggingface.co/heqin-zhu/structRFM).
206
+ Hugging Face port maintained by Taykhoom Dalal.
207
+
208
+ ## License
209
+
210
+ MIT, following the original repository.
config.json ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "BertForMaskedLM"
4
+ ],
5
+ "model_type": "bert_updated",
6
+ "auto_map": {
7
+ "AutoConfig": "configuration_bert_updated.BertUpdatedConfig",
8
+ "AutoModel": "modeling_bert.BertModel",
9
+ "AutoModelForMaskedLM": "modeling_bert.BertForMaskedLM"
10
+ },
11
+ "vocab_size": 10,
12
+ "hidden_size": 768,
13
+ "num_hidden_layers": 12,
14
+ "num_attention_heads": 12,
15
+ "intermediate_size": 3072,
16
+ "hidden_act": "gelu",
17
+ "hidden_dropout_prob": 0.1,
18
+ "attention_probs_dropout_prob": 0.1,
19
+ "max_position_embeddings": 514,
20
+ "type_vocab_size": 2,
21
+ "initializer_range": 0.02,
22
+ "layer_norm_eps": 1e-12,
23
+ "pad_token_id": 0,
24
+ "model_max_length": 514,
25
+ "transformers_version": "4.57.6",
26
+ "_name_or_path": "Taykhoom/structRFM"
27
+ }
configuration_bert_updated.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import PretrainedConfig
2
+
3
+
4
+ class BertUpdatedConfig(PretrainedConfig):
5
+ model_type = "bert_updated"
6
+
7
+ auto_map = {
8
+ "AutoConfig": "configuration_bert_updated.BertUpdatedConfig",
9
+ "AutoModel": "modeling_bert.BertModel",
10
+ "AutoModelForMaskedLM": "modeling_bert.BertForMaskedLM",
11
+ }
12
+
13
+ def __init__(
14
+ self,
15
+ vocab_size=30522,
16
+ hidden_size=768,
17
+ num_hidden_layers=12,
18
+ num_attention_heads=12,
19
+ intermediate_size=3072,
20
+ hidden_act="gelu",
21
+ mlm_hidden_act=None,
22
+ hidden_dropout_prob=0.1,
23
+ attention_probs_dropout_prob=0.1,
24
+ max_position_embeddings=512,
25
+ type_vocab_size=2,
26
+ initializer_range=0.02,
27
+ layer_norm_eps=1e-12,
28
+ **kwargs,
29
+ ):
30
+ super().__init__(**kwargs)
31
+ self.vocab_size = vocab_size
32
+ self.hidden_size = hidden_size
33
+ self.num_hidden_layers = num_hidden_layers
34
+ self.num_attention_heads = num_attention_heads
35
+ self.intermediate_size = intermediate_size
36
+ self.hidden_act = hidden_act
37
+ self.mlm_hidden_act = mlm_hidden_act
38
+ self.hidden_dropout_prob = hidden_dropout_prob
39
+ self.attention_probs_dropout_prob = attention_probs_dropout_prob
40
+ self.max_position_embeddings = max_position_embeddings
41
+ self.type_vocab_size = type_vocab_size
42
+ self.initializer_range = initializer_range
43
+ self.layer_norm_eps = layer_norm_eps
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8d8e8dcc064b1b584b8ba6ee756cbfbc7953002e8ce580dfcfe85dc27a216a36
3
+ size 344262720
modeling_bert.py ADDED
@@ -0,0 +1,547 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ from typing import Optional, Tuple, Union
3
+
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.nn.functional as F
7
+ import torch.utils.checkpoint
8
+ from transformers.activations import ACT2FN
9
+ from transformers import PreTrainedModel, PretrainedConfig
10
+ from transformers.modeling_outputs import BaseModelOutputWithPooling, MaskedLMOutput
11
+
12
+ from .configuration_bert_updated import BertUpdatedConfig
13
+
14
+
15
+ class BertSelfAttention(nn.Module):
16
+
17
+ def __init__(self, config):
18
+ super().__init__()
19
+ self.num_attention_heads = config.num_attention_heads
20
+ self.attention_head_size = config.hidden_size // config.num_attention_heads
21
+ self.all_head_size = self.num_attention_heads * self.attention_head_size
22
+
23
+ self.query = nn.Linear(config.hidden_size, self.all_head_size)
24
+ self.key = nn.Linear(config.hidden_size, self.all_head_size)
25
+ self.value = nn.Linear(config.hidden_size, self.all_head_size)
26
+ self.dropout = nn.Dropout(config.attention_probs_dropout_prob)
27
+
28
+ def _split_heads(self, x: torch.Tensor) -> torch.Tensor:
29
+ B, T, _ = x.shape
30
+ return x.view(B, T, self.num_attention_heads, self.attention_head_size).permute(0, 2, 1, 3)
31
+
32
+ def forward(
33
+ self,
34
+ hidden_states: torch.Tensor,
35
+ key_padding_mask: Optional[torch.Tensor] = None,
36
+ output_attentions: bool = False,
37
+ head_mask: Optional[torch.Tensor] = None,
38
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
39
+ q = self._split_heads(self.query(hidden_states))
40
+ k = self._split_heads(self.key(hidden_states))
41
+ v = self._split_heads(self.value(hidden_states))
42
+
43
+ scale = math.sqrt(self.attention_head_size)
44
+ scores = torch.matmul(q, k.transpose(-1, -2)) / scale
45
+ if key_padding_mask is not None:
46
+ scores = scores.masked_fill(key_padding_mask[:, None, None, :], float("-inf"))
47
+ probs = torch.nan_to_num(
48
+ F.softmax(scores.float(), dim=-1),
49
+ nan=0.0,
50
+ )
51
+ context_probs = self.dropout(probs)
52
+ if head_mask is not None:
53
+ context_probs = context_probs * head_mask
54
+ context = torch.matmul(context_probs.to(v.dtype), v)
55
+
56
+ B, _, T, _ = context.shape
57
+ context = context.permute(0, 2, 1, 3).contiguous().view(B, T, self.all_head_size)
58
+
59
+ if output_attentions:
60
+ return context, probs
61
+ return context, None
62
+
63
+
64
+ class BertSdpaSelfAttention(BertSelfAttention):
65
+
66
+ def forward(
67
+ self,
68
+ hidden_states: torch.Tensor,
69
+ key_padding_mask: Optional[torch.Tensor] = None,
70
+ output_attentions: bool = False,
71
+ head_mask: Optional[torch.Tensor] = None,
72
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
73
+ if output_attentions or head_mask is not None:
74
+ return super().forward(
75
+ hidden_states,
76
+ key_padding_mask,
77
+ output_attentions=output_attentions,
78
+ head_mask=head_mask,
79
+ )
80
+
81
+ B, T, _ = hidden_states.shape
82
+ q = self._split_heads(self.query(hidden_states))
83
+ k = self._split_heads(self.key(hidden_states))
84
+ v = self._split_heads(self.value(hidden_states))
85
+
86
+ attn_mask = None
87
+ if key_padding_mask is not None:
88
+ attn_mask = torch.zeros(B, 1, 1, T, dtype=q.dtype, device=q.device)
89
+ attn_mask = attn_mask.masked_fill(key_padding_mask[:, None, None, :], float("-inf"))
90
+
91
+ context = F.scaled_dot_product_attention(
92
+ q,
93
+ k,
94
+ v,
95
+ attn_mask=attn_mask,
96
+ dropout_p=self.dropout.p if self.training else 0.0,
97
+ )
98
+ context = context.permute(0, 2, 1, 3).contiguous().view(B, T, self.all_head_size)
99
+ return context, None
100
+
101
+
102
+ class BertFlashSelfAttention(BertSelfAttention):
103
+
104
+ def forward(
105
+ self,
106
+ hidden_states: torch.Tensor,
107
+ key_padding_mask: Optional[torch.Tensor] = None,
108
+ output_attentions: bool = False,
109
+ head_mask: Optional[torch.Tensor] = None,
110
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
111
+ if (
112
+ output_attentions
113
+ or head_mask is not None
114
+ or (
115
+ key_padding_mask is not None
116
+ and (~key_padding_mask).sum(dim=-1).eq(0).any()
117
+ )
118
+ ):
119
+ return super().forward(
120
+ hidden_states,
121
+ key_padding_mask,
122
+ output_attentions=output_attentions,
123
+ head_mask=head_mask,
124
+ )
125
+
126
+ try:
127
+ from flash_attn import flash_attn_func, flash_attn_varlen_func
128
+ from flash_attn.bert_padding import pad_input, unpad_input
129
+ except ImportError as e:
130
+ raise ImportError(
131
+ "flash_attn is required for attn_implementation='flash_attention_2'. "
132
+ "Install with: pip install flash-attn --no-build-isolation"
133
+ ) from e
134
+
135
+ B, T, _ = hidden_states.shape
136
+ q = self._split_heads(self.query(hidden_states)).permute(0, 2, 1, 3)
137
+ k = self._split_heads(self.key(hidden_states)).permute(0, 2, 1, 3)
138
+ v = self._split_heads(self.value(hidden_states)).permute(0, 2, 1, 3)
139
+
140
+ if q.dtype not in (torch.float16, torch.bfloat16):
141
+ raise ValueError(
142
+ "flash_attention_2 requires float16 or bfloat16 model weights. "
143
+ f"Received {q.dtype}."
144
+ )
145
+
146
+ if key_padding_mask is not None and key_padding_mask.any():
147
+ attend = ~key_padding_mask
148
+ q_u, indices, cu_seqlens, max_seqlen, _ = unpad_input(q, attend)
149
+ k_u, _, _, _, _ = unpad_input(k, attend)
150
+ v_u, _, _, _, _ = unpad_input(v, attend)
151
+ out_u = flash_attn_varlen_func(
152
+ q_u, k_u, v_u,
153
+ cu_seqlens_q=cu_seqlens, cu_seqlens_k=cu_seqlens,
154
+ max_seqlen_q=max_seqlen, max_seqlen_k=max_seqlen,
155
+ dropout_p=self.dropout.p if self.training else 0.0,
156
+ causal=False,
157
+ )
158
+ out = pad_input(out_u, indices, B, T)
159
+ else:
160
+ out = flash_attn_func(
161
+ q,
162
+ k,
163
+ v,
164
+ dropout_p=self.dropout.p if self.training else 0.0,
165
+ causal=False,
166
+ )
167
+
168
+ out = out.reshape(B, T, self.all_head_size)
169
+ return out, None
170
+
171
+
172
+ BERT_SELF_ATTENTION_CLASSES = {
173
+ "eager": BertSelfAttention,
174
+ "sdpa": BertSdpaSelfAttention,
175
+ "flash_attention_2": BertFlashSelfAttention,
176
+ }
177
+
178
+
179
+ class BertSelfOutput(nn.Module):
180
+ def __init__(self, config):
181
+ super().__init__()
182
+ self.dense = nn.Linear(config.hidden_size, config.hidden_size)
183
+ self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
184
+ self.dropout = nn.Dropout(config.hidden_dropout_prob)
185
+
186
+ def forward(self, hidden_states: torch.Tensor, input_tensor: torch.Tensor) -> torch.Tensor:
187
+ hidden_states = self.dropout(self.dense(hidden_states))
188
+ return self.LayerNorm(hidden_states + input_tensor)
189
+
190
+
191
+ class BertAttention(nn.Module):
192
+ def __init__(self, config):
193
+ super().__init__()
194
+ attn_cls = BERT_SELF_ATTENTION_CLASSES[getattr(config, "_attn_implementation", "eager")]
195
+ self.self = attn_cls(config)
196
+ self.output = BertSelfOutput(config)
197
+
198
+ def forward(
199
+ self,
200
+ hidden_states: torch.Tensor,
201
+ key_padding_mask: Optional[torch.Tensor],
202
+ output_attentions: bool = False,
203
+ head_mask: Optional[torch.Tensor] = None,
204
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
205
+ self_out, attn_weights = self.self(
206
+ hidden_states,
207
+ key_padding_mask,
208
+ output_attentions,
209
+ head_mask,
210
+ )
211
+ return self.output(self_out, hidden_states), attn_weights
212
+
213
+
214
+ class BertIntermediate(nn.Module):
215
+ def __init__(self, config):
216
+ super().__init__()
217
+ self.dense = nn.Linear(config.hidden_size, config.intermediate_size)
218
+ if config.hidden_act in (None, "identity", "linear"):
219
+ self.intermediate_act_fn = lambda value: value
220
+ elif isinstance(config.hidden_act, str):
221
+ self.intermediate_act_fn = ACT2FN[config.hidden_act]
222
+ else:
223
+ self.intermediate_act_fn = config.hidden_act
224
+
225
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
226
+ return self.intermediate_act_fn(self.dense(hidden_states))
227
+
228
+
229
+ class BertOutput(nn.Module):
230
+ def __init__(self, config):
231
+ super().__init__()
232
+ self.dense = nn.Linear(config.intermediate_size, config.hidden_size)
233
+ self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
234
+ self.dropout = nn.Dropout(config.hidden_dropout_prob)
235
+
236
+ def forward(self, hidden_states: torch.Tensor, input_tensor: torch.Tensor) -> torch.Tensor:
237
+ hidden_states = self.dropout(self.dense(hidden_states))
238
+ return self.LayerNorm(hidden_states + input_tensor)
239
+
240
+
241
+ class BertLayer(nn.Module):
242
+ def __init__(self, config):
243
+ super().__init__()
244
+ self.attention = BertAttention(config)
245
+ self.intermediate = BertIntermediate(config)
246
+ self.output = BertOutput(config)
247
+
248
+ def forward(
249
+ self,
250
+ hidden_states: torch.Tensor,
251
+ key_padding_mask: Optional[torch.Tensor],
252
+ output_attentions: bool = False,
253
+ head_mask: Optional[torch.Tensor] = None,
254
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
255
+ attn_out, attn_weights = self.attention(
256
+ hidden_states,
257
+ key_padding_mask,
258
+ output_attentions,
259
+ head_mask,
260
+ )
261
+ return self.output(self.intermediate(attn_out), attn_out), attn_weights
262
+
263
+
264
+ class BertEncoder(nn.Module):
265
+ def __init__(self, config):
266
+ super().__init__()
267
+ self.layer = nn.ModuleList([BertLayer(config) for _ in range(config.num_hidden_layers)])
268
+ self.gradient_checkpointing = False
269
+
270
+ def forward(
271
+ self,
272
+ hidden_states: torch.Tensor,
273
+ key_padding_mask: Optional[torch.Tensor],
274
+ output_hidden_states: bool = False,
275
+ output_attentions: bool = False,
276
+ head_mask: Optional[torch.Tensor] = None,
277
+ ) -> Tuple:
278
+ all_hidden_states = (hidden_states,) if output_hidden_states else None
279
+ all_attentions = () if output_attentions else None
280
+
281
+ for layer_index, layer in enumerate(self.layer):
282
+ layer_head_mask = (
283
+ head_mask[layer_index] if head_mask is not None else None
284
+ )
285
+ if self.gradient_checkpointing and self.training:
286
+ hidden_states, attn_weights = torch.utils.checkpoint.checkpoint(
287
+ layer.__call__,
288
+ hidden_states,
289
+ key_padding_mask,
290
+ output_attentions,
291
+ layer_head_mask,
292
+ use_reentrant=False,
293
+ )
294
+ else:
295
+ hidden_states, attn_weights = layer(
296
+ hidden_states,
297
+ key_padding_mask,
298
+ output_attentions,
299
+ layer_head_mask,
300
+ )
301
+ if output_hidden_states:
302
+ all_hidden_states = all_hidden_states + (hidden_states,)
303
+ if output_attentions:
304
+ all_attentions = all_attentions + (attn_weights,)
305
+
306
+ return hidden_states, all_hidden_states, all_attentions
307
+
308
+
309
+ class BertEmbeddings(nn.Module):
310
+ def __init__(self, config):
311
+ super().__init__()
312
+ self.word_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id)
313
+ self.position_embeddings = nn.Embedding(config.max_position_embeddings, config.hidden_size)
314
+ self.token_type_embeddings = nn.Embedding(config.type_vocab_size, config.hidden_size)
315
+ self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
316
+ self.dropout = nn.Dropout(config.hidden_dropout_prob)
317
+ self.register_buffer("position_ids", torch.arange(config.max_position_embeddings).expand((1, -1)), persistent=False)
318
+
319
+ def forward(
320
+ self,
321
+ input_ids: Optional[torch.LongTensor] = None,
322
+ token_type_ids: Optional[torch.LongTensor] = None,
323
+ position_ids: Optional[torch.LongTensor] = None,
324
+ inputs_embeds: Optional[torch.FloatTensor] = None,
325
+ ) -> torch.Tensor:
326
+ if (input_ids is None) == (inputs_embeds is None):
327
+ raise ValueError("Specify exactly one of input_ids or inputs_embeds.")
328
+ B, T = (
329
+ input_ids.shape
330
+ if input_ids is not None
331
+ else inputs_embeds.shape[:2]
332
+ )
333
+ if token_type_ids is None:
334
+ token_type_ids = torch.zeros(
335
+ (B, T),
336
+ dtype=torch.long,
337
+ device=(
338
+ input_ids.device
339
+ if input_ids is not None
340
+ else inputs_embeds.device
341
+ ),
342
+ )
343
+ if position_ids is None:
344
+ position_ids = self.position_ids[:, :T]
345
+ x = (
346
+ self.word_embeddings(input_ids)
347
+ if inputs_embeds is None
348
+ else inputs_embeds
349
+ )
350
+ x = x + self.token_type_embeddings(token_type_ids)
351
+ x = x + self.position_embeddings(position_ids)
352
+ return self.dropout(self.LayerNorm(x))
353
+
354
+
355
+ class BertPooler(nn.Module):
356
+ def __init__(self, config):
357
+ super().__init__()
358
+ self.dense = nn.Linear(config.hidden_size, config.hidden_size)
359
+ self.activation = nn.Tanh()
360
+
361
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
362
+ return self.activation(self.dense(hidden_states[:, 0]))
363
+
364
+
365
+ class BertPredictionHeadTransform(nn.Module):
366
+ def __init__(self, config):
367
+ super().__init__()
368
+ self.dense = nn.Linear(config.hidden_size, config.hidden_size)
369
+ self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
370
+ hidden_act = (
371
+ config.mlm_hidden_act
372
+ if getattr(config, "mlm_hidden_act", None) is not None
373
+ else config.hidden_act
374
+ )
375
+ if hidden_act in (None, "identity", "linear"):
376
+ self.transform_act_fn = lambda value: value
377
+ elif isinstance(hidden_act, str):
378
+ self.transform_act_fn = ACT2FN[hidden_act]
379
+ else:
380
+ self.transform_act_fn = hidden_act
381
+
382
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
383
+ return self.LayerNorm(self.transform_act_fn(self.dense(hidden_states)))
384
+
385
+
386
+ class BertModel(PreTrainedModel):
387
+ config_class = BertUpdatedConfig
388
+ base_model_prefix = "bert"
389
+ _supports_sdpa = True
390
+ _supports_flash_attn_2 = True
391
+ supports_gradient_checkpointing = True
392
+ _keys_to_ignore_on_load_missing = [r"pooler\."]
393
+
394
+ def __init__(self, config, add_pooling_layer=True):
395
+ super().__init__(config)
396
+ self.embeddings = BertEmbeddings(config)
397
+ self.encoder = BertEncoder(config)
398
+ self.pooler = BertPooler(config) if add_pooling_layer else None
399
+ self.post_init()
400
+
401
+ def get_input_embeddings(self):
402
+ return self.embeddings.word_embeddings
403
+
404
+ def set_input_embeddings(self, value):
405
+ self.embeddings.word_embeddings = value
406
+
407
+ def forward(
408
+ self,
409
+ input_ids: Optional[torch.LongTensor] = None,
410
+ attention_mask: Optional[torch.Tensor] = None,
411
+ token_type_ids: Optional[torch.LongTensor] = None,
412
+ position_ids: Optional[torch.LongTensor] = None,
413
+ head_mask: Optional[torch.Tensor] = None,
414
+ inputs_embeds: Optional[torch.FloatTensor] = None,
415
+ output_hidden_states: Optional[bool] = None,
416
+ output_attentions: Optional[bool] = None,
417
+ return_dict: Optional[bool] = None,
418
+ ) -> Union[Tuple, BaseModelOutputWithPooling]:
419
+ output_hidden_states = output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
420
+ output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
421
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
422
+
423
+ if (input_ids is None) == (inputs_embeds is None):
424
+ raise ValueError("Specify exactly one of input_ids or inputs_embeds.")
425
+ input_shape = (
426
+ input_ids.shape
427
+ if input_ids is not None
428
+ else inputs_embeds.shape[:2]
429
+ )
430
+ input_device = (
431
+ input_ids.device
432
+ if input_ids is not None
433
+ else inputs_embeds.device
434
+ )
435
+ if attention_mask is None:
436
+ attention_mask = torch.ones(input_shape, device=input_device)
437
+ key_padding_mask = attention_mask.eq(0)
438
+ if not key_padding_mask.any():
439
+ key_padding_mask = None
440
+ head_mask = self.get_head_mask(
441
+ head_mask,
442
+ self.config.num_hidden_layers,
443
+ )
444
+ if all(mask is None for mask in head_mask):
445
+ head_mask = None
446
+
447
+ x = self.embeddings(
448
+ input_ids=input_ids,
449
+ token_type_ids=token_type_ids,
450
+ position_ids=position_ids,
451
+ inputs_embeds=inputs_embeds,
452
+ )
453
+ last_hidden_state, all_hidden_states, all_attentions = self.encoder(
454
+ x, key_padding_mask,
455
+ output_hidden_states=output_hidden_states,
456
+ output_attentions=output_attentions,
457
+ head_mask=head_mask,
458
+ )
459
+ pooled = self.pooler(last_hidden_state) if self.pooler is not None else None
460
+
461
+ if not return_dict:
462
+ output = (last_hidden_state, pooled)
463
+ if output_hidden_states:
464
+ output += (all_hidden_states,)
465
+ if output_attentions:
466
+ output += (all_attentions,)
467
+ return output
468
+
469
+ return BaseModelOutputWithPooling(
470
+ last_hidden_state=last_hidden_state,
471
+ pooler_output=pooled,
472
+ hidden_states=all_hidden_states,
473
+ attentions=all_attentions,
474
+ )
475
+
476
+
477
+ class BertForMaskedLM(PreTrainedModel):
478
+ config_class = BertUpdatedConfig
479
+ base_model_prefix = "bert"
480
+ _supports_sdpa = True
481
+ _supports_flash_attn_2 = True
482
+ supports_gradient_checkpointing = True
483
+ _keys_to_ignore_on_load_unexpected = [r"bert\.pooler\."]
484
+
485
+ def __init__(self, config):
486
+ super().__init__(config)
487
+ self.bert = BertModel(config, add_pooling_layer=False)
488
+ self.transform = BertPredictionHeadTransform(config)
489
+ self.cls = nn.Linear(config.hidden_size, config.vocab_size)
490
+ self.post_init()
491
+
492
+ def get_input_embeddings(self):
493
+ return self.bert.embeddings.word_embeddings
494
+
495
+ def set_input_embeddings(self, value):
496
+ self.bert.embeddings.word_embeddings = value
497
+
498
+ def get_output_embeddings(self):
499
+ return self.cls
500
+
501
+ def set_output_embeddings(self, value):
502
+ self.cls = value
503
+
504
+ def forward(
505
+ self,
506
+ input_ids: Optional[torch.LongTensor] = None,
507
+ attention_mask: Optional[torch.Tensor] = None,
508
+ token_type_ids: Optional[torch.LongTensor] = None,
509
+ position_ids: Optional[torch.LongTensor] = None,
510
+ head_mask: Optional[torch.Tensor] = None,
511
+ inputs_embeds: Optional[torch.FloatTensor] = None,
512
+ labels: Optional[torch.LongTensor] = None,
513
+ output_hidden_states: Optional[bool] = None,
514
+ output_attentions: Optional[bool] = None,
515
+ return_dict: Optional[bool] = None,
516
+ ) -> Union[Tuple, MaskedLMOutput]:
517
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
518
+
519
+ outputs = self.bert(
520
+ input_ids=input_ids,
521
+ attention_mask=attention_mask,
522
+ token_type_ids=token_type_ids,
523
+ position_ids=position_ids,
524
+ head_mask=head_mask,
525
+ inputs_embeds=inputs_embeds,
526
+ output_hidden_states=output_hidden_states,
527
+ output_attentions=output_attentions,
528
+ return_dict=True,
529
+ )
530
+ logits = self.cls(self.transform(outputs.last_hidden_state))
531
+
532
+ loss = None
533
+ if labels is not None:
534
+ loss = F.cross_entropy(logits.view(-1, self.config.vocab_size), labels.view(-1), ignore_index=-100)
535
+
536
+ if not return_dict:
537
+ output = (logits,)
538
+ if output_hidden_states:
539
+ output += (outputs.hidden_states,)
540
+ if output_attentions:
541
+ output += (outputs.attentions,)
542
+ return (loss,) + output if loss is not None else output
543
+
544
+ return MaskedLMOutput(
545
+ loss=loss, logits=logits,
546
+ hidden_states=outputs.hidden_states, attentions=outputs.attentions,
547
+ )
special_tokens_map.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "cls_token": "[CLS]",
3
+ "sep_token": "[SEP]",
4
+ "pad_token": "[PAD]",
5
+ "mask_token": "[MASK]",
6
+ "unk_token": "[UNK]"
7
+ }
tokenization_structrfm.py ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+
4
+ from transformers import PreTrainedTokenizer
5
+
6
+ _DEFAULT_VOCAB = {
7
+ "[UNK]": 0,
8
+ "[CLS]": 1,
9
+ "[SEP]": 2,
10
+ "[PAD]": 3,
11
+ "[MASK]": 4,
12
+ "A": 5,
13
+ "U": 6,
14
+ "C": 7,
15
+ "G": 8,
16
+ "N": 9,
17
+ }
18
+
19
+
20
+ class StructRFMTokenizer(PreTrainedTokenizer):
21
+ """Single-nucleotide tokenizer for structRFM.
22
+
23
+ Matches the upstream preprocessing (`seq.upper().replace("T", "U")`,
24
+ then one token per character) and adds [CLS] ... [SEP] when
25
+ `add_special_tokens=True`. Characters outside the vocabulary
26
+ (including whitespace) map to [UNK], as in the upstream tokenizer.
27
+ """
28
+
29
+ vocab_files_names = {"vocab_file": "vocab.json"}
30
+ model_input_names = ["input_ids", "attention_mask"]
31
+
32
+ def __init__(
33
+ self,
34
+ vocab_file=None,
35
+ cls_token="[CLS]",
36
+ sep_token="[SEP]",
37
+ pad_token="[PAD]",
38
+ mask_token="[MASK]",
39
+ unk_token="[UNK]",
40
+ **kwargs,
41
+ ):
42
+ self._vocab = dict(_DEFAULT_VOCAB)
43
+ if vocab_file and os.path.isfile(vocab_file):
44
+ with open(vocab_file) as f:
45
+ self._vocab = json.load(f)
46
+ self._ids_to_tokens = {v: k for k, v in self._vocab.items()}
47
+ super().__init__(
48
+ cls_token=cls_token,
49
+ sep_token=sep_token,
50
+ pad_token=pad_token,
51
+ mask_token=mask_token,
52
+ unk_token=unk_token,
53
+ **kwargs,
54
+ )
55
+
56
+ @property
57
+ def vocab_size(self):
58
+ return len(self._vocab)
59
+
60
+ def get_vocab(self):
61
+ return dict(self._vocab)
62
+
63
+ def _tokenize(self, text):
64
+ return list(text.upper().replace("T", "U"))
65
+
66
+ def _convert_token_to_id(self, token):
67
+ return self._vocab.get(token, self._vocab["[UNK]"])
68
+
69
+ def _convert_id_to_token(self, index):
70
+ return self._ids_to_tokens.get(index, "[UNK]")
71
+
72
+ def convert_tokens_to_string(self, tokens):
73
+ return "".join(tokens)
74
+
75
+ def save_vocabulary(self, save_directory, filename_prefix=None):
76
+ os.makedirs(save_directory, exist_ok=True)
77
+ fname = (filename_prefix + "-" if filename_prefix else "") + "vocab.json"
78
+ path = os.path.join(save_directory, fname)
79
+ with open(path, "w") as f:
80
+ json.dump(self._vocab, f, indent=2)
81
+ return (path,)
82
+
83
+ def build_inputs_with_special_tokens(self, token_ids_0, token_ids_1=None):
84
+ cls = [self.cls_token_id]
85
+ sep = [self.sep_token_id]
86
+ if token_ids_1 is None:
87
+ return cls + token_ids_0 + sep
88
+ return cls + token_ids_0 + sep + token_ids_1 + sep
89
+
90
+ def get_special_tokens_mask(self, token_ids_0, token_ids_1=None,
91
+ already_has_special_tokens=False):
92
+ if already_has_special_tokens:
93
+ return super().get_special_tokens_mask(
94
+ token_ids_0, token_ids_1, already_has_special_tokens=True
95
+ )
96
+ mask = [1] + [0] * len(token_ids_0) + [1]
97
+ if token_ids_1 is not None:
98
+ mask += [0] * len(token_ids_1) + [1]
99
+ return mask
100
+
101
+ def create_token_type_ids_from_sequences(self, token_ids_0, token_ids_1=None):
102
+ if token_ids_1 is None:
103
+ return [0] * (len(token_ids_0) + 2)
104
+ return [0] * (len(token_ids_0) + 2) + [1] * (len(token_ids_1) + 1)
tokenizer_config.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "auto_map": {
3
+ "AutoTokenizer": [
4
+ "tokenization_structrfm.StructRFMTokenizer",
5
+ null
6
+ ]
7
+ },
8
+ "tokenizer_class": "StructRFMTokenizer",
9
+ "model_max_length": 514,
10
+ "padding_side": "right",
11
+ "truncation_side": "right",
12
+ "cls_token": "[CLS]",
13
+ "sep_token": "[SEP]",
14
+ "pad_token": "[PAD]",
15
+ "mask_token": "[MASK]",
16
+ "unk_token": "[UNK]"
17
+ }
vocab.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "[UNK]": 0,
3
+ "[CLS]": 1,
4
+ "[SEP]": 2,
5
+ "[PAD]": 3,
6
+ "[MASK]": 4,
7
+ "A": 5,
8
+ "U": 6,
9
+ "C": 7,
10
+ "G": 8,
11
+ "N": 9
12
+ }