LeetLLM
My PlanLearnGlossaryTracksPracticeBlog
LeetLLM

Your go-to resource for mastering AI & LLM systems.

Product

  • Learn
  • Glossary
  • Tracks
  • Practice
  • Blog
  • RSS

Legal

  • Terms of Service
  • Privacy Policy

© 2026 LeetLLM. All rights reserved.

All Topics
Your Progress
0%

0 of 177 articles completed

🛠️Computing Foundations0/9
Git, Shell, Linux for AIDocker for Reproducible AIPython for AI EngineeringNumPy and Tensor ShapesCUDA for ML TrainingMPS & Metal for ML on MacData Structures for AISQL and Data ModelingAlgorithms for ML Engineers
📊Math & Statistics0/8
Gradients and BackpropVectors, Matrices & TensorsLinear Algebra for MLAdam, Momentum, SchedulersProbability for Machine LearningStatistics and UncertaintyDistributions and SamplingHypothesis Tests, Intervals, and pass@k
📚Preparation & Prerequisites0/13
Neural Networks from ScratchCNNs from ScratchTraining & BackpropagationSoftmax, Cross-Entropy & OptimizationRNNs, LSTMs, GRUs, and Sequence ModelingAutoencoders and VAEsThe Transformer Architecture End-to-EndLanguage Modeling & Next TokensFrom GPT to Modern LLMsPrompt Engineering FundamentalsCalling LLM APIs in ProductionFirst AI App End-to-EndThe LLM Lifecycle
🧮ML Algorithms & Evaluation0/11
Linear Regression from ScratchLogistic Regression and MetricsDecision Trees, Forests, and BoostingReinforcement Learning BasicsValidation and LeakageClustering and PCACore Retrieval AlgorithmsDecoding AlgorithmsExperiment Design and A/B TestingPyTorch Training LoopsDataset Pipelines and Data Quality
📦Production ML Systems0/6
Feature Engineering for Production MLBatch and Streaming Feature PipelinesGradient Boosted Trees in ProductionRanking and Recommendation SystemsForecasting and Anomaly DetectionMonitoring Predictive Models
🧪Core LLM Foundations0/8
The Bitter Lesson & ComputeBPE, WordPiece, and SentencePieceStatic to Contextual EmbeddingsPerplexity & Model EvaluationFile Ingestion for AIChunking StrategiesLLM Benchmarks & LimitationsInstruction Tuning & Chat Templates
🧰Applied LLM Engineering0/24
Dimensionality Reduction for EmbeddingsCoT, ToT & Self-Consistency PromptingFunction Calling & Tool UseMCP & Tool Protocol StandardsContext EngineeringPrompt Injection DefenseResponsible AI GovernanceData Labeling and Human FeedbackEvaluating AI AgentsProduction RAG PipelinesHybrid Search: Dense + SparseReranking and Cross-Encoders for RAGRAG Evaluation for Reliable AnswersLLM-as-a-Judge EvaluationBias & Fairness in LLMsHallucination Detection & MitigationLLM Observability & MonitoringExperiment Tracking with MLflow and W&BPrompt Optimization with DSPyModel Versioning & DeploymentSemantic Caching & Cost OptimizationLLM Cost Engineering & Token EconomicsModel Gateways, Routing, and FallbacksDesign an Automated Support Agent
🎓Portfolio Capstones0/9
Capstone: Delivery ETA PredictionCapstone: Product RankingCapstone: Demand ForecastingCapstone: Image Damage ClassifierCapstone: Production ML PipelineCapstone: Document QACapstone: Eval DashboardCapstone: Fine-Tuned ClassifierCapstone: Reproducible ML Study
🧠Transformer Deep Dives0/8
Sentence Embeddings & Contrastive LossEmbedding Similarity & QuantizationScaled Dot-Product AttentionVision Transformers and Image EncodersPositional Encoding: RoPE & ALiBiLayer Normalization: Pre-LN vs Post-LNMechanistic InterpretabilityDecoding Strategies: Greedy to Nucleus
🧬Advanced Training & Adaptation0/16
Scaling Laws & Compute-Optimal TrainingPre-training Data at ScaleBuild GPT from Scratch LabJAX for PyTorch ResearchersContinued Pretraining for Domain ShiftSynthetic Data PipelinesSupervised Fine-Tuning PipelineMixed Precision TrainingDistributed Training: FSDP & ZeROLoRA & Parameter-Efficient TuningReward Modeling from Preference DataRLHF & DPO AlignmentConstitutional AI & Red TeamingRLVR & Verifiable RewardsKnowledge Distillation for LLMsModel Merging and Weight Interpolation
🤖Advanced Agents & Retrieval0/16
Vector DB Internals: HNSW & IVFAdvanced RAG: HyDE & Self-RAGGraphRAG & Knowledge GraphsRAG Security & Access ControlStructured Output GenerationReAct & Plan-and-ExecuteGuardrails & Safety FiltersCode Generation & SandboxingComputer-Use / GUI / Browser AgentsHuman-in-the-Loop Agent ArchitectureAI Coding Workflow with AgentsAgent Memory & PersistenceAgent Failure & RecoveryRecursive Language Models (RLM)Multi-Agent OrchestrationCapstone: Production Agent
⚡Inference & Production Scale0/19
Inference: TTFT, TPS & KV CacheMulti-Query & Grouped-Query AttentionKV Cache & PagedAttentionPrefix Caching and Prompt CachingFlashAttention & Memory EfficiencyContinuous Batching & SchedulingScaling LLM InferenceModel Parallelism for LLM InferenceModel Quantization: GPTQ, AWQ & GGUFLocal LLM DeploymentSLM Specialization & Edge DeploymentSpeculative DecodingLong Context Window ManagementMixture of Experts ArchitectureMamba & State Space ModelsReasoning & Test-Time ComputeAdvanced MLOps & DevOps for AIGPU Serving & AutoscalingA/B Testing for LLMs
🏗️System Design Capstones0/9
Content Moderation SystemCode Completion SystemMulti-Tenant LLM PlatformLLM-Powered Search EngineVision-Language Models & CLIPMultimodal LLM ArchitectureDiffusion Models: Images & TextReal-Time Voice AI AgentReasoning Agent System Design
🎤AI Lab Interviewing0/4
AI Lab Coding Interview: Python SystemsAI Lab System Design InterviewAI Lab Behavioral InterviewAI Lab Technical Presentation
🔬Project Deep Dives0/17
Deep Dive - vLLMDeep Dive - SkyRLDeep Dive - FlashAttentionDeep Dive - FlashInferDeep Dive - DeepGEMMDeep Dive - NCCLDeep Dive - MegatronDeep Dive - DeepSpeedDeep Dive - RayDeep Dive - MLflowDeep Dive - PyTorchDeep Dive - TransformersDeep Dive - SGLangDeep Dive - slimeDeep Dive - DeepEPDeep Dive - TinkerDeep Dive - Light-PEFT
Back to Topics
LearnAdvanced Training & AdaptationModel Merging and Weight Interpolation
⚡HardFine-Tuning & Training

