| import os |
| from sklearn.model_selection import train_test_split |
| import numpy as np |
| import matplotlib.pyplot as plt |
|
|
|
|
| import logging |
| import sys |
| import traceback |
| from datetime import datetime |
|
|
| from datasets import load_dataset |
|
|
| from sentence_transformers import SentenceTransformer, losses |
| from sentence_transformers.evaluation import EmbeddingSimilarityEvaluator,TripletEvaluator,SequentialEvaluator |
| from sentence_transformers.similarity_functions import SimilarityFunction |
| from sentence_transformers.trainer import SentenceTransformerTrainer |
| from sentence_transformers.training_args import SentenceTransformerTrainingArguments |
| import torch |
| from sentence_transformers.training_args import BatchSamplers |
| import pandas as pd |
| from arabert.preprocess import ArabertPreprocessor |
| from pathlib import Path |
|
|
| |
| logging.basicConfig( |
| format="%(asctime)s - %(message)s", |
| datefmt="%Y-%m-%d %H:%M:%S", |
| level=logging.INFO, |
| handlers=[ |
| logging.FileHandler("logs.txt") |
| ] |
| ) |
| class Tee: |
| def __init__(self, *files): |
| self.files = files |
| def write(self, obj): |
| for f in self.files: |
| f.write(obj) |
| f.flush() |
| def flush(self): |
| for f in self.files: |
| f.flush() |
| def isatty(self): |
| return False |
|
|
| log_file = open("logs.txt", "a") |
| sys.stdout = Tee(sys.stdout, log_file) |
|
|
| train_batch_size = 64 |
|
|
| model_name = "bert-base-arabertv02" |
| model_nickname = "arabert" |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M") |
| output_dir = f"output/{model_nickname}_{timestamp}" |
|
|
| device = "cuda" if torch.cuda.is_available() else "cpu" |
|
|
| model = SentenceTransformer(model_name, device=device) |
| print(f"Model is running on: {device}") |
|
|
| logging.info("Reading the training and eval dataset") |
| train_dataset = load_dataset("csv", data_files="train.csv") |
| eval_dataset = load_dataset("csv", data_files="val.csv") |
| test_dataset = load_dataset("csv", data_files="test.csv") |
| logging.info(train_dataset) |
| logging.info(eval_dataset) |
| logging.info(test_dataset) |
| |
| eval_subset = eval_dataset["train"].shuffle(seed=42).select(range(250000)) |
| |
| matryoshka_dims = [768, 512, 256, 128, 64] |
| inner_train_loss = losses.MultipleNegativesRankingLoss(model=model) |
| train_loss = losses.MatryoshkaLoss(model, inner_train_loss, matryoshka_dims=matryoshka_dims) |
|
|
| |
| evaluators = [] |
| for dim in matryoshka_dims: |
| evaluators.append( |
| TripletEvaluator( |
| anchors=eval_subset["anchor"], |
| positives=eval_subset["positive"], |
| negatives=eval_subset["negative"], |
| name=f"dev-{dim}", |
| truncate_dim=dim, |
| ) |
| ) |
| dev_evaluator = SequentialEvaluator(evaluators, main_score_function=lambda scores: scores[0]) |
| dev_evaluator(model) |
|
|
|
|
| args = SentenceTransformerTrainingArguments( |
| |
| output_dir=output_dir, |
| seed=42, |
|
|
| |
| num_train_epochs=2, |
| per_device_train_batch_size=train_batch_size, |
| per_device_eval_batch_size=train_batch_size, |
| gradient_accumulation_steps=2, |
| |
| |
| bf16=True, |
| fp16=False, |
| learning_rate=2e-5, |
| lr_scheduler_type="linear", |
| warmup_ratio=0.1, |
| weight_decay=0.01, |
|
|
| |
| batch_sampler=BatchSamplers.NO_DUPLICATES, |
| dataloader_num_workers=8, |
|
|
| |
| eval_strategy="steps", |
| eval_steps=6000, |
| save_strategy="steps", |
| save_steps=6000, |
| save_total_limit=2, |
|
|
| |
| report_to="tensorboard", |
| logging_steps=200, |
| logging_dir="arabvert02-matryoshka/runs", |
| ) |
|
|
|
|
| trainer = SentenceTransformerTrainer( |
| model=model, |
| args=args, |
| train_dataset=train_dataset, |
| eval_dataset=eval_dataset, |
| loss=train_loss, |
| evaluator=dev_evaluator, |
| ) |
| trainer.train() |
|
|
| |
| final_output_dir = f"{output_dir}/final" |
| model.save(final_output_dir) |
| print("model saved successfully") |
|
|
| |
| evaluators = [] |
| for dim in matryoshka_dims: |
| evaluators.append( |
| TripletEvaluator( |
| anchors=test_dataset["train"]["anchor"], |
| positives=test_dataset["train"]["positive"], |
| negatives=test_dataset["train"]["negative"], |
| name=f"test-{dim}", |
| truncate_dim=dim, |
| ) |
| ) |
| test_evaluator = SequentialEvaluator(evaluators) |
| test_evaluator(model) |
|
|
|
|