failed09 commited on
Commit
2b3226f
·
verified ·
1 Parent(s): af74cc1

Initial BashkirRoBERTa release

Browse files
README.md ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - ba
4
+ license: other
5
+ library_name: transformers
6
+ pipeline_tag: fill-mask
7
+ tags:
8
+ - bashkir
9
+ - masked-language-modeling
10
+ - roberta
11
+ - sentencepiece
12
+ - custom-code
13
+ ---
14
+
15
+ # BashkirRoBERTa
16
+
17
+ BashkirRoBERTa is a 50M-parameter masked language model for Bashkir.
18
+ It predicts a missing token from both sides of its context. The release includes
19
+ the original 16,384-piece SentencePiece BPE tokenizer and an exact Pre-LayerNorm
20
+ Transformer implementation.
21
+
22
+ It is intended for fill-mask experiments and further fine-tuning. It is not a
23
+ chat or text-generation model.
24
+
25
+ ## Quick start
26
+
27
+ ```python
28
+ from transformers import AutoModelForMaskedLM, AutoTokenizer
29
+
30
+ repo_id = "failed09/bashkir-roberta"
31
+ tokenizer = AutoTokenizer.from_pretrained(repo_id, trust_remote_code=True)
32
+ model = AutoModelForMaskedLM.from_pretrained(repo_id, trust_remote_code=True)
33
+
34
+ inputs = tokenizer("Мин башҡорт телен [MASK].", return_tensors="pt")
35
+ logits = model(**inputs).logits
36
+ mask_index = inputs["input_ids"][0].tolist().index(tokenizer.mask_token_id)
37
+ top_id = logits[0, mask_index].argmax().item()
38
+ print(tokenizer.decode([top_id])) # яратам
39
+ ```
40
+
41
+ `trust_remote_code=True` is required because this checkpoint uses a custom
42
+ Pre-LayerNorm architecture, not the post-LayerNorm implementation in the stock
43
+ `RobertaForMaskedLM` class.
44
+
45
+ ## Architecture
46
+
47
+ | Property | Value |
48
+ |---|---:|
49
+ | Transformer blocks | 8, Pre-LayerNorm |
50
+ | Hidden size / attention heads | 640 / 10 |
51
+ | Feed-forward size | 2,560 |
52
+ | Context window | 256 subword tokens |
53
+ | Vocabulary | SentencePiece BPE, 16,384 tokens |
54
+ | Parameters | 50.04M |
55
+ | MLM head | tied to input embeddings |
56
+
57
+ Special IDs are fixed: `<pad>` 0, `<unk>` 1, `<s>` 2, `</s>` 3, `[CLS]` 4,
58
+ `[SEP]` 5, and `[MASK]` 6.
59
+
60
+ ## Training and evaluation
61
+
62
+ The model was pretrained with dynamic masked-language modelling on a Bashkir
63
+ text collection assembled from encyclopedic, periodical, and literary sources.
64
+ The source texts are not distributed in this repository. Public Bashkir
65
+ Wikipedia is one component; the remaining source materials may carry separate
66
+ terms. This release contains only model weights, code, and tokenizer assets.
67
+
68
+ On a held-out Bashkir encyclopedic evaluation set, the project reports 24.7%
69
+ top-1 and 54.0% top-5 accuracy for masked subword prediction. These results are
70
+ diagnostic MLM measurements, not a general-purpose language understanding score.
71
+
72
+ ## Limitations
73
+
74
+ - A mask corresponds to one SentencePiece token, which may be a full word or a
75
+ subword fragment.
76
+ - The model can reflect errors, source bias, and rare memorized sequences from
77
+ its training material. Do not use it to reconstruct non-public source text.
78
+ - It has not been contrastively trained for semantic retrieval. Do not treat raw
79
+ MLM outputs as sentence embeddings.
80
+
81
+ ## License and provenance
82
+
83
+ The checkpoint is released under the repository's **custom terms** (`other` on
84
+ the Hub) while the source-rights audit is completed. No training texts are
85
+ redistributed. Please contact the maintainer through the Hub for provenance or
86
+ removal requests before commercial redistribution.
87
+
88
+ ## Reproducibility
89
+
90
+ The original checkpoint was converted to `model.safetensors` without
91
+ retraining. The included exporter verifies that the converted model produces
92
+ exactly the same logits as the original checkpoint for a fixed inference input.
config.json ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "transformers_version": "5.15.1",
3
+ "architectures": [
4
+ "BashkirRobertaForMaskedLM"
5
+ ],
6
+ "output_hidden_states": false,
7
+ "return_dict": true,
8
+ "dtype": "float32",
9
+ "chunk_size_feed_forward": 0,
10
+ "is_encoder_decoder": false,
11
+ "id2label": {
12
+ "0": "LABEL_0",
13
+ "1": "LABEL_1"
14
+ },
15
+ "label2id": {
16
+ "LABEL_0": 0,
17
+ "LABEL_1": 1
18
+ },
19
+ "problem_type": null,
20
+ "_name_or_path": "",
21
+ "pad_token_id": 0,
22
+ "bos_token_id": 2,
23
+ "eos_token_id": 3,
24
+ "cls_token_id": 4,
25
+ "sep_token_id": 5,
26
+ "mask_token_id": 6,
27
+ "tie_word_embeddings": true,
28
+ "vocab_size": 16384,
29
+ "hidden_size": 640,
30
+ "num_hidden_layers": 8,
31
+ "num_attention_heads": 10,
32
+ "intermediate_size": 2560,
33
+ "max_position_embeddings": 256,
34
+ "hidden_dropout_prob": 0.1,
35
+ "model_type": "bashkir-roberta-preln",
36
+ "output_attentions": false,
37
+ "auto_map": {
38
+ "AutoConfig": "configuration_bashkir_roberta.BashkirRobertaConfig",
39
+ "AutoModelForMaskedLM": "modeling_bashkir_roberta.BashkirRobertaForMaskedLM",
40
+ "AutoTokenizer": [
41
+ "tokenization_bashkir_roberta.BashkirRobertaTokenizer",
42
+ null
43
+ ]
44
+ }
45
+ }
configuration_bashkir_roberta.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Configuration for the BashkirRoBERTa Pre-LN masked-language model."""
2
+
3
+ from transformers import PretrainedConfig
4
+
5
+
6
+ class BashkirRobertaConfig(PretrainedConfig):
7
+ """Keeps the exact architecture of the project's flagship checkpoint.
8
+
9
+ Despite the familiar name, this is not Hugging Face's post-LayerNorm
10
+ ``RobertaConfig``: the encoder blocks here use pre-LayerNorm.
11
+ """
12
+
13
+ model_type = "bashkir-roberta-preln"
14
+
15
+ def __init__(
16
+ self,
17
+ vocab_size=16_384,
18
+ hidden_size=640,
19
+ num_hidden_layers=8,
20
+ num_attention_heads=10,
21
+ intermediate_size=2_560,
22
+ max_position_embeddings=256,
23
+ hidden_dropout_prob=0.1,
24
+ pad_token_id=0,
25
+ bos_token_id=2,
26
+ eos_token_id=3,
27
+ cls_token_id=4,
28
+ sep_token_id=5,
29
+ mask_token_id=6,
30
+ tie_word_embeddings=True,
31
+ **kwargs,
32
+ ):
33
+ super().__init__(
34
+ pad_token_id=pad_token_id,
35
+ bos_token_id=bos_token_id,
36
+ eos_token_id=eos_token_id,
37
+ cls_token_id=cls_token_id,
38
+ sep_token_id=sep_token_id,
39
+ mask_token_id=mask_token_id,
40
+ tie_word_embeddings=tie_word_embeddings,
41
+ **kwargs,
42
+ )
43
+ self.vocab_size = vocab_size
44
+ self.hidden_size = hidden_size
45
+ self.num_hidden_layers = num_hidden_layers
46
+ self.num_attention_heads = num_attention_heads
47
+ self.intermediate_size = intermediate_size
48
+ self.max_position_embeddings = max_position_embeddings
49
+ self.hidden_dropout_prob = hidden_dropout_prob
50
+
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:48e4d4e7b8af675d222e58e14776abac24b7e83a937d7884bd9d735ea9dd2173
3
+ size 200171016
modeling_bashkir_roberta.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Exact Hugging Face-compatible implementation of BashkirRoBERTa Pre-LN."""
2
+
3
+ import torch
4
+ from torch import nn
5
+ from transformers import PreTrainedModel
6
+ from transformers.modeling_outputs import MaskedLMOutput
7
+
8
+ from configuration_bashkir_roberta import BashkirRobertaConfig
9
+
10
+
11
+ class BashkirRobertaEmbeddings(nn.Module):
12
+ def __init__(self, config):
13
+ super().__init__()
14
+ self.word_embeddings = nn.Embedding(
15
+ config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id
16
+ )
17
+ self.position_embeddings = nn.Embedding(
18
+ config.max_position_embeddings, config.hidden_size
19
+ )
20
+ self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=1e-12)
21
+ self.dropout = nn.Dropout(config.hidden_dropout_prob)
22
+
23
+ def forward(self, input_ids):
24
+ sequence_length = input_ids.shape[1]
25
+ positions = torch.arange(
26
+ sequence_length, dtype=torch.long, device=input_ids.device
27
+ ).unsqueeze(0)
28
+ hidden_states = self.word_embeddings(input_ids) + self.position_embeddings(positions)
29
+ return self.dropout(self.LayerNorm(hidden_states))
30
+
31
+
32
+ class BashkirRobertaLayer(nn.Module):
33
+ """Pre-LayerNorm transformer block, matching ``train_flagship.py`` exactly."""
34
+
35
+ def __init__(self, config):
36
+ super().__init__()
37
+ self.self_attn = nn.MultiheadAttention(
38
+ config.hidden_size,
39
+ config.num_attention_heads,
40
+ dropout=config.hidden_dropout_prob,
41
+ batch_first=True,
42
+ )
43
+ self.norm1 = nn.LayerNorm(config.hidden_size, eps=1e-12)
44
+ self.ffn = nn.Sequential(
45
+ nn.Linear(config.hidden_size, config.intermediate_size),
46
+ nn.GELU(),
47
+ nn.Dropout(config.hidden_dropout_prob),
48
+ nn.Linear(config.intermediate_size, config.hidden_size),
49
+ nn.Dropout(config.hidden_dropout_prob),
50
+ )
51
+ self.norm2 = nn.LayerNorm(config.hidden_size, eps=1e-12)
52
+
53
+ def forward(self, hidden_states, padding_mask=None):
54
+ normalized = self.norm1(hidden_states)
55
+ attention, _ = self.self_attn(
56
+ normalized, normalized, normalized, key_padding_mask=padding_mask
57
+ )
58
+ hidden_states = hidden_states + attention
59
+ return hidden_states + self.ffn(self.norm2(hidden_states))
60
+
61
+
62
+ class BashkirRobertaForMaskedLM(PreTrainedModel):
63
+ config_class = BashkirRobertaConfig
64
+ base_model_prefix = "bashkir_roberta"
65
+ main_input_name = "input_ids"
66
+ _tied_weights_keys = {"lm_head.weight": "embeddings.word_embeddings.weight"}
67
+
68
+ def __init__(self, config):
69
+ super().__init__(config)
70
+ self.embeddings = BashkirRobertaEmbeddings(config)
71
+ self.layers = nn.ModuleList(
72
+ [BashkirRobertaLayer(config) for _ in range(config.num_hidden_layers)]
73
+ )
74
+ self.norm_final = nn.LayerNorm(config.hidden_size, eps=1e-12)
75
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
76
+ self.post_init()
77
+
78
+ def get_input_embeddings(self):
79
+ return self.embeddings.word_embeddings
80
+
81
+ def set_input_embeddings(self, value):
82
+ self.embeddings.word_embeddings = value
83
+
84
+ def get_output_embeddings(self):
85
+ return self.lm_head
86
+
87
+ def set_output_embeddings(self, new_embeddings):
88
+ self.lm_head = new_embeddings
89
+
90
+ def tie_weights(self, **kwargs):
91
+ if self.config.tie_word_embeddings:
92
+ self.lm_head.weight = self.embeddings.word_embeddings.weight
93
+
94
+ def forward(self, input_ids, attention_mask=None, labels=None, return_dict=True, **kwargs):
95
+ if input_ids.shape[1] > self.config.max_position_embeddings:
96
+ raise ValueError(
97
+ f"Sequence length {input_ids.shape[1]} exceeds "
98
+ f"max_position_embeddings={self.config.max_position_embeddings}."
99
+ )
100
+ padding_mask = input_ids.eq(self.config.pad_token_id) if attention_mask is None else attention_mask.eq(0)
101
+ hidden_states = self.embeddings(input_ids)
102
+ for layer in self.layers:
103
+ hidden_states = layer(hidden_states, padding_mask=padding_mask)
104
+ hidden_states = self.norm_final(hidden_states)
105
+ logits = self.lm_head(hidden_states)
106
+
107
+ loss = None
108
+ if labels is not None:
109
+ loss = nn.functional.cross_entropy(
110
+ logits.view(-1, self.config.vocab_size), labels.view(-1), ignore_index=-100
111
+ )
112
+ if not return_dict:
113
+ return (loss, logits) if loss is not None else (logits,)
114
+ return MaskedLMOutput(loss=loss, logits=logits)
spm_bashkir_bert_16k.model ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4e77b9cfc9ab8c200406ee46c2d20fc46734da9ddcf01dff0f0e370f6c4ac244
3
+ size 586970
tokenization_bashkir_roberta.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """SentencePiece tokenizer preserving BashkirRoBERTa's original token IDs."""
2
+
3
+ from pathlib import Path
4
+
5
+ import sentencepiece as spm
6
+ from transformers import PreTrainedTokenizer
7
+
8
+
9
+ class BashkirRobertaTokenizer(PreTrainedTokenizer):
10
+ vocab_files_names = {"vocab_file": "spm_bashkir_bert_16k.model"}
11
+ model_input_names = ["input_ids", "attention_mask"]
12
+
13
+ def __init__(self, vocab_file, **kwargs):
14
+ self.vocab_file = vocab_file
15
+ self.sp_model = spm.SentencePieceProcessor(model_file=vocab_file)
16
+ defaults = {
17
+ "bos_token": "<s>", "eos_token": "</s>", "unk_token": "<unk>",
18
+ "pad_token": "<pad>", "cls_token": "[CLS]", "sep_token": "[SEP]",
19
+ "mask_token": "[MASK]",
20
+ }
21
+ for key, value in defaults.items():
22
+ kwargs.setdefault(key, value)
23
+ super().__init__(**kwargs)
24
+
25
+ @property
26
+ def vocab_size(self):
27
+ return self.sp_model.get_piece_size()
28
+
29
+ def get_vocab(self):
30
+ return {self.sp_model.id_to_piece(i): i for i in range(self.vocab_size)}
31
+
32
+ def _tokenize(self, text):
33
+ return self.sp_model.encode(text, out_type=str)
34
+
35
+ def _convert_token_to_id(self, token):
36
+ return self.sp_model.piece_to_id(token)
37
+
38
+ def _convert_id_to_token(self, index):
39
+ return self.sp_model.id_to_piece(index)
40
+
41
+ def convert_tokens_to_string(self, tokens):
42
+ return self.sp_model.decode(tokens)
43
+
44
+ def build_inputs_with_special_tokens(self, token_ids_0, token_ids_1=None):
45
+ if token_ids_1 is not None:
46
+ return [self.bos_token_id] + token_ids_0 + [self.sep_token_id] + token_ids_1 + [self.eos_token_id]
47
+ return [self.bos_token_id] + token_ids_0 + [self.eos_token_id]
48
+
49
+ def get_special_tokens_mask(self, token_ids_0, token_ids_1=None, already_has_special_tokens=False):
50
+ if already_has_special_tokens:
51
+ return super().get_special_tokens_mask(token_ids_0, token_ids_1, True)
52
+ if token_ids_1 is None:
53
+ return [1] + [0] * len(token_ids_0) + [1]
54
+ return [1] + [0] * len(token_ids_0) + [1] + [0] * len(token_ids_1) + [1]
55
+
56
+ def save_vocabulary(self, save_directory, filename_prefix=None):
57
+ source = Path(self.vocab_file)
58
+ name = ((filename_prefix + "-") if filename_prefix else "") + self.vocab_files_names["vocab_file"]
59
+ target = Path(save_directory) / name
60
+ target.write_bytes(source.read_bytes())
61
+ return (str(target),)
tokenizer_config.json ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "added_tokens_decoder": {
3
+ "0": {
4
+ "content": "<pad>",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": true
10
+ },
11
+ "1": {
12
+ "content": "<unk>",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false,
17
+ "special": true
18
+ },
19
+ "2": {
20
+ "content": "<s>",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": true
26
+ },
27
+ "3": {
28
+ "content": "</s>",
29
+ "lstrip": false,
30
+ "normalized": false,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": true
34
+ },
35
+ "4": {
36
+ "content": "[CLS]",
37
+ "lstrip": false,
38
+ "normalized": false,
39
+ "rstrip": false,
40
+ "single_word": false,
41
+ "special": true
42
+ },
43
+ "5": {
44
+ "content": "[SEP]",
45
+ "lstrip": false,
46
+ "normalized": false,
47
+ "rstrip": false,
48
+ "single_word": false,
49
+ "special": true
50
+ },
51
+ "6": {
52
+ "content": "[MASK]",
53
+ "lstrip": false,
54
+ "normalized": false,
55
+ "rstrip": false,
56
+ "single_word": false,
57
+ "special": true
58
+ }
59
+ },
60
+ "backend": "custom",
61
+ "bos_token": "<s>",
62
+ "cls_token": "[CLS]",
63
+ "eos_token": "</s>",
64
+ "mask_token": "[MASK]",
65
+ "model_max_length": 1000000000000000019884624838656,
66
+ "pad_token": "<pad>",
67
+ "sep_token": "[SEP]",
68
+ "tokenizer_class": "BashkirRobertaTokenizer",
69
+ "unk_token": "<unk>",
70
+ "auto_map": {
71
+ "AutoTokenizer": [
72
+ "tokenization_bashkir_roberta.BashkirRobertaTokenizer",
73
+ null
74
+ ]
75
+ }
76
+ }