Model Merging and Weight Interpolation

Learn model merging techniques, from simple weight averaging and task arithmetic to TIES-Merging and DARE, including practical guidance on tokenizer compatibility, mergekit workflows, and evaluation.

29 min read
Learning path
Step 112 of 177 in the full curriculum
Knowledge Distillation for LLMsVector DB Internals: HNSW & IVF

Personalize this lesson

Adapt explanations and teaching visuals to your background and preferred voice.

Knowledge distillation compressed teacher behavior into a smaller student. Model merging asks a different deployment question: if you already have several useful fine-tuned checkpoints from the same base model, can you combine their weights into one checkpoint without launching another training run?

Your model platform team runs separate assistant checkpoints for code generation, math reasoning, and general chat. All three came from the same base model, but serving them behind a router raises memory and operational costs and complicates rollback. A merge creates a candidate checkpoint without another gradient-training run, but retained behavior remains an evaluation question.

A hard prerequisite for direct tensor interpolation is compatible parameter structure: corresponding tensors must have compatible shapes and meanings. Embedding matrices and language-model heads also need an explicit tokenizer policy. You can't interpolate a 7B checkpoint with a 70B checkpoint, or blindly combine token rows from different vocabularies. Mergekit can construct a union tokenizer and assign fallback embeddings for missing tokens, but that's an explicit output-space choice that still needs evaluation.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit Same-base checkpoints are the conservative starting point for task-vector merging because their parameter coordinates share lineage; compatible shapes alone don't establish merge quality.

Four recipes compare how same-base specialist checkpoints combine, from simple averaging to sparse conflict-aware task-vector merging.

Four model merging recipes compared before deployment evaluation.
Model soups average checkpoints, task arithmetic adds scaled task vectors, TIES trims and sign-aligns conflicting updates, and DARE sparsifies task vectors before a downstream merge.

When averaging weights is worth testing

If someone told you to average the internal numbers of two trained neural networks, skepticism is correct. Weight averaging is plausible in some fine-tuning settings because nearby checkpoints can occupy a connected low-loss region in parameter space. It isn't safe merely because both endpoints are good models.

Fine-tuning moves a checkpoint from a shared starting point through weight space. Linear mode connectivity studies whether the straight interpolation path between endpoints crosses a high-loss barrier.[2]Reference 2Linear Mode Connectivity and the Lottery Ticket Hypothesis.https://arxiv.org/abs/1912.05671 The Model Soups paper motivates averaging in a specific setting: models fine-tuned from a shared pretrained initialization under different hyperparameters often admit useful averages in its evaluated vision and text-classification experiments.[3]Reference 3Model Soups: Averaging Weights of Multiple Fine-tuned Models Improves Accuracy without Increasing Inference Timehttps://arxiv.org/abs/2203.05482 This is evidence for testing nearby same-lineage candidates, not a proof that differently specialized LLM checkpoints share one basin.

In concrete terms, evaluate points on θ(α)=(1−α)θA+αθB\theta(\alpha) = (1-\alpha)\theta_A + \alpha\theta_Bθ(α)=(1−α)θA​+αθB​ rather than assuming the midpoint is usable. Two checkpoints can each be strong on their own evaluation and still interfere when combined, especially when they represent different tasks. Models with unrelated pretraining lineages are even poorer candidates for direct interpolation because their parameter coordinate systems weren't preserved by a common base.

The screening logic below treats interpolation measurements as evidence, rather than granting the midpoint a pass because the sources share lineage. In a real run, losses and task_scores come from the candidate checkpoints and held-out evaluations:

screen-measured-interpolation-path.py
1alphas = [0.00, 0.25, 0.50, 0.75, 1.00] 2losses = [0.18, 0.20, 0.61, 0.23, 0.19] 3task_scores = [0.88, 0.86, 0.70, 0.85, 0.89] 4 5max_accepted_loss = 0.30 6min_accepted_score = 0.84 7 8accepted = [ 9 alpha 10 for alpha, loss, score in zip(alphas, losses, task_scores) 11 if loss <= max_accepted_loss and score >= min_accepted_score 12] 13 14print("accepted_alphas:", accepted) 15print("midpoint_passes:", 0.50 in accepted)
Output
1accepted_alphas: [0.0, 0.25, 0.75, 1.0] 2midpoint_passes: False
Interpolation diagnostic comparing a measured low-loss path between nearby same-lineage checkpoints with a measured high-loss ridge between incompatible candidates.
Check interpolation loss or downstream quality rather than inferring it from lineage. Shared lineage is a useful precondition, not a pass result.

Same-base lineage: Same-base lineage makes a merge experiment defensible. It doesn't establish that a code-generation and math-reasoning merge retained either behavior. Only per-task evaluation does that.

The permutation invariance problem

Neural networks can exhibit permutation invariance: under appropriate corresponding reordering of incoming and outgoing weights, hidden-unit permutations can preserve the function a network computes.[4]Reference 4The Role of Permutation Invariance in Linear Mode Connectivity of Neural Networks.https://arxiv.org/abs/2110.06296 This helps explain why independently trained networks may be poorly aligned for naive averaging even if they solve similar tasks.

Git Re-Basin[5]Reference 5Git Re-Basin: Merging Models modulo Permutation Symmetries.https://arxiv.org/abs/2209.04836 addresses this by finding the optimal permutation π\piπ that aligns the neurons of one model to match the other before merging:

θmerged=12(θA+π(θB))\theta_{\text{merged}} = \frac{1}{2}(\theta_A + \pi(\theta_B))θmerged​=21​(θA​+π(θB​))

Permutation invariance makes the failure mode concrete in the next figure. Two checkpoints can learn the same three hidden features but store them in different slot orders, so Git Re-Basin permutes one model before averaging.

Permutation-alignment diagram showing equivalent hidden features before and after slot reordering.
Permutation invariance means slot numbers aren't semantic IDs. Git Re-Basin searches for a permutation that aligns equivalent hidden units in the network architectures studied by its paper.

Git Re-Basin uses permutation matching and reports merged independently trained MLP, CNN, and ResNet models in its studied settings, including a zero-barrier ResNet result on CIFAR-10.[5]Reference 5Git Re-Basin: Merging Models modulo Permutation Symmetries.https://arxiv.org/abs/2209.04836 That paper is a useful alignment concept, but it isn't evidence that an arbitrary pair of large language models can be repaired and merged. For LLM work, same-base candidates plus downstream evaluation remain the practical default here.

Why does Git Re-Basin apply π\piπ before averaging?

Answer

Two models can represent the same function with neurons in different orders. The permutation aligns corresponding neurons first, so averaging combines matching features instead of unrelated ones.

The merging toolkit: from simple averages to conflict-aware methods

Several techniques exist for merging models, ranging from mathematical averages to geometric interpolation rules. Choice depends on source lineage, observed delta conflict, and the evaluations the output must pass.

