Safetensors
bert
Generated from Trainer
apapagi commited on
Commit
ff902da
ยท
1 Parent(s): 4f7dce5

june 2026 update

Browse files
README.md CHANGED
@@ -91,18 +91,19 @@ EUBERT is a pretrained BERT model that leverages a substantial corpus of documen
91
 
92
  ## Training procedure
93
 
94
- Dedicated Word Piece tokenizer vocabulary size 2**16,
95
 
96
  ### Training hyperparameters
97
 
98
  The following hyperparameters were used during training:
99
- - learning_rate: 5e-05
100
- - train_batch_size: 32
101
- - eval_batch_size: 32
 
 
 
102
  - seed: 42
103
- - optimizer: Adam with betas=(0.9,0.999) and epsilon=1e-08
104
- - lr_scheduler_type: linear
105
- - num_epochs: 1.85
106
 
107
  ### Framework versions
108
 
 
91
 
92
  ## Training procedure
93
 
94
+ Trained using the EuroVoc dataset.
95
 
96
  ### Training hyperparameters
97
 
98
  The following hyperparameters were used during training:
99
+ - learning_rate: 2e-4
100
+ - train_batch_size: 8
101
+ - eval_batch_size: 8
102
+ - warmup_steps: 200
103
+ - lora_alpha: 16
104
+ - lora_dropout: 0.1
105
  - seed: 42
106
+ - num_epochs: 1
 
 
107
 
108
  ### Framework versions
109
 
adapter_config.json ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "alora_invocation_tokens": null,
3
+ "alpha_pattern": {},
4
+ "arrow_config": null,
5
+ "auto_mapping": null,
6
+ "base_model_name_or_path": "nlpaueb/legal-bert-base-uncased",
7
+ "bias": "none",
8
+ "corda_config": null,
9
+ "ensure_weight_tying": false,
10
+ "eva_config": null,
11
+ "exclude_modules": null,
12
+ "fan_in_fan_out": false,
13
+ "inference_mode": true,
14
+ "init_lora_weights": true,
15
+ "layer_replication": null,
16
+ "layers_pattern": null,
17
+ "layers_to_transform": null,
18
+ "loftq_config": {},
19
+ "lora_alpha": 16,
20
+ "lora_bias": false,
21
+ "lora_dropout": 0.1,
22
+ "lora_ga_config": null,
23
+ "megatron_config": null,
24
+ "megatron_core": "megatron.core",
25
+ "modules_to_save": null,
26
+ "peft_type": "LORA",
27
+ "peft_version": "0.19.1",
28
+ "qalora_group_size": 16,
29
+ "r": 8,
30
+ "rank_pattern": {},
31
+ "revision": null,
32
+ "target_modules": [
33
+ "query",
34
+ "value"
35
+ ],
36
+ "target_parameters": null,
37
+ "task_type": "FEATURE_EXTRACTION",
38
+ "trainable_token_indices": null,
39
+ "use_bdlora": null,
40
+ "use_dora": false,
41
+ "use_qalora": false,
42
+ "use_rslora": false
43
+ }
adapter_model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b5bc8eb3b718153088f03cc5fd984198f8f0c143b9936ea6bee3efadf5e5d65b
3
+ size 1186328
inference.py CHANGED
@@ -1,21 +1,47 @@
1
- from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
 
2
 
3
- # Path of fine-tuned model
4
- model_path = "./fine_tuned_model"
 
 
5
 
6
- # Load tokenizer and model
7
- tokenizer = AutoTokenizer.from_pretrained(model_path)
8
- model = AutoModelForCausalLM.from_pretrained(model_path)
9
 
10
- # Create chatbot pipeline
11
- chatbot = pipeline(
12
- "text-generation",
13
- model=model,
14
- tokenizer=tokenizer,
15
- device=0 if torch.cuda.is_available() else -1 # Use GPU if available
16
- )
17
 
18
- # Example usage
19
- prompt = "Hello, can you tell me some fun facts about european legislation?"
20
- response = chatbot(prompt, max_length=100, do_sample=True, temperature=0.7)
21
- print(response[0]['generated_text'])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """EuroBERT Inference - Predict Masked Tokens"""
3
 
4
+ import torch
5
+ import argparse
6
+ from transformers import AutoTokenizer, AutoModelForMaskedLM, pipeline
7
+ from peft import PeftModel
8
 
