הצג באתר TensorFlow.org | הפעל בגוגל קולאב | צפה במקור ב-GitHub | הורד מחברת |
במדריך זה, אנו הולכים לבנות מודל אחזור רציף. המלצה רציפה היא מודל פופולרי שבוחן רצף של פריטים שמשתמשים יצרו איתם אינטראקציה בעבר ולאחר מכן מנבא את הפריט הבא. כאן יש חשיבות לסדר הפריטים בכל רצף, אז אנחנו הולכים להשתמש ברשת עצבית חוזרת כדי לדגמן את הקשר הרציף. לפרטים נוספים, עיין זה נייר GRU4Rec .
יבוא
ראשית בואו נוציא מהדרך את התלות והיבוא שלנו.
pip install -q tensorflow-recommenders
pip install -q --upgrade tensorflow-datasets
import os
import pprint
import tempfile
from typing import Dict, Text
import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds
import tensorflow_recommenders as tfrs
הכנת מערך הנתונים
לאחר מכן, עלינו להכין את מערך הנתונים שלנו. אנחנו הולכים למנף את שירות יצירת הקובץ הזה אפליקצית התייחסות המלצת TensorFlow לייט במכשיר .
נתונים MovieLens 1M מכיל ratings.dat (עמודות: זיהוי המשתמש, MovieID, דירוג, חותמת זמן), ואת movies.dat (עמודות: MovieID, כותרת, ז'אנרים). תסריט הדור לדוגמה מוריד את מערך הנתונים של 1M, לוקח את שני הקבצים, רק שומר על דירוגים גבוהים מ-2, יוצר לוחות זמנים של אינטראקציה עם סרטי משתמש, פעילויות לדוגמה כתוויות ו-10 פעילויות קודמות של משתמשים כהקשר לחיזוי.
wget -nc https://raw.githubusercontent.com/tensorflow/examples/master/lite/examples/recommendation/ml/data/example_generation_movielens.py
python -m example_generation_movielens --data_dir=data/raw --output_dir=data/examples --min_timeline_length=3 --max_context_length=10 --max_context_movie_genre_length=10 --min_rating=2 --train_data_fraction=0.9 --build_vocabs=False
--2021-12-02 12:10:29-- https://raw.githubusercontent.com/tensorflow/examples/master/lite/examples/recommendation/ml/data/example_generation_movielens.py Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.110.133, 185.199.111.133, ... Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 18040 (18K) [text/plain] Saving to: ‘example_generation_movielens.py’ example_generation_ 100%[===================>] 17.62K --.-KB/s in 0s 2021-12-02 12:10:29 (107 MB/s) - ‘example_generation_movielens.py’ saved [18040/18040] I1202 12:10:32.036267 140629273970496 example_generation_movielens.py:460] Downloading and extracting data. Downloading data from http://files.grouplens.org/datasets/movielens/ml-1m.zip 5922816/5917549 [==============================] - 1s 0us/step 5931008/5917549 [==============================] - 1s 0us/step I1202 12:10:33.549675 140629273970496 example_generation_movielens.py:406] Reading data to dataframes. /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/pandas/util/_decorators.py:311: ParserWarning: Falling back to the 'python' engine because the 'c' engine does not support regex separators (separators > 1 char and different from '\s+' are interpreted as regex); you can avoid this warning by specifying engine='python'. return func(*args, **kwargs) I1202 12:10:37.734699 140629273970496 example_generation_movielens.py:408] Generating movie rating user timelines. I1202 12:10:40.836473 140629273970496 example_generation_movielens.py:410] Generating train and test examples. 6040/6040 [==============================] - 76s 13ms/step I1202 12:11:57.162662 140629273970496 example_generation_movielens.py:421] Writing generated training examples. 844195/844195 [==============================] - 14s 17us/step I1202 12:12:11.266682 140629273970496 example_generation_movielens.py:424] Writing generated testing examples. 93799/93799 [==============================] - 2s 17us/step I1202 12:12:22.758407 140629273970496 example_generation_movielens.py:473] Generated dataset: {'train_size': 844195, 'test_size': 93799, 'train_file': 'data/examples/train_movielens_1m.tfrecord', 'test_file': 'data/examples/test_movielens_1m.tfrecord'}
הנה דוגמה של מערך הנתונים שנוצר.
0 : {
features: {
feature: {
key : "context_movie_id"
value: { int64_list: { value: [ 1124, 2240, 3251, ..., 1268 ] } }
}
feature: {
key : "context_movie_rating"
value: { float_list: {value: [ 3.0, 3.0, 4.0, ..., 3.0 ] } }
}
feature: {
key : "context_movie_year"
value: { int64_list: { value: [ 1981, 1980, 1985, ..., 1990 ] } }
}
feature: {
key : "context_movie_genre"
value: { bytes_list: { value: [ "Drama", "Drama", "Mystery", ..., "UNK" ] } }
}
feature: {
key : "label_movie_id"
value: { int64_list: { value: [ 3252 ] } }
}
}
}
אתה יכול לראות שהוא כולל רצף של מזהי סרטי הקשר, ומזהה סרט תווית (הסרט הבא), בתוספת תכונות הקשר כגון שנת סרט, דירוג וז'אנר.
במקרה שלנו נשתמש רק ברצף של מזהי הסרט ההקשרים ובמזהה הסרט של התווית. אתה יכול להתייחס להקשר מינוף תכונות הדרכה כדי ללמוד עוד על הוספת תכונות נוספות בהקשר.
train_filename = "./data/examples/train_movielens_1m.tfrecord"
train = tf.data.TFRecordDataset(train_filename)
test_filename = "./data/examples/test_movielens_1m.tfrecord"
test = tf.data.TFRecordDataset(test_filename)
feature_description = {
'context_movie_id': tf.io.FixedLenFeature([10], tf.int64, default_value=np.repeat(0, 10)),
'context_movie_rating': tf.io.FixedLenFeature([10], tf.float32, default_value=np.repeat(0, 10)),
'context_movie_year': tf.io.FixedLenFeature([10], tf.int64, default_value=np.repeat(1980, 10)),
'context_movie_genre': tf.io.FixedLenFeature([10], tf.string, default_value=np.repeat("Drama", 10)),
'label_movie_id': tf.io.FixedLenFeature([1], tf.int64, default_value=0),
}
def _parse_function(example_proto):
return tf.io.parse_single_example(example_proto, feature_description)
train_ds = train.map(_parse_function).map(lambda x: {
"context_movie_id": tf.strings.as_string(x["context_movie_id"]),
"label_movie_id": tf.strings.as_string(x["label_movie_id"])
})
test_ds = test.map(_parse_function).map(lambda x: {
"context_movie_id": tf.strings.as_string(x["context_movie_id"]),
"label_movie_id": tf.strings.as_string(x["label_movie_id"])
})
for x in train_ds.take(1).as_numpy_iterator():
pprint.pprint(x)
{'context_movie_id': array([b'2589', b'202', b'1038', b'1767', b'951', b'129', b'1256', b'955', b'3097', b'3462'], dtype=object), 'label_movie_id': array([b'3629'], dtype=object)}
כעת מערכי הנתונים של הרכבות/בדיקות שלנו כוללים רק רצף של מזהי סרטים היסטוריים ותווית של מזהה הסרט הבא. שים לב כי אנו משתמשים [10]
כמו הצורה של תכונות במהלך ניתוח tf.Example משום שאנו לציין 10 שכן אורך בהקשר כולל בשלב למשל generateion.
אנחנו צריכים עוד דבר אחד לפני שנוכל להתחיל לבנות את המודל - אוצר המילים של מזהי הסרטים שלנו.
movies = tfds.load("movielens/1m-movies", split='train')
movies = movies.map(lambda x: x["movie_id"])
movie_ids = movies.batch(1_000)
unique_movie_ids = np.unique(np.concatenate(list(movie_ids)))
הטמעת מודל רציף
בשינה שלנו ההדרכה תחזור הבסיסית , אנו משתמשים מגדל בשאילתא אחת עבור המשתמש, ואת גרירת מועמד סרט המועמד. עם זאת, ארכיטקטורת שני המגדלים ניתנת להכללה ואינה מוגבלת ל
כאן אנחנו עדיין הולכים להשתמש בארכיטקטורת שני המגדלים. Specificially, אנו משתמשים המגדל שאילתה עם יחידת חוזרות מגודרת (GRU) שכבה לקידוד רצף של סרטים היסטוריים, ולשמור אותו למגדל מועמד הסרט מועמד.
embedding_dimension = 32
query_model = tf.keras.Sequential([
tf.keras.layers.StringLookup(
vocabulary=unique_movie_ids, mask_token=None),
tf.keras.layers.Embedding(len(unique_movie_ids) + 1, embedding_dimension),
tf.keras.layers.GRU(embedding_dimension),
])
candidate_model = tf.keras.Sequential([
tf.keras.layers.StringLookup(
vocabulary=unique_movie_ids, mask_token=None),
tf.keras.layers.Embedding(len(unique_movie_ids) + 1, embedding_dimension)
])
המדדים, המשימה והמודל המלא מוגדרים בדומה למודל האחזור הבסיסי.
metrics = tfrs.metrics.FactorizedTopK(
candidates=movies.batch(128).map(candidate_model)
)
task = tfrs.tasks.Retrieval(
metrics=metrics
)
class Model(tfrs.Model):
def __init__(self, query_model, candidate_model):
super().__init__()
self._query_model = query_model
self._candidate_model = candidate_model
self._task = task
def compute_loss(self, features, training=False):
watch_history = features["context_movie_id"]
watch_next_label = features["label_movie_id"]
query_embedding = self._query_model(watch_history)
candidate_embedding = self._candidate_model(watch_next_label)
return self._task(query_embedding, candidate_embedding, compute_metrics=not training)
התאמה והערכה
כעת אנו יכולים לקמפל, לאמן ולהעריך את מודל האחזור הרציף שלנו.
model = Model(query_model, candidate_model)
model.compile(optimizer=tf.keras.optimizers.Adagrad(learning_rate=0.1))
cached_train = train_ds.shuffle(10_000).batch(12800).cache()
cached_test = test_ds.batch(2560).cache()
model.fit(cached_train, epochs=3)
Epoch 1/3 67/67 [==============================] - 25s 291ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0000e+00 - factorized_top_k/top_5_categorical_accuracy: 0.0000e+00 - factorized_top_k/top_10_categorical_accuracy: 0.0000e+00 - factorized_top_k/top_50_categorical_accuracy: 0.0000e+00 - factorized_top_k/top_100_categorical_accuracy: 0.0000e+00 - loss: 107448.4467 - regularization_loss: 0.0000e+00 - total_loss: 107448.4467 Epoch 2/3 67/67 [==============================] - 2s 25ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0000e+00 - factorized_top_k/top_5_categorical_accuracy: 0.0000e+00 - factorized_top_k/top_10_categorical_accuracy: 0.0000e+00 - factorized_top_k/top_50_categorical_accuracy: 0.0000e+00 - factorized_top_k/top_100_categorical_accuracy: 0.0000e+00 - loss: 100932.0125 - regularization_loss: 0.0000e+00 - total_loss: 100932.0125 Epoch 3/3 67/67 [==============================] - 2s 25ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0000e+00 - factorized_top_k/top_5_categorical_accuracy: 0.0000e+00 - factorized_top_k/top_10_categorical_accuracy: 0.0000e+00 - factorized_top_k/top_50_categorical_accuracy: 0.0000e+00 - factorized_top_k/top_100_categorical_accuracy: 0.0000e+00 - loss: 99336.2015 - regularization_loss: 0.0000e+00 - total_loss: 99336.2015 <keras.callbacks.History at 0x7f0904d5b410>
model.evaluate(cached_test, return_dict=True)
37/37 [==============================] - 10s 235ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0146 - factorized_top_k/top_5_categorical_accuracy: 0.0780 - factorized_top_k/top_10_categorical_accuracy: 0.1358 - factorized_top_k/top_50_categorical_accuracy: 0.3735 - factorized_top_k/top_100_categorical_accuracy: 0.5058 - loss: 15478.0652 - regularization_loss: 0.0000e+00 - total_loss: 15478.0652 {'factorized_top_k/top_1_categorical_accuracy': 0.014605699107050896, 'factorized_top_k/top_5_categorical_accuracy': 0.07804987579584122, 'factorized_top_k/top_10_categorical_accuracy': 0.1358330100774765, 'factorized_top_k/top_50_categorical_accuracy': 0.3735221028327942, 'factorized_top_k/top_100_categorical_accuracy': 0.5058262944221497, 'loss': 9413.1240234375, 'regularization_loss': 0, 'total_loss': 9413.1240234375}
בכך מסתיים מערך האחזור הרציף.