Kendi LLM’inizi Yaratın: Hugging Face Transformers ile LLM Model Egitiminin Tüm Detayları

Alican Kiraz
6 min readDec 23, 2024

--

Image Credits: NicoElNino / Getty Images

Huggingface’in Transformers eğitim kütüphanesi, eğitim metriklerine hakim olduğunuzda harika bir araçtir. Kullanmaya başlayip hakim oldugunuzda da asla diğer yapay zeka eğitim araçlarına ihtiyacınız olmayacaktir. Gelin şimdi detaylica Transformers kutuphanesini, kullandığı diğer eğitim materyallerini ve parametrelerini detaylı inceleyelim. Ardından base bir LLM modelini eğitelim, kendi LLM’ımızı yaratalım ve huggingface’e yükleyelim.

Makaleyi okurken bir yandan da kurcalamaniz için örnek bir training kodu yazdım. Bu kod ile huggingface’den bir model indirip bu modeli yine uygun bir dataset ile (Instruction, Input, Output kolonlarina sahip) egitebilirsiniz.

import os
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
Trainer,
TrainingArguments,
BitsAndBytesConfig,
pipeline,
)
from datasets import load_dataset
from peft import LoraConfig, get_peft_model

# Suppress tokenizers parallelism warning
os.environ["TOKENIZERS_PARALLELISM"] = "false"

# 1. Load dataset
dataset = load_dataset("Dataset_Name")

# 2. Preprocess data
def preprocess_data(batch):
texts = [f"Instruction: {instruction}\nInput: {input_text}\nOutput: {output_text}" for instruction, input_text, output_text in zip(batch["instruction"], batch["input"], batch["output"])]
return {"text": texts}

processed_dataset = dataset.map(preprocess_data, batched=True)

# 3. Load tokenizer and model
model_path = "Model_Name"
tokenizer = AutoTokenizer.from_pretrained(model_path)

if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token

# 4. Tokenize data and add labels
def tokenize_function(batch):
tokenized_inputs = tokenizer(batch["text"], truncation=True, padding="max_length", max_length=512)
tokenized_inputs["labels"] = [
[(label if label != tokenizer.pad_token_id else -100) for label in input_ids]
for input_ids in tokenized_inputs["input_ids"]
]
return tokenized_inputs

tokenized_dataset = processed_dataset.map(tokenize_function, batched=True, remove_columns=["instruction", "input", "output"])
train_test_split = tokenized_dataset["train"].train_test_split(test_size=0.2, seed=42)
train_dataset = train_test_split["train"]
eval_dataset = train_test_split["test"]

# 5. Load model with quantization
bnb_config = BitsAndBytesConfig(load_in_8bit=True)
base_model = AutoModelForCausalLM.from_pretrained(
model_path,
quantization_config=bnb_config,
device_map="auto"
)

# Configure PEFT (LoRA)
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "v_proj"],
lora_dropout=0.1,
bias="none",
task_type="CAUSAL_LM"
)
peft_model = get_peft_model(base_model, lora_config)
peft_model.print_trainable_parameters()

# 6. Training arguments
training_args = TrainingArguments(
output_dir="./output_model",
evaluation_strategy="steps",
eval_steps=500,
logging_steps=1000,
learning_rate=2e-5,
per_device_train_batch_size=4, # Increased for better throughput
gradient_accumulation_steps=4, # Adjusted for effective batch size
num_train_epochs=3,
save_strategy="steps",
save_steps=500,
save_total_limit=2,
fp16=True,
logging_dir="./logs",
warmup_steps=500,
dataloader_num_workers=4,
max_grad_norm=1.0,
)

# 7. Trainer
trainer = Trainer(
model=peft_model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
)

# 8. Train model
trainer.train()

# 9. Save model and tokenizer
peft_model.save_pretrained("./output_model")
tokenizer.save_pretrained("./output_model")

print("Training completed successfully. Model and tokenizer saved to './output_model'.")

# 10. Switch to base model for inference
inference_pipeline = pipeline(
"text-generation",
model=base_model, # Use the base model, not PeftModelForCausalLM
tokenizer=tokenizer
)

# 11. Ask 3 questions to the trained model
questions = [
"QUESTION 1",
"QUESTION 2",
"QUESTION 3"
]

answers = []
for question in questions:
output = inference_pipeline(
question,
max_length=100,
num_return_sequences=1,
temperature=0.7, # Encourage creativity
top_p=0.9, # Nucleus sampling
top_k=50, # Limit to top 50 tokens
truncation=True # Explicit truncation
)
answers.append(output[0]["generated_text"])

# 12. Display the questions and answers
for question, answer in zip(questions, answers):
print(f"Q: {question}")
print(f"A: {answer}")
print("-" * 50)

Ilk adımda sıklıkla karşılaşacağınız ve eğitim sırasında ihtiyacınız olacak aşağıdaki kütüphanelere bir bakalım;

transformers datasets peft accelerate bitsandbytes torch

Transformers

