TensorFlow.org'da görüntüleyin | Google Colab'da çalıştırın | Kaynağı GitHub'da görüntüleyin | Not defterini indir |
Gerçek dünya tavsiye sistemleri genellikle iki aşamadan oluşur:
- Geri alma aşaması, olası tüm adaylar arasından yüzlerce adaydan oluşan bir başlangıç kümesinin seçilmesinden sorumludur. Bu modelin temel amacı, kullanıcının ilgilenmediği tüm adayları verimli bir şekilde ayıklamaktır. Alma modeli milyonlarca adayla ilgilenebileceğinden, hesaplama açısından verimli olmalıdır.
- Sıralama aşaması, erişim modelinin çıktılarını alır ve mümkün olan en iyi avuç tavsiyeyi seçmek için bunları ince ayarlar. Görevi, kullanıcının ilgilenebileceği öğe kümesini olası adayların kısa bir listesine daraltmaktır.
İkinci aşama olan sıralamaya odaklanacağız. Eğer alma aşamasında ilgilenen varsa, bizim de bir göz alma öğretici.
Bu eğitimde şunları yapacağız:
- Verilerimizi alın ve bir eğitim ve test setine bölün.
- Bir sıralama modeli uygulayın.
- Sığdırın ve değerlendirin.
ithalat
Önce ithalatımızı aradan çıkaralım.
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
Veri kümesinin hazırlanması
Biz aynı verileri kullanacağız alma öğretici. Bu sefer reytingleri de tutacağız: bunlar tahmin etmeye çalıştığımız hedefler.
ratings = tfds.load("movielens/100k-ratings", split="train")
ratings = ratings.map(lambda x: {
"movie_title": x["movie_title"],
"user_id": x["user_id"],
"user_rating": x["user_rating"]
})
2021-10-02 11:04:25.388548: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected
Daha önce olduğu gibi, derecelendirmelerin %80'ini tren setine ve %20'sini test setine koyarak verileri böleceğiz.
tf.random.set_seed(42)
shuffled = ratings.shuffle(100_000, seed=42, reshuffle_each_iteration=False)
train = shuffled.take(80_000)
test = shuffled.skip(80_000).take(20_000)
Verilerde bulunan benzersiz kullanıcı kimliklerini ve film adlarını da bulalım.
Bu önemlidir çünkü kategorik özelliklerimizin ham değerlerini modellerimizde vektörleri gömmek için eşleştirebilmemiz gerekir. Bunu yapmak için, ham özellik değerini bitişik bir aralıktaki bir tamsayıya eşleyen bir kelime dağarcığına ihtiyacımız var: bu, gömme tablolarımızda karşılık gelen gömmelere bakmamızı sağlar.
movie_titles = ratings.batch(1_000_000).map(lambda x: x["movie_title"])
user_ids = ratings.batch(1_000_000).map(lambda x: x["user_id"])
unique_movie_titles = np.unique(np.concatenate(list(movie_titles)))
unique_user_ids = np.unique(np.concatenate(list(user_ids)))
Bir modelin uygulanması
Mimari
Sıralama modelleri, alma modelleriyle aynı verimlilik kısıtlamalarıyla karşı karşıya değildir ve bu nedenle, mimari seçimlerimizde biraz daha özgürlüğe sahibiz.
Birden çok yığılmış yoğun katmandan oluşan bir model, görevleri sıralamak için nispeten yaygın bir mimaridir. Aşağıdaki gibi uygulayabiliriz:
class RankingModel(tf.keras.Model):
def __init__(self):
super().__init__()
embedding_dimension = 32
# Compute embeddings for users.
self.user_embeddings = tf.keras.Sequential([
tf.keras.layers.StringLookup(
vocabulary=unique_user_ids, mask_token=None),
tf.keras.layers.Embedding(len(unique_user_ids) + 1, embedding_dimension)
])
# Compute embeddings for movies.
self.movie_embeddings = tf.keras.Sequential([
tf.keras.layers.StringLookup(
vocabulary=unique_movie_titles, mask_token=None),
tf.keras.layers.Embedding(len(unique_movie_titles) + 1, embedding_dimension)
])
# Compute predictions.
self.ratings = tf.keras.Sequential([
# Learn multiple dense layers.
tf.keras.layers.Dense(256, activation="relu"),
tf.keras.layers.Dense(64, activation="relu"),
# Make rating predictions in the final layer.
tf.keras.layers.Dense(1)
])
def call(self, inputs):
user_id, movie_title = inputs
user_embedding = self.user_embeddings(user_id)
movie_embedding = self.movie_embeddings(movie_title)
return self.ratings(tf.concat([user_embedding, movie_embedding], axis=1))
Bu model, kullanıcı kimliklerini ve film adlarını alır ve tahmini bir derecelendirme verir:
RankingModel()((["42"], ["One Flew Over the Cuckoo's Nest (1975)"]))
WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor, but we receive a <class 'list'> input: ['42'] Consider rewriting this model with the Functional API. WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor, but we receive a <class 'list'> input: ['42'] Consider rewriting this model with the Functional API. WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor, but we receive a <class 'list'> input: ["One Flew Over the Cuckoo's Nest (1975)"] Consider rewriting this model with the Functional API. WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor, but we receive a <class 'list'> input: ["One Flew Over the Cuckoo's Nest (1975)"] Consider rewriting this model with the Functional API. <tf.Tensor: shape=(1, 1), dtype=float32, numpy=array([[0.03740937]], dtype=float32)>
Kayıp ve metrikler
Bir sonraki bileşen, modelimizi eğitmek için kullanılan kayıptır. TFRS'nin bunu kolaylaştıracak birkaç kayıp katmanı ve görevi vardır.
Bu durumda, biz faydalanmak edeceğiz Ranking
birlikte kayıp fonksiyonu ve metrik hesaplama demetleri bir kolaylık sarıcı: Görev nesnesi.
Biz bunu birlikte kullanacağız MeanSquaredError
derecelendirme tahmin etmek amacıyla Keras kaybı.
task = tfrs.tasks.Ranking(
loss = tf.keras.losses.MeanSquaredError(),
metrics=[tf.keras.metrics.RootMeanSquaredError()]
)
Görevin kendisi, doğru ve tahmin edilen argümanları alan ve hesaplanan kaybı döndüren bir Keras katmanıdır. Bunu, modelin eğitim döngüsünü uygulamak için kullanacağız.
tam model
Şimdi hepsini bir modelde birleştirebiliriz. TFRS bir temel modeli sınıfını (açığa tfrs.models.Model
bulding modeller kolaylaştırır): Yapmamız gereken tüm bileşenleri kurmaktır __init__
yöntemi ve uygulama compute_loss
ham özellikleri alıp bir kayıp değerini döndüren yöntem .
Temel model daha sonra modelimize uyacak uygun eğitim döngüsünü oluşturmaya özen gösterecektir.
class MovielensModel(tfrs.models.Model):
def __init__(self):
super().__init__()
self.ranking_model: tf.keras.Model = RankingModel()
self.task: tf.keras.layers.Layer = tfrs.tasks.Ranking(
loss = tf.keras.losses.MeanSquaredError(),
metrics=[tf.keras.metrics.RootMeanSquaredError()]
)
def call(self, features: Dict[str, tf.Tensor]) -> tf.Tensor:
return self.ranking_model(
(features["user_id"], features["movie_title"]))
def compute_loss(self, features: Dict[Text, tf.Tensor], training=False) -> tf.Tensor:
labels = features.pop("user_rating")
rating_predictions = self(features)
# The task computes the loss and the metrics.
return self.task(labels=labels, predictions=rating_predictions)
Takma ve değerlendirme
Modeli tanımladıktan sonra, modeli sığdırmak ve değerlendirmek için standart Keras uydurma ve değerlendirme rutinlerini kullanabiliriz.
Önce modeli somutlaştıralım.
model = MovielensModel()
model.compile(optimizer=tf.keras.optimizers.Adagrad(learning_rate=0.1))
Ardından eğitim ve değerlendirme verilerini karıştırın, gruplayın ve önbelleğe alın.
cached_train = train.shuffle(100_000).batch(8192).cache()
cached_test = test.batch(4096).cache()
Ardından modeli eğitin:
model.fit(cached_train, epochs=3)
Epoch 1/3 10/10 [==============================] - 2s 26ms/step - root_mean_squared_error: 2.1718 - loss: 4.3303 - regularization_loss: 0.0000e+00 - total_loss: 4.3303 Epoch 2/3 10/10 [==============================] - 0s 8ms/step - root_mean_squared_error: 1.1227 - loss: 1.2602 - regularization_loss: 0.0000e+00 - total_loss: 1.2602 Epoch 3/3 10/10 [==============================] - 0s 8ms/step - root_mean_squared_error: 1.1162 - loss: 1.2456 - regularization_loss: 0.0000e+00 - total_loss: 1.2456 <keras.callbacks.History at 0x7f28389eaa90>
Model ilerledikçe, kayıp düşüyor ve RMSE metriği gelişiyor.
Son olarak test setinde modelimizi değerlendirebiliriz:
model.evaluate(cached_test, return_dict=True)
5/5 [==============================] - 2s 14ms/step - root_mean_squared_error: 1.1108 - loss: 1.2287 - regularization_loss: 0.0000e+00 - total_loss: 1.2287 {'root_mean_squared_error': 1.1108061075210571, 'loss': 1.2062578201293945, 'regularization_loss': 0, 'total_loss': 1.2062578201293945}
RMSE metriği ne kadar düşükse, modelimiz derecelendirmeleri tahmin etmede o kadar doğru olur.
Sıralama modelini test etme
Şimdi, bir dizi film için tahminleri hesaplayarak sıralama modelini test edebilir ve ardından bu filmleri tahminlere göre sıralayabiliriz:
test_ratings = {}
test_movie_titles = ["M*A*S*H (1970)", "Dances with Wolves (1990)", "Speed (1994)"]
for movie_title in test_movie_titles:
test_ratings[movie_title] = model({
"user_id": np.array(["42"]),
"movie_title": np.array([movie_title])
})
print("Ratings:")
for title, score in sorted(test_ratings.items(), key=lambda x: x[1], reverse=True):
print(f"{title}: {score}")
Ratings: M*A*S*H (1970): [[3.584712]] Dances with Wolves (1990): [[3.551556]] Speed (1994): [[3.5215874]]
Sunum için dışa aktarılıyor
Model, hizmet için kolayca dışa aktarılabilir:
tf.saved_model.save(model, "export")
2021-10-02 11:04:38.235611: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them. WARNING:absl:Found untraced functions such as ranking_1_layer_call_and_return_conditional_losses, ranking_1_layer_call_fn, ranking_1_layer_call_fn, ranking_1_layer_call_and_return_conditional_losses, ranking_1_layer_call_and_return_conditional_losses while saving (showing 5 of 5). These functions will not be directly callable after loading. INFO:tensorflow:Assets written to: export/assets INFO:tensorflow:Assets written to: export/assets
Şimdi onu geri yükleyebilir ve tahminler yapabiliriz:
loaded = tf.saved_model.load("export")
loaded({"user_id": np.array(["42"]), "movie_title": ["Speed (1994)"]}).numpy()
array([[3.5215874]], dtype=float32)
Sonraki adımlar
Yukarıdaki model bize bir sıralama sistemi oluşturmaya yönelik iyi bir başlangıç sağlıyor.
Tabii ki pratik bir sıralama sistemi yapmak çok daha fazla çaba gerektiriyor.
Çoğu durumda, bir sıralama modeli, yalnızca kullanıcı ve aday tanımlayıcıları yerine daha fazla özellik kullanılarak önemli ölçüde geliştirilebilir. Bunun nasıl yapılacağını görmek için, bir göz tarafında özellikleri öğretici.
Optimize etmeye değer hedeflerin dikkatli bir şekilde anlaşılması da gereklidir. Birden çok hedefi optimize eden bir tavsiye eden oluşturmaya başlamak için, bizim de bir göz çoklu görev öğretici.