9
+ BASE_MODEL = "nlpaueb/legal-bert-base-uncased"
10
+ ADAPTER_PATH = "./model"
 
11
 
 
 
 
 
 
 
 
12
 
13
+ def main():
14
+ parser = argparse.ArgumentParser(description="EuroBERT - Predict Masked Tokens")
15
+ parser.add_argument("--text", type=str, default="The European [MASK] regulates digital platforms.",
16
+ help="Text with [MASK] tokens to predict")
17
+ parser.add_argument("--top-k", type=int, default=5, help="Number of top predictions")
18
+ parser.add_argument("--adapter-path", type=str, default=ADAPTER_PATH, help="Path to LoRA adapter")
19
+ parser.add_argument("--device", type=str, default="cuda" if torch.cuda.is_available() else "cpu")
20
+
21
+ args = parser.parse_args()
22
+
23
+ # Load model
24
+ print(f"๐Ÿ“ฆ Loading {BASE_MODEL}")
25
+ model = AutoModelForMaskedLM.from_pretrained(BASE_MODEL)
26
+ tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)
27
+
28
+ print(f"โšก Loading LoRA adapter from {args.adapter_path}")
29
+ model = PeftModel.from_pretrained(model, args.adapter_path)
30
+ model.to(args.device)
31
+ model.eval()
32
+
33
+ print(f"๐ŸŽฎ Device: {args.device}\n")
34
+
35
+ # Predict masked tokens
36
+ pipe = pipeline("fill-mask", model=model, tokenizer=tokenizer)
37
+ results = pipe(args.text, top_k=args.top_k)
38
+
39
+ print(f"๐Ÿ“ Input: {args.text}")
40
+ print(f"๐ŸŽฏ Top {args.top_k} predictions:")
41
+ for i, result in enumerate(results, 1):
42
+ print(f" {i}. '{result['token_str']}' (score: {result['score']:.4f})")
43
+ print(f" โ†’ {result['sequence']}")
44
+
45
+
46
+ if __name__ == "__main__":
47
+ main()
optimizer.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a3d02bfa992da6e69864499fd31dcb3d704675d16e55a0c5ad7c329ad3798f24
3
+ size 2401099
rng_state.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:16b08ab4ae85fee7596463136852d5f70af6c20c7d3271c15beaff64a55bfa82
3
+ size 14645
scaler.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d0ed87b5f1b332e484564368c4a705e3c051fee55e9e66e1633af48d12d24104
3
+ size 1383
scheduler.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:dd3190e85b69bf1e75bdbf9b2e683ac33113ee45837950be410af0b40d2c7f0b
3
+ size 1465
tokenizer.json CHANGED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json CHANGED
@@ -1,58 +1,15 @@
1
  {
2
- "add_prefix_space": false,
3
- "added_tokens_decoder": {
4
- "0": {
5
- "content": "<s>",
6
- "lstrip": false,
7
- "normalized": true,
8
- "rstrip": false,
9
- "single_word": false,
10
- "special": true
11
- },
12
- "1": {
13
- "content": "<pad>",
14
- "lstrip": false,
15
- "normalized": true,
16
- "rstrip": false,
17
- "single_word": false,
18
- "special": true
19
- },
20
- "2": {
21
- "content": "</s>",
22
- "lstrip": false,
23
- "normalized": true,
24
- "rstrip": false,
25
- "single_word": false,
26
- "special": true
27
- },
28
- "3": {
29
- "content": "<unk>",
30
- "lstrip": false,
31
- "normalized": true,
32
- "rstrip": false,
33
- "single_word": false,
34
- "special": true
35
- },
36
- "50264": {
37
- "content": "<mask>",
38
- "lstrip": true,
39
- "normalized": false,
40
- "rstrip": false,
41
- "single_word": false,
42
- "special": true
43
- }
44
- },
45
- "bos_token": "<s>",
46
- "clean_up_tokenization_spaces": false,
47
- "cls_token": "<s>",
48
- "eos_token": "</s>",
49
- "errors": "replace",
50
- "extra_special_tokens": {},
51
- "mask_token": "<mask>",
52
  "model_max_length": 512,
53
- "pad_token": "<pad>",
54
- "sep_token": "</s>",
55
- "tokenizer_class": "RobertaTokenizer",
56
- "trim_offsets": true,
57
- "unk_token": "<unk>"
 
58
  }
 