MethodMechanismProsConsBest For
Model Soups / LinearUniform or weighted averagingSimple baselineInterference between conflicting parametersNearby checkpoints with representative evaluation
Task ArithmeticWeighted task vectorsSeparate coefficients per deltaCoefficients don't guarantee separate capabilities surviveSame-base task-vector experiments
TIES-Merging (Trim, Elect Sign, Merge)Trim and aggregate-sign filteringExplicitly handles conflicting delta signsDensity and scale need tuningConflicting same-base task vectors
DARE (sparsify first)Random dropping and rescaling of task vectorsSparse preprocessing evaluated by its paperNot a complete merge rule on its ownTesting DARE plus a downstream merge
SLERP (Spherical Linear Interpolation)Spherical interpolation in direction spaceHas a norm-preserving geometric interpretationGeometry alone doesn't establish task qualityPairwise interpolation experiment

Model soups (uniform averaging)

The simplest approach to merging is called Model Soups[3]Reference 3Model Soups: Averaging Weights of Multiple Fine-tuned Models Improves Accuracy without Increasing Inference Timehttps://arxiv.org/abs/2203.05482. It averages the weights of multiple fine-tuned models to create a single averaged model:

θmerged=1N∑i=1Nθi\theta_{\text{merged}} = \frac{1}{N} \sum_{i=1}^{N} \theta_iθmerged​=N1​∑i=1N​θi​

To see the operation, imagine two scalars instead of billion-parameter tensors. If checkpoint A has a weight 2.0 and checkpoint B has 4.0, their equal average is 3.0. Whether that compromise retains behavior can't be determined from this parameter alone. Model Soups evaluates averaging models fine-tuned from a shared initialization over hyperparameter configurations and reports improved accuracy and robustness in its studied settings without the inference cost of an ensemble.[3]Reference 3Model Soups: Averaging Weights of Multiple Fine-tuned Models Improves Accuracy without Increasing Inference Timehttps://arxiv.org/abs/2203.05482

Uniform vs. greedy soups

The original Model Soups paper distinguishes between two selection strategies:

  • Uniform Soups: Average all fine-tuned checkpoints with equal weight. Simple but risky, as a single poorly-performing checkpoint can drag down the overall quality.
  • Greedy Soups: Iteratively add checkpoints to the soup only if they improve performance on a held-out validation set. Start with the best individual model, then test each remaining model: if adding it to the average improves the validation metric, keep it; otherwise, discard it.

In the original paper, greedy soups outperform uniform averaging in the reported experiments because the selection rule skips candidates that hurt its held-out validation metric.[3]Reference 3Model Soups: Averaging Weights of Multiple Fine-tuned Models Improves Accuracy without Increasing Inference Timehttps://arxiv.org/abs/2203.05482 A similar selection rule is reasonable to test only when your validation slices represent the behavior you need to keep.

uniform_merge performs uniform averaging. It takes a list of model state dictionaries and an optional list of weights, and returns a single state dictionary containing the weighted average of their parameters:

uniform-vs-greedy-soups.py
1import torch 2 3def uniform_merge( 4 models: list[dict[str, torch.Tensor]], 5 weights: list[float] | None = None, 6) -> dict[str, torch.Tensor]: 7 """Merge models by weighted averaging of parameters.""" 8 if weights is None: 9 weights = [1.0 / len(models)] * len(models) 10 11 if abs(sum(weights) - 1.0) >= 1e-6: 12 raise ValueError("Weights must sum to 1") 13 14 merged = {} 15 for key in models[0].keys(): 16 merged[key] = sum(w * m[key] for w, m in zip(weights, models)) 17 18 return merged 19 20code_model = {"w": torch.tensor([2.0, 4.0]), "bias": torch.tensor([1.0])} 21math_model = {"w": torch.tensor([4.0, 2.0]), "bias": torch.tensor([3.0])} 22merged = uniform_merge([code_model, math_model]) 23 24print("weights_ok:", bool(torch.allclose(merged["w"], torch.tensor([3.0, 3.0])))) 25print("bias_ok:", bool(torch.allclose(merged["bias"], torch.tensor([2.0])))) 26print("merged w:", merged["w"].tolist()) 27print("merged bias:", merged["bias"].tolist())
Output
1weights_ok: True 2bias_ok: True 3merged w: [3.0, 3.0] 4merged bias: [2.0]

Pros

Exceptionally simple to implement and requires no hyperparameters beyond the optional weighting scheme.

Cons

If the models are fine-tuned on wildly different tasks, direct averaging can cause destructive interference between conflicting parameters, degrading overall performance.

Task arithmetic

Instead of averaging absolute weights, Task Arithmetic[6]Reference 6Editing Models with Task Arithmetichttps://arxiv.org/abs/2212.04089 operates on task vectors (the difference between fine-tuned weights and the base model). Task vectors are specific directions from the base checkpoint (e.g., "walk 10 steps north"). Instead of averaging the final destinations of different hikers, you take the specific path each hiker took from base camp and combine them. By scaling these paths (e.g., "take half the steps north"), you can carefully mix different skills.

τi=θi−θ0(task vector for model i)\tau_i = \theta_i - \theta_0 \quad \text{(task vector for model } i \text{)}τi​=θi​−θ0​(task vector for model i)

θmerged=θ0+∑i=1Nλi⋅τi\theta_{\text{merged}} = \theta_0 + \sum_{i=1}^{N} \lambda_i \cdot \tau_iθmerged​=θ0​+∑i=1N​λi​⋅τi​

Where θ0\theta_0θ0​ is the base model, θi\theta_iθi​ are fine-tuned models, τi\tau_iτi​ are per-task deltas, and λi\lambda_iλi​ are merge weights.

A concrete scalar walkthrough

Before you run this on billion-parameter tensors, try it on a single parameter. Imagine a base model where one weight is 2.0. A code-generation fine-tune pushes that weight to 2.5, so its task vector is +0.5. A math-reasoning fine-tune pushes it to 1.5, so its task vector is -0.5. If you want to favor the code delta without discarding the math delta, you might set λcode=0.6\lambda_{\text{code}} = 0.6λcode​=0.6 and λmath=0.4\lambda_{\text{math}} = 0.4λmath​=0.4:

merged weight=2.0+0.6(0.5)+0.4(−0.5)=2.0+0.3−0.2=2.1\text{merged weight} = 2.0 + 0.6(0.5) + 0.4(-0.5) = 2.0 + 0.3 - 0.2 = 2.1merged weight=2.0+0.6(0.5)+0.4(−0.5)=2.0+0.3−0.2=2.1

The result, 2.1, is a parameter nudge in the code-generation direction. If you had instead averaged the absolute fine-tuned weights (2.5 and 1.5), you'd get 2.0, cancelling both deltas at this coordinate. A scalar calculation can't establish how either capability performs; it only shows how task-vector coefficients act on weights.

Why did absolute averaging cancel the two specialist deltas in the scalar example?

Answer

The code-generation fine-tune moved this coordinate up by +0.5 and the math-reasoning fine-tune moved it down by -0.5. Averaging final weights lands this coordinate back at the base value, cancelling both deltas here. Task evaluation determines the broader behavioral effect.

