Κοινή χρήση μέσω


Εκμάθηση: Δημιουργία, αξιολόγηση και βαθμολογία συστήματος προτάσεων

Αυτό το εκπαιδευτικό βοήθημα παρουσιάζει ένα τελικό παράδειγμα μιας ροής εργασιών Synapse Data Science στο Microsoft Fabric. Το σενάριο δημιουργεί ένα μοντέλο για προτάσεις ηλεκτρονικών βιβλίων.

Αυτό το εκπαιδευτικό βοήθημα καλύπτει τα εξής βήματα:

  • Αποστολή των δεδομένων σε ένα lakehouse
  • Εκτέλεση διερευνητικής ανάλυσης των δεδομένων
  • Εκπαίδευση μοντέλου και καταγραφή του με MLflow
  • Φόρτωση του μοντέλου και πραγματοποίηση προβλέψεων

Έχουμε πολλούς διαθέσιμους τύπους αλγόριθμων προτάσεων. Αυτό το εκπαιδευτικό βοήθημα χρησιμοποιεί τον αλγόριθμο παραγοντισμού μήτρας Alternating Least Squares (ALS). Το ALS είναι ένας αλγόριθμος συνεργατικού φιλτραρίσματος βάσει μοντέλου.

Screenshot showing a chart of recommendation algorithms types.

Το ALS προσπαθεί να εκτιμήσει τη μήτρα αξιολογήσεων R ως προϊόν δύο μήτρες χαμηλότερης κατάταξης, εσείς και η V. Εδώ, R = U * Vt. Συνήθως, αυτές οι εκτιμήσεις ονομάζονται μήτρες παραγόντων .

Ο αλγόριθμος ALS είναι επαναληπτικός. Κάθε διαδοχική προσέγγιση διατηρεί μία από τις σταθερές μήτρες παραγόντων, ενώ επιλύει την άλλη χρησιμοποιώντας τη μέθοδο των ελάχιστων τετραγώνων. Στη συνέχεια, διατηρεί αυτή τη σταθερά μήτρας παραγόντων που έχει επιλυθεί πρόσφατα, ενώ επιλύει την άλλη μήτρα παραγόντων.

Screenshot of two side-by-side factor matrices.

Προαπαιτούμενα στοιχεία

  • Λάβετε μια συνδρομή Microsoft Fabric. Εναλλακτικά, εγγραφείτε για μια δωρεάν δοκιμαστική έκδοση του Microsoft Fabric.

  • Εισέλθετε στο Microsoft Fabric.

  • Χρησιμοποιήστε την εναλλαγή εμπειρίας στην αριστερή πλευρά της αρχικής σελίδας σας για να μεταβείτε στην εμπειρία Synapse Data Science.

    Screenshot of the experience switcher menu, showing where to select Data Science.

Παρακολούθηση σε σημειωματάριο

Μπορείτε να κάνετε μία από αυτές τις επιλογές για να ακολουθήσετε τις οδηγίες σε ένα σημειωματάριο:

  • Άνοιγμα και εκτέλεση του ενσωματωμένου σημειωματάριου στην εμπειρία Synapse Data Science
  • Αποστείλετε το σημειωματάριό σας από το GitHub στην εμπειρία Synapse Data Science

Άνοιγμα του ενσωματωμένου σημειωματάριου

Το δείγμα σημειωματάριου προτάσεων βιβλίων συνοδεύει αυτό το πρόγραμμα εκμάθησης.

Για να ανοίξετε το ενσωματωμένο δείγμα σημειωματάριου της εκμάθησης στην εμπειρία Synapse Data Science:

  1. Μεταβείτε στην αρχική σελίδα Synapse Data Science.

  2. Επιλέξτε Χρήση δείγματος.

  3. Επιλέξτε το αντίστοιχο δείγμα:

    • Από την προεπιλεγμένη καρτέλα Ροές εργασιών από άκρο σε τέλος (Python ), εάν το δείγμα αφορά ένα πρόγραμμα εκμάθησης Python.
    • Από την καρτέλα Ολοκληρωμένες ροές εργασιών (R), εάν το δείγμα αφορά μια εκμάθηση R.
    • Από την καρτέλα Γρήγορα προγράμματα εκμάθησης , εάν το δείγμα προορίζεται για μια γρήγορη εκμάθηση.
  4. Επισυνάψτε μια λίμνη στο σημειωματάριο προτού ξεκινήσετε την εκτέλεση κώδικα.

