Begreper & referanser
Alle nøkkelbegrepene, formlene og referansene fra Forklarbar maskinlæring, samlet på én side. Bruk denne som oppslag når du leser, øver flashcards eller tar quiz.
Begreper
Sentrale begreper fra kapittelet med korte definisjoner.
I hvilken grad et menneske kan forstå hvordan modellens input henger sammen med prediksjonene.
En forklaring som gjelder én bestemt prediksjon eller et lite område rundt den.
En oppsummering av modellens overordnede oppførsel på tvers av mange observasjoner.
En enklere modell som trenes til å etterligne en mer kompleks modell lokalt eller globalt.
En metode som tilpasser en enkel, lokalt vektet surrogatmodell rundt observasjonen som skal forklares.
En familie av metoder som fordeler forskjellen fra en baseline på features ved hjelp av Shapley-prinsipper.
Et gjennomsnittlig marginalbidrag som tar hensyn til alle mulige rekkefølger features kan inngå i.
Et tallfestet bidrag fra en feature til en bestemt prediksjon eller modellscore.
En kunstig variant av en observasjon der én eller flere featureverdier er endret litt eller byttet ut. LIME spør modellen om mange perturbasjoner for å se hvordan den oppfører seg i nabolaget.
Hvor godt en forklaring eller surrogatmodell etterligner modellen den forklarer, i området forklaringen gjelder. Høy fidelity sier ikke at modellen er riktig, rettferdig eller kausal.
Referanseverdien i en additiv forklaring, typisk modellens gjennomsnittlige output over bakgrunnsdataene. Bidragene forklarer avstanden fra baseline til prediksjonen.
Et beeswarm-plott med én rad per feature, sortert etter gjennomsnittlig , der x-aksen viser SHAP-verdien og fargen viser featureverdien for hver observasjon.
Formler
Hver formel: hva den heter, hvordan den ser ut, og hva symbolene betyr.
Shapley-verdi
Shapley-verdien er feature sitt gjennomsnittlige marginalbidrag over alle rekkefølger av features.
LIME-mål
LIME balanserer lokal likhet med originalmodellen mot enkelheten til forklaringsmodellen .
Additiv forklaringsmodell
En additiv forklaring deler prediksjonen i en baseline og ett bidrag per feature.
LIME-nærhetsvekt
Nabopunkter nær observasjonen får vekt nær 1, fjerne punkter vekt nær 0. Kernelbredden bestemmer hvor stort nabolaget er.
Shapley-verdi via rekkefølger
Snittet av marginalbidraget til spiller over alle rekkefølger spillerne kan komme inn i.
Effektivitet
Shapley-verdiene fordeler hele forskjellen mellom alle spillere og ingen spillere. Nyttig kontroll når du regner for hånd.
SHAP for lineær modell
For en lineær modell med uavhengige features er bidraget vekt ganger avviket fra gjennomsnittet i bakgrunnsdataene.
Kodesnutter
Kodesnutter fra kapittelet, vist literal.
Lokal effekt og globale snitt for en vekselvirkning
import numpy as np rng = np.random.default_rng(16)X = rng.uniform(-1, 1, size=(500, 2)) # bakgrunnsdata med to features# 1 = ren vekselvirkning 2·x1·x2, 0 = additiv modell 2·x1 + x2samspill = 1.0 # @param 0..1 0.1 def f(X): return samspill * 2 * X[:, 0] * X[:, 1] + (1 - samspill) * (2 * X[:, 0] + X[:, 1]) def effekt_x1(X, h=1e-4): Xh = X.copy() Xh[:, 0] += h return (f(Xh) - f(X)) / h # lokal helning for x1 i hvert punkt A = np.array([[0.5, 0.8]])B = np.array([[0.5, -0.8]])print(f"lokal effekt av x1 i A: {effekt_x1(A)[0]:+.2f}")print(f"lokal effekt av x1 i B: {effekt_x1(B)[0]:+.2f}")alle = effekt_x1(X)print(f"globalt snitt med fortegn: {alle.mean():+.2f}")print(f"globalt snitt av |effekt|: {np.abs(alle).mean():.2f}")Prøv: Dra samspill fra 1 til 0 og se «lokal effekt av x1» i A og B bli lik «globalt snitt» når vekselvirkningen forsvinner.
En lokal, vektet lineær surrogatmodell
import numpy as npimport matplotlib.pyplot as plt rng = np.random.default_rng(4172)x0 = np.array([0.4, -0.7])naboer = x0 + rng.normal(0, 0.55, size=(300, 2)) # perturbasjoner rundt x0bredde = 0.45 # @param 0.05..5 0.05 def svart_boks(X): score = 1.4 * X[:, 0] - 0.9 * X[:, 1] + 0.8 * X[:, 0] * X[:, 1] return 1 / (1 + np.exp(-score)) y = svart_boks(naboer)vekt = np.exp(-np.sum((naboer - x0) ** 2, axis=1) / bredde) # kernel: nære naboer teller mestA = np.column_stack([np.ones(len(naboer)), naboer])koef = np.linalg.lstsq(A * np.sqrt(vekt[:, None]), y * np.sqrt(vekt), rcond=None)[0]rest = np.sum(vekt * (y - A @ koef) ** 2) / np.sum(vekt * (y - np.average(y, weights=vekt)) ** 2)print(f"helninger {np.round(koef[1:], 3)}, lokal fidelity (vektet R²) {1 - rest:.3f}") t = np.linspace(-1.2, 2.0, 100) # snitt langs feature 1 gjennom x0snitt = np.column_stack([t, np.full_like(t, x0[1])])plt.figure()plt.plot(t, svart_boks(snitt), label="svart boks")plt.plot(t, np.column_stack([np.ones_like(t), snitt]) @ koef, label="lokal surrogat")plt.xlabel("feature 1 (feature 2 holdt fast i x0)")plt.ylabel("modellens output")plt.legend()plt.tight_layout()plt.show()Prøv: Dra bredde fra 0,45 mot 5 og se den rette linjen slippe kurven rundt x0, mens «lokal fidelity» faller.
Shapley-verdier med rå kraft over alle rekkefølger
from itertools import permutationsfrom math import factorial spillere = ["Avstand", "Regn", "Ledige bud"]v_avstand_regn = 16 # @param 0..30# v(S): ekstra minutter når bare featurene i S har sin faktiske verdiv = {(): 0, ("Avstand",): 10, ("Regn",): 4, ("Ledige bud",): -2, ("Avstand", "Regn"): v_avstand_regn, ("Avstand", "Ledige bud"): 6, ("Regn", "Ledige bud"): 2, ("Avstand", "Regn", "Ledige bud"): 12} def verdi(S): return v[tuple(p for p in spillere if p in S)] phi = {p: 0.0 for p in spillere}for rekkefolge in permutations(spillere): # alle 3! = 6 rekkefølger S = set() for p in rekkefolge: phi[p] += verdi(S | {p}) - verdi(S) # marginalbidraget til p S.add(p) n_fak = factorial(len(spillere))for p in spillere: print(f"{p:11s} φ = {phi[p] / n_fak:6.2f}")print(f"sum φ = {sum(phi.values()) / n_fak:.2f}, v(alle) - v(tom) = {verdi(spillere) - verdi([])}")Prøv: Dra v_avstand_regn og se hvilke φ-linjer som endrer seg, og at «sum φ» fortsatt er lik «v(alle) - v(tom)».
Eksakte Shapley-bidrag for tre features
import itertoolsimport mathimport numpy as np x = np.array([1.2, -0.6, 0.8])b0 = 0.0 # @param 0..1 0.1b2 = 0.0 # @param 0..1 0.1baseline = np.array([b0, 0.0, b2]) # bakgrunnsverdier for x0, x1, x2 def modell(v): return 0.25 + 0.7 * v[0] - 0.4 * v[1] + 0.3 * v[0] * v[2] d = len(x)phi = np.zeros(d)for j in range(d): andre = [k for k in range(d) if k != j] for r in range(d): for S in itertools.combinations(andre, r): v = baseline.copy() v[list(S)] = x[list(S)] # featurene i S får sin faktiske verdi uten = modell(v) v[j] = x[j] # ... og så legger vi til j vekt = math.factorial(r) * math.factorial(d - r - 1) / math.factorial(d) phi[j] += vekt * (modell(v) - uten) print(f"baseline-output φ0 = {modell(baseline):.3f}")print(f"bidrag φ = {np.round(phi, 3)}")print(f"φ0 + sum φ = {modell(baseline) + phi.sum():.3f}, modell(x) = {modell(x):.3f}")Prøv: Dra b0 og b2 og se «bidrag φ» endre seg, mens «φ0 + sum φ» alltid er lik «modell(x)».
Les et sammendragsplott med kode
import numpy as np navn = ["Avstand", "Ledige bud", "Regn", "Ordrestørrelse"]# SHAP-verdier i minutter for seks leveranser (én kolonne per feature)phi = np.array([[9.0, -4.0, 0.5, 1.0], [3.0, 6.0, 4.0, -0.5], [-5.0, -3.5, 0.0, 0.5], [7.5, 5.0, -1.0, 0.0], [-6.0, -2.0, 3.5, -1.0], [1.0, 4.5, 0.0, 0.5]])# Normaliserte featureverdier, 0 = lav og 1 = høy (fargen i plottet)verdi = np.array([[0.9, 0.7, 0.3, 0.8], [0.6, 0.1, 0.9, 0.2], [0.1, 0.8, 0.2, 0.6], [0.8, 0.2, 0.1, 0.4], [0.0, 0.6, 0.8, 0.1], [0.5, 0.0, 0.2, 0.7]])snu_regn = 0 # @param 0..1if snu_regn: phi[:, 2] *= -1 # bytt fortegn på hele Regn-kolonnen viktighet = np.abs(phi).mean(axis=0)for j in np.argsort(-viktighet): # viktigst øverst, som i plottet r = np.corrcoef(verdi[:, j], phi[:, j])[0, 1] retning = "høy verdi trekker opp" if r > 0 else "høy verdi trekker ned" print(f"{navn[j]:15s} snitt |φ| = {viktighet[j]:4.2f} {retning} (r = {r:+.2f})")Prøv: Sett snu_regn til 1 og se «Regn» snu fra «trekker opp» til «trekker ned», mens rekkefølgen etter «snitt |φ|» står stille.
Like prediksjoner, ulike forklaringer
import numpy as np rng = np.random.default_rng(3)n = 200stoy = 0.05 # @param 0..1 0.05x1 = rng.normal(0, 1, n) # ordre siste time (standardisert)x2 = x1 + rng.normal(0, stoy, n) # aktive brukere i appen: nesten en kopiX = np.column_stack([x1, x2])snitt = X.mean(axis=0)x = X[0] # leveransen vi forklarer for navn, w in [("A", np.array([2.0, 0.0])), ("B", np.array([1.0, 1.0]))]: phi = w * (x - snitt) # lineær SHAP: w_j (x_j - snitt_j) print(f"modell {navn}: f(x) = {x @ w:+.2f} φ = {np.round(phi, 2)}") avvik = np.abs(X @ np.array([2.0, 0.0]) - X @ np.array([1.0, 1.0]))print(f"største forskjell i prediksjon over datasettet: {avvik.max():.2f}")Prøv: Dra stoy i x2 opp mot 1 og se «største forskjell i prediksjon» vokse, mens φ for modell A og B var ulike hele tiden.
Læringsmål
Hva du skal kunne etter å ha lest kapittelet.
- 01Skill mellom lokale og globale forklaringer og velg riktig nivå for et gitt spørsmål
- 02Forklar hvordan LIME bruker perturbasjoner, nærhetsvekting og en enkel surrogatmodell, og hva fidelity måler
- 03Regn ut Shapley-verdier for tre features fra en tabell over og kontroller svaret med effektivitet
- 04Regn ut en additiv SHAP-forklaring og tolk fortegnet relativt til baseline
- 05Tolk et SHAP-sammendragsplott ut fra rekkefølge, x-akse og farge
- 06Forklar hvorfor featureattribusjon ikke viser kausalitet, særlig når features er korrelerte