A different coefficient pair shows the same tuning choice. Suppose a code-generation fine-tune nudges a weight to 2.4 (task vector +0.4) and a math-reasoning fine-tune nudges it to 1.8 (task vector -0.2). Setting λcode=0.7\lambda_{\text{code}} = 0.7λcode​=0.7 and λmath=0.5\lambda_{\text{math}} = 0.5λmath​=0.5 gives 2.0 + 0.28 - 0.10 = 2.18. Whether this coefficient pair keeps either capability is measured after the merge.

task_arithmetic_merge implements the recipe in code. It takes a shared base model, a list of fine-tuned models, and scaling coefficients. It subtracts the base to get task vectors, applies a scaling coefficient, and adds them back to return the merged model:

a-concrete-scalar-walkthrough.py
1import torch 2 3def task_arithmetic_merge( 4 base_model: dict[str, torch.Tensor], 5 fine_tuned_models: list[dict[str, torch.Tensor]], 6 scaling_coefficients: list[float] 7) -> dict[str, torch.Tensor]: 8 """Merge via task vectors (differences from base model). 9 10 Args: 11 base_model: The shared base model weights 12 fine_tuned_models: List of fine-tuned model weights 13 scaling_coefficients: Per-task scaling factors (lambda_i) 14 """ 15 merged = {k: v.clone() for k, v in base_model.items()} 16 17 for model, coeff in zip(fine_tuned_models, scaling_coefficients): 18 for key in merged: 19 task_vector = model[key] - base_model[key] 20 merged[key] += coeff * task_vector 21 22 return merged 23 24shared_base = {"w": torch.tensor([2.0])} 25code_ft = {"w": torch.tensor([2.5])} 26math_ft = {"w": torch.tensor([1.5])} 27 28# Example: 0.6x code delta + 0.4x math delta 29merged = task_arithmetic_merge( 30 base_model=shared_base, 31 fine_tuned_models=[code_ft, math_ft], 32 scaling_coefficients=[0.6, 0.4], 33) 34 35print("base:", float(shared_base["w"])) 36print("matches_expected:", bool(torch.allclose(merged["w"], torch.tensor([2.1])))) 37print("merged:", round(float(merged["w"]), 2))
Output
1base: 2.0 2matches_expected: True 3merged: 2.1

Advantage

Scaling coefficients control how much of each task vector enters the candidate checkpoint; evaluation determines retained behavior.

TIES-Merging (trim, elect sign, merge)

A major issue with simple averaging is that task vectors can directly contradict one another (e.g., one model increases a weight by 0.5, while another decreases it by 0.5). TIES-Merging[7]Reference 7TIES-Merging: Resolving Interference When Merging Modelshttps://arxiv.org/abs/2306.01708 addresses two forms of interference in its recipe: it trims low-magnitude deltas, elects a sign for each coordinate using total signed movement, and merges only values aligned with that elected sign.

TIES resolves a coordinate as if three specialists proposed parameter deltas for it. First, discard small proposals (Trim). Next, sum the size of increases against the size of decreases, rather than counting voters (Elect sign). Finally, average only proposals in the winning direction (Disjoint merge).

TIES-Merging flow from raw task vectors to trimmed updates, aggregate-magnitude sign election, and a merged aligned delta.
TIES handles interference coordinate by coordinate: trim low-magnitude updates, elect the direction with greater aggregate movement, then average aligned deltas.

Step 1: Trim

First, it drops low-magnitude changes treated as redundant by the recipe. The trim function below takes a task vector and a density threshold, then keeps high-magnitude updates:

step-1-trim.py
1import torch 2 3def trim(task_vector: torch.Tensor, density: float = 0.2) -> torch.Tensor: 4 """Keep only the top-k% of parameter changes by magnitude.""" 5 threshold = torch.quantile(task_vector.abs(), 1 - density) 6 mask = task_vector.abs() >= threshold 7 return task_vector * mask 8 9task_vector = torch.tensor([0.1, -0.5, 0.02, 0.8]) 10trimmed = trim(task_vector, density=0.5) 11 12print("matches_expected:", bool(torch.allclose(trimmed, torch.tensor([0.0, -0.5, 0.0, 0.8])))) 13print("trimmed:", [round(float(x), 2) for x in trimmed])
Output
1matches_expected: True 2trimmed: [0.0, -0.5, 0.0, 0.8]

Step 2: Elect sign

When multiple task vectors update the same parameter, TIES-Merging resolves conflicting directions with γmp=sgn(∑tτ^tp)\gamma_m^p = \mathrm{sgn}(\sum_t \hat{\tau}_t^p)γmp​=sgn(∑t​τ^tp​).[7]Reference 7TIES-Merging: Resolving Interference When Merging Modelshttps://arxiv.org/abs/2306.01708 The elect_sign function sums the trimmed signed deltas and takes the resulting sign. This differs from a majority vote: one large update can outweigh two smaller opposing updates.

step-2-elect-sign.py
1import torch 2 3def elect_sign(trimmed_vectors: list[torch.Tensor]) -> torch.Tensor: 4 """Elect sign with greatest aggregate signed movement per parameter.""" 5 aggregate_delta = sum(trimmed_vectors) 6 return torch.sign(aggregate_delta) 7 8trimmed_vectors = [ 9 torch.tensor([0.0, -0.5, 0.0, 0.8]), 10 torch.tensor([0.0, 1.1, 0.0, -0.6]), 11 torch.tensor([0.0, -0.4, 0.0, 0.7]), 12] 13elected = elect_sign(trimmed_vectors) 14print("two_negative_votes_at_p2:", True) 15print("positive_mass_wins_at_p2:", bool(elected[1] == 1)) 16print("matches_expected:", bool(torch.allclose(elected, torch.tensor([0.0, 1.0, 0.0, 1.0])))) 17print("elected signs:", elected.tolist())
Output
1two_negative_votes_at_p2: True 2positive_mass_wins_at_p2: True 3matches_expected: True 4elected signs: [0.0, 1.0, 0.0, 1.0]

Step 3: Disjoint merge

Finally, it computes the average of only those task vectors whose updates match the consensus direction. The disjoint_merge function takes trimmed task vectors and their elected signs. It averages only the parameter updates that agree with the elected direction, zeroing out any dissenting values to produce the final merged task vector:

step-3-disjoint-merge.py
1import torch 2 3def disjoint_merge( 4 trimmed_vectors: list[torch.Tensor], 5 elected_signs: torch.Tensor 6) -> torch.Tensor: 7 """Average only non-zero values that agree with the elected sign.""" 8 merged = torch.zeros_like(trimmed_vectors[0]) 9 counts = torch.zeros_like(trimmed_vectors[0]) 10 11 for tv in trimmed_vectors: 12 agree = (tv != 0) & (elected_signs != 0) & (torch.sign(tv) == elected_signs) 13 merged += torch.where(agree, tv, 0) 14 counts += agree.float() 15 16 return torch.where( 17 counts > 0, 18 merged / counts.clamp(min=1), 19 torch.zeros_like(merged) 20 ) 21 22trimmed_vectors = [ 23 torch.tensor([0.0, -0.5, 0.0, 0.8]), 24 torch.tensor([0.0, 1.1, 0.0, -0.6]), 25 torch.tensor([0.0, -0.4, 0.0, 0.7]), 26] 27elected_signs = torch.tensor([0.0, 1.0, 0.0, 1.0]) 28merged = disjoint_merge(trimmed_vectors, elected_signs) 29 30print("matches_expected:", bool(torch.allclose(merged, torch.tensor([0.0, 1.1, 0.0, 0.75])))) 31print("merged task vector:", [round(float(x), 2) for x in merged])
Output
1matches_expected: True 2merged task vector: [0.0, 1.1, 0.0, 0.75]