Popüler ve güncel büyük dil modelleri (GPT, BERT, vb.) için kullanıma hazır mimariler ve yüksek seviyede train/fine-tuning fonksiyonları sunan bir yapıdadır. Hem PyTorch hem de TensorFlow backend’lerini destekler. Metin sınıflandırma, soru-cevap, metin üretimi, çeviri, özetleme gibi pek çok görev için yaygın olarak kullanılır.

import os
import torch
from transformers

Datasets

Farklı formatlardaki hazırlanmış veri setlerini (CSV, JSON, text dosyaları, vs.) kolayca yükleme, yönetme, dönüştürme ve paylaşma amaçlı veri kümelerini kullandıran bir kütüphanedir. Dağıtık ve paralel işlemeye uygun tasarlanmış yapı sayesinde milyonlarca satırlık büyük veri setlerini bile rahatça çalıştirabiliyor. Ayrıca map, filter, shuffle, train_test_split gibi fonksiyonlarıyla veri setlerinizi düzenleyip on işleme yapabilirsiniz.

import os
import torch
from datasets import load_dataset, DatasetDict
from transformers

Peft

peft yani (Parameter-Efficient Fine-Tuning); LLM’lerin fine-tuning sırasında çok az sayıda parametresini güncelleyerek geliştirme yapmanızı sağlar. Bunu; LoRA (Löw-Rank Adaptation), Prefix Tuning, Prompt Tuning gibi metodolojilerle yapar ve modelin tüm parametrelerini döndürüp sadece ek parametrelerini egitebilirsiniz. Bu sayede modelinizdeki kusur ve hatalar azalmış olur. Ayrıca bu sayede büyü modelleri dahi egitebilirsiniz.

import os
import torch
from datasets import load_dataset, DatasetDict
from transformers
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training

Accelerate, Bitsandbytes ve torch (PyTorch)

PyTorch tabanlı eğitimlerde dağıtık veya çok GPU’lu eğitim senaryolarını kolaylaştıran bir kütüphanedir. Yani PyTorch kodunu minimum değişiklikle tek GPU’dan çoklu GPU’ya veya çoklu node’a ölçeklendirebilirsiniz. Bitsandbytes ise büyük modelleri düşük bit (8-bit, 4-bit) hassasiyetle eğitme ve çalıştırma imkânı sunan bir kütüphanedir. Torch ise bildiğiniz gibi, deep learning ve hesaplamalı grafikleri hızlandırmak için kullanılan en popüler kutuphanelerdendir.

import os
import torch
from datasets import load_dataset, DatasetDict
from transformers import (
AutoTokenizer,
AutoModelForCausalLM,
Trainer,
TrainingArguments,
BitsAndBytesConfig,
DefaultDataCollator
)
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training

Şimdi trainer argümanlarını inceleyelim.

{
"auto_find_batch_size": "false",
"chat_template": "none",
"disable_gradient_checkpointing": "false",
"distributed_backend": "ddp",
"eval_strategy": "epoch",
"merge_adapter": "false",
"mixed_precision": "fp16",
"optimizer": "adamw_torch",
"peft": "true",
"padding": "right",
"quantization": "int4",
"scheduler": "linear",
"unsloth": "false",
"use_flash_attention_2": "false",
"batch_size": "2",
"block_size": "1024",
"epochs": "3",
"gradient_accumulation": "4",
"lr": "0.00003",
"logging_steps": "-1",
"lora_alpha": "32",
"lora_dropout": "0.05",
"lora_r": "16",
"max_grad_norm": "1",
"model_max_length": "2048",
"save_total_limit": "1",
"seed": "42",
"warmup_ratio": "0.1",
"weight_decay": "0",
"target_modules": "all-linear"
}

auto_find_batch_size

Bu parametre, batch boyutunu otomatik olarak belirleyip belirlemeyeceğinizi ayarlar. true olsaydı, GPU hafızasına sığacak en büyük batch boyutunu otomatik tespit etmeye çalışırdı. “false” ise, belirlenmiş sabit batch_size ile eğitim yapılacağını bize gösterir.

chat_template

Eğitim sırasında modelin giriş-çıkış formatını özel bir “chat” şablonu göre nasıl şekilleneceğini belirler.

disable_gradient_checkpointing

Gradient checkpointing, genelde büyük modellerin eğitimi sırasında bellek tasarrufu sağlar.

distributed_backend

Eğitim çoklu GPU (ve/veya çoklu node) üzerinde yapılacaksa, dağıtılmış eğitim yöntemi olarak DDP kullanıldığını gösterir.

eval_strategy

Değerlendirmenin ne zaman yapılacağını belirtir. “epoch” her epoch sonunda değerlendirme yapılacağını belirtir.

merge_adapter

LoRA gibi adapter tabanlı yöntemlerde, eğitim sonrası adaptör ağırlıklarını ana modele birleştirme seçeneğini gösterir.

mixed_precision

Eğitimde karma hassasiyet kullanılıp kullanılmadığını gösterir. “fp16”, 16 bit eğitimin yapıldığını belirtir. Bu genelde hız ve bellek tasarrufu sağlar.

optimizer

Kullanılan optimizasyon algoritmasını gösterir. adamw_torch, PyTorch’un yerleşik AdamW optimizatörüdür.

peft