Εισαγωγή του σημειωματάριου από το GitHub

Το σημειωματάριο AIsample - Book Recommendation.ipynb συνοδεύει αυτό το πρόγραμμα εκμάθησης.

Για να ανοίξετε το σημειωματάριο που συνοδεύει αυτό το εκπαιδευτικό βοήθημα, ακολουθήστε τις οδηγίες στο θέμα Προετοιμασία του συστήματός σας για προγράμματα εκμάθησης επιστήμης δεδομένων, για να εισαγάγετε το σημειωματάριο στον χώρο εργασίας σας.

Εάν προτιμάτε να αντιγράψετε και να επικολλήσετε τον κώδικα από αυτή τη σελίδα, μπορείτε να δημιουργήσετε ένα νέο σημειωματάριο.

Φροντίστε να επισυνάψετε ένα lakehouse στο σημειωματάριο προτού ξεκινήσετε την εκτέλεση κώδικα.

Βήμα 1: Φόρτωση των δεδομένων

Το σύνολο δεδομένων προτάσεων βιβλίων σε αυτό το σενάριο αποτελείται από τρία ξεχωριστά σύνολα δεδομένων:

  • Books.csv: Ένας διεθνής αριθμός τυπικού βιβλίου (ISBN) προσδιορίζει κάθε βιβλίο, με τις μη έγκυρες ημερομηνίες να έχουν ήδη καταργηθεί. Το σύνολο δεδομένων περιλαμβάνει επίσης τον τίτλο, τον συντάκτη και τον εκδότη. Για ένα βιβλίο με πολλούς συντάκτες, το αρχείο Books.csv παραθέτει μόνο τον πρώτο συντάκτη. Οι διευθύνσεις URL δείχνουν πόρους ιστότοπων της Amazon για τις εικόνες εξωφύλλου, σε τρία μεγέθη.

    ISBN Τίτλος-βιβλίου Συντάκτης βιβλίου Έτος δημοσίευσης Publisher Image-URL-S Εικόνα-διεύθυνση URL-M Image-URL-l
    0195153448 Κλασσική μυθολογία Μαρκ Π. Ο. Μόρφορντ 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 Κλάρα Κάλαν Ρίτσαρντ Μπρους Ράιτ 2001 HarperFlamingo Καναδάς 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: Οι αξιολογήσεις για κάθε βιβλίο είναι είτε ρητές (παρέχονται από τους χρήστες, σε κλίμακα από 1 έως 10) είτε έμμεσες (παρατηρούνται χωρίς εισαγωγή από τον χρήστη και υποδεικνύονται από το 0).

    Αναγνωριστικό χρήστη ISBN Αξιολόγηση βιβλίων
    276725 034545104X 0
    276726 0155061224 5
  • Users.csv: Τα αναγνωριστικά χρηστών ανωνυμοποιούνται και αντιστοιχίζονται σε ακέραιους. Τα δημογραφικά δεδομένα - για παράδειγμα, η τοποθεσία και η ηλικία - παρέχονται, εάν υπάρχουν. Εάν αυτά τα δεδομένα δεν είναι διαθέσιμα, αυτές οι τιμές είναι null.

    Αναγνωριστικό χρήστη Τοποθεσία Ηλικία
    1 "nyc new york usa"
    2 "stockton california usa" 18,0

Καθορίστε αυτές τις παραμέτρους, ώστε να μπορείτε αυτό το σημειωματάριο με διαφορετικά σύνολα δεδομένων:

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

Λήψη και αποθήκευση των δεδομένων σε ένα lakehouse

Αυτός ο κώδικας κάνει λήψη του συνόλου δεδομένων και, στη συνέχεια, το αποθηκεύει στο lakehouse.

Σημαντικό

Φροντίστε να προσθέσετε ένα lakehouse στο σημειωματάριο προτού το εκτελέσετε. Διαφορετικά, θα λάβετε ένα σφάλμα.

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.")

Ρύθμιση της παρακολούθησης του πειράματος MLflow

Χρησιμοποιήστε αυτόν τον κώδικα για να ρυθμίσετε την παρακολούθηση του πειράματος MLflow. Αυτό το παράδειγμα απενεργοποιεί την αυτόματη καταχώρηση. Για περισσότερες πληροφορίες, ανατρέξτε στο άρθρο Αυτόματη καταχώρηση στο Microsoft Fabric .