1
  {
2
+ "backend": "tokenizers",
3
+ "cls_token": "[CLS]",
4
+ "do_lower_case": true,
5
+ "is_local": false,
6
+ "local_files_only": false,
7
+ "mask_token": "[MASK]",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  "model_max_length": 512,
9
+ "pad_token": "[PAD]",
10
+ "sep_token": "[SEP]",
11
+ "strip_accents": null,
12
+ "tokenize_chinese_chars": true,
13
+ "tokenizer_class": "BertTokenizer",
14
+ "unk_token": "[UNK]"
15
  }
train.py CHANGED
@@ -1,85 +1,227 @@
1
- from datasets import load_dataset
2
- from transformers import DataCollatorForLanguageModeling
3
- from transformers import Trainer, TrainingArguments
 
 
 
 
 
 
4
  import os
 
 
5
  import torch
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
 
 
 
7
 
8
 
9
  def main():
10
-
11
- local_rank = int(os.environ['LOCAL_RANK'])
12
- rank = int(os.environ['RANK'])
13
- world_size = int(os.environ['WORLD_SIZE'])
14
-
15
- torch.distributed.init_process_group("nccl")
16
- print(f"Local Rank = {local_rank}/{world_size}")
17
-
18
-
19
-
20
- # Load your JSONL file
21
- dataset = load_dataset('json', data_files='../../data/m500_clean.jsonl', split='train')
22
-
23
- # Load a Model
24
- from transformers import AutoTokenizer, AutoModelForCausalLM
25
-
26
- model_name = "FacebookAI/roberta-base"
27
-
28
- tokenizer = AutoTokenizer.from_pretrained(model_name)
29
- model = AutoModelForCausalLM.from_pretrained(model_name)
30
-
31
- # Set pad token if not set
32
  if tokenizer.pad_token is None:
33
- tokenizer.pad_token = tokenizer.eos_token
34
-
35
- # Tokenize the dataset
36
- def tokenize_function(examples):
37
- return tokenizer(examples["text"], truncation=True, max_length=512)
38
-
39
- tokenized_dataset = dataset.map(tokenize_function, batched=True)
40
-
41
- # Split the dataset into training and validation sets
42
- split_dataset = tokenized_dataset.train_test_split(test_size=0.1)
43
-
44
- # Data collator, pad the inputs to the maximum length in the batch
45
  data_collator = DataCollatorForLanguageModeling(
46
- tokenizer=tokenizer, mlm=False # mlm=False: causal language modeling
 
 
47
  )
48
-
49
- # Training
 
 
 
 
 
 
 
 
 
 
50
  training_args = TrainingArguments(
51
- output_dir="./results",
52
- overwrite_output_dir=True,
53
- num_train_epochs=3,
54
- per_device_train_batch_size=4,
55
- per_device_eval_batch_size=4,
56
- dataloader_num_workers=8,
57
  eval_steps=500,
58
  save_steps=1000,
59
- warmup_steps=500,
60
- prediction_loss_only=True,
61
- logging_dir="./logs",
62
  logging_steps=100,
63
- learning_rate=5e-5,
64
- fp16=True, # true for GPU
 
 
 
 
 
 
65
  )
66
-
 
 
 
 
 
 
 
 
 
67
  trainer = Trainer(
68
  model=model,
69
  args=training_args,
70
- train_dataset=split_dataset["train"],
71
- eval_dataset=split_dataset["test"],
72
  data_collator=data_collator,
 
73
  )
74
-
75
- # Start training
 
76
  trainer.train()
77
 
78
- torch.distributed.destroy_process_group()
79
-
80
- # Save the model and tokenizer
81
- model.save_pretrained("./fine_tuned_model")
82
- tokenizer.save_pretrained("./fine_tuned_model")
 
83
 
84
  if __name__ == "__main__":