PEFT, büyük modelleri daha az sayıda parametreyi güncelleyerek verimli bir şekilde ince ayar yapma stratejisidir (or. LoRA, Prefix Tuning).

padding

Token dizilerinin hizalanması sırasında padding’in nereye yapılacağını söyler. “right” padding, dizinin sağ tarafına boşluk (pad token) ekler.quantization

quantization

Modellerin bellek kullanımını azaltmak için ağırlıkların tamsayı formatında kuantizasyonunu ifade eder. “int4”, ağırlıkların 4-bit tamsayı formatına indirgenmesini gösterir. Bu sayede çok büyük modelleri hafızaya sığdırmak için kullanabiliriz, ancak hassasiyeti kısmen düşürebilir.

scheduler

Öğrenme oranının eğitim sürecinde nasıl değiştirileceğini belirtir. “linear”, başlangıç değerinden yavaş yavaş 0'a doğru lineer azalan bir scheduler olduğunu gösterir.

batch_size

Her ileri besleme adımında kullanılacak örnek sayısını ifade eder.

block_size

Girdi metinlerinin kırpıldığı ya da segmentlere ayrıldığı maksimum uzunluğu belirler.

epochs

Veri setinin baştan sona 3 epoch eğitim yapılacağını gösterir.

gradient_accumulation

Her geri yayılım öncesinde 4 adım boyunca gradyanların toplanacağını ve sonra güncelleme yapılacağını belirtir. Bu, efektif batch boyutunu artırmak için kullanılır.

lr

Değer: "0.00003" (3e-5). Öğrenme oranıdır. Bu, modelin parametrelerinin ne kadar hızlı güncelleneceğini kontrol eder.

lora_alpha

LoRA katmanlarının çıktılarını yeniden ölçeklendirmek için kullanılır. Bu sayede düşük rank’lı matrislerin güncellenmesi sırasında denge sağlanır.

lora_dropout

LoRA katmanlarında kullanılacak dropout oranıdır. Düşük bir dropout değeri modeli hafifçe düzenlileştirmeye yardımcı olur.

max_grad_norm

Gradientlerin maksimum normunu 1 ile sınırlar. Bu, gradient clipping kullanarak eğitimi daha kararlı hale getirir, büyük güncelleme adımlarını sınırlar.

model_max_length

Modelin işlemleyebileceği maksimum token sayısını belirtir.

seed

Rastgelelik içeren işlemler için sabit bir random seed ayarlayarak tekrar üretilebilir sonuçlar elde etmeye yarar. “42” popüler bir örnek değerdir.

Şimdi birde çıktılar sonrası modelimiz ile Lora ağırlıklarını nasıl birlestirecegimize ve huggingface’e yukleyecegimize bakalım.

from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
from huggingface_hub import HfApi, HfFolder, upload_folder

# Hugging Face repository details
repository_name = "REPO_NAME"
private = True # Set repository as private

# Paths to base and LoRA models
base_model_path = "BASE_MODEL_NAME"
lora_model_path = "SAVED_MODEL_NAME"
merged_model_path = "./merged_finetuned_model"

# Step 1: Load the base model
print("Loading base model...")
base_model = AutoModelForCausalLM.from_pretrained(base_model_path, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained(base_model_path)

# Step 2: Load LoRA weights and merge
print("Loading LoRA weights and merging with base model...")
lora_model = PeftModel.from_pretrained(base_model, lora_model_path)
merged_model = lora_model.merge_and_unload() # Merge LoRA weights into the base model

# Step 3: Save the merged model locally
print(f"Saving merged model to {merged_model_path}...")
merged_model.save_pretrained(merged_model_path)
tokenizer.save_pretrained(merged_model_path)

# Step 4: Upload to Hugging Face Hub
print(f"Uploading merged model to Hugging Face Hub ({repository_name})...")

# Authenticate with Hugging Face
hf_token = HfFolder.get_token() # Ensure you are logged in using `huggingface-cli login`
if not hf_token:
raise ValueError("Hugging Face token not found. Please log in using `huggingface-cli login`.")

# Initialize API and create repository
api = HfApi()

# Create the repository
api.create_repo(
repo_id=repository_name, # Use repo_id instead of name
token=hf_token,
private=private,
exist_ok=True # Avoid errors if the repo already exists
)

# Upload the folder to the repository
upload_folder(
folder_path=merged_model_path,
repo_id=repository_name,
token=hf_token
)

print(f"Model uploaded successfully to {repository_name} as private.")

Bu kod sayesinde eğitim ciktilarimizi base modelimiz ile merge ederek, huggingface’e yüklüyoruz. Huggingface’e yüklemek için huggingface’de access token üretip repo’ya erişim vermeyi unutmayın.

Artık kendi LLM’ınızı eğitip, oluşturabilirsiniz :)

--

--

Alican Kiraz
Alican Kiraz

Written by Alican Kiraz

Head of Cyber Defense Center @Trendyol | CSIE | CSAE | CCISO | CASP+ | OSCP | eCIR | CPENT | eWPTXv2 | eCDFP | eCTHPv2 | OSWP | CEH Master | Pentest+ | CySA+

Responses (2)