# Set up MLflow for experiment tracking
import mlflow

mlflow.set_experiment(EXPERIMENT_NAME)
mlflow.autolog(disable=True)  # Disable MLflow autologging

Ανάγνωση δεδομένων από το lakehouse

Αφού τοποθετήσετε τα σωστά δεδομένα στη λίμνη, διαβάστε τα τρία σύνολα δεδομένων σε ξεχωριστά Spark DataFrame στο σημειωματάριο. Οι διαδρομές αρχείων σε αυτόν τον κώδικα χρησιμοποιούν τις παραμέτρους που ορίστηκαν προηγουμένως.

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()
)

Βήμα 2: Εκτέλεση διερευνητικής ανάλυσης δεδομένων

Εμφάνιση ανεπεξέργαστων δεδομένων

Εξερευνήστε τα DataFrames με την display εντολή . Με αυτήν την εντολή, μπορείτε να προβάλετε στατιστικά στοιχεία πλαισίου δεδομένων υψηλού επιπέδου και να κατανοήσετε πώς οι διαφορετικές στήλες συνόλου δεδομένων σχετίζονται μεταξύ τους. Πριν εξερευνήσετε τα σύνολα δεδομένων, χρησιμοποιήστε αυτόν τον κώδικα για να εισαγάγετε τις απαιτούμενες βιβλιοθήκες:

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

Χρησιμοποιήστε αυτόν τον κώδικα για να δείτε το DataFrame που περιέχει τα δεδομένα του βιβλίου:

display(df_items, summary=True)

Προσθέστε μια _item_id στήλη για μελλοντική χρήση. Η _item_id τιμή πρέπει να είναι ακέραιος για μοντέλα προτάσεων. Ο κωδικός αυτός χρησιμοποιείται StringIndexer για τον μετασχηματισμό ITEM_ID_COL σε δείκτες:

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"))
)

Εμφανίστε το DataFrame και ελέγξτε εάν η _item_id τιμή αυξάνεται μονοτονικά και διαδοχικά, όπως αναμένεται:

display(df_items.sort(F.col("_item_id").desc()))

Χρησιμοποιήστε αυτόν τον κώδικα για να σχεδιάσετε τους 10 κορυφαίους συγγραφείς, κατά αριθμό βιβλίων που έχουν συνταχθεί, σε φθίνουσα σειρά. Η Αγκάθα Κρίστι είναι η κορυφαία συγγραφέας με περισσότερα από 600 βιβλία, ακολουθούμενη από τον Ουίλιαμ Σαίξπηρ.

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")

Screenshot showing a graph of the top 10 authors who wrote the highest number of books.

Στη συνέχεια, εμφανίστε το DataFrame που περιέχει τα δεδομένα χρήστη:

display(df_users, summary=True)

Εάν μια γραμμή διαθέτει μια τιμή που λείπει User-ID , αποθέστε αυτήν τη γραμμή. Οι τιμές που λείπουν σε ένα προσαρμοσμένο σύνολο δεδομένων δεν προκαλούν προβλήματα.

df_users = df_users.dropna(subset=(USER_ID_COL))
display(df_users, summary=True)

Προσθέστε μια _user_id στήλη για μελλοντική χρήση. Για τα μοντέλα προτάσεων, η _user_id τιμή πρέπει να είναι ακέραιος. Το ακόλουθο δείγμα κώδικα χρησιμοποιείται StringIndexer για τον μετασχηματισμό USER_ID_COL σε δείκτες.

Το σύνολο δεδομένων βιβλίου έχει ήδη μια στήλη ακέραιων User-ID . Ωστόσο, η προσθήκη μιας _user_id στήλης για συμβατότητα με διαφορετικά σύνολα δεδομένων καθιστά αυτό το παράδειγμα πιο ισχυρό. Χρησιμοποιήστε αυτόν τον κώδικα για να προσθέσετε τη _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()))

Χρησιμοποιήστε αυτόν τον κώδικα για να προβάλετε τα δεδομένα αξιολόγησης:

display(df_ratings, summary=True)

Αποκτήστε τις διακριτές αξιολογήσεις και αποθηκεύστε τις για μελλοντική χρήση σε μια λίστα με την ονομασία ratings:

