Muistiinpano
Tämän sivun käyttö edellyttää valtuutusta. Voit yrittää kirjautua sisään tai vaihtaa hakemistoa.
Tämän sivun käyttö edellyttää valtuutusta. Voit yrittää vaihtaa hakemistoa.
Käytä Kernel SHAP (SHapley Additive ExPlanations) selittämään taulukkomaisen luokittelumallin. Kernel SHAP on malliriippumaton menetelmä, joka arvioi kunkin ominaisuuden panosta mallin ennusteeseen. Koulutat logistisen regressiomallin Adult Census Income -aineistolla ja käytät sitten SynapseML-muuntajaa TabularSHAP ominaisuustason selityksien laskemiseen.
Edellytykset
Hanki Microsoft Fabric -tilaus. Voit myös rekisteröityä ilmaiseen Microsoft Fabric -kokeiluversioon.
Vaihda Fabric-tilaan käyttämällä etusivun vasemmassa alakulmassa olevaa kokemuskytkintä.
- Luo uusi muistikirja työtilaasi ja kiinnitä se järvimajaan. Lisätietoja löytyy kohdasta Luo muistikirja.
SynapseML, PySpark, pandas ja plotly on valmiiksi asennettu Fabric-muistikirjaympäristöihin. Lisäpakettien asennusta ei tarvita.
Tuo paketteja ja määrittele apu-UDF:t
Liitä seuraava koodi Fabric-muistikirjaasi soluun ja suorita se. Tämä vaihe tuo tarvittavat kirjastot ja määrittelee kaksi käyttäjän määrittelemää funktiota (UDF) vektorielementtien poimimista varten myöhemmin.
import pyspark
from synapse.ml.explainers import TabularSHAP
from pyspark.ml import Pipeline
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.feature import StringIndexer, OneHotEncoder, VectorAssembler
from pyspark.sql.types import FloatType, ArrayType
from pyspark.sql.functions import col, lit, rand, broadcast, udf
import pandas as pd
vec_access = udf(lambda v, i: float(v[i]), FloatType())
vec2array = udf(lambda vec: vec.toArray().tolist(), ArrayType(FloatType()))
Vahvista: Suorita seuraava koodi uudessa solussa. Sinun pitäisi nähdä ulostulo TabularSHAP imported successfully.
print("TabularSHAP imported successfully")
print(f"PySpark version: {pyspark.__version__}")
Lataa data ja kouluta luokitusmalli
Lataa Adult Census Income -tietoaineisto Azure Blob Storage:sta, indeksoi kohdetunniste ja kouluta logistinen regressioputki.
df = spark.read.parquet(
"wasbs://publicwasb@mmlspark.blob.core.windows.net/AdultCensusIncome.parquet"
)
labelIndexer = StringIndexer(
inputCol="income", outputCol="label", stringOrderType="alphabetAsc"
).fit(df)
print("Label index assignment: " + str(set(zip(labelIndexer.labels, [0, 1]))))
training = labelIndexer.transform(df).cache()
categorical_features = [
"workclass",
"education",
"marital-status",
"occupation",
"relationship",
"race",
"sex",
"native-country",
]
categorical_features_idx = [feat + "_idx" for feat in categorical_features]
categorical_features_enc = [feat + "_enc" for feat in categorical_features]
numeric_features = [
"age",
"education-num",
"capital-gain",
"capital-loss",
"hours-per-week",
]
strIndexer = StringIndexer(
inputCols=categorical_features, outputCols=categorical_features_idx
)
onehotEnc = OneHotEncoder(
inputCols=categorical_features_idx, outputCols=categorical_features_enc
)
vectAssem = VectorAssembler(
inputCols=categorical_features_enc + numeric_features, outputCol="features"
)
lr = LogisticRegression(featuresCol="features", labelCol="label", weightCol="fnlwgt")
pipeline = Pipeline(stages=[strIndexer, onehotEnc, vectAssem, lr])
model = pipeline.fit(training)
Vahvista: Käynnistä seuraava solu. Sinun pitäisi nähdä rivimäärät koulutusdatalle ja putkivaiheiden vahvistuksille.
print(f"Training rows: {training.count()}")
print(f"Pipeline stages: {[type(s).__name__ for s in model.stages]}")
assert training.count() > 30000, "Dataset should contain over 30,000 rows"
print("Model trained successfully")
# Expected output:
#Training rows: 32561
#Pipeline stages: ['StringIndexerModel', 'OneHotEncoderModel', #'VectorAssembler', 'LogisticRegressionModel']
#Model trained successfully
Valikoituja havaintoja selitettäväksi
Valitse satunnaisesti viisi havaintoa pisteytetystä harjoitusdatasta. Nämä havainnot ovat tilanteita, joissa luot SHAP-selityksiä.
explain_instances = (
model.transform(training).orderBy(rand()).limit(5).repartition(200).cache()
)
display(explain_instances)
Vahvista: Vahvista otoskoko.
count = explain_instances.count()
print(f"Explain instances: {count}")
assert count == 5, f"Expected 5 rows, got {count}"
print("Sample selected successfully")
Määritä ja aja TabularSHAP
Luo selitys TabularSHAP ja sovella sitä valittuihin havaintoihin. Keskeiset parametrit ovat:
| Parametri | Description |
|---|---|
inputCols |
Mallin käyttämät ominaisuussarakkeet ennustamiseen. |
outputCol |
Nimi sarakkeelle, joka sisältää SHAP-tulosarvot. |
numSamples |
Perturbaationäytteiden määrä ytimen SHAP-estimaatiota varten. Korkeammat arvot ovat tarkempia, mutta hitaampia. |
model |
Koulutettu putkimalli selittää. |
targetCol |
Mallin ulostulosarake selittämään. Tässä esimerkissä sarake on probability. |
targetClasses |
Luokkaindeksit selitettäväksi.
[1] Selittää vain luokan 1 todennäköisyyden. Käytin [0, 1] selittämään molempia kursseja. |
backgroundData |
Koulutusdatan otos, jota käytetään viitejakaumana ominaisuuksien integrointiin. |
shap = TabularSHAP(
inputCols=categorical_features + numeric_features,
outputCol="shapValues",
numSamples=5000,
model=model,
targetCol="probability",
targetClasses=[1],
backgroundData=broadcast(training.orderBy(rand()).limit(100).cache()),
)
shap_df = shap.transform(explain_instances)
Muistio
Tämä vaihe voi kestää useita minuutteja riippuen numSamples klusterin koosta.
numSamples=5000 ja viiden havainnon myötä odotettavissa on 3–10 minuuttia oletus Fabric Spark-klusterilla.
Varmista: Tarkista, että SHAP-ulostulosarake on olemassa.
assert "shapValues" in shap_df.columns, "shapValues column missing"
print(f"SHAP output columns: {shap_df.columns}")
print("TabularSHAP transform completed")
Poimi SHAP-arvot
Poima luokan 1 todennäköisyys- ja SHAP-arvot tuloksesta DataFrame. Jokaisessa havainnossa SHAP-arvovektori alkaa perusarvosta (taustaaineiston keskimääräisestä tulosta), jota seuraa yksi arvo per ominaisuus.
shaps = (
shap_df.withColumn("probability", vec_access(col("probability"), lit(1)))
.withColumn("shapValues", vec2array(col("shapValues").getItem(0)))
.select(
["shapValues", "probability", "label"] + categorical_features + numeric_features
)
)
shaps_local = shaps.toPandas()
shaps_local.sort_values("probability", ascending=False, inplace=True, ignore_index=True)
pd.set_option("display.max_colwidth", None)
display(shaps_local)
Vahvista: Vahvista pandas DataFramen rakenne.
expected_cols = len(categorical_features) + len(numeric_features) + 3
print(f"DataFrame shape: {shaps_local.shape}")
print(f"Expected columns: {expected_cols}, Actual: {shaps_local.shape[1]}")
assert shaps_local.shape == (5, expected_cols), f"Unexpected shape: {shaps_local.shape}"
print("SHAP values extracted successfully")
Visualisoi SHAP-arvot
Luo jokaiselle havaintolle pylväskaavio, joka näyttää, miten kukin piirre vaikuttaa ennustettuun todennäköisyyteen.
from plotly.subplots import make_subplots
import plotly.graph_objects as go
features = categorical_features + numeric_features
features_with_base = ["Base"] + features
rows = shaps_local.shape[0]
fig = make_subplots(
rows=rows,
cols=1,
subplot_titles="Probability: "
+ shaps_local["probability"].apply("{:.2%}".format)
+ "; Label: "
+ shaps_local["label"].astype(str),
)
for index, row in shaps_local.iterrows():
feature_values = [0] + [row[feature] for feature in features]
shap_values = row["shapValues"]
list_of_tuples = list(zip(features_with_base, feature_values, shap_values))
shap_pdf = pd.DataFrame(list_of_tuples, columns=["name", "value", "shap"])
fig.add_trace(
go.Bar(
x=shap_pdf["name"],
y=shap_pdf["shap"],
hovertext="value: " + shap_pdf["value"].astype(str),
),
row=index + 1,
col=1,
)
fig.update_yaxes(range=[-1, 1], fixedrange=True, zerolinecolor="black")
fig.update_xaxes(type="category", tickangle=45, fixedrange=True)
fig.update_layout(height=400 * rows, title_text="SHAP explanations")
fig.show()
Vahvista: Vahvista, että juoniobjekti on luotu.
print(f"Figure traces: {len(fig.data)}")
print(f"Figure height: {fig.layout.height}px")
assert len(fig.data) == 5, f"Expected 5 traces, got {len(fig.data)}"
print("Visualization created successfully")
Tulosten tulkitseminen
Jokainen sivukuva edustaa yhtä havaintoa. Baarit näyttävät:
- Perusta: Keskimääräinen mallin tuotos taustaaineistossa (perustodennäköisyys).
- Positiiviset SHAP-arvot: Ominaisuudet, jotka ohjaavat ennustetta kohti luokkaa 1 (tulot yli 50K).
- Negatiiviset SHAP-arvot: Ominaisuudet, jotka ohjaavat ennustetta kohti luokkaa 0 (tulot alle 50K tai yhtä suuret).
Perusarvon ja kaikkien ominaisuuksien SHAP-arvojen summa vastaa mallin ennustettua todennäköisyyttä kyseiselle havainnolle.
Vianmääritys
| Ongelma | Syy | Ratkaisu |
|---|---|---|
OutOfMemoryError TabularSHAPin aikana |
numSamples on liian suuri käytettävissä olevalle muistille. |
Esimerkiksi vähennä numSamples, 1 000:een tai lisää Sparkin suoritusohjelman muistia. |
| SHAP-muunnos on hidas | Korkea numSamples ja moni ominaisuus lisää laskenta-aikaa. |
Vähennä numSamples 1 000–2 000:een nopeampien tutkimustulosten saamiseksi. Korotus lopullista analyysiä varten. |
FileNotFoundException parkettia varten |
Verkkoyhteys mmlspark.blob.core.windows.net on estetty. |
Varmista, että Fabric-työtilassasi on ulospäin suuntautuva internet-yhteys. Vaihtoehtoisesti lataa aineisto järvenmajasi. |
shapValues sarake sisältää nollapisteitä |
Jotkut havainnot voivat epäonnistua, jos ominaisuusarvot ovat harjoitusjakauman ulkopuolella. | Tarkista nolla- tai odottamattomia arvoja syöteominaisuuksista. Suodata nullit tuloksista. |
display() Ei ulostuloa |
Koodi toimii Fabric-muistikirjaympäristön ulkopuolella. | Käytä shaps_local.head() tai print(shaps_local) tavallisissa Python-ympäristöissä. |
Pestä
Jos latasit aineiston järventaloon tätä opetusta varten, poista se vapaaseen tallennustilaan:
# Remove cached DataFrames from memory
training.unpersist()
explain_instances.unpersist()
print("Cached DataFrames released")