mirror of
https://github.com/luxfi/torus-ml.git
synced 2026-10-30 15:15:23 +00:00
The distribution called itself torus-ml while shipping a package directory named concrete, so the name a user installs and the name they import disagreed — and most of the tree already said torus.ml, which could not resolve against src/concrete. Moved src/concrete to src/torus and pointed the include at it. The dependency was Zama's concrete-python from their index. It is torus-fhe from ours, which is what luxfhe/torus already ships: that frontend declares torus-fhe and ships a torus/fhe module, so every 'from torus.fhe' in this tree was already naming our compiler and only the dependency lagged. Two distributions share one namespace, which is the shape the upstream this forked from used and the reason the split works: torus-fhe gives torus.fhe, torus-ml gives torus.ml. Swept every other spelling — identifiers, enum members, workflow variables, filenames, notebooks. LICENSE and NOTICE keep the upstream attribution a fork owes; the figures carry the old name in JPEG metadata a text sweep cannot reach.
113 KiB
113 KiB
In [1]:
import math
import os
import random
import shutil
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
import torch
import torch.nn.functional as F
from datasets import load_dataset
from peft import LoraConfig, get_peft_model
from torch.utils.data import DataLoader
from tqdm import tqdm
from transformers import AutoModelForCausalLM, AutoTokenizer, Trainer, TrainingArguments
from utils_lora import generate_and_print
from torus.ml.torch.lora import LoraTrainerIn [2]:
# Training mode: 'torch', '7bit', or '16bit'
MODE = "7bit"
# Number of steps between evaluations
EVAL_STEPS = 100
# Set to True to force CPU
FORCE_CPU = False
# File paths based on mode
mode_str = MODE
EVAL_RESPONSES_FILE = f"eval_generated_responses_{mode_str}.txt"
TRAIN_LOG_FILE = f"training_log_{mode_str}.txt"
SAVE_PATH = Path(f"deployment/llama_lora_finetuned_{mode_str}")
print(f"Mode: {MODE}, Eval Steps: {EVAL_STEPS}, Force CPU: {FORCE_CPU}")Mode: 7bit, Eval Steps: 100, Force CPU: False
In [3]:
def get_device():
if FORCE_CPU:
return "cpu"
if torch.cuda.is_available():
return "cuda"
if torch.backends.mps.is_available() and torch.backends.mps.is_built():
os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
return "mps"
return "cpu"
def set_seed(seed):
"""Set random seeds for reproducibility.
Args:
seed (int): The random seed to use
"""
random.seed(seed)
np.random.seed(seed)
torch.use_deterministic_algorithms(True, warn_only=True)
torch.manual_seed(seed)
if torch.cuda.is_available():
torch.cuda.manual_seed_all(seed)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
SEED = 0
DEVICE = get_device()
set_seed(SEED)
print(f"Using device: {DEVICE}")Using device: mps
In [4]:
model_name = "meta-llama/Llama-3.2-1B"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name).to(DEVICE)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
model.config.pad_token_id = model.config.eos_token_id
for p in model.parameters():
p.requires_grad = False
PROMPT = "When you multiply a number by 7, it becomes 98. What is that number?\n"
_ = generate_and_print(PROMPT, model, tokenizer, seed=SEED)Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: I have a problem with my math. I know that 7 is the answer, but I can't figure out what number it is. I am
In [5]:
peft_config = LoraConfig(
r=8,
lora_alpha=32,
lora_dropout=0.01,
bias="none",
task_type="CAUSAL_LM",
target_modules="all-linear",
)
peft_model = get_peft_model(model, peft_config)In [6]:
MAX_LENGTH = 64
raw_dataset = load_dataset("microsoft/orca-math-word-problems-200k", split="train")
def length_filter(example):
q_len = len(tokenizer(example["question"], add_special_tokens=False)["input_ids"])
a_len = len(tokenizer(example["answer"], add_special_tokens=False)["input_ids"])
return (q_len + a_len + 1) <= MAX_LENGTH
filtered_dataset = raw_dataset.filter(length_filter)
def get_lengths(example):
q_len = len(tokenizer(example["question"], add_special_tokens=False)["input_ids"])
a_len = len(tokenizer(example["answer"], add_special_tokens=False)["input_ids"])
total_len = q_len + a_len + 1
return {"q_len": q_len, "a_len": a_len, "total_len": total_len}
lengths = filtered_dataset.map(get_lengths)
q_lengths = [x["q_len"] for x in lengths]
a_lengths = [x["a_len"] for x in lengths]
total_lengths = [x["total_len"] for x in lengths]
print("\nLength Distribution Statistics:")
print(f"Original dataset size: {len(raw_dataset):,}")
print(f"Filtered dataset size: {len(filtered_dataset):,}")
print(f"Percentage kept: {100 * len(filtered_dataset)/len(raw_dataset):.1f}%\n")
print("Question lengths: ")
print(f" Min: {min(q_lengths)}, Max: {max(q_lengths)}")
print(f" Mean: {sum(q_lengths)/len(q_lengths):.1f}")
print(f" Median: {sorted(q_lengths)[len(q_lengths)//2]}")
print("\nAnswer lengths:")
print(f" Min: {min(a_lengths)}, Max: {max(a_lengths)}")
print(f" Mean: {sum(a_lengths)/len(a_lengths):.1f}")
print(f" Median: {sorted(a_lengths)[len(a_lengths)//2]}")
print("\nTotal lengths (including newline):")
print(f" Min: {min(total_lengths)}, Max: {max(total_lengths)}")
print(f" Mean: {sum(total_lengths)/len(total_lengths):.1f}")
print(f" Median: {sorted(total_lengths)[len(total_lengths)//2]}\n")
def process_example(example):
"""Tokenize a question-answer pair and prepare labels for training.
Args:
example (dict): Dictionary with 'question' and 'answer' strings
Returns:
dict: Processed tokens with masked labels for the question portion
"""
question = example["question"].strip()
answer = example["answer"].strip()
tokens = tokenizer(
question + "\n" + answer,
padding="max_length",
truncation=True,
max_length=MAX_LENGTH,
)
question_length = len(tokenizer(question, add_special_tokens=False)["input_ids"]) + 1
labels = tokens["input_ids"].copy()
for i in range(question_length):
if i < len(labels):
labels[i] = -100
tokens["labels"] = labels
return tokens
tokenized_dataset = filtered_dataset.map(
process_example,
batched=False,
remove_columns=filtered_dataset.column_names,
)
tokenized = tokenized_dataset.train_test_split(test_size=0.05, seed=SEED, shuffle=True)
train_dataset, test_dataset = tokenized["train"], tokenized["test"]
print(f"Train samples: {len(train_dataset)}, Test samples: {len(test_dataset)}")huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks... To disable this warning, you can either: - Avoid using `tokenizers` before the fork if possible - Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)
Length Distribution Statistics: Original dataset size: 200,035 Filtered dataset size: 1,557 Percentage kept: 0.8% Question lengths: Min: 4, Max: 61 Mean: 24.7 Median: 25 Answer lengths: Min: 1, Max: 55 Mean: 23.5 Median: 23 Total lengths (including newline): Min: 6, Max: 64 Mean: 49.2 Median: 51 Train samples: 1479, Test samples: 78
In [7]:
class DataCollator:
def __init__(self, tokenizer):
self.pad_id = tokenizer.pad_token_id
def __call__(self, examples):
inputs, attention_masks, labels = [], [], []
max_length = max(len(example["input_ids"]) for example in examples)
for example in examples:
inputs.append(example["input_ids"])
attention_masks.append(example["attention_mask"])
labels.append(example["labels"])
def pad(sequences, value):
return [x + [value] * (max_length - len(x)) for x in sequences]
return {
"input_ids": torch.tensor(pad(inputs, self.pad_id)),
"attention_mask": torch.tensor(pad(attention_masks, 0)),
"labels": torch.tensor(pad(labels, -100)),
}
collator = DataCollator(tokenizer)In [8]:
training_args = TrainingArguments(
output_dir="./checkpoints",
num_train_epochs=1,
per_device_train_batch_size=1,
gradient_accumulation_steps=1,
save_total_limit=1,
use_cpu=True,
learning_rate=2e-4,
lr_scheduler_type="linear",
seed=SEED,
data_seed=SEED,
warmup_steps=10,
weight_decay=0.01,
prediction_loss_only=True,
report_to="none",
)In [9]:
def causal_lm_loss(logits, labels):
shift_logits = logits[..., :-1, :].contiguous()
shift_labels = labels[..., 1:].contiguous()
return F.cross_entropy(
shift_logits.view(-1, shift_logits.size(-1)),
shift_labels.view(-1),
ignore_index=-100,
reduction="mean",
)
def metric_fn(model, dataloader):
model.eval()
model.to(DEVICE)
total_loss, total_tokens, results = 0.0, 0, []
response = generate_and_print(PROMPT, model, tokenizer, seed=SEED)
if response:
results.append({"prompt": PROMPT, "response": response})
for batch in tqdm(dataloader, desc="Evaluating", leave=False):
with torch.no_grad():
input_ids = batch["input_ids"].to(DEVICE)
batch_labels = batch["labels"].to(DEVICE)
attention_mask = batch["attention_mask"].to(DEVICE)
outputs = model(input_ids, attention_mask=attention_mask).logits
valid = batch_labels[..., 1:] != -100
loss = F.cross_entropy(
outputs[..., :-1, :].contiguous().view(-1, outputs.size(-1)),
batch_labels[..., 1:].contiguous().view(-1),
ignore_index=-100,
reduction="sum",
)
total_loss += loss.item()
total_tokens += valid.sum().item()
perplexity = math.exp(total_loss / total_tokens) if total_tokens > 0 else float("inf")
with open(EVAL_RESPONSES_FILE, "a", encoding="utf-8") as f:
f.write(f"Perplexity: {perplexity:.2f}\n")
for i, r in enumerate(results):
f.write(
f"== Generation {i+1} ==\nPrompt:\n{r['prompt']}\n\nResponse:\n{r['response']}\n"
)
f.write("=" * 40 + "\n")
return {"perplexity": perplexity}In [10]:
hf_trainer = Trainer(
model=peft_model,
args=training_args,
train_dataset=train_dataset,
data_collator=collator,
)
train_dl = hf_trainer.get_train_dataloader()
hf_trainer.create_optimizer_and_scheduler(len(train_dl) * training_args.num_train_epochs)
optimizer, lr_scheduler = hf_trainer.optimizer, hf_trainer.lr_schedulerIn [11]:
def get_inputset():
return {
"input_ids": torch.randint(0, tokenizer.vocab_size, (4, MAX_LENGTH)),
"attention_mask": torch.ones((4, MAX_LENGTH), dtype=torch.long),
"labels": torch.randint(0, tokenizer.vocab_size, (4, MAX_LENGTH)),
}
eval_dl = DataLoader(test_dataset, batch_size=4, shuffle=False, collate_fn=collator)In [12]:
def initialize_model(seed=SEED):
"""Initialize the model with consistent weights."""
set_seed(seed)
model = AutoModelForCausalLM.from_pretrained(model_name).to(DEVICE)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
model.config.pad_token_id = model.config.eos_token_id
for p in model.parameters():
p.requires_grad = False
peft_config = LoraConfig(
r=8,
lora_alpha=32,
lora_dropout=0.01,
bias="none",
task_type="CAUSAL_LM",
target_modules="all-linear",
)
peft_model = get_peft_model(model, peft_config)
peft_model = peft_model.to(DEVICE)
return peft_model
def setup_trainer(model, steps=EVAL_STEPS, logging_steps=1):
"""Set up the trainer, optimizer and scheduler."""
hf_trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
data_collator=collator,
)
train_dl = hf_trainer.get_train_dataloader()
hf_trainer.create_optimizer_and_scheduler(len(train_dl) * training_args.num_train_epochs)
optimizer, lr_scheduler = hf_trainer.optimizer, hf_trainer.lr_scheduler
lora_trainer = LoraTrainer(
model=model,
optimizer=optimizer,
loss_fn=causal_lm_loss,
lr_scheduler=lr_scheduler,
training_args=vars(training_args),
n_layers_to_skip_for_backprop=3,
eval_loader=eval_dl,
eval_metric_fn=metric_fn,
logging_steps=logging_steps,
eval_steps=steps,
train_log_path=TRAIN_LOG_FILE,
)
if MODE != "torch":
bits = 7 if MODE == "7bit" else 16
lora_trainer.compile(get_inputset(), n_bits=bits)
return lora_trainer, train_dl
def extract_lora_weights(model):
"""Extract LoRA weights from model for comparison."""
weights = {}
for name, param in model.named_parameters():
if "lora_" in name and param.requires_grad:
weights[name] = param.detach().cpu().numpy().copy()
return weights
# Select only the first 5 batches for initial comparison
def get_limited_batches(dataloader, num_batches=5):
"""Get a limited number of batches from dataloader."""
limited_batches = []
for i, batch in enumerate(dataloader):
if i < num_batches:
limited_batches.append(batch)
else:
break
return limited_batchesIn [13]:
# Original model trainer for reference
lora_trainer = LoraTrainer(
model=peft_model,
optimizer=optimizer,
loss_fn=causal_lm_loss,
lr_scheduler=lr_scheduler,
training_args=vars(training_args),
n_layers_to_skip_for_backprop=3,
eval_loader=eval_dl,
eval_metric_fn=None,
logging_steps=1,
eval_steps=EVAL_STEPS,
train_log_path=TRAIN_LOG_FILE,
)
# Clear the existing file for our experiments
with open(EVAL_RESPONSES_FILE, "w", encoding="utf-8") as f:
f.write("=== Experiment: disable vs simulate ===\n")2025-03-25 15:18:36,880 - INFO - === Starting new training session ===
LoRA layers detected in the model.
In [14]:
print("Initializing first model (fhe=disable)...")
model_disable = initialize_model()
initial_weights_disable = extract_lora_weights(model_disable)
trainer_disable, train_dl = setup_trainer(model_disable)
# Evaluate pre-training
print("Evaluating pre-training model...")
model_disable.eval()
pre_training_metrics = metric_fn(model_disable, eval_dl)
print(f"Pre-training perplexity: {pre_training_metrics['perplexity']:.2f}")
# Get limited batches for consistent training
limited_batches = get_limited_batches(train_dl, 5)
# Train with fhe=disable for 5 steps
print("\nTraining with fhe=disable for 5 steps...")
trainer_disable.train(limited_batches, fhe="disable", device=DEVICE)
losses_disable = trainer_disable.get_training_losses()
# Store LoRA weights
weights_disable = extract_lora_weights(model_disable)Initializing first model (fhe=disable)...
2025-03-25 15:18:39,194 - INFO - === Starting new training session ===
LoRA layers detected in the model.
Compiling FHE layers: 0%| | 0/221 [00:00<?, ?it/s]
2025-03-25 15:20:24,975 - INFO - Compilation complete.
Evaluating pre-training model... Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: I have a problem with this question. I know that 7 is a factor of 98, but what is the number that is a factor of
Pre-training perplexity: 37.06 Training with fhe=disable for 5 steps...
Epoch 1: 0%| | 0/5 [00:00<?, ?it/s]
2025-03-25 15:21:27,313 - INFO - Step 1: loss=2.163410, avg_loss=2.163410 2025-03-25 15:21:27,374 - INFO - Average gradient magnitude: 0.764078 2025-03-25 15:21:29,799 - INFO - Step 2: loss=3.122139, avg_loss=2.642774 2025-03-25 15:21:29,842 - INFO - Average gradient magnitude: 1.383245 2025-03-25 15:21:32,195 - INFO - Step 3: loss=4.424260, avg_loss=3.236603 2025-03-25 15:21:32,240 - INFO - Average gradient magnitude: 2.932004 2025-03-25 15:21:34,564 - INFO - Step 4: loss=0.981824, avg_loss=2.672908 2025-03-25 15:21:34,607 - INFO - Average gradient magnitude: 0.219038 2025-03-25 15:21:37,091 - INFO - Step 5: loss=0.893339, avg_loss=2.316994 2025-03-25 15:21:37,138 - INFO - Average gradient magnitude: 0.286395 2025-03-25 15:21:37,204 - INFO - Epoch 1 completed. Avg Loss: 2.316994, FHE Mode: disable 2025-03-25 15:21:37,204 - INFO - Training completed. Final Avg Loss: 2.316994, FHE Mode: disable
In [15]:
print("\nInitializing second model (fhe=execute)...")
model_execute = initialize_model()
trainer_execute, _ = setup_trainer(model_execute)
# Verify weights are the same before training
print("Verifying initial weights are identical...")
initial_weights_execute = extract_lora_weights(model_execute)
weights_match = True
for name, weight in initial_weights_disable.items():
if not np.allclose(weight, initial_weights_execute[name]):
print(f"Weight mismatch in {name}")
weights_match = False
if weights_match:
print("Initial weights match between models.")
# Train with fhe=execute for 5 steps
print("\nTraining with fhe=execute for 5 steps...")
trainer_execute.train(limited_batches, fhe="execute", device=DEVICE)
losses_execute = trainer_execute.get_training_losses()
# Compare LoRA weights after training
weights_execute = extract_lora_weights(model_execute)Initializing second model (fhe=execute)...
2025-03-25 15:24:17,754 - INFO - === Starting new training session ===
LoRA layers detected in the model.
Compiling FHE layers: 0%| | 0/221 [00:00<?, ?it/s]
2025-03-25 15:26:01,179 - INFO - Compilation complete.
Verifying initial weights are identical... Initial weights match between models. Training with fhe=execute for 5 steps...
Epoch 1: 0%| | 0/5 [00:00<?, ?it/s]
2025-03-25 08:47:17,002 - INFO - Step 1: loss=2.198043, avg_loss=2.198043 2025-03-25 08:47:17,018 - INFO - Average gradient magnitude: 10.796187 2025-03-25 09:45:10,070 - INFO - Step 2: loss=3.195699, avg_loss=2.696871 2025-03-25 09:45:10,087 - INFO - Average gradient magnitude: 14.245789 2025-03-25 10:43:01,591 - INFO - Step 3: loss=5.219449, avg_loss=3.537730 2025-03-25 10:43:01,608 - INFO - Average gradient magnitude: 22.919750 2025-03-25 11:40:54,081 - INFO - Step 4: loss=0.987054, avg_loss=2.900061 2025-03-25 11:40:54,097 - INFO - Average gradient magnitude: 3.477989 2025-03-25 12:38:47,204 - INFO - Step 5: loss=0.822733, avg_loss=2.484596 2025-03-25 12:38:47,222 - INFO - Average gradient magnitude: 7.610127 2025-03-25 12:38:47,240 - INFO - Epoch 1 completed. Avg Loss: 2.484596, FHE Mode: execute 2025-03-25 12:38:47,241 - INFO - Training completed. Final Avg Loss: 2.484596, FHE Mode: execute
In [16]:
plt.figure(figsize=(10, 6))
steps = np.arange(len(losses_disable))
plt.plot(steps, losses_disable, label="Disable Loss", color="blue")
plt.plot(steps, losses_execute, label="Execute Loss", color="red", linestyle="--")
plt.scatter(steps, losses_disable, color="blue", s=100)
plt.scatter(steps, losses_execute, color="red", marker="s", s=100)
plt.xlabel("Step")
plt.ylabel("Loss")
plt.title("Loss Comparison")
plt.legend()
plt.grid()
plt.xticks(steps)
plt.tight_layout()
plt.show()In [17]:
# Fully train the model in disable mode
model_final = initialize_model()
trainer_final, full_train_dl = setup_trainer(model_final, logging_steps=100)
trainer_final.train(full_train_dl, fhe="disable", device=DEVICE)
# Final evaluation
print("\nEvaluating final model after full training...")
model_final.eval()
metrics_final = metric_fn(model_final, eval_dl)
print(f"Final perplexity after extended training: {metrics_final['perplexity']:.2f}")
print(
f"Improvement from initial model: "
f"{pre_training_metrics['perplexity'] - metrics_final['perplexity']:.2f}"
)2025-03-26 10:29:58,595 - INFO - === Starting new training session ===
LoRA layers detected in the model.
Compiling FHE layers: 0%| | 0/221 [00:00<?, ?it/s]
2025-03-26 10:31:43,299 - INFO - Compilation complete.
Epoch 1: 0%| | 0/1479 [00:00<?, ?it/s]
2025-03-26 10:35:42,918 - INFO - Step 100: loss=0.335604, avg_loss=0.592850 2025-03-26 10:35:42,962 - INFO - Average gradient magnitude: 0.244334 2025-03-26 10:35:42,963 - INFO - Running evaluation at step 100...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: If you multiply a number by 7, it becomes 98. So, the number you're asking about is 98.
2025-03-26 10:36:44,321 - INFO - [Evaluation at step 100] perplexity: 1.4078 2025-03-26 10:40:45,460 - INFO - Step 200: loss=0.247193, avg_loss=0.450941 2025-03-26 10:40:45,501 - INFO - Average gradient magnitude: 0.335301 2025-03-26 10:40:45,502 - INFO - Running evaluation at step 200...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: The number that 98 is multiplied by is 7. So, the number is 98 * 7 = 702.
2025-03-26 10:41:44,560 - INFO - [Evaluation at step 200] perplexity: 1.4067 2025-03-26 10:45:56,970 - INFO - Step 300: loss=0.079890, avg_loss=0.444334 2025-03-26 10:45:57,016 - INFO - Average gradient magnitude: 0.091397 2025-03-26 10:45:57,017 - INFO - Running evaluation at step 300...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: If you multiply 7 by 98, you get 98 * 7 = 702.
2025-03-26 10:46:49,066 - INFO - [Evaluation at step 300] perplexity: 1.3947 2025-03-26 10:51:04,550 - INFO - Step 400: loss=0.016669, avg_loss=0.420956 2025-03-26 10:51:04,598 - INFO - Average gradient magnitude: 0.034923 2025-03-26 10:51:04,598 - INFO - Running evaluation at step 400...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: The number 98 is the answer to the question.
2025-03-26 10:51:50,182 - INFO - [Evaluation at step 400] perplexity: 1.3715 2025-03-26 10:55:48,938 - INFO - Step 500: loss=0.268339, avg_loss=0.405399 2025-03-26 10:55:48,981 - INFO - Average gradient magnitude: 0.268719 2025-03-26 10:55:48,982 - INFO - Running evaluation at step 500...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: If you multiply 7 by 98, you get 98 * 7 = 672.
2025-03-26 10:56:41,760 - INFO - [Evaluation at step 500] perplexity: 1.3689 2025-03-26 11:00:47,376 - INFO - Step 600: loss=0.061164, avg_loss=0.389228 2025-03-26 11:00:47,424 - INFO - Average gradient magnitude: 0.094080 2025-03-26 11:00:47,424 - INFO - Running evaluation at step 600...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: The number that becomes 98 when you multiply 7 by itself is 49.
2025-03-26 11:01:37,540 - INFO - [Evaluation at step 600] perplexity: 1.3429 2025-03-26 11:05:34,106 - INFO - Step 700: loss=0.049174, avg_loss=0.372756 2025-03-26 11:05:34,148 - INFO - Average gradient magnitude: 0.076843 2025-03-26 11:05:34,149 - INFO - Running evaluation at step 700...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: The number that is being multiplied by 7 is 98.
2025-03-26 11:06:18,797 - INFO - [Evaluation at step 700] perplexity: 1.3076 2025-03-26 11:10:16,397 - INFO - Step 800: loss=0.114913, avg_loss=0.366715 2025-03-26 11:10:16,440 - INFO - Average gradient magnitude: 0.201189 2025-03-26 11:10:16,441 - INFO - Running evaluation at step 800...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: To find the number, you need to divide 98 by 7. 98 ÷ 7 = 14 So the number is
2025-03-26 11:11:14,821 - INFO - [Evaluation at step 800] perplexity: 1.2973 2025-03-26 11:15:14,813 - INFO - Step 900: loss=0.126561, avg_loss=0.354234 2025-03-26 11:15:14,867 - INFO - Average gradient magnitude: 0.104785 2025-03-26 11:15:14,867 - INFO - Running evaluation at step 900...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: To find the number, you need to divide 98 by 7. 98 ÷ 7 = 14 So, the number is
2025-03-26 11:16:16,442 - INFO - [Evaluation at step 900] perplexity: 1.2808 2025-03-26 11:20:13,539 - INFO - Step 1000: loss=0.344479, avg_loss=0.344842 2025-03-26 11:20:13,582 - INFO - Average gradient magnitude: 0.255919 2025-03-26 11:20:13,583 - INFO - Running evaluation at step 1000...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: To find the number, you need to divide 98 by 7. 98 ÷ 7 = 14 So the number is 14
2025-03-26 11:21:16,761 - INFO - [Evaluation at step 1000] perplexity: 1.2511 2025-03-26 11:25:15,729 - INFO - Step 1100: loss=0.354381, avg_loss=0.335532 2025-03-26 11:25:15,771 - INFO - Average gradient magnitude: 0.290001 2025-03-26 11:25:15,771 - INFO - Running evaluation at step 1100...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: To find the number, you need to divide 98 by 7. 98 ÷ 7 = 14 So the number is 14
2025-03-26 11:26:15,104 - INFO - [Evaluation at step 1100] perplexity: 1.2496 2025-03-26 11:30:04,476 - INFO - Step 1200: loss=0.130505, avg_loss=0.326929 2025-03-26 11:30:04,518 - INFO - Average gradient magnitude: 0.197031 2025-03-26 11:30:04,518 - INFO - Running evaluation at step 1200...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: To find the number, you need to divide 98 by 7. 98 ÷ 7 = 14 So the number is 14
2025-03-26 11:31:01,618 - INFO - [Evaluation at step 1200] perplexity: 1.2336 2025-03-26 11:34:59,935 - INFO - Step 1300: loss=0.782768, avg_loss=0.323717 2025-03-26 11:34:59,978 - INFO - Average gradient magnitude: 0.438046 2025-03-26 11:34:59,979 - INFO - Running evaluation at step 1300...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: To find the number, you need to divide 98 by 7. 98 ÷ 7 = 14 So the number is
2025-03-26 11:35:59,463 - INFO - [Evaluation at step 1300] perplexity: 1.2246 2025-03-26 11:39:52,631 - INFO - Step 1400: loss=0.323173, avg_loss=0.316051 2025-03-26 11:39:52,673 - INFO - Average gradient magnitude: 0.343263 2025-03-26 11:39:52,673 - INFO - Running evaluation at step 1400...
Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: To find the number, you need to divide 98 by 7. 98 ÷ 7 = 14 So the number is
2025-03-26 11:40:52,313 - INFO - [Evaluation at step 1400] perplexity: 1.2274 2025-03-26 11:43:57,682 - INFO - Epoch 1 completed. Avg Loss: 0.311628, FHE Mode: disable 2025-03-26 11:43:57,682 - INFO - Training completed. Final Avg Loss: 0.311628, FHE Mode: disable
Evaluating final model after full training... Prompt: When you multiply a number by 7, it becomes 98. What is that number? Response: To find the number, you need to divide 98 by 7. 98 ÷ 7 = 14 So the number is
Final perplexity after extended training: 1.22 Improvement from initial model: 35.84
In [18]:
if SAVE_PATH.is_dir() and any(SAVE_PATH.iterdir()):
shutil.rmtree(SAVE_PATH)
trainer_final.save_and_clear_private_info(SAVE_PATH)
print("Model saved to:", SAVE_PATH)2025-03-26 11:54:06,388 - INFO - Model saved at deployment/llama_lora_finetuned_7bit
Model saved to: deployment/llama_lora_finetuned_7bit