Beskärning och gleshet
Kunna beskära vikter och mäta accuracy–hastighet.
Förkunskaper
- FKvantiseringkrävs
Intuition
Beskärning (pruning) tar bort vikter som bidrar lite. Två familjer med helt olika praktiska konsekvenser:
| Typ | Vad tas bort | Kompression | Snabbare? |
|---|---|---|---|
| Ostrukturerad | enskilda vikter, var som helst | hög (50–90 %) | oftast nej utan specialstöd |
| Strukturerad | hela kanaler, huvuden, lager | lägre (10–50 %) | ja, direkt |
| Semi-strukturerad (2:4) | 2 av 4 intilliggande vikter | 50 % | ja, på Ampere+ med sparse tensor cores |
Den vanligaste besvikelsen: man beskär bort 80 % av vikterna, filen blir liten — och inferensen går precis lika långsamt. Ostrukturerad gleshet kräver hårdvaru- eller kärnstöd för att ge hastighet; annars multipliceras nollorna precis som alla andra tal.
Formellt
Magnitudbeskärning är baslinjen: ta bort de vikter som har minst absolutbelopp, lager för lager eller globalt. Enkelt och förvånansvärt starkt.
SparseGPT och Wanda är post-training-metoder anpassade för stora språkmodeller. Wanda är slående enkel: viktighet = — viktens storlek gånger normen på motsvarande aktivering, beräknad på kalibreringsdata. Ingen omträning, ingen gradientberäkning, och den når 50 % gleshet med liten förlust.
Lotteribiljettshypotesen (Frankle & Carbin 2018): i ett slumpmässigt initierat nät finns ett litet delnät som, tränat från samma initiering, kan nå jämförbar prestanda. Det förklarar varför beskärning fungerar — men ger inte en praktisk väg till snabbare träning, eftersom delnätet hittas genom att först träna hela nätet.
Beslutsordning i praktiken: kvantisering först (enklare, ger nästan alltid hastighet), sedan strukturerad beskärning om mer behövs, och ostrukturerad bara om körmiljön har stöd för den. Att kombinera kvantisering och gleshet fungerar men kräver noggrann mätning — förlusterna adderas inte linjärt.
Kod
import torch
def magnitudbeskar(modell, andel=0.5, global_=True):
"""Nollställ de minsta vikterna. Returnerar faktisk gleshet."""
vikter = [p for n, p in modell.named_parameters() if p.dim() > 1]
if global_:
alla = torch.cat([p.detach().abs().flatten() for p in vikter])
trosk = torch.quantile(alla, andel)
for p in vikter:
p.data[p.abs() < trosk] = 0
else:
for p in vikter:
trosk = torch.quantile(p.detach().abs().flatten(), andel)
p.data[p.abs() < trosk] = 0
nollor = sum(int((p == 0).sum()) for p in vikter)
totalt = sum(p.numel() for p in vikter)
return nollor / totalt
def wanda_poang(W, aktiveringsnorm):
"""Wanda: |w| * ||x||. aktiveringsnorm: (in_features,) från kalibreringsdata."""
return W.abs() * aktiveringsnorm.unsqueeze(0)
# Mät ALLTID tre saker efter beskärning:
# 1. gleshet (andel nollor) 2. kvalitet på din eval 3. faktisk tokens/s
# Om (3) är oförändrad har du bara gjort modellen sämre.
Behärskning innebär
- Beskär vikter strukturerat och ostrukturerat
- Mäter avvägningen accuracy mot hastighet
- Vet när gleshet faktiskt ger snabbare inferens
Logga in för att göra övningarna och bygga upp din behärskning.
Källor
- arXiv — A Simple and Effective Pruning Approach for Large Language Models (Wanda) — arXiv (öppen åtkomst; licens per artikel)
- arXiv — SparseGPT: Massive Language Models Can Be Accurately Pruned in One-Shot — arXiv (öppen åtkomst; licens per artikel)
- arXiv — The Lottery Ticket Hypothesis — arXiv (öppen åtkomst; licens per artikel)