ratings = [i[0] for i in df_ratings.select(RATING_COL).distinct().collect()]
print(ratings)

Χρησιμοποιήστε αυτόν τον κώδικα για να εμφανίσετε τα 10 κορυφαία βιβλία με τις υψηλότερες βαθμολογίες:

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")

Σύμφωνα με τις βαθμολογίες, τα Επιλεγμένα Ποιήματα είναι το πιο δημοφιλές βιβλίο. Οι περιπέτειες του Χάκλμπερι Φιν, του Μυστικού Κήπου και του Δράκουλα έχουν την ίδια βαθμολογία.

Screenshot showing a graph of the top-rated books.

Συγχώνευση δεδομένων

Συγχωνεύστε τα τρία DataFrame σε ένα DataFrame για μια πιο ολοκληρωμένη ανάλυση:

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)

Χρησιμοποιήστε αυτόν τον κώδικα για να εμφανίσετε το πλήθος των διακριτών χρηστών, βιβλίων και αλληλεπιδράσεων:

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()}")

Χρησιμοποιήστε αυτόν τον κώδικα για να υπολογίσετε και να εμφανίσετε τα 10 πιο δημοφιλή βιβλία:

# 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)

Φιλοδώρημα

Χρησιμοποιήστε την τιμή για τις ενότητες <topn> Προτάσεις δημοφιλούς ή κορυφαίας αγοράς.

# 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()

Screenshot of a graph of the most popular books.

Προετοιμασία συνόλων δεδομένων εκπαίδευσης και δοκιμής

Η μήτρα ALS απαιτεί κάποια προετοιμασία δεδομένων πριν από την εκπαίδευση. Χρησιμοποιήστε αυτό το δείγμα κώδικα για να προετοιμάσετε τα δεδομένα. Ο κώδικας εκτελεί αυτές τις ενέργειες:

  • Μετατροπή της στήλης αξιολόγησης στον σωστό τύπο
  • Δείγμα των δεδομένων εκπαίδευσης με αξιολογήσεις χρηστών
  • Διαίρεση των δεδομένων σε σύνολα δεδομένων εκπαίδευσης και δοκιμής
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
)

Η αραιότητα αναφέρεται σε αραιά δεδομένα σχολίων, τα οποία δεν μπορούν να προσδιορίσουν ομοιότητες για τα συμφέροντα των χρηστών. Για καλύτερη κατανόηση τόσο των δεδομένων όσο και του τρέχοντος προβλήματος, χρησιμοποιήστε αυτόν τον κώδικα για να υπολογίσετε την αραιότητα του συνόλου δεδομένων:

# 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]}")

Βήμα 3: Ανάπτυξη και εκπαίδευση του μοντέλου

Εκπαιδεύστε ένα μοντέλο ALS για να παρέχετε στους χρήστες εξατομικευμένες προτάσεις.

Ορισμός μοντέλου

Το Spark ML παρέχει ένα εύχρηστο API για τη δημιουργία του μοντέλου ALS. Ωστόσο, το μοντέλο δεν χειρίζεται αξιόπιστα προβλήματα όπως η αραιότητα των δεδομένων και η ψυχρή εκκίνηση (κάνοντας προτάσεις όταν οι χρήστες ή τα στοιχεία είναι νέα). Για να βελτιώσετε τις επιδόσεις του μοντέλου, συνδυάστε διασταυρούμενη επικύρωση και αυτόματη ρύθμιση υπερπαραμετρικών.

Χρησιμοποιήστε αυτόν τον κώδικα για να εισαγάγετε τις βιβλιοθήκες που απαιτούνται για την εκπαίδευση και αξιολόγηση μοντέλου:

# 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,
)

Ρύθμιση υπερπαραμετών μοντέλου

Το επόμενο δείγμα κώδικα κατασκευάζει ένα πλέγμα παραμέτρων, για να σας βοηθήσει στην αναζήτηση των υπερπαραμετών. Ο κώδικας δημιουργεί επίσης μια αξιολόγηση παλινδρόμησης που χρησιμοποιεί το σφάλμα ριζικού-τετραγώνου (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"
)