85
  main()
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ EuroBERT Fine-tuning Script with Improvements
4
+ - Multi-GPU support
5
+ - Early stopping (loss stabilization detection)
6
+ - Random data sampling (removed date sorting)
7
+ - Reduced epochs for efficiency
8
+ """
9
+
10
  import os
11
+ import argparse
12
+ from datetime import datetime
13
  import torch
14
+ from datasets import load_dataset
15
+ from transformers import (
16
+ AutoTokenizer,
17
+ AutoModelForMaskedLM,
18
+ DataCollatorForLanguageModeling,
19
+ TrainingArguments,
20
+ Trainer,
21
+ EarlyStoppingCallback,
22
+ )
23
+ from peft import LoraConfig, get_peft_model, TaskType
24
+
25
+
26
+ def parse_arguments():
27
+ parser = argparse.ArgumentParser(description="Train EuroBERT model with LoRA")
28
+ parser.add_argument(
29
+ "--gpu-ids",
30
+ type=str,
31
+ default="0,1,2",
32
+ help="GPU IDs to use (comma-separated). Default: all 3 RTX 3080s",
33
+ )
34
+ parser.add_argument(
35
+ "--batch-size",
36
+ type=int,
37
+ default=16,
38
+ help="Per-device batch size. With 3 GPUs and LoRA: 16 per GPU = 48 total",
39
+ )
40
+ parser.add_argument(
41
+ "--epochs",
42
+ type=int,
43
+ default=1,
44
+ help="Number of epochs (default: 1, reduced from 3 due to large dataset)",
45
+ )
46
+ parser.add_argument(
47
+ "--data-path",
48
+ type=str,
49
+ default="/home/apapagiannis/EuroVoc/files/*",
50
+ help="Path to training data",
51
+ )
52
+ parser.add_argument(
53
+ "--output-dir",
54
+ type=str,
55
+ default="./results",
56
+ help="Output directory for results",
57
+ )
58
+ parser.add_argument(
59
+ "--model-name",
60
+ type=str,
61
+ default="nlpaueb/legal-bert-base-uncased",
62
+ help="Base model to fine-tune",
63
+ )
64
+ return parser.parse_args()
65
+
66
+
67
+ def load_and_prepare_data(data_path, tokenizer, model_name):
68
+ """Load dataset and prepare for training."""
69
+ print("๐Ÿ“ฆ Loading dataset...")
70
+ dataset = load_dataset("json", data_files=data_path, split="train")
71
+ print(f"Total samples: {len(dataset):,}")
72
+
73
+ # Split into train/eval
74
+ print("Splitting data (90% train, 10% eval)...")
75
+ split_dataset = dataset.train_test_split(test_size=0.1, seed=42)
76
+ train_dataset = split_dataset["train"]
77
+ eval_dataset = split_dataset["test"]
78
+
79
+ print(f" Train: {len(train_dataset):,} samples")
80
+ print(f" Eval: {len(eval_dataset):,} samples")
81
+
82
+ # Tokenization function
83
+ def tokenize_function(batch):
84
+ texts = []
85
+ for t in batch.get("text", batch.get("content", [])):
86
+ texts.append(str(t) if t is not None else "")
87
+
88
+ return tokenizer(
89
+ texts,
90
+ truncation=True,
91
+ max_length=512,
92
+ padding="max_length",
93
+ )
94
+
95
+ print("Tokenizing datasets...")
96
+ tokenized_train = train_dataset.map(
97
+ tokenize_function,
98
+ batched=True,
99
+ remove_columns=train_dataset.column_names,
100
+ desc="Tokenizing train",
101
+ )
102
+ tokenized_eval = eval_dataset.map(
103
+ tokenize_function,
104
+ batched=True,
105
+ remove_columns=eval_dataset.column_names,
106
+ desc="Tokenizing eval",
107
+ )
108
+
109
+ return tokenized_train, tokenized_eval
110
+
111
+
112
+ def setup_model_with_lora(model_name):
113
+ """Load model and apply LoRA configuration."""
114
+ print(f"๐Ÿค– Loading model: {model_name}")
115
+ model = AutoModelForMaskedLM.from_pretrained(model_name)
116
+
117
+ print("โšก Setting up LoRA configuration...")
118
+ # IMPORTANT: For BERT MLM training, use FEATURE_EXTRACTION
119
+ # NOTE: If you switch to causal LM (GPT-style), change to TaskType.CAUSAL_LM
120
+ lora_config = LoraConfig(
121
+ task_type=TaskType.FEATURE_EXTRACTION, # MLM pre-training task
122
+ r=8,
123
+ lora_alpha=16,
124
+ lora_dropout=0.1,
125
+ target_modules=["query", "value"], # BERT attention layers
126
+ bias="none",
127
+ )
128
 
129
+ model = get_peft_model(model, lora_config)
130
+ model.print_trainable_parameters()
131
+ return model
132
 
133
 
134
  def main():
135
+ args = parse_arguments()
136
+
137
+ # Set GPU devices
138
+ os.environ["CUDA_VISIBLE_DEVICES"] = args.gpu_ids
139
+ num_gpus = len(args.gpu_ids.split(","))
140
+ print(f"๐ŸŽฎ Using {num_gpus} GPU(s): {args.gpu_ids}")
141
+ print(f"๐Ÿ“Š GPU Info:")
142
+ if torch.cuda.is_available():
143
+ for i in range(torch.cuda.device_count()):
144
+ print(f" GPU {i}: {torch.cuda.get_device_name(i)}")
145
+
146
+ # Load tokenizer
147
+ print(f"๐Ÿ“ Loading tokenizer from {args.model_name}")
148
+ tokenizer = AutoTokenizer.from_pretrained(args.model_name)
 
 
 
 
 
 
 
 
149
  if tokenizer.pad_token is None:
150
+ tokenizer.pad_token = tokenizer.cls_token
151
+
152
+ # Load and prepare data
153
+ tokenized_train, tokenized_eval = load_and_prepare_data(
154
+ args.data_path, tokenizer, args.model_name
155
+ )
156
+
157
+ # Setup model with LoRA
158
+ model = setup_model_with_lora(args.model_name)
159
+
160
+ # Data collator
 
161
  data_collator = DataCollatorForLanguageModeling(
162
+ tokenizer=tokenizer,
163
+ mlm=True,
164
+ mlm_probability=0.15,
165
  )
166
+
167
+ # Calculate steps for context
168
+ train_steps_per_epoch = len(tokenized_train) // (args.batch_size * num_gpus)
169
+ print(f"\n๐Ÿ“ˆ Training Configuration:")
170
+ print(f" Batch size (per GPU): {args.batch_size}")
171
+ print(f" Total batch size: {args.batch_size * num_gpus}")
172
+ print(f" Steps per epoch: {train_steps_per_epoch:,}")
173
+ print(f" Epochs: {args.epochs}")
174
+ print(f" Total steps: {train_steps_per_epoch * args.epochs:,}")
175
+ print(f" Early stopping: YES (monitor loss stability around 60k steps)")
176
+
177
+ # Training arguments with early stopping
178
  training_args = TrainingArguments(
179
+ output_dir=args.output_dir,
180
+ num_train_epochs=args.epochs,
181
+ per_device_train_batch_size=args.batch_size,
182
+ per_device_eval_batch_size=args.batch_size,
183
+ eval_strategy="steps",
 
184
  eval_steps=500,
185
  save_steps=1000,
 
 
 
186
  logging_steps=100,
187
+ learning_rate=2e-4,
188
+ warmup_steps=200,
189
+ fp16=True, # RTX 3080 supports FP16
190
+ report_to="none",
191
+ save_total_limit=3, # Keep only last 3 checkpoints
192
+ load_best_model_at_end=True,
193
+ metric_for_best_model="eval_loss",
194
+ greater_is_better=False,
195
  )
196
+
197
+ # Early stopping callback
198
+ # Monitors eval loss - stops if no improvement for 3 evaluations (~1500 steps)
199
+ early_stopping = EarlyStoppingCallback(
200
+ early_stopping_patience=3, # Stop if no improvement for 3 evals
201
+ early_stopping_threshold=0.001, # Minimum improvement threshold
202
+ )
203
+
204
+ # Create trainer
205
+ print("\n๐Ÿš€ Initializing trainer...")
206
  trainer = Trainer(
207
  model=model,
208
  args=training_args,
209
+ train_dataset=tokenized_train,
210
+ eval_dataset=tokenized_eval,
211
  data_collator=data_collator,
212
+ callbacks=[early_stopping],
213
  )
214
+
215
+ # Train
216
+ print("\n๐Ÿ”ฅ Starting training...\n")
217
  trainer.train()
218
 
219
+ # Save model
220
+ print("\n๐Ÿ’พ Saving fine-tuned model...")
221
+ model.save_pretrained(os.path.join(args.output_dir, "fine_tuned_model"))
222
+ tokenizer.save_pretrained(os.path.join(args.output_dir, "fine_tuned_model"))
223
+ print(f"โœ“ Model saved to {os.path.join(args.output_dir, 'fine_tuned_model')}")
224
+
225
 
226
  if __name__ == "__main__":
227
  main()
trainer_state.json ADDED
The diff for this file is too large to render. See raw diff
 
training_args.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:40a4825312a77639f789ba54a89fc281e36a6ca718b6259b972c5a5db048463b
3
+ size 5201