TIES-Merging outperforms compared baselines in the paper's evaluated vision and T5 task-vector settings, and its analysis identifies sign interference.[7]Reference 7TIES-Merging: Resolving Interference When Merging Modelshttps://arxiv.org/abs/2306.01708 For an LLM merge, use it as a candidate recipe when task vectors conflict, then compare per-task evaluation against simpler baselines.

DARE (drop and rescale)[8]Reference 8Language Models are Super Mario: Absorbing Capabilities from Homologous Models as a Free Lunchhttps://arxiv.org/abs/2311.03099

DARE randomly drops entries from each task vector and rescales the survivors before a downstream merge. The rescaling preserves an entry's expected delta under the random mask; it doesn't by itself prove that the resulting model preserves a capability.

The paper studies redundancy in supervised fine-tuning (SFT) deltas and reports that its evaluated models can often tolerate dropping 90% of delta entries, and in some cases 99%, before merging. Its size ablation reports that WizardMath-70B remains effective at a 99% drop rate while the evaluated 7B and 13B variants fail there.[8]Reference 8Language Models are Super Mario: Absorbing Capabilities from Homologous Models as a Free Lunchhttps://arxiv.org/abs/2311.03099 Treat that as experimental evidence for the paper's SFT models, not a default density setting for a new merge. DARE is a sparsification step, not a complete merge recipe: sparsified task vectors still need a merger such as averaging or TIES.

DARE's analysis also separates SFT deltas, which it observes are typically within roughly 0.002, from continued-pretraining deltas that approach 0.03; its drop-and-rescale approach becomes ineffective on the latter.[8]Reference 8Language Models are Super Mario: Absorbing Capabilities from Homologous Models as a Free Lunchhttps://arxiv.org/abs/2311.03099 One candidate pipeline is DARE-TIES: DARE sparsifies each delta, then TIES resolves directional conflicts among surviving values. Mergekit exposes that composition as dare_ties.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit

τiDARE=τi⊙m1−p\tau_i^{\text{DARE}} = \frac{\tau_i \odot m}{1 - p}τiDARE​=1−pτi​⊙m​

where mmm is a random binary mask with drop rate ppp and the 1/(1−p)1/(1-p)1/(1−p) factor preserves each entry's expectation under masking.[8]Reference 8Language Models are Super Mario: Absorbing Capabilities from Homologous Models as a Free Lunchhttps://arxiv.org/abs/2311.03099

Why does DARE divide by 1−p1-p1−p after dropping weights?

Answer

Only a fraction 1−p1-p1−p of task-vector entries survive. Dividing by 1−p1-p1−p keeps each randomly masked delta entry unbiased in expectation; retained task quality still requires evaluation.

dare_sparsify implements the DARE step itself. It sparsifies one task vector, after which you can pass the result to a downstream merge rule:

dare-drop-and-rescale-yu2023.py
1import torch 2 3def dare_sparsify( 4 task_vector: torch.Tensor, 5 drop_rate: float = 0.9 6) -> torch.Tensor: 7 """DARE preprocessing for one task vector.""" 8 keep_prob = 1.0 - drop_rate 9 if not 0.0 < keep_prob <= 1.0: 10 raise ValueError("drop_rate must be in [0, 1)") 11 12 mask = torch.bernoulli(torch.full_like(task_vector, keep_prob)) 13 return (task_vector * mask) / keep_prob 14 15torch.manual_seed(4) 16task_vector = torch.tensor([0.2, -0.4, 0.1, 0.6]) 17sparsified = dare_sparsify(task_vector, drop_rate=0.5) 18 19shape_ok = sparsified.shape == task_vector.shape 20finite_ok = bool(torch.isfinite(sparsified).all()) 21binary_mask_ok = set(torch.unique((sparsified != 0).int()).tolist()).issubset({0, 1}) 22makes_invalid_drop_rate_fail = False 23 24try: 25 dare_sparsify(task_vector, drop_rate=1.0) 26except ValueError as exc: 27 makes_invalid_drop_rate_fail = "drop_rate" in str(exc) 28 29print("shape_ok:", shape_ok) 30print("finite_ok:", finite_ok) 31print("binary_mask_ok:", binary_mask_ok) 32print("invalid_drop_rate_rejected:", makes_invalid_drop_rate_fail) 33print("original nonzero:", int((task_vector != 0).sum())) 34print("sparsified nonzero:", int((sparsified != 0).sum())) 35print("sparsified:", [0.0 if abs(float(x)) < 1e-8 else round(float(x), 2) for x in sparsified])
Output
1shape_ok: True 2finite_ok: True 3binary_mask_ok: True 4invalid_drop_rate_rejected: True 5original nonzero: 4 6sparsified nonzero: 2 7sparsified: [0.0, 0.0, 0.2, 1.2]

What the paper establishes

On the SFT models and tasks it evaluates, DARE finds substantial redundancy in task-vector entries and improves several downstream merge methods after drop-and-rescale preprocessing.[8]Reference 8Language Models are Super Mario: Absorbing Capabilities from Homologous Models as a Free Lunchhttps://arxiv.org/abs/2311.03099 For a new checkpoint family, density remains a tuned parameter: compare unsparsified and DARE-preprocessed merges on every required task slice.

SLERP (spherical linear interpolation)

SLERP is a geometric interpolation rule. It follows an angular arc between normalized vector directions rather than the chord used by linear interpolation. It isn't an algorithm for discovering a low-loss path around an incompatible-model ridge.

Rather than interpolating directions along a straight line, SLERP[9]Reference 9Animating Rotation with Quaternion Curveshttps://dl.acm.org/doi/10.1145/325334.325242 interpolates along a sphere. Write the geometry in terms of normalized directions:

SLERP(θ^A,θ^B,t)=sin⁡((1−t)Ω)sin⁡Ωθ^A+sin⁡(tΩ)sin⁡Ωθ^B\begin{aligned} \text{SLERP}(\hat{\theta}_A, \hat{\theta}_B, t) &= \frac{\sin((1-t)\Omega)}{\sin \Omega} \hat{\theta}_A \\ &\quad + \frac{\sin(t\Omega)}{\sin \Omega} \hat{\theta}_B \end{aligned}SLERP(θ^A​,θ^B​,t)​=sinΩsin((1−t)Ω)​θ^A​+sinΩsin(tΩ)​θ^B​​