Το επόμενο δείγμα κώδικα ξεκινά διαφορετικές μεθόδους ρύθμισης μοντέλου με βάση τις προκαθορισμένες παραμέτρους. Για περισσότερες πληροφορίες σχετικά με τη ρύθμιση μοντέλου, ανατρέξτε στο θέμα Ρύθμιση εκμάθησης μηχανής: επιλογή μοντέλου και ρύθμιση υπερπαραμετέρων στην τοποθεσία Web 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}")

Αξιολόγηση του μοντέλου

Θα πρέπει να αξιολογήσετε τις λειτουργικές μονάδες σε σχέση με τα δεδομένα δοκιμής. Ένα καλά εκπαιδευμένο μοντέλο θα πρέπει να έχει υψηλά μετρικά για το σύνολο δεδομένων.

Ένα ακατάλληλο μοντέλο μπορεί να χρειαστεί αύξηση του μεγέθους των δεδομένων εκπαίδευσης ή μείωση ορισμένων από τις πλεονάζουσες δυνατότητες. Η αρχιτεκτονική μοντέλου μπορεί να χρειαστεί να αλλάξει ή οι παράμετροι της μπορεί να χρειαστούν κάποια λεπτομερή ρύθμιση.

Σημείωμα

Μια αρνητική τιμή μετρικού R στο τετράγωνο υποδεικνύει ότι το εκπαιδευμένο μοντέλο έχει χειρότερη απόδοση από μια οριζόντια ευθεία γραμμή. Αυτό το εύρημα υποδεικνύει ότι το εκπαιδευμένο μοντέλο δεν εξηγεί τα δεδομένα.

Για να ορίσετε μια συνάρτηση αξιολόγησης, χρησιμοποιήστε αυτόν τον κώδικα:

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)

Παρακολούθηση του πειράματος με χρήση MLflow

Χρησιμοποιήστε τη ροή ML για να παρακολουθήσετε όλα τα πειράματα και να καταγράψετε παραμέτρους, μετρικά και μοντέλα. Για να ξεκινήσετε την εκπαίδευση και την αξιολόγηση του μοντέλου, χρησιμοποιήστε αυτόν τον κώδικα:

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,
        }
    )

Επιλέξτε το πείραμα που ονομάζεται aisample-recommendation από τον χώρο εργασίας σας για να προβάλετε τις πληροφορίες που έχουν καταγραφεί για την εκτέλεση εκπαίδευσης. Εάν αλλάξατε το όνομα του πειράματος, επιλέξτε το πείραμα που περιέχει το νέο όνομα. Οι πληροφορίες που έχουν καταγραφεί μοιάζουν με αυτή την εικόνα:

Screenshot of the experiment logs.

Βήμα 4: Φόρτωση του τελικού μοντέλου για βαθμολόγηση και πραγματοποίηση προβλέψεων

Αφού ολοκληρώσετε την εκπαίδευση του μοντέλου και, στη συνέχεια, επιλέξετε το καλύτερο μοντέλο, φορτώστε το μοντέλο για βαθμολόγηση (μερικές φορές ονομάζεται συνάφεια). Αυτός ο κώδικας φορτώνει το μοντέλο και χρησιμοποιεί προβλέψεις για να προτείνει τα 10 κορυφαία βιβλία για κάθε χρήστη:

# 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()

Το αποτέλεσμα μοιάζει με αυτόν τον πίνακα:

_item_id _user_id αξιολόγηση Τίτλος-βιβλίου
44865 7 7.9996786 Lasher: Ζωές από ...
786 7 6.2255826 Ο πιανίστας...
45330 7 4.980466 Κατάσταση του μυαλού
38960 7 4.980466 Το μόνο που ήθελε
125415 7 4.505084 Χάρι Πότερ και...
44939 7 4.3579073 Τάλτος: Ζωές...
175247 7 4.3579073 Της Μπόουνςτερ...
170183 7 4.228735 Ζώντας την απλή...
88503 7 4.221206 Νησί της Μπλου...
32894 7 3.9031885 Χειμερινό ηλιοστάσιο

Αποθηκεύστε τις προβλέψεις στο lakehouse

Χρησιμοποιήστε αυτόν τον κώδικα για να γράψετε τις προτάσεις πίσω στο lakehouse:

# Code to save userRecs into the lakehouse
userRecs.write.format("delta").mode("overwrite").save(
    f"{DATA_FOLDER}/predictions/userRecs"
)