Task Arithmetic
Bei der Task-Arithmetik wird ein vortrainiertes Modell durch Addieren, Subtrahieren oder Kombinieren von Aufgabenvektoren verändert. So lassen sich Fähigkeiten zusammenführen oder Verhaltensweisen entfernen – ganz ohne Training.
Task-Arithmetik ist ein Verfahren zum Bearbeiten eines vortrainierten Modells durch Addition und Subtraktion von Aufgabenvektoren, also den Gewichtsänderungen, die das Fine-Tuning für jede Aufgabe hervorgerufen hat. Addiert man die Aufgabenvektoren mehrerer Aufgaben zu den vortrainierten Modellgewichten, entsteht ein Modell, das alle diese Aufgaben bewältigt. Durch Subtraktion eines Aufgabenvektors wird das Modell bei der betreffenden Aufgabe schlechter, während die übrigen Aufgaben weitgehend unbeeinträchtigt bleiben. Bei einer Analogie überträgt die Kombination von Vektoren eine Fähigkeit auf eine Umgebung ohne beschriftete Daten. Jede Bearbeitung besteht aus einer elementweisen Addition der Gewichte. Dafür werden außer den ursprünglichen Fine-Tuning-Durchläufen weder Trainingsdaten noch Gradientenberechnungen benötigt. Gabriel Ilharco und seine Kolleginnen und Kollegen an der University of Washington, Microsoft Research und dem Allen Institute for AI stellten das Verfahren in Editing Models with Task Arithmetic vor, das 2023 auf der ICLR veröffentlicht wurde.
Die drei Operationen#
Alle drei Operationen erzeugen neue Gewichte nach der Formel θ_new = θ_pretrained + λτ_new. Der Skalierungskoeffizient λ wird anhand zurückgehaltener Validierungsdaten ausgewählt. Ilharco und sein Team testeten die Operationen an CLIP-Modellen, die für acht Aufgaben der Bildklassifizierung – etwa die Erkennung von Verkehrsschildern und Satellitenbildern – feinabgestimmt wurden, sowie an den Sprachmodellen GPT-2 und T5.
Negation verwendet τ_new = −τ, damit ein Modell eine Aufgabe verlernt. Durch Negation der acht CLIP-Aufgabenvektoren sank die durchschnittliche Genauigkeit des ViT-L/14-Modells bei diesen Aufgaben um 45,8 Prozentpunkte, während mindestens 95 % der ImageNet-Genauigkeit erhalten blieben. Durch Subtraktion eines Vektors, der mit toxischen Kommentaren feinabgestimmt wurde, sank der Anteil toxischer Ausgaben von GPT-2 Large von 4,8 % auf 0,8 %. Die Perplexität bei gewöhnlichen Texten lag dabei höchstens 0,5 Punkte über der des ursprünglichen Modells.
Addition verwendet τ_new = τ_1 + τ_2 + …, um Modelle für mehrere Aufgaben zu erstellen. Durch Addition der Vektoren zweier CLIP-Aufgaben entstand ein Modell, das im Durchschnitt 98,9 % der Genauigkeit der beiden spezialisierten Modelle erreichte. Bei Addition aller acht Vektoren lag der Wert bei 91,2 %.
Analogien kommen zum Einsatz, wenn Aufgaben nach dem Muster „A verhält sich zu B wie C zu D“ zusammenhängen. Dabei gilt τ_D ≈ τ_C + (τ_B − τ_A). Ilharco und sein Team erstellten ein Modell zur Sentimentanalyse von Yelp-Bewertungen, ohne beschriftete Yelp-Daten zu verwenden. Dazu addierten sie einen Vektor für die Stimmung in Amazon-Bewertungen zur Differenz zwischen Sprachmodellierungsvektoren, die mit Yelp- und Amazon-Texten trainiert wurden.
Diese Operationen funktionieren, weil Aufgabenvektoren verschiedener Aufgaben in nahezu orthogonale Richtungen weisen und Kosinusähnlichkeiten nahe null aufweisen. Die Addition eines Vektors verändert daher kaum, was ein anderer Vektor codiert. Mit der Zahl der Aufgaben nimmt die gegenseitige Beeinflussung dennoch zu. Verfahren zum Zusammenführen von Modellen wie TIES-Merging verringern diesen Effekt, indem sie die kleinsten Änderungen jedes Vektors entfernen und Parameter mit widersprüchlichen Vorzeichen auflösen, bevor die Vektoren addiert werden.
Fähigkeiten im Code hinzufügen und negieren#
Dieses PyTorch-Beispiel trainiert zunächst kurz einen kleinen Klassifikator mit handgeschriebenen Ziffern im Format 8x8. Anschließend wird die erste Schicht für zwei Aufgaben feinabgestimmt: Aufgabe A klassifiziert die Ziffern 0–4, Aufgabe B die Ziffern 5–9. Jede Aufgabe liest ihre Werte aus den jeweils eigenen fünf eingefrorenen Ausgabelogits aus, so wie im Paper jede CLIP-Aufgabe ihren eigenen eingefrorenen Klassifikationskopf verwendet. Danach werden die vortrainierten Gewichte mit verschiedenen Kombinationen der beiden Aufgabenvektoren ausgewertet:
import copy
import torch
from sklearn.datasets import load_digits
from torch import nn
torch.manual_seed(0)
X, y = load_digits(return_X_y=True)
X, y = torch.tensor(X / 16, dtype=torch.float32), torch.tensor(y)
tasks = {"A": (0, 5), "B": (5, 10)} # task A classifies digits 0-4, task B digits 5-9, each with its own 5 logits
train, test = torch.arange(len(X)) < 1000, torch.arange(len(X)) >= 1000
def task_loss(model, task, rows):
"""Cross-entropy and accuracy of one task's 5-way classifier on the given rows."""
lo, hi = tasks[task]
keep = rows & (y >= lo) & (y < hi)
logits, labels = model(X[keep])[:, lo:hi], y[keep] - lo
return nn.functional.cross_entropy(logits, labels), (logits.argmax(1) == labels).float().mean().item()
def fit(model, params, steps, loss_fn):
"""Run full-batch SGD on the given parameters."""
optimizer = torch.optim.SGD(params, lr=0.05, momentum=0.9)
for _ in range(steps):
optimizer.zero_grad()
loss_fn().backward()
optimizer.step()
return model
# Pretrained model: a few steps on 200 images of all ten digits
base = nn.Sequential(nn.Linear(64, 64), nn.ReLU(), nn.Linear(64, 10))
fit(base, base.parameters(), 50, lambda: nn.functional.cross_entropy(base(X[:200]), y[:200]))
# Fine-tune the first layer for each task (heads stay frozen) and keep the task vectors
vectors = {}
for task in tasks:
tuned = copy.deepcopy(base)
fit(tuned, tuned[0].parameters(), 100, lambda: task_loss(tuned, task, train)[0])
vectors[task] = {k: v - base.state_dict()[k] for k, v in tuned.state_dict().items()}
edits = {"Pretrained": {}, "+A": {"A": 1}, "+B": {"B": 1}, "+A +B": {"A": 1, "B": 1}, "-A": {"A": -1}}
for name, coefs in edits.items():
# Pretrained weights plus a weighted sum of task vectors
model = copy.deepcopy(base)
weights = {k: v + sum(c * vectors[t][k] for t, c in coefs.items()) for k, v in base.state_dict().items()}
model.load_state_dict(weights)
with torch.no_grad():
print(f"{name}: task A {task_loss(model, 'A', test)[1]:.3f}, task B {task_loss(model, 'B', test)[1]:.3f}")Bei den 797 Testziffern erreicht das vortrainierte Modell bei Aufgabe A 0.802 und bei Aufgabe B 0.897. Die Addition des Vektors von Aufgabe A erhöht den Wert für Aufgabe A auf 0.925, senkt aber den Wert für Aufgabe B auf 0.850. Das ist das katastrophale Vergessen, das bei gewöhnlichem Fine-Tuning auftritt. Die Addition des Vektors von Aufgabe B allein bewirkt das Gegenteil. Werden beide Vektoren addiert, erreicht ein einzelnes Modell 0.922 und 0.940 und kommt damit bei der jeweiligen Aufgabe beinahe an die spezialisierten Modelle heran. Durch Subtraktion des Vektors von Aufgabe A sinkt der Wert für Aufgabe A auf 0.616, während sich der Wert für Aufgabe B nur von 0.897 auf 0.887 verändert.
Voraussetzungen und Grenzen#
Bei der Task-Arithmetik müssen alle Fine-Tuning-Durchläufe mit denselben vortrainierten Gewichten und derselben Architektur beginnen. Wenn Ultralytics YOLO26 mit yolo26n.pt auf einem neuen Datensatz trainiert wird, kopiert das Modell alle vortrainierten Tensoren mit passenden Abmessungen, ordnet Zeilen im Klassifikationskopf anhand der Klassennamen zu und protokolliert die Anzahl mit „Transferred N/M items from pretrained weights“. Bei Datensätzen mit unterschiedlicher Anzahl von Klassen haben die abschließenden Faltungen für die Klassifikation verschiedene Abmessungen. Daher lassen sich Aufgabenvektoren aus diesen Trainingsläufen nur in den gemeinsamen Schichten addieren.
Die Arithmetik funktioniert auch nicht mehr zuverlässig, wenn Vektoren miteinander in Konflikt stehen oder zu stark skaliert werden, denn große λ-Werte verschieben die Gewichte aus dem Bereich heraus, in dem die feinabgestimmten Modelle gut abschneiden. Eine Negation mindert die Leistung bei allen Inhalten, die von den Fine-Tuning-Daten abgedeckt wurden, und ist damit eine einfache Form des maschinellen Verlernens. Guillermo Ortiz-Jimenez, Alessandro Favero und Pascal Frossard führten erfolgreiche Arithmetik in Task Arithmetic in the Tangent Space auf die Entflechtung der Gewichte zurück: Getrennte Richtungen im Gewichtsraum verändern die Modellausgaben in getrennten, nicht überlappenden Bereichen des Eingaberaums. Außerdem zeigten sie, dass Fine-Tuning einer linearisierten Version des Modells diesen Effekt verstärkt.
Task-Arithmetik im Vergleich zu verwandten Konzepten#
- Aufgabenvektoren: Die Gewichtsänderungen, auf denen Task-Arithmetik beruht. Task-Arithmetik umfasst die Operationen Addition, Negation und Analogiebildung.
- Modellsuppen: Mittelt mehrere Feinabstimmungen für dieselbe Aufgabe, um diese Aufgabe zu verbessern. Bei der Aufgabenarithmetik werden Feinabstimmungen verschiedener Aufgaben addiert. Zwei Aufgabenvektoren mit λ = 0.5 zu addieren entspricht dem Mitteln der beiden feinabgestimmten Modelle.
- Modellanpassung: Ändert gezielt eine Tatsache oder ein eng umrissenes Verhalten, häufig durch ein Update der Gewichte in geschlossener Form. Aufgabenarithmetik passt ganze Aufgaben auf einmal an.
- Training mit mehreren Aufgaben: Trainiert ein Modell gemeinsam mit den Daten aller Aufgaben. Dadurch wird gegenseitige Beeinflussung vermieden, aber alle Datensätze müssen gleichzeitig verfügbar sein. Aufgabenarithmetik kombiniert Modelle, deren Daten möglicherweise nicht mehr verfügbar sind, und vermeidet das Vergessen, das entsteht, wenn Aufgaben nacheinander feinabgestimmt werden.