where ttt is the interpolation factor (from 0 to 1) and Ω=arccos⁡(θ^A⋅θ^B)\Omega = \arccos(\hat{\theta}_A \cdot \hat{\theta}_B)Ω=arccos(θ^A​⋅θ^B​) is the angle between normalized weight vectors. Practical merge implementations may handle magnitude separately after interpolating direction, as the code does here.

SLERP was introduced for computer graphics to interpolate rotations represented as quaternions.[9]Reference 9Animating Rotation with Quaternion Curveshttps://dl.acm.org/doi/10.1145/325334.325242 That source establishes its geometry, not downstream quality for neural-network weight merges. Use a SLERP checkpoint as another candidate and measure loss and required tasks just as you would for a linear merge.

The slerp function performs this geometric interpolation. It takes two unnormalized vectors and an interpolation factor t, projects them onto a unit sphere, computes the interpolation, and returns the combined vector:

slerp-spherical-linear-interpolation.py
1import torch 2 3def slerp( 4 v0: torch.Tensor, 5 v1: torch.Tensor, 6 t: float 7) -> torch.Tensor: 8 """Practical SLERP for a single weight tensor.""" 9 flat_v0 = v0.flatten() 10 flat_v1 = v1.flatten() 11 12 v0_mag = flat_v0.norm() 13 v1_mag = flat_v1.norm() 14 if v0_mag.item() == 0 or v1_mag.item() == 0: 15 return (1 - t) * v0 + t * v1 16 17 # Separate direction from magnitude 18 v0_dir = flat_v0 / v0_mag 19 v1_dir = flat_v1 / v1_mag 20 21 dot = torch.dot(v0_dir, v1_dir) 22 omega = torch.acos(torch.clamp(dot, -1.0, 1.0)) 23 24 # Parallel and antipodal directions make the spherical path degenerate. 25 sin_omega = torch.sin(omega) 26 if sin_omega.abs().item() < 1e-6: 27 return (1 - t) * v0 + t * v1 28 29 direction = ( 30 torch.sin((1 - t) * omega) / sin_omega * v0_dir + 31 torch.sin(t * omega) / sin_omega * v1_dir 32 ) 33 magnitude = (1 - t) * v0_mag + t * v1_mag 34 return direction.view_as(v0) * magnitude 35 36v0 = torch.tensor([1.0, 0.0]) 37v1 = torch.tensor([0.0, 1.0]) 38mid = slerp(v0, v1, t=0.5) 39antipodal_mid = slerp(v0, -v0, t=0.5) 40 41print("unit_norm:", bool(torch.allclose(mid.norm(), torch.tensor(1.0), atol=1e-6))) 42print("matches_45_degree:", bool(torch.allclose(mid, torch.tensor([2**-0.5, 2**-0.5]), atol=1e-6))) 43print("antipodal_fallback_finite:", bool(torch.isfinite(antipodal_mid).all())) 44print("midpoint:", [round(float(x), 4) for x in mid]) 45print("norm:", round(float(mid.norm()), 4))
Output
1unit_norm: True 2matches_45_degree: True 3antipodal_fallback_finite: True 4midpoint: [0.7071, 0.7071] 5norm: 1.0

What it guarantees geometrically

In the equal-norm orthogonal-vector example above, the SLERP midpoint remains on the unit circle while a linear midpoint would have smaller norm. That's a geometric property of this example, not evidence that the midpoint preserves either model's behavior. For a pair of checkpoints, evaluate linear and spherical candidates against the same release gates.

Running a merge with mergekit

