Open LLM Leaderboard’da zirveye yerleşen modellerin önemli bir kısmı, başlangıçta pek de sezgisel görünmeyen bir yöntemle üretildi: birden fazla checkpoint’i eğitim yapmadan, doğrudan ağırlık uzayında birleştirmek. 2023-2024 döneminde Hugging Face topluluğunun bu teknikle ürettiği modeller hem maliyet hem de performans tarafında şaşırtıcı sonuçlar ortaya koydu.
Model merging (model birleştirme), iki veya daha fazla fine-tuned modelin ağırlıklarını matematiksel olarak birleştirerek yeni bir model üretmektir. Ek eğitim verisi gerekmez, GPU saati harcanmaz. Elinizdeki checkpoint’ler ham malzeme, birleştirme algoritması ise bunları işleyen araç.
Bu yazıda temel yöntemleri adım adım inceliyoruz: naive averaging, Task Arithmetic, SLERP, TIES ve DARE. Ardından Mergekit ile bu yöntemleri pratikte nasıl uygulayacağınıza bakıyoruz.

Model birleştirme neden ortaya çıktı?
Bir senaryo düşünün: elinizde matematik için fine-tune edilmiş bir Llama modeli var, ayrı bir checkpoint’te ise Türkçe diyalogda güçlü bir versiyon. Her iki beceriyi tek modelde toplamak için iki seçenek görünür: ya baştan yeni bir fine-tuning çalıştırırsınız (veri, zaman, GPU), ya da bu iki checkpoint’i doğrudan birleştirirsiniz.
Model birleştirmenin temel iddiası şu: fine-tuned modeller aynı base model üzerinden türetildiğinde, ağırlık uzayında başlangıç noktalarına göre birer “vektör” oluşturur. Bu vektörler bağımsız görevlere karşılık geliyorsa, doğru bir interpolasyonla her ikisini de kapsayan bir nokta bulmak mümkündür.
Bu iddianın arkasında 2022-2023 döneminde çıkan birkaç araştırma var: Ilharco ve arkadaşlarının Task Arithmetic çalışması, Yadav ve ekibinin TIES-Merging makalesi, Yu ve ekibinin DARE çalışması. Hepsinin ortak noktası: fine-tuned model ağırlıkları, anlamlı bir yapıya sahip bir vektör uzayında yer alıyor.
Temel kavram: task vektörü
Model merging’i anlamak için önce task vektörü kavramına bakmak gerekiyor.
Fine-tuned bir model ile onun base modeli arasındaki fark şöyle ifade edilir:
τ = θ_finetuned - θ_base
Bu fark, τ (tau), o görev için öğrenilen bilgiyi temsil eden bir vektördür. Base modele bu vektörü eklerseniz, fine-tuned modeli geri elde edersiniz. Çıkarırsanız, modeli o görev için öğrendiği bilgiden arındırmış olursunuz.
Task vektörleri toplandığında ise birden fazla görevin bilgisi aynı modelde toplanabilir:
θ_merged = θ_base + λ₁ · τ₁ + λ₂ · τ₂ + ...
λ (lambda) değerleri her görevin ağırlığını belirler. Bu basit formül Task Arithmetic’in özüdür ve daha gelişmiş yöntemlerin de başlangıç noktasıdır.
Naive averaging: en basit birleştirme
Karmaşık algoritmalardan önce en basit yaklaşımı anlamak faydalı. Naive averaging, iki modelin ağırlıklarını doğrudan ortalamaktır:
θ_merged = (θ_A + θ_B) / 2
Bu yöntemin işe yaradığı durumlar var: iki modelin benzer görevler için eğitildiği ve başlangıç noktalarının birbirine yakın olduğu hallerde. Ama birleştirilmek istenen modeller birbirinden farklı yeteneklere odaklanmışsa, doğrudan ortalama her iki modelin güçlü yanlarını da silebilir. Ağırlıklar arasındaki çatışmalar, beklenen sinerji yerine ortalama bir yetersizlik üretebilir.
Bu sorunu çözmek için daha sofistike yöntemler geliştirildi.
SLERP: küresel doğrusal interpolasyon
SLERP (Spherical Linear Interpolation, yani Küresel Doğrusal İnterpolasyon), iki model arasında bir noktayı bulmak için düz bir çizgi yerine küre yüzeyini takip eden bir yol kullanır.
Görsel olarak düşünün: iki nokta arasında düz bir çizgi çizmek yerine, her iki noktanın üzerinde bulunduğu kürenin yüzeyini takip eden bir yay oluşturmak. Ağırlık vektörlerinin büyüklükleri (normları) farklıysa, doğrudan ortalama bu büyüklükleri çarpıtır. SLERP ise her iki vektörün yönü ve büyüklüğünü koruyarak aralarında geçiş yapar.
import torch
def slerp(t: float, v0: torch.Tensor, v1: torch.Tensor, eps: float = 1e-8):
# Vektörleri normalize et
v0_norm = v0 / (torch.norm(v0) + eps)
v1_norm = v1 / (torch.norm(v1) + eps)
# Açıyı hesapla
dot = torch.clamp(torch.dot(v0_norm.flatten(), v1_norm.flatten()), -1.0, 1.0)
theta = torch.acos(dot)
if torch.abs(theta) < eps:
# Vektörler çok yakınsa doğrudan lerp
return torch.lerp(v0, v1, t)
sin_theta = torch.sin(theta)
return (torch.sin((1 - t) * theta) / sin_theta) * v0 + \
(torch.sin(t * theta) / sin_theta) * v1
t = 0.5 değeriyle tam orta noktaya, t = 0.3 ile modelin birine daha yakın bir noktaya ulaşırsınız. SLERP özellikle iki modeli birleştirirken avantajlıdır; üçten fazla model için uygun değildir.
Pratikte SLERP, her parametre tensörüne ayrı ayrı uygulanır. Bu işlem Mergekit’te tek bir YAML satırıyla tetiklenebilir.
Task Arithmetic: vektör aritmetiği ile birleştirme
Knowledge distillation eğitim gerektirir; Task Arithmetic gerektirmez. Bu yöntemin gücü, görev vektörlerini toplama ve çıkarmaya indirgenmesinden kaynaklanır.
Üç modeli birleştirdiğinizi varsayın: biri matematik, biri kod, biri çok dilli dil anlama için eğitilmiş. Hepsinin aynı base model üzerinden türetildiğini farz edelim. Task Arithmetic şöyle çalışır:
τ_math = θ_math - θ_base
τ_code = θ_code - θ_base
τ_multilingual = θ_multilingual - θ_base
θ_merged = θ_base + 0.4 · τ_math + 0.4 · τ_code + 0.3 · τ_multilingual
Lambda katsayıları her görevin ağırlığını ayarlar. Bir göreve daha fazla ağırlık vermek istiyorsanız, o görevin lambda değerini artırırsınız.
Task Arithmetic’in sınırı şurada ortaya çıkar: görev vektörleri arasında örtüşme ve çatışma olduğunda birleştirme kalitesi düşer. İki model, base model üzerinde tam tersi yönde değişiklikler yapmışsa, bu vektörler birbirini iptal eder. TIES-Merging bu soruna doğrudan çözüm getirmek için geliştirildi.
TIES-Merging: çatışmaları çözerek birleştirme
TIES (Trim, Elect Sign, Disjoint Merge), Task Arithmetic’in çatışma sorununu üç adımda ele alır.
İlk adım Trim (Kırp): Her görev vektöründeki küçük değerler sıfıra çekilir. Modelin fine-tuning sırasında önemsiz gürültü ürettiği parametreler elenir; genellikle en büyük %20 değer korunur, geri kalanlar sıfırlanır.
İkinci adım Elect Sign (İşaret Seç): Her parametre için çatışan işaretler tespit edilir. İki görev vektörü aynı parametre üzerinde birbirinin zıt yönünde değişiklik yapmışsa, toplu büyüklük açısından baskın olan tarafın işareti seçilir.
Son adım Disjoint Merge (Ayrık Birleştirme): Seçilen işaretle uyumlu görev vektörleri ortalanır; uyumsuz olanlar dışarıda bırakılır. Bu sayede çatışan ağırlıklar birbirini iptal etmek yerine göz ardı edilir.
# TIES: basitleştirilmiş sözde kod
for each parameter p:
signs = [sign(τ₁[p]), sign(τ₂[p]), sign(τ₃[p])]
elected_sign = majority_sign(signs, weights)
contributors = [i for i if sign(τᵢ[p]) == elected_sign]
merged[p] = mean([τᵢ[p] for i in contributors]) * elected_sign
TIES, özellikle çok sayıda modeli (4+) birleştirirken Task Arithmetic’e göre belirgin şekilde daha iyi sonuç verir.
DARE: ağırlık damıtma ile gürültü azaltma
DARE (Drop And REscale), TIES’in trim adımını farklı bir açıdan ele alır. Temel soru şu: fine-tuning sırasında modelde gereksiz yere değişen parametreler varsa, bunları rastgele bırakmak yerine sistematik biçimde elersek ne olur?
DARE üç adımda çalışır. Her görev vektöründeki parametreler belirli bir olasılıkla (p drop rate) rastgele sıfıra çekilir. Geriye kalan parametreler 1/(1-p) faktörüyle ölçeklenir; bu yeniden ölçekleme, beklenen değeri korumak için gereklidir. Son olarak seyrek vektörler birleştirilir.
# DARE sözde kodu
def dare_merge(task_vectors, drop_rate=0.9):
sparse_vectors = []
for τ in task_vectors:
mask = torch.bernoulli(torch.ones_like(τ) * (1 - drop_rate))
sparse = τ * mask / (1 - drop_rate) # Unbiased rescale
sparse_vectors.append(sparse)
return sum(sparse_vectors)
DARE’nin ilginç bulgusu: büyük dil modellerinde fine-tuning sırasında değişen parametrelerin %90’a kadarı çıkarılıp kalan %10’u ölçeklendiğinde, model performansı neredeyse hiç düşmüyor. Bu, LLM fine-tuning’inin son derece seyrek bir güncelleme yaptığını gösteriyor. DARE bu özelliği birleştirme sürecinde kullanarak gürültüyü azaltır.
DARE tek başına bir birleştirme algoritması değil; TIES veya Task Arithmetic ile birlikte ön adım olarak kullanılır.
Mergekit: pratikte model birleştirme
Tüm bu algoritmaları sıfırdan uygulamak yerine Mergekit kullanmak en pratik yol. Hugging Face ekosisteminde yaygınlaşan bu açık kaynak araç, YAML konfigürasyonu ile birleştirme işlemini yönetir.
pip install mergekit
SLERP ile iki model birleştirme
# slerp_merge.yaml
models:
- model: mistralai/Mistral-7B-v0.1
parameters:
weight: 0.5
- model: HuggingFaceH4/zephyr-7b-beta
parameters:
weight: 0.5
merge_method: slerp
base_model: mistralai/Mistral-7B-v0.1
parameters:
t: 0.5
dtype: float16
mergekit-yaml slerp_merge.yaml ./merged-model --copy-tokenizer
Task Arithmetic ile üç model birleştirme
# task_arithmetic_merge.yaml
models:
- model: meta-llama/Llama-3.1-8B
parameters:
weight: 1.0
- model: my-org/llama-3.1-8b-math
parameters:
weight: 0.4
- model: my-org/llama-3.1-8b-code
parameters:
weight: 0.4
merge_method: task_arithmetic
base_model: meta-llama/Llama-3.1-8B
dtype: bfloat16
TIES-Merging ile çatışma çözümü
# ties_merge.yaml
models:
- model: meta-llama/Llama-3.1-8B-Instruct
parameters:
density: 0.5
weight: 1.0
- model: my-org/llama-math-instruct
parameters:
density: 0.5
weight: 0.8
- model: my-org/llama-code-instruct
parameters:
density: 0.5
weight: 0.8
merge_method: ties
base_model: meta-llama/Llama-3.1-8B
parameters:
normalize: true
dtype: bfloat16
density parametresi TIES’in trim adımını kontrol eder: 0.5 değeri parametre değerlerinin %50’sini korur, kalanı sıfırlar.
DARE + TIES kombinasyonu
# dare_ties.yaml
models:
- model: base-model
parameters:
weight: 1.0
- model: specialized-model-1
parameters:
density: 0.1 # DARE: %90 drop
weight: 0.7
- model: specialized-model-2
parameters:
density: 0.1
weight: 0.7
merge_method: dare_ties
base_model: base-model
dtype: bfloat16
Yöntem karşılaştırması
| Yöntem | Model sayısı | Çatışma yönetimi | Hesaplama maliyeti | En iyi kullanım |
|---|---|---|---|---|
| Naive Averaging | 2-4 | Yok | Çok düşük | Benzer görevler, deney |
| SLERP | 2 | Kısmi | Düşük | İki modeli düzgün harmanlamak |
| Task Arithmetic | 2-8 | Yok | Düşük | Birbirini tamamlayan görevler |
| TIES | 2-12 | Var | Orta | Çatışan fine-tuning’ler |
| DARE + TIES | 2-12 | Var | Orta | Büyük LLM’ler, yüksek gürültü ortamı |
Model birleştirme ile knowledge distillation farkı
Bu iki tekniği karıştırmak sık rastlanan bir hata. Knowledge distillation, teacher modelin öğretici rolüyle student modeli yeniden eğitir; bu süreç GPU saati, veri ve hesaplama gerektirir. Model birleştirme ise çıkarım öncesi statik bir işlemdir: hiçbir gradyan hesaplanmaz, hiçbir parametre öğrenme kuralıyla güncellenmez. Mevcut ağırlıklar matematiksel olarak birleştirilir ve yeni bir checkpoint üretilir.
Distillation daha fazla kaynak gerektirirken daha hassas kontrol sunar; birleştirme hızlı ve düşük maliyetlidir ama her zaman distillation kadar iyi bir sonuç vermez.
Sınırlılıklar ve dikkat edilmesi gerekenler
Model birleştirme her sorunu çözmez. Birkaç pratik kısıt var.
Birincisi, aynı base model zorunluluğu. Farklı mimarilerden türetilmiş ağırlıklar doğrudan birleştirilemez. Llama 3 ile Mistral’ı doğrudan birleştirmek, tensör boyutlarındaki uyumsuzluk nedeniyle mümkün değildir.
İkincisi, kapasite tavanı. Fine-tuned modellerin kabiliyetleri base modelin kapasitesini aşamaz. Birleştirme, var olan bilgiyi yeniden dağıtır; yeni bilgi üretmez. Birden fazla görevi birleştirmek, her görevde biraz taviz vermek anlamına da gelebilir.
Üçüncüsü, değerlendirme zorluğu. Birleştirme konfigürasyonu (lambda değerleri, density oranları) kör arama gerektirir. Her konfigürasyon için model indirme ve değerlendirme döngüsü, deneysel bir süreç demektir.
Son olarak, instruction tuning çatışması. Base model üzerinden instruction tuned iki modeli birleştirmek, bazen formatları karıştırabilir. Sistemin doğru talimat şablonunu kullandığından emin olun.
Prompt engineering ile ilişkisi
Model birleştirme, ağırlık seviyesinde çalışır ama model davranışını da doğrudan etkiler. İyi birleştirilmiş bir model, aynı kalitedeki tek bir modele kıyasla çok daha az prompt mühendisliği gerektirebilir; çünkü her görev için ayrı fine-tune edilmiş bilgi tek checkpoint’te toplanmıştır.
Öte yandan, RLHF ile hizalanmış modelleri birleştirmek dikkat gerektirir: güvenlik davranışları ve hizalama özellikleri de ağırlık uzayında temsil edilir. Hizalanmış iki modeli birleştirdiğinizde, hizalama özelliklerinin korunup korunmadığını ayrıca değerlendirmeniz gerekir.
Mergekit ile küçük bir deney
Pratik adım olarak 7B veya 8B ölçekli iki modeli seçin, SLERP ya da Task Arithmetic ile birleştirin, ardından lm-evaluation-harness ile temel görevlerde birleşik modeli ölçün.
# Değerlendirme örneği
lm_eval --model hf \
--model_args pretrained=./merged-model \
--tasks hellaswag,arc_easy,truthfulqa_mc \
--device cuda:0 \
--batch_size 8
Birleştirme konfigürasyonlarını sistematik biçimde deneyin: lambda değerlerini 0.1’lik adımlarla değiştirin, density oranlarını karşılaştırın. Bu tür deneyler Hugging Face Model Hub’da kamuya açık birleştirilmiş modellerin üretim sürecine benziyor.
Hugging Face’teki yüzlerce model bu yöntemle üretildi; bunların bir kısmı Open LLM Leaderboard’da başlangıçta beklenenin üzerinde puanlar elde etti. Sıfırdan eğitim veya distillation için kaynak yoksa, mevcut checkpoint’leri birleştirmek gerçekçi bir seçenek.