Kurz: Vytvorenie, vyhodnotenie a skóre systému odporúčaní
Tento kurz predstavuje komplexný príklad pracovného postupu synapse Data Science v službe Microsoft Fabric. Scenár vytvára model pre odporúčania online knihy.
V tomto kurze sú obsiahnuté tieto kroky:
- Nahratie údajov do služby lakehouse
- Vykonanie prieskumnej analýzy údajov
- Trénovať model a zapísať ho pomocou toku MLflow
- Načítanie modelu a vytváranie predpovedí
K dispozícii je mnoho typov algoritmov odporúčania. V tomto kurze sa používa algoritmus faktorizácie matice Alternating Least Squares (ALS). ALS je modelový algoritmus filtrovania založené na spolupráci.
ALS sa pokúsi odhadnúť maticu R hodnotenia ako súčin dvoch matíc s nižším poradím, vás a V. Tu, R = U * Vt. Tieto aproximácie sa zvyčajne nazývajú faktor matice.
Algoritmus ALS je iteratívny. Každá iterácia obsahuje konštantu faktora matice, pričom druhý vyrieši použitím metódy najmenších štvorcov. To potom ustáli, že novo vyriešená matica faktora je konštantná a vyrieši aj inú maticu faktora.
Predpoklady
Získajte predplatné služby Microsoft Fabric . Alebo si zaregistrujte bezplatnú skúšobnú služby Microsoft Fabric.
Prihláste sa do služby Microsoft Fabric.
Pomocou prepínača skúseností v ľavej dolnej časti domovskej stránky sa prepnete na službu Fabric.
- Ak je to potrebné, vytvorte si podľa popisu v téme Vytvorenie jazera v službe Microsoft Fabric.
Sledovanie v poznámkovom bloke
Môžete si vybrať jednu z týchto možností, ktorú si môžete vyskúšať v notebooku:
- Otvorte a spustite vstavaný poznámkový blok.
- Nahrajte poznámkový blok z GitHubu.
Otvorenie vstavaného poznámkového bloku
Tento kurz sprevádza ukážkový odporúčanie poznámkovým blokom.
Ak chcete otvoriť vzorový poznámkový blok pre tento kurz, postupujte podľa pokynov v téme Príprava systému na kurzy dátovej vedy.
Uistite sa, že pripojiť lakehouse na notebook, ako začnete bežať kód.
Importovanie notebooku z GitHubu
Tento kurz sprevádza poznámkový blok AIsample – Book Recommendation.ipynb.
Ak chcete otvoriť sprievodný poznámkový blok pre tento kurz, postupujte podľa pokynov v téme Príprava systému na kurzy dátových vied na import notebooku do pracovného priestoru.
Ak by ste radšej skopírovali a prilepili kód z tejto stránky, môžete vytvoriť nový poznámkový blok.
Uistite sa, že pripojiť lakehouse k notebooku, ako začnete bežať kód.
Krok č. 1: Načítanie údajov
Množina údajov odporúčania knihy v tomto scenári sa skladá z troch samostatných množín údajov:
Books.csv: Medzinárodné štandardné číslo knihy (ISBN) identifikuje každú knihu, pričom už boli odstránené neplatné dátumy. Množina údajov obsahuje aj názov, autor a vydavateľ. V prípade knihy s viacerými autormi Books.csv súbor uvádza iba prvého autora. URL adresy odkazujú na zdroje webových stránok Amazon pre pokrytie obrázkov, v troch veľkostiach.
ISBN Book-Title Book-Author Rok –Of-Publication Vydavateľ Image-URL-S Image-URL-M Obrázok-URL-l 0195153448 Klasická mytológia Mark P. O. Morford 2002 Oxford University Press http://images.amazon.com/images/P/0195153448.01.THUMBZZZ.jpg http://images.amazon.com/images/P/0195153448.01.MZZZZZZZ.jpg http://images.amazon.com/images/P/0195153448.01.LZZZZZZZ.jpg 0002005018 Clara Callan Richard Bruce Wright 2001 HarperFlamingo Kanada http://images.amazon.com/images/P/0002005018.01.THUMBZZZ.jpg http://images.amazon.com/images/P/0002005018.01.MZZZZZZZ.jpg http://images.amazon.com/images/P/0002005018.01.LZZZZZZZ.jpg Ratings.csv: Hodnotenia pre každú knihu sú buď explicitné (poskytované používateľmi, na stupnici od 1 do 10) alebo implicitné (dodržiavané bez vstupu používateľa a označené číslom 0).
User-ID ISBN Book-Rating 276725 034545104X 0 276726 0155061224 5 Users.csv: ID používateľov sa anonymizuje a priraďuje k celým číslam. Ak sú k dispozícii demografické údaje, napríklad miesto a vek. Ak tieto údaje nie sú k dispozícii, tieto hodnoty sú
null
.User-ID Miesto Vek 1 "nyc New York USA" 2 "stockton california usa" 18.0
Definujte tieto parametre, aby ste v tomto poznámkovom bloke mohli použiť rôzne množiny údajov:
IS_CUSTOM_DATA = False # If True, the dataset has to be uploaded manually
USER_ID_COL = "User-ID" # Must not be '_user_id' for this notebook to run successfully
ITEM_ID_COL = "ISBN" # Must not be '_item_id' for this notebook to run successfully
ITEM_INFO_COL = (
"Book-Title" # Must not be '_item_info' for this notebook to run successfully
)
RATING_COL = (
"Book-Rating" # Must not be '_rating' for this notebook to run successfully
)
IS_SAMPLE = True # If True, use only <SAMPLE_ROWS> rows of data for training; otherwise, use all data
SAMPLE_ROWS = 5000 # If IS_SAMPLE is True, use only this number of rows for training
DATA_FOLDER = "Files/book-recommendation/" # Folder that contains the datasets
ITEMS_FILE = "Books.csv" # File that contains the item information
USERS_FILE = "Users.csv" # File that contains the user information
RATINGS_FILE = "Ratings.csv" # File that contains the rating information
EXPERIMENT_NAME = "aisample-recommendation" # MLflow experiment name
Stiahnutie a uloženie údajov v úložisku Lakehouse
Tento kód stiahne množinu údajov a potom ju uloží v úložisku lakehouse.
Dôležitý
Uistite sa, že ste pred spustením pridali do notebooku. V opačnom prípade sa zobrazí chyba.
if not IS_CUSTOM_DATA:
# Download data files into a lakehouse if they don't exist
import os, requests
remote_url = "https://synapseaisolutionsa.blob.core.windows.net/public/Book-Recommendation-Dataset"
file_list = ["Books.csv", "Ratings.csv", "Users.csv"]
download_path = f"/lakehouse/default/{DATA_FOLDER}/raw"
if not os.path.exists("/lakehouse/default"):
raise FileNotFoundError(
"Default lakehouse not found, please add a lakehouse and restart the session."
)
os.makedirs(download_path, exist_ok=True)
for fname in file_list:
if not os.path.exists(f"{download_path}/{fname}"):
r = requests.get(f"{remote_url}/{fname}", timeout=30)
with open(f"{download_path}/{fname}", "wb") as f:
f.write(r.content)
print("Downloaded demo data files into lakehouse.")
Nastavenie sledovania experimentov toku MLflow
Pomocou tohto kódu môžete nastaviť sledovanie experimentov s tokom MLflow. Tento príklad zakáže automatické označovanie. Ďalšie informácie nájdete v článku Automatické označovanie v službe Microsoft Fabric.
# Set up MLflow for experiment tracking
import mlflow
mlflow.set_experiment(EXPERIMENT_NAME)
mlflow.autolog(disable=True) # Disable MLflow autologging
Čítať údaje z jazera
Po umiestnení správnych údajov do úložiska Lakehouse prečítať tri množiny údajov do samostatných spark dataframes v notebooku. Cesty k súborom v tomto kóde používajú parametre definované vyššie.
df_items = (
spark.read.option("header", True)
.option("inferSchema", True)
.csv(f"{DATA_FOLDER}/raw/{ITEMS_FILE}")
.cache()
)
df_ratings = (
spark.read.option("header", True)
.option("inferSchema", True)
.csv(f"{DATA_FOLDER}/raw/{RATINGS_FILE}")
.cache()
)
df_users = (
spark.read.option("header", True)
.option("inferSchema", True)
.csv(f"{DATA_FOLDER}/raw/{USERS_FILE}")
.cache()
)
Krok č. 2: Vykonanie prieskumnej analýzy údajov
Zobrazenie nespracovaných údajov
Preskúmajte údajové rámce pomocou príkazu display
. Pomocou tohto príkazu môžete zobraziť štatistiky údajového rámca vysokej úrovne a zistiť, ako navzájom súvisia rôzne stĺpce množiny údajov. Pred preskúmaním množín údajov použite tento kód na import požadovaných knižníc:
import pyspark.sql.functions as F
from pyspark.ml.feature import StringIndexer
import matplotlib.pyplot as plt
import seaborn as sns
color = sns.color_palette() # Adjusting plotting style
import pandas as pd # DataFrames
Pomocou tohto kódu sa pozrite na údajový rámec, ktorý obsahuje údaje knihy:
display(df_items, summary=True)
Pridanie _item_id
stĺpca na neskoršie použitie. Hodnota _item_id
musí byť celé číslo pre modely odporúčaní. Tento kód používa StringIndexer
na transformáciu ITEM_ID_COL
na indexy:
df_items = (
StringIndexer(inputCol=ITEM_ID_COL, outputCol="_item_id")
.setHandleInvalid("skip")
.fit(df_items)
.transform(df_items)
.withColumn("_item_id", F.col("_item_id").cast("int"))
)
Zobrazte údajový rámec a skontrolujte, či sa hodnota _item_id
podľa očakávania zvyšuje monotónne a postupne:
display(df_items.sort(F.col("_item_id").desc()))
Pomocou tohto kódu môžete vykresliť prvých 10 autorov podľa počtu napísaných kníh v zostupnom poradí. Agatha Christie je popredným autorom s viac ako 600 knihami, za ktorými nasleduje William Shakespeare.
df_books = df_items.toPandas() # Create a pandas DataFrame from the Spark DataFrame for visualization
plt.figure(figsize=(8,5))
sns.countplot(y="Book-Author",palette = 'Paired', data=df_books,order=df_books['Book-Author'].value_counts().index[0:10])
plt.title("Top 10 authors with maximum number of books")
V ďalšom kroku si zobrazte údajový rámec, ktorý obsahuje údaje používateľa:
display(df_users, summary=True)
Ak má riadok chýbajúcu User-ID
hodnotu, zrušte tento riadok. Chýbajúce hodnoty vo prispôsobenej množine údajov nespôsobujú problémy.
df_users = df_users.dropna(subset=(USER_ID_COL))
display(df_users, summary=True)
Pridajte _user_id
stĺpec na neskoršie použitie. V prípade modelov odporúčania musí byť hodnota _user_id
celým číslom. Nasledujúca ukážka kódu používa StringIndexer
na transformáciu USER_ID_COL
na indexy.
Množina údajov knihy už má celočíselný stĺpec User-ID
. Pridaním _user_id
stĺpca na účely kompatibility s rôznymi množinami údajov je však tento príklad ešte robustnejší. Pomocou tohto kódu pridajte stĺpec _user_id
:
df_users = (
StringIndexer(inputCol=USER_ID_COL, outputCol="_user_id")
.setHandleInvalid("skip")
.fit(df_users)
.transform(df_users)
.withColumn("_user_id", F.col("_user_id").cast("int"))
)
display(df_users.sort(F.col("_user_id").desc()))
Údaje o hodnotení zobrazíte pomocou tohto kódu:
display(df_ratings, summary=True)
Získajte jedinečné hodnotenia a uložte ich na neskoršie použitie v zozname s názvom ratings
:
ratings = [i[0] for i in df_ratings.select(RATING_COL).distinct().collect()]
print(ratings)
Pomocou tohto kódu zobrazíte prvých 10 kníh s najvyššími hodnoteniami:
plt.figure(figsize=(8,5))
sns.countplot(y="Book-Title",palette = 'Paired',data= df_books, order=df_books['Book-Title'].value_counts().index[0:10])
plt.title("Top 10 books per number of ratings")
Podľa hodnotenia, vybraté básne je najobľúbenejšia kniha. Adventures of Huckleberry Finn, The Secret Garden, a Dracula majú rovnaké hodnotenie.
Zlúčenie údajov
Zlúčenie troch údajových rámca do jedného údajového rámca pre komplexnejšiu analýzu:
df_all = df_ratings.join(df_users, USER_ID_COL, "inner").join(
df_items, ITEM_ID_COL, "inner"
)
df_all_columns = [
c for c in df_all.columns if c not in ["_user_id", "_item_id", RATING_COL]
]
# Reorder the columns to ensure that _user_id, _item_id, and Book-Rating are the first three columns
df_all = (
df_all.select(["_user_id", "_item_id", RATING_COL] + df_all_columns)
.withColumn("id", F.monotonically_increasing_id())
.cache()
)
display(df_all)
Pomocou tohto kódu môžete zobraziť počet rôznych používateľov, kníh a interakcií:
print(f"Total Users: {df_users.select('_user_id').distinct().count()}")
print(f"Total Items: {df_items.select('_item_id').distinct().count()}")
print(f"Total User-Item Interactions: {df_all.count()}")
Výpočet a vykresliť najpopulárnejšie položky
Pomocou tohto kódu môžete vypočítať a zobraziť prvých 10 najobľúbenejších kníh:
# Compute top popular products
df_top_items = (
df_all.groupby(["_item_id"])
.count()
.join(df_items, "_item_id", "inner")
.sort(["count"], ascending=[0])
)
# Find top <topn> popular items
topn = 10
pd_top_items = df_top_items.limit(topn).toPandas()
pd_top_items.head(10)
Tip
Použite hodnotu <topn>
pre obľúbené alebo najkúpilejšie zakúpené častiach odporúčania.
# Plot top <topn> items
f, ax = plt.subplots(figsize=(10, 5))
plt.xticks(rotation="vertical")
sns.barplot(y=ITEM_INFO_COL, x="count", data=pd_top_items)
ax.tick_params(axis='x', rotation=45)
plt.xlabel("Number of Ratings for the Item")
plt.show()
Príprava tréningových a testovacích množín údajov
Matica ALS pred trénovaním vyžaduje prípravu údajov. Na prípravu údajov použite túto ukážku kódu. Kód vykonáva tieto akcie:
- Pretypovanie stĺpca hodnotenia do správneho typu
- Vzorka tréningových údajov s hodnoteniami používateľov
- Rozdelenie údajov na trénované a testovacie množiny údajov
if IS_SAMPLE:
# Must sort by '_user_id' before performing limit to ensure that ALS works normally
# If training and test datasets have no common _user_id, ALS will fail
df_all = df_all.sort("_user_id").limit(SAMPLE_ROWS)
# Cast the column into the correct type
df_all = df_all.withColumn(RATING_COL, F.col(RATING_COL).cast("float"))
# Using a fraction between 0 and 1 returns the approximate size of the dataset; for example, 0.8 means 80% of the dataset
# Rating = 0 means the user didn't rate the item, so it can't be used for training
# We use the 80% of the dataset with rating > 0 as the training dataset
fractions_train = {0: 0}
fractions_test = {0: 0}
for i in ratings:
if i == 0:
continue
fractions_train[i] = 0.8
fractions_test[i] = 1
# Training dataset
train = df_all.sampleBy(RATING_COL, fractions=fractions_train)
# Join with leftanti will select all rows from df_all with rating > 0 and not in the training dataset; for example, the remaining 20% of the dataset
# test dataset
test = df_all.join(train, on="id", how="leftanti").sampleBy(
RATING_COL, fractions=fractions_test
)
Riedkaosť sa vzťahuje na riedke údaje pripomienok, ktoré nemôžu identifikovať podobnosti v záujmoch používateľov. Na lepšie pochopenie údajov aj aktuálneho problému použite tento kód na výpočet riedkych údajov množiny údajov:
# Compute the sparsity of the dataset
def get_mat_sparsity(ratings):
# Count the total number of ratings in the dataset - used as numerator
count_nonzero = ratings.select(RATING_COL).count()
print(f"Number of rows: {count_nonzero}")
# Count the total number of distinct user_id and distinct product_id - used as denominator
total_elements = (
ratings.select("_user_id").distinct().count()
* ratings.select("_item_id").distinct().count()
)
# Calculate the sparsity by dividing the numerator by the denominator
sparsity = (1.0 - (count_nonzero * 1.0) / total_elements) * 100
print("The ratings DataFrame is ", "%.4f" % sparsity + "% sparse.")
get_mat_sparsity(df_all)
# Check the ID range
# ALS supports only values in the integer range
print(f"max user_id: {df_all.agg({'_user_id': 'max'}).collect()[0][0]}")
print(f"max user_id: {df_all.agg({'_item_id': 'max'}).collect()[0][0]}")
Krok č. 3: Vývoj a trénovanie modelu
Trénujte model ALS, aby ste používateľom poskytli prispôsobené odporúčania.
Definovanie modelu
Spark ML poskytuje pohodlné rozhranie API na vytváranie modelu ALS. Model však spoľahlivo nevyrieši problémy, ako je riedkaosť údajov a studený začiatok (dáva odporúčania, keď sú používatelia alebo položky nové). Ak chcete zvýšiť výkon modelu, skombinujte ladenie krížového overenia a automatického ladenia hyperparametrov.
Pomocou tohto kódu importujte knižnice potrebné na trénovanie a vyhodnocovanie modelu:
# Import Spark required libraries
from pyspark.ml.evaluation import RegressionEvaluator
from pyspark.ml.recommendation import ALS
from pyspark.ml.tuning import ParamGridBuilder, CrossValidator, TrainValidationSplit
# Specify the training parameters
num_epochs = 1 # Number of epochs; here we use 1 to reduce the training time
rank_size_list = [64] # The values of rank in ALS for tuning
reg_param_list = [0.01, 0.1] # The values of regParam in ALS for tuning
model_tuning_method = "TrainValidationSplit" # TrainValidationSplit or CrossValidator
# Build the recommendation model by using ALS on the training data
# We set the cold start strategy to 'drop' to ensure that we don't get NaN evaluation metrics
als = ALS(
maxIter=num_epochs,
userCol="_user_id",
itemCol="_item_id",
ratingCol=RATING_COL,
coldStartStrategy="drop",
implicitPrefs=False,
nonnegative=True,
)
Vyladenie hyperparametrov modelu
V ďalšej ukážke kódu sa vytvorí mriežka parametra, ktorá pomáha pri vyhľadávaní hyperparametrov. Kód tiež vytvorí regresného hodnotiteľa, ktorý ako metriku hodnotenia používa chybu root-mean-square (RMSE):
# Construct a grid search to select the best values for the training parameters
param_grid = (
ParamGridBuilder()
.addGrid(als.rank, rank_size_list)
.addGrid(als.regParam, reg_param_list)
.build()
)
print("Number of models to be tested: ", len(param_grid))
# Define the evaluator and set the loss function to the RMSE
evaluator = RegressionEvaluator(
metricName="rmse", labelCol=RATING_COL, predictionCol="prediction"
)
Nasledujúca ukážka kódu spustí rôzne metódy ladenia modelu na základe vopred konfigurovaných parametrov. Ďalšie informácie o ladení modelu nájdete v téme Ladenie strojového učenia: výber modelu a ladenie hyperparametrov na webovej lokalite Apache Spark.
# Build cross-validation by using CrossValidator and TrainValidationSplit
if model_tuning_method == "CrossValidator":
tuner = CrossValidator(
estimator=als,
estimatorParamMaps=param_grid,
evaluator=evaluator,
numFolds=5,
collectSubModels=True,
)
elif model_tuning_method == "TrainValidationSplit":
tuner = TrainValidationSplit(
estimator=als,
estimatorParamMaps=param_grid,
evaluator=evaluator,
# 80% of the training data will be used for training; 20% for validation
trainRatio=0.8,
collectSubModels=True,
)
else:
raise ValueError(f"Unknown model_tuning_method: {model_tuning_method}")
Vyhodnotenie modelu
Moduly by ste mali vyhodnotiť na základe testovacích údajov. Dobre trénovaný model by mal mať vysoké metriky v množine údajov.
Preťažený model môže vyžadovať zväčšenie veľkosti tréningových údajov alebo zníženie niektorých nadbytočných funkcií. Možno bude potrebné zmeniť architektúru modelu alebo je možné, že jej parametre budú potrebovať doladenie.
Nota
Záporná hodnota metriky R so štvorčekom označuje, že trénovaný model má horší výkon ako vodorovná rovná čiara. Toto zistenie naznačuje, že trénovaný model nevysvetluje údaje.
Ak chcete definovať funkciu vyhodnocovania, použite tento kód:
def evaluate(model, data, verbose=0):
"""
Evaluate the model by computing rmse, mae, r2, and variance over the data.
"""
predictions = model.transform(data).withColumn(
"prediction", F.col("prediction").cast("double")
)
if verbose > 1:
# Show 10 predictions
predictions.select("_user_id", "_item_id", RATING_COL, "prediction").limit(
10
).show()
# Initialize the regression evaluator
evaluator = RegressionEvaluator(predictionCol="prediction", labelCol=RATING_COL)
_evaluator = lambda metric: evaluator.setMetricName(metric).evaluate(predictions)
rmse = _evaluator("rmse")
mae = _evaluator("mae")
r2 = _evaluator("r2")
var = _evaluator("var")
if verbose > 0:
print(f"RMSE score = {rmse}")
print(f"MAE score = {mae}")
print(f"R2 score = {r2}")
print(f"Explained variance = {var}")
return predictions, (rmse, mae, r2, var)
Sledovanie experimentu pomocou toku MLflow
MLflow môžete použiť na sledovanie všetkých experimentov a zaznamenávanie parametrov, metrík a modelov. Ak chcete začať trénovať a vyhodnocovať model, použite tento kód:
from mlflow.models.signature import infer_signature
with mlflow.start_run(run_name="als"):
# Train models
models = tuner.fit(train)
best_metrics = {"RMSE": 10e6, "MAE": 10e6, "R2": 0, "Explained variance": 0}
best_index = 0
# Evaluate models
# Log models, metrics, and parameters
for idx, model in enumerate(models.subModels):
with mlflow.start_run(nested=True, run_name=f"als_{idx}") as run:
print("\nEvaluating on test data:")
print(f"subModel No. {idx + 1}")
predictions, (rmse, mae, r2, var) = evaluate(model, test, verbose=1)
signature = infer_signature(
train.select(["_user_id", "_item_id"]),
predictions.select(["_user_id", "_item_id", "prediction"]),
)
print("log model:")
mlflow.spark.log_model(
model,
f"{EXPERIMENT_NAME}-alsmodel",
signature=signature,
registered_model_name=f"{EXPERIMENT_NAME}-alsmodel",
dfs_tmpdir="Files/spark",
)
print("log metrics:")
current_metric = {
"RMSE": rmse,
"MAE": mae,
"R2": r2,
"Explained variance": var,
}
mlflow.log_metrics(current_metric)
if rmse < best_metrics["RMSE"]:
best_metrics = current_metric
best_index = idx
print("log parameters:")
mlflow.log_params(
{
"subModel_idx": idx,
"num_epochs": num_epochs,
"rank_size_list": rank_size_list,
"reg_param_list": reg_param_list,
"model_tuning_method": model_tuning_method,
"DATA_FOLDER": DATA_FOLDER,
}
)
# Log the best model and related metrics and parameters to the parent run
mlflow.spark.log_model(
models.subModels[best_index],
f"{EXPERIMENT_NAME}-alsmodel",
signature=signature,
registered_model_name=f"{EXPERIMENT_NAME}-alsmodel",
dfs_tmpdir="Files/spark",
)
mlflow.log_metrics(best_metrics)
mlflow.log_params(
{
"subModel_idx": idx,
"num_epochs": num_epochs,
"rank_size_list": rank_size_list,
"reg_param_list": reg_param_list,
"model_tuning_method": model_tuning_method,
"DATA_FOLDER": DATA_FOLDER,
}
)
Ak chcete zobraziť zaznamenané informácie na trénovanie, vyberte vo svojom pracovnom priestore experiment s názvom aisample-recommendation
. Ak ste si zmenili názov experimentu, vyberte experiment, ktorý má nový názov. Zaznamenané informácie sa podobajú na tomto obrázku:
Krok č. 4: Načítanie konečného modelu pre bodovanie a vytváranie predpovedí
Po dokončení trénovania modelu a potom vyberte najlepší model, načítajte model na bodovanie (niekedy sa nazýva odvodenie). Tento kód načíta model a používa predpovede na odporúčanie prvých 10 kníh pre každého používateľa:
# Load the best model
# MLflow uses PipelineModel to wrap the original model, so we extract the original ALSModel from the stages
model_uri = f"models:/{EXPERIMENT_NAME}-alsmodel/1"
loaded_model = mlflow.spark.load_model(model_uri, dfs_tmpdir="Files/spark").stages[-1]
# Generate top 10 book recommendations for each user
userRecs = loaded_model.recommendForAllUsers(10)
# Represent the recommendations in an interpretable format
userRecs = (
userRecs.withColumn("rec_exp", F.explode("recommendations"))
.select("_user_id", F.col("rec_exp._item_id"), F.col("rec_exp.rating"))
.join(df_items.select(["_item_id", "Book-Title"]), on="_item_id")
)
userRecs.limit(10).show()
Výstup pripomína túto tabuľku:
_item_id | _user_id | ohodnotenie | Book-Title |
---|---|---|---|
44865 | 7 | 7.9996786 | Lasher: Životy ... |
786 | 7 | 6.2255826 | Klavírny muž je D... |
45330 | 7 | 4.980466 | Stav mysle |
38960 | 7 | 4.980466 | Všetko, čo kedy chcel |
125415 | 7 | 4.505084 | Harry Potter a ... |
44939 | 7 | 4.3579073 | Taltos: Životy ... |
175247 | 7 | 4.3579073 | Bonesetter je ... |
170183 | 7 | 4.228735 | Život jednoduchý ... |
88503 | 7 | 4.221206 | Ostrov blu... |
32894 | 7 | 3.9031885 | Zimný slnovrat |
Uložiť predpovede na lakehouse
Pomocou tohto kódu napíšte odporúčania späť do jazera:
# Code to save userRecs into the lakehouse
userRecs.write.format("delta").mode("overwrite").save(
f"{DATA_FOLDER}/predictions/userRecs"
)