mergekit[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit is an open-source toolkit for merging language-model checkpoints. Its documented CLI supports YAML-defined merges with CPU or limited-VRAM execution, and mergekit-multi can run multi-stage recipes where later merges consume earlier outputs.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit

To use mergekit, you typically define a YAML configuration file that specifies the base model, the fine-tuned source models, their respective merging coefficients, and the desired algorithm. This configuration acts as the input to the CLI tool to generate the merged model:

running-a-merge-with-mergekit.yaml
1# mergekit config: merge_config.yml 2models: 3 - model: your-org/base-8b-code 4 parameters: 5 weight: 0.35 6 density: 0.5 # retained fraction for this task vector 7 - model: your-org/base-8b-math 8 parameters: 9 weight: 0.35 10 density: 0.5 11 - model: your-org/base-8b-chat 12 parameters: 13 weight: 0.30 14 density: 0.5 15 16merge_method: dare_ties 17base_model: your-org/base-8b 18tokenizer: 19 source: base # switch to union if you must preserve extra tokens 20chat_template: auto # or pin a specific template when model families differ 21dtype: float16

For dare_ties, each source model's density controls the retained fraction of that source's task vector. Merge methods have different schemas, so don't treat merge_method as a drop-in switch: for example, mergekit's slerp method takes exactly two source models.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit If all required tokens are already in the base tokenizer, tokenizer.source: base pins the output vocabulary to that base. Modern mergekit configuration defaults to a union tokenizer, which adds tokens present in source vocabularies and assigns fallback embeddings where an input model lacks them.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit Either policy is an output-space decision that needs targeted evaluation.

Common Mistake: Assuming all specialist checkpoints use the same tokenizer because they began from the same base. If the code checkpoint added fill-in-the-middle tokens such as <fim_prefix>, choosing base drops those added output entries while choosing union introduces filled embeddings for models that lack them. Verify tokenizer vocabularies, choose the output policy explicitly, and test code-completion prompts that require those tokens.

This preflight check makes the output-vocabulary decision explicit before any expensive merge runs:

choose-output-vocabulary-policy.py
1def output_vocab(base_vocab, source_vocabs, policy): 2 if policy == "base": 3 return set(base_vocab) 4 if policy == "union": 5 return set().union(*source_vocabs) 6 raise ValueError("policy must be 'base' or 'union'") 7 8base_vocab = {"<bos>", "def", "return"} 9code_vocab = base_vocab | {"<fim_prefix>"} 10required_tokens = {"def", "<fim_prefix>"} 11 12base_output = output_vocab(base_vocab, [base_vocab, code_vocab], "base") 13union_output = output_vocab(base_vocab, [base_vocab, code_vocab], "union") 14 15print("base_missing_required:", sorted(required_tokens - base_output)) 16print("union_missing_required:", sorted(required_tokens - union_output)) 17print("union_requires_added_embedding_eval:", "<fim_prefix>" not in base_vocab)
Output
1base_missing_required: ['<fim_prefix>'] 2union_missing_required: [] 3union_requires_added_embedding_eval: True

Once the configuration is set, you can execute the merge using the CLI tool. The command below takes the YAML configuration file and the output path, producing the final merged model on disk:

terminal
1# Run merge on a local GPU 2mergekit-yaml merge_config.yml ./output_model --cuda

For hardware-specific and memory-saving flags, check mergekit-yaml --help because supported options vary by version.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit

Mergekit lets engineers build candidate checkpoints without a new gradient-training run. Iterate over parameters such as retained density and task weights only against a defined evaluation suite.

Run an iterative validation loop after every merge: evaluate each target slice, compare it to declared gates and source baselines, and retune or reject any candidate that misses a critical threshold.

Merge validation loop from source models through merged candidate and per-task evaluation, showing that promotion stops when a critical task misses its threshold.
Every merge is provisional until a per-task evaluation suite confirms that each critical slice clears its release threshold instead of hiding misses behind an aggregate score.

An aggregate score is useful for ranking candidates, but a release decision should fail on any critical threshold miss:

evaluate-per-task-release-gates.py
1def failed_release_gates(scores, thresholds): 2 return { 3 task: (scores[task], minimum) 4 for task, minimum in thresholds.items() 5 if scores[task] < minimum 6 } 7 8scores = {"code": 92.4, "math": 82.1, "chat": 87.0} 9thresholds = {"code": 90.0, "math": 85.0, "chat": 84.0} 10failures = failed_release_gates(scores, thresholds) 11 12print("aggregate_score:", round(sum(scores.values()) / len(scores), 1)) 13print("failed_tasks:", sorted(failures)) 14print("promote:", not failures)
Output
1aggregate_score: 87.2 2failed_tasks: ['math'] 3promote: False

Finding good coefficients automatically

Manually searching merge coefficients and layer selections can be expensive. Evolutionary model merging[10]Reference 10Evolutionary Optimization of Model Merging Recipes.https://sakana.ai/evolutionary-model-merge/ applies evolutionary search to optimize merge recipes against a supplied fitness evaluation. Its search space can include per-layer source choices, interpolation weights, and whether to merge in parameter space, data-flow space, or both.

Sakana AI reports using this approach to build EvoLLM-JP from Japanese-language and math-oriented models, optimizing for the evaluations selected in that work.[10]Reference 10Evolutionary Optimization of Model Merging Recipes.https://sakana.ai/evolutionary-model-merge/ The principle is straightforward: treat each merge configuration as a "genome," score it on validation data, mutate its parameters, and retain better-scoring candidates. The resulting model inherits the objective's coverage and blind spots, so release gates still need independent slices.

In practice, a small grid search is a transparent baseline: try lambda values in [0.2, 0.4, 0.6, 0.8] for each task vector, measure each required slice on held-out data, and retain only configurations that clear all release gates. For a code/math/chat merge, those slices should include code-generation tests, math word problems, and instruction-following prompts; a code-only objective doesn't protect math behavior.

Passthrough and frankenmerging

Not every merge averages weights. Mergekit's passthrough method copies selected tensors or layer ranges from source models into the output checkpoint.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit This is model splicing rather than interpolation: tensor dimensions must compose, while useful behavior across the splice remains an evaluation result.

For example, a recipe might copy layers 0-19 from checkpoint A and layers 20-31 from checkpoint B. Compatible dimensions make that artifact constructible; they don't show that B's later layers can interpret the hidden states produced by A's earlier layers.

Use passthrough as an experiment with explicit source lineage, layer boundaries, and the same per-task gates used for any other candidate. A successful build only proves shape compatibility.

Merging pitfalls and hard limits

Direct weight merging requires aligned parameter meaning, shape, and output-space assumptions. You can't directly interpolate a 7-billion-parameter checkpoint with a 70-billion-parameter checkpoint, or silently combine incompatible vocabulary mappings and treat token IDs as equivalent. A generated merged artifact is a candidate, not evidence of retained quality.

Avoid direct interpolation when:

  1. Different architectures: Source models must share the exact same structural architecture, parameter count, and layer layout. You can't directly interpolate a MiniMax model with a Mistral model, nor an 8B model with a 72B model.
  2. Different tokenizers: Direct interpolation assumes aligned embeddings and next-token heads. Mergekit can help with tokenizer union in compatible cases, but it doesn't make arbitrary vocabulary mismatches disappear.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit
  3. Mismatched prompt formats or chat templates: These usually won't block the raw tensor merge, but they can make the merged checkpoint look broken at inference time because the prompt serialization no longer matches the behaviors learned during tuning.
  4. Quantized-only checkpoints: If you want to merge, do it on dequantized or full-precision weights first, then quantize the final artifact. The merge math depends on real-valued deltas, not already-rounded integers. Treat the merged checkpoint as a new model and re-run your quantization calibration and evals.
  5. Distant fine-tuning trajectories: Models fine-tuned on divergent data or with large update magnitudes may be poor interpolation candidates. Git Re-Basin demonstrates permutation alignment in studied MLP, CNN, and ResNet settings; it isn't an established repair step for arbitrary LLM merges.[5]Reference 5Git Re-Basin: Merging Models modulo Permutation Symmetries.https://arxiv.org/abs/2209.04836
  6. Critical precision tasks: Don't ship a merge when a required slice misses its threshold, even if an aggregate metric rises. A specialist baseline remains part of the comparison.

Diagnosing a broken merge

When a merge goes wrong, the model usually tells you quickly. Three common failure patterns, their causes, and their fixes are:

SymptomLikely CauseFix
Output is incoherent or random tokensTokenizer/output mapping, prompt template, or architecture mismatchVerify output vocabulary policy, chat template, and layer shapes
Model loops repetitive textCoefficient overload or weights pushed too far out of distributionReduce coefficient magnitudes, start additive lambdas in the 0.0-1.0 range, and re-run evals
Merged model is worse than every sourceSource interference or incompatible lineageCheck source lineage and tokenizer policy; prefer compatible sources and retune or reject the merge

Don't predict quality from the merge rule alone. Model Soups[3]Reference 3Model Soups: Averaging Weights of Multiple Fine-tuned Models Improves Accuracy without Increasing Inference Timehttps://arxiv.org/abs/2203.05482 reported gains over the best individual checkpoint in its evaluated shared-initialization experiments, including ImageNet settings. That result motivates trying a merge; it doesn't predict whether a new LLM merge will clear its specialist task gates.

After merging, run a full evaluation suite across all target tasks, not the aggregate score alone. Strong code-generation accuracy can mask a miss in math reasoning. Track per-task metrics independently and compare against declared thresholds and each source model's baseline.

Complete the lesson

Mastery Check

Answer every question, then check your score. Score 75% or higher to mark this lesson complete.

1.Two 8B checkpoints have matching parameter counts, but they use different architectures, layer layouts, and pretraining lineages. What should an engineer do?

Correct answer: Don't directly interpolate them; matching size doesn't align parameter meaning.

Direct weight interpolation requires corresponding tensors to have compatible shapes and meanings. Equal model size alone doesn't establish that layers or parameter coordinates represent the same functions, and unrelated lineages make alignment still less plausible. SLERP and DARE don't repair those prerequisites.

2.Two checkpoints share a base model. At alpha = 0.50, interpolation loss is 0.61 and task score is 0.70. The gates are loss <= 0.30 and score >= 0.84. Which conclusion is warranted?

Correct answer: Reject alpha 0.50 because it fails both gates despite the shared lineage.

Shared lineage makes interpolation worth testing, but it doesn't establish midpoint quality. The measured midpoint exceeds the maximum accepted loss and falls below the minimum task score. That rejects this point, not necessarily every other alpha on the path.

3.A greedy soup starts with a validation score of 88. Adding checkpoint X scores 89, adding Y to that soup scores 87, and adding Z after rejecting Y scores 90. Which checkpoints are retained?

Correct answer: Keep X and Z; reject Y because only improving additions enter the soup.

A greedy soup starts with the strongest individual model and retains a candidate only when the resulting average improves the held-out validation metric. X raises the score, Y lowers it and is discarded, and Z then raises the accepted soup's score. The validation set must still represent the capabilities the deployment needs.

4.A base scalar weight is 2.0. A code fine-tune has weight 2.5, and a math fine-tune has weight 1.5. Using task arithmetic with lambda_code = 0.6 and lambda_math = 0.4, what scalar weight is produced?

Correct answer: 2.1, because the merge adds 0.6 times the +0.5 code delta and 0.4 times the -0.5 math delta to the base.

Task arithmetic merges deltas from the shared base: tau_code = 2.5 - 2.0 = +0.5 and tau_math = 1.5 - 2.0 = -0.5. The merged scalar is 2.0 + 0.6(0.5) + 0.4(-0.5) = 2.1. Equal averaging of the final weights would be a different operation and would land at 2.0.

5.At one coordinate, three already-trimmed task-vector deltas are -0.5, +1.1, and -0.4. TIES elects the sign using total signed movement, then disjoint-merges only nonzero deltas that match the elected sign. What happens at this coordinate?

Correct answer: Positive is elected and the merged delta is +1.1, because +1.1 outweighs the two negative deltas in total signed movement.

TIES doesn't use a simple majority vote. It sums the signed trimmed deltas: -0.5 + 1.1 - 0.4 = +0.2, so the elected sign is positive. The disjoint merge then averages only values aligned with that sign; here only +1.1 agrees, so the merged delta is +1.1.

6.A DARE preprocessing step uses drop rate p = 0.75 on a task-vector entry with value 0.4. If that entry survives the random mask, what value is passed to the downstream merge, and why?

Correct answer: 1.6, because DARE divides by 1 - p so the masked entry remains 0.4 in expectation before a downstream merge rule is applied.

With p = 0.75, the keep probability is 1 - p = 0.25. A surviving value is rescaled to 0.4 / 0.25 = 1.6. Since it survives only 25 percent of the time, its expected masked value is 0.25 * 1.6 = 0.4. This sparsification still must feed into a merge method such as averaging or TIES.

7.For equal-norm orthogonal vectors v0 = [1, 0] and v1 = [0, 1], a SLERP midpoint is approximately [0.7071, 0.7071], while a linear midpoint is [0.5, 0.5]. What does this establish for model merging?

Correct answer: SLERP preserves the unit-sphere geometry in this example, but the resulting checkpoint still needs loss and task evaluation.

SLERP follows an angular path between normalized directions, so the midpoint of these orthogonal unit vectors stays on the unit circle. That's only a geometric guarantee. The lesson explicitly warns that SLERP geometry doesn't establish retained neural-network behavior or a low-loss merge.

8.Two independently trained networks with the same architecture learned similar hidden features, but one stores them in slots [A, B, C] and the other in slots [C, A, B]. Why would Git Re-Basin apply a permutation before averaging?

Correct answer: To reorder one model's hidden units and corresponding weights so that averaging combines matching features rather than unrelated slots.

Permutation invariance means hidden-unit slot numbers aren't semantic identifiers. If equivalent features occupy different slots, naive averaging can combine mismatched units. Git Re-Basin searches for a neuron permutation that aligns one model to the other before averaging in its studied settings.

9.A base tokenizer contains , def, and return. A code checkpoint added <fim_prefix>, and fill-in-the-middle prompts are required after the merge. What tokenizer policy issue must be handled before trusting the merged model?

Correct answer: Using the base tokenizer would omit <fim_prefix>; using a union tokenizer can include it, but added or fallback embeddings still require targeted evaluation.

Tokenizer choice is an output-space decision. Pinning the output to the base vocabulary drops tokens that only exist in a source checkpoint. A union tokenizer can preserve added tokens, but models that lack those tokens need fallback embeddings, so fill-in-the-middle prompts still need evaluation.

10.A merged assistant scores code = 92.4, math = 82.1, and chat = 87.0. The release gates are code >= 90.0, math >= 85.0, and chat >= 84.0. The aggregate score is 87.2. What release decision follows?

Correct answer: Block promotion, because the math slice misses its threshold even though the aggregate and the other two slices look acceptable.

The lesson's release logic fails a candidate on any critical threshold miss. Here math is 82.1, below the required 85.0, so the model should not be promoted. The aggregate can help rank candidates, but it must not hide a failed specialist capability.

10 questions remaining.

Next Step
Continue to Vector DB Internals: HNSW & IVF

You can now train, adapt, distill, and combine model weights under evaluation gates. The advanced systems phase begins with retrieval infrastructure, where <span data-glossary="hnsw">HNSW</span>, IVF, and <span data-glossary="product-quantization">Product Quantization</span> decide which evidence reaches those models under latency and memory limits.

PreviousKnowledge Distillation for LLMs
Share this article
XFacebookLinkedInBlueskyRedditHacker NewsEmail
References

Mergekit: Tools for merging pre-trained large language models

Goddard, C., et al. · 2023

https://github.com/arcee-ai/mergekit

Linear Mode Connectivity and the Lottery Ticket Hypothesis.

Frankle, J., Dziugaite, G. K., Roy, D. M., & Carlin, M. · 2020 · ICML 2020

https://arxiv.org/abs/1912.05671

Model Soups: Averaging Weights of Multiple Fine-tuned Models Improves Accuracy without Increasing Inference Time

Wortsman, M., et al. · 2022 · ICML 2022

https://arxiv.org/abs/2203.05482

The Role of Permutation Invariance in Linear Mode Connectivity of Neural Networks.

Entezari, R., Sedghi, H., Saukh, O., & Neyshabur, B. · 2022 · ICLR 2022

https://arxiv.org/abs/2110.06296

Git Re-Basin: Merging Models modulo Permutation Symmetries.

Ainsworth, S. K., Hayase, J., & Srinivasa, S. · 2022 · ICLR 2023

https://arxiv.org/abs/2209.04836

Editing Models with Task Arithmetic

Ilharco, G., et al. · 2022 · ICLR 2023

https://arxiv.org/abs/2212.04089

TIES-Merging: Resolving Interference When Merging Models

Yadav, P., et al. · 2023 · NeurIPS 2023

https://arxiv.org/abs/2306.01708

Language Models are Super Mario: Absorbing Capabilities from Homologous Models as a Free Lunch

Yu, L., et al. · 2023 · ICML 2024

https://arxiv.org/abs/2311.03099

Animating Rotation with Quaternion Curves

Shoemake, K. · 1985 · SIGGRAPH '85

https://dl.acm.org/doi/10.1145/325334.325242

Evolutionary Optimization of Model Merging Recipes.

Sakana AI · 2024

https://sakana.ai/evolutionary-model-merge/

Discussion

Questions and insights from fellow learners.

Discussion loads when you reach this section.