Film yang direkomendasikan: pengambilan

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub Unduh buku catatan

Sistem pemberi rekomendasi dunia nyata sering terdiri dari dua tahap:

  1. Tahap pengambilan bertanggung jawab untuk memilih satu set awal ratusan kandidat dari semua kandidat yang mungkin. Tujuan utama model ini adalah untuk secara efisien menyingkirkan semua kandidat yang tidak diminati pengguna. Karena model pengambilan mungkin berurusan dengan jutaan kandidat, model ini harus efisien secara komputasi.
  2. Tahap pemeringkatan mengambil output dari model pengambilan dan menyempurnakannya untuk memilih beberapa rekomendasi terbaik. Tugasnya adalah mempersempit set item yang mungkin diminati pengguna menjadi daftar kandidat yang mungkin.

Dalam tutorial ini, kita akan fokus pada tahap pertama, pengambilan. Jika Anda tertarik dalam tahap peringkat, kita lihat kami peringkat tutorial.

Model pengambilan sering terdiri dari dua sub-model:

  1. Model kueri yang menghitung representasi kueri (biasanya vektor embedding dimensi tetap) menggunakan fitur kueri.
  2. Model kandidat yang menghitung representasi kandidat (vektor berukuran sama) menggunakan fitur kandidat

Keluaran dari kedua model tersebut kemudian dikalikan bersama untuk memberikan skor afinitas kandidat kueri, dengan skor yang lebih tinggi menunjukkan kecocokan yang lebih baik antara kandidat dan kueri.

Dalam tutorial ini, kita akan membangun dan melatih model dua menara menggunakan dataset Movielens.

Akan:

  1. Dapatkan data kami dan bagi menjadi satu set pelatihan dan pengujian.
  2. Menerapkan model pengambilan.
  3. Sesuaikan dan evaluasi.
  4. Ekspor untuk penyajian yang efisien dengan membangun indeks perkiraan tetangga terdekat (ANN).

kumpulan data

The Movielens dataset adalah dataset klasik dari GroupLens penelitian kelompok di University of Minnesota. Ini berisi serangkaian peringkat yang diberikan untuk film oleh sekelompok pengguna, dan merupakan pekerja keras dari penelitian sistem pemberi rekomendasi.

Data dapat diperlakukan dengan dua cara:

  1. Ini dapat diartikan sebagai mengekspresikan film mana yang ditonton (dan diberi peringkat) oleh pengguna, dan mana yang tidak. Ini adalah bentuk umpan balik implisit, di mana jam tangan pengguna memberi tahu kami hal mana yang mereka sukai untuk dilihat dan mana yang tidak ingin mereka lihat.
  2. Itu juga dapat dilihat sebagai ekspresi betapa pengguna menyukai film yang mereka tonton. Ini adalah bentuk umpan balik eksplisit: mengingat bahwa pengguna menonton film, kami dapat mengetahui secara kasar seberapa banyak mereka menyukai dengan melihat peringkat yang mereka berikan.

Dalam tutorial ini, kami berfokus pada sistem pengambilan: model yang memprediksi sekumpulan film dari katalog yang kemungkinan akan ditonton pengguna. Seringkali, data implisit lebih berguna di sini, jadi kita akan memperlakukan Movielens sebagai sistem implisit. Ini berarti bahwa setiap film yang ditonton pengguna adalah contoh positif, dan setiap film yang belum mereka tonton adalah contoh negatif implisit.

Impor

Pertama-tama mari kita singkirkan impor kita.

pip install -q tensorflow-recommenders
pip install -q --upgrade tensorflow-datasets
pip install -q scann
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

Mempersiapkan kumpulan data

Kita lihat dulu datanya.

Kami menggunakan dataset MovieLens dari Tensorflow Datasets . Memuat movielens/100k_ratings menghasilkan tf.data.Dataset objek yang berisi data rating dan pemuatan movielens/100k_movies hasil sebuah tf.data.Dataset objek yang hanya berisi data film.

Perhatikan bahwa sejak MovieLens dataset tidak memiliki standar perpecahan, semua data berada di bawah train split.

# Ratings data.
ratings = tfds.load("movielens/100k-ratings", split="train")
# Features of all the available movies.
movies = tfds.load("movielens/100k-movies", split="train")
2021-10-02 11:05:34.633747: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected

Dataset peringkat mengembalikan kamus id film, id pengguna, peringkat yang ditetapkan, stempel waktu, informasi film, dan informasi pengguna:

for x in ratings.take(1).as_numpy_iterator():
  pprint.pprint(x)
{'bucketized_user_age': 45.0,
 'movie_genres': array([7]),
 'movie_id': b'357',
 'movie_title': b"One Flew Over the Cuckoo's Nest (1975)",
 'raw_user_age': 46.0,
 'timestamp': 879024327,
 'user_gender': True,
 'user_id': b'138',
 'user_occupation_label': 4,
 'user_occupation_text': b'doctor',
 'user_rating': 4.0,
 'user_zip_code': b'53211'}
2021-10-02 11:05:35.718641: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.

Kumpulan data film berisi id film, judul film, dan data tentang genrenya. Perhatikan bahwa genre dikodekan dengan label bilangan bulat.

for x in movies.take(1).as_numpy_iterator():
  pprint.pprint(x)
{'movie_genres': array([4]),
 'movie_id': b'1681',
 'movie_title': b'You So Crazy (1994)'}
2021-10-02 11:05:35.893098: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.

Dalam contoh ini, kita akan fokus pada data peringkat. Tutorial lain mengeksplorasi cara menggunakan data informasi film juga untuk meningkatkan kualitas model.

Kami tetap hanya user_id , dan movie_title bidang dalam dataset.

ratings = ratings.map(lambda x: {
    "movie_title": x["movie_title"],
    "user_id": x["user_id"],
})
movies = movies.map(lambda x: x["movie_title"])

Untuk menyesuaikan dan mengevaluasi model, kita perlu membaginya menjadi satu set pelatihan dan evaluasi. Dalam sistem recommender industri, ini kemungkinan besar akan dilakukan pada saat: data sampai dengan waktu \(T\) akan digunakan untuk memprediksi interaksi setelah \(T\).

Namun, dalam contoh sederhana ini, mari kita gunakan pemisahan acak, menempatkan 80% peringkat di set kereta, dan 20% di set tes.

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)

Mari kita juga mencari tahu id pengguna unik dan judul film yang ada dalam data.

Hal ini penting karena kita harus mampu memetakan nilai mentah dari fitur kategoris kita untuk menyematkan vektor dalam model kita. Untuk melakukan itu, kita memerlukan kosakata yang memetakan nilai fitur mentah ke bilangan bulat dalam rentang yang berdekatan: ini memungkinkan kita untuk mencari embedding yang sesuai di tabel embedding kita.

movie_titles = movies.batch(1_000)
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)))

unique_movie_titles[:10]
array([b"'Til There Was You (1997)", b'1-900 (1994)',
       b'101 Dalmatians (1996)', b'12 Angry Men (1957)', b'187 (1997)',
       b'2 Days in the Valley (1996)',
       b'20,000 Leagues Under the Sea (1954)',
       b'2001: A Space Odyssey (1968)',
       b'3 Ninjas: High Noon At Mega Mountain (1998)',
       b'39 Steps, The (1935)'], dtype=object)

Menerapkan model

Memilih arsitektur model kami adalah bagian penting dari pemodelan.

Karena kami sedang membangun model pengambilan dua menara, kami dapat membangun setiap menara secara terpisah dan kemudian menggabungkannya dalam model akhir.

Menara kueri

Mari kita mulai dengan menara kueri.

Langkah pertama adalah memutuskan dimensi kueri dan representasi kandidat:

embedding_dimension = 32

Nilai yang lebih tinggi akan sesuai dengan model yang mungkin lebih akurat, tetapi juga akan lebih lambat untuk menyesuaikan dan lebih rentan terhadap overfitting.

Yang kedua adalah mendefinisikan model itu sendiri. Di sini, kita akan menggunakan Keras preprocessing lapisan untuk mengkonversi pertama id pengguna untuk bilangan bulat, dan kemudian dikonversi mereka untuk embeddings pengguna melalui Embedding lapisan. Perhatikan bahwa kami menggunakan daftar id pengguna unik yang kami hitung sebelumnya sebagai kosakata:

user_model = tf.keras.Sequential([
  tf.keras.layers.StringLookup(
      vocabulary=unique_user_ids, mask_token=None),
  # We add an additional embedding to account for unknown tokens.
  tf.keras.layers.Embedding(len(unique_user_ids) + 1, embedding_dimension)
])

Sebuah model sederhana seperti ini sesuai persis dengan klasik faktorisasi matriks pendekatan. Sementara mendefinisikan subclass dari tf.keras.Model untuk model sederhana ini mungkin berlebihan, kita dapat dengan mudah memperpanjang untuk model sewenang-wenang kompleks menggunakan komponen Keras standar, selama kita mengembalikan embedding_dimension keluaran -lebar di akhir.

Kandidat menara

Kita bisa melakukan hal yang sama dengan calon tower.

movie_model = 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)
])

Metrik

Dalam data pelatihan kami, kami memiliki pasangan positif (pengguna, film). Untuk mengetahui seberapa bagus model kita, kita perlu membandingkan skor afinitas yang dihitung model untuk pasangan ini dengan skor semua kandidat lain yang mungkin: jika skor untuk pasangan positif lebih tinggi daripada semua kandidat lain, model kita sangat akurat.

Untuk melakukan hal ini, kita dapat menggunakan tfrs.metrics.FactorizedTopK metrik. Metrik ini memiliki satu argumen yang diperlukan: kumpulan data kandidat yang digunakan sebagai negatif implisit untuk evaluasi.

Dalam kasus kami, itulah movies dataset, diubah menjadi embeddings melalui Model film kami:

metrics = tfrs.metrics.FactorizedTopK(
  candidates=movies.batch(128).map(movie_model)
)

Kehilangan

Komponen selanjutnya adalah loss yang digunakan untuk melatih model kita. TFRS memiliki beberapa lapisan kerugian dan tugas untuk membuatnya mudah.

Dalam hal ini, kami akan memanfaatkan Retrieval objek tugas: a kenyamanan pembungkus yang bundel bersama-sama fungsi kerugian dan metrik perhitungan:

task = tfrs.tasks.Retrieval(
  metrics=metrics
)

Tugas itu sendiri adalah lapisan Keras yang mengambil kueri dan penyematan kandidat sebagai argumen, dan mengembalikan kerugian yang dihitung: kami akan menggunakannya untuk mengimplementasikan loop pelatihan model.

Model lengkapnya

Sekarang kita dapat menggabungkan semuanya menjadi sebuah model. TFRS mengekspos kelas model dasar ( tfrs.models.Model ) yang merampingkan model bangunan: semua yang perlu kita lakukan adalah untuk mengatur komponen dalam __init__ metode, dan melaksanakan compute_loss metode, mengambil dalam fitur mentah dan mengembalikan nilai kerugian .

Model dasar kemudian akan mengurus pembuatan loop pelatihan yang sesuai agar sesuai dengan model kita.

class MovielensModel(tfrs.Model):

  def __init__(self, user_model, movie_model):
    super().__init__()
    self.movie_model: tf.keras.Model = movie_model
    self.user_model: tf.keras.Model = user_model
    self.task: tf.keras.layers.Layer = task

  def compute_loss(self, features: Dict[Text, tf.Tensor], training=False) -> tf.Tensor:
    # We pick out the user features and pass them into the user model.
    user_embeddings = self.user_model(features["user_id"])
    # And pick out the movie features and pass them into the movie model,
    # getting embeddings back.
    positive_movie_embeddings = self.movie_model(features["movie_title"])

    # The task computes the loss and the metrics.
    return self.task(user_embeddings, positive_movie_embeddings)

The tfrs.Model kelas dasar kelas hanya kenyamanan: memungkinkan kita untuk menghitung baik pelatihan dan uji kerugian menggunakan metode yang sama.

Di bawah kap, masih model Keras polos. Anda bisa mencapai fungsi yang sama dengan mewarisi dari tf.keras.Model dan menimpa train_step dan test_step fungsi (lihat panduan untuk rincian):

class NoBaseClassMovielensModel(tf.keras.Model):

  def __init__(self, user_model, movie_model):
    super().__init__()
    self.movie_model: tf.keras.Model = movie_model
    self.user_model: tf.keras.Model = user_model
    self.task: tf.keras.layers.Layer = task

  def train_step(self, features: Dict[Text, tf.Tensor]) -> tf.Tensor:

    # Set up a gradient tape to record gradients.
    with tf.GradientTape() as tape:

      # Loss computation.
      user_embeddings = self.user_model(features["user_id"])
      positive_movie_embeddings = self.movie_model(features["movie_title"])
      loss = self.task(user_embeddings, positive_movie_embeddings)

      # Handle regularization losses as well.
      regularization_loss = sum(self.losses)

      total_loss = loss + regularization_loss

    gradients = tape.gradient(total_loss, self.trainable_variables)
    self.optimizer.apply_gradients(zip(gradients, self.trainable_variables))

    metrics = {metric.name: metric.result() for metric in self.metrics}
    metrics["loss"] = loss
    metrics["regularization_loss"] = regularization_loss
    metrics["total_loss"] = total_loss

    return metrics

  def test_step(self, features: Dict[Text, tf.Tensor]) -> tf.Tensor:

    # Loss computation.
    user_embeddings = self.user_model(features["user_id"])
    positive_movie_embeddings = self.movie_model(features["movie_title"])
    loss = self.task(user_embeddings, positive_movie_embeddings)

    # Handle regularization losses as well.
    regularization_loss = sum(self.losses)

    total_loss = loss + regularization_loss

    metrics = {metric.name: metric.result() for metric in self.metrics}
    metrics["loss"] = loss
    metrics["regularization_loss"] = regularization_loss
    metrics["total_loss"] = total_loss

    return metrics

Dalam tutorial ini, namun, kami tetap menggunakan tfrs.Model kelas dasar untuk menjaga fokus kami pada pemodelan dan abstrak pergi beberapa boilerplate.

Pas dan mengevaluasi

Setelah mendefinisikan model, kita dapat menggunakan rutinitas pemasangan dan evaluasi Keras standar untuk menyesuaikan dan mengevaluasi model.

Mari kita instantiate modelnya dulu.

model = MovielensModel(user_model, movie_model)
model.compile(optimizer=tf.keras.optimizers.Adagrad(learning_rate=0.1))

Kemudian shuffle, batch, dan cache data pelatihan dan evaluasi.

cached_train = train.shuffle(100_000).batch(8192).cache()
cached_test = test.batch(4096).cache()

Kemudian latih modelnya:

model.fit(cached_train, epochs=3)
Epoch 1/3
10/10 [==============================] - 6s 302ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0011 - factorized_top_k/top_5_categorical_accuracy: 0.0094 - factorized_top_k/top_10_categorical_accuracy: 0.0203 - factorized_top_k/top_50_categorical_accuracy: 0.1001 - factorized_top_k/top_100_categorical_accuracy: 0.1772 - loss: 69885.1129 - regularization_loss: 0.0000e+00 - total_loss: 69885.1129
Epoch 2/3
10/10 [==============================] - 3s 286ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0029 - factorized_top_k/top_5_categorical_accuracy: 0.0186 - factorized_top_k/top_10_categorical_accuracy: 0.0376 - factorized_top_k/top_50_categorical_accuracy: 0.1689 - factorized_top_k/top_100_categorical_accuracy: 0.2923 - loss: 67523.3707 - regularization_loss: 0.0000e+00 - total_loss: 67523.3707
Epoch 3/3
10/10 [==============================] - 3s 269ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0036 - factorized_top_k/top_5_categorical_accuracy: 0.0224 - factorized_top_k/top_10_categorical_accuracy: 0.0459 - factorized_top_k/top_50_categorical_accuracy: 0.1880 - factorized_top_k/top_100_categorical_accuracy: 0.3162 - loss: 66302.9609 - regularization_loss: 0.0000e+00 - total_loss: 66302.9609
<keras.callbacks.History at 0x7f560e5ea090>

Jika Anda ingin memantau proses pelatihan dengan TensorBoard, Anda dapat menambahkan callback TensorBoard untuk fit () fungsi dan kemudian mulai TensorBoard menggunakan %tensorboard --logdir logs/fit . Silahkan lihat dokumentasi TensorBoard untuk lebih jelasnya.

Saat model berlatih, kerugian berkurang dan satu set metrik pengambilan top-k diperbarui. Ini memberitahu kita apakah benar positif ada di top-k item yang diambil dari seluruh set kandidat. Misalnya, metrik akurasi kategoris 5 teratas sebesar 0,2 akan memberi tahu kami bahwa, rata-rata, nilai positif sebenarnya ada di 5 item teratas yang diambil sebanyak 20% dari waktu.

Perhatikan bahwa, dalam contoh ini, kami mengevaluasi metrik selama pelatihan serta evaluasi. Karena ini bisa sangat lambat dengan kumpulan kandidat yang besar, mungkin lebih bijaksana untuk menonaktifkan penghitungan metrik dalam pelatihan, dan hanya menjalankannya dalam evaluasi.

Akhirnya, kami dapat mengevaluasi model kami pada set pengujian:

model.evaluate(cached_test, return_dict=True)
5/5 [==============================] - 2s 149ms/step - factorized_top_k/top_1_categorical_accuracy: 7.5000e-04 - factorized_top_k/top_5_categorical_accuracy: 0.0099 - factorized_top_k/top_10_categorical_accuracy: 0.0226 - factorized_top_k/top_50_categorical_accuracy: 0.1245 - factorized_top_k/top_100_categorical_accuracy: 0.2324 - loss: 31079.0635 - regularization_loss: 0.0000e+00 - total_loss: 31079.0635
{'factorized_top_k/top_1_categorical_accuracy': 0.000750000006519258,
 'factorized_top_k/top_5_categorical_accuracy': 0.009850000031292439,
 'factorized_top_k/top_10_categorical_accuracy': 0.02264999970793724,
 'factorized_top_k/top_50_categorical_accuracy': 0.12449999898672104,
 'factorized_top_k/top_100_categorical_accuracy': 0.23235000669956207,
 'loss': 28244.771484375,
 'regularization_loss': 0,
 'total_loss': 28244.771484375}

Kinerja set tes jauh lebih buruk daripada kinerja pelatihan. Hal ini disebabkan oleh dua faktor:

  1. Model kami cenderung berkinerja lebih baik pada data yang telah dilihatnya, hanya karena dapat mengingatnya. Fenomena overfitting ini sangat kuat ketika model memiliki banyak parameter. Ini dapat dimediasi oleh regularisasi model dan penggunaan fitur pengguna dan film yang membantu model menggeneralisasi lebih baik ke data yang tidak terlihat.
  2. Model ini merekomendasikan kembali beberapa film yang sudah ditonton pengguna. Jam tangan yang dikenal positif ini dapat mengeluarkan film uji dari rekomendasi K teratas.

Fenomena kedua dapat diatasi dengan mengecualikan film yang dilihat sebelumnya dari rekomendasi pengujian. Pendekatan ini relatif umum dalam literatur sistem pemberi rekomendasi, tetapi kami tidak mengikutinya dalam tutorial ini. Jika tidak merekomendasikan jam tangan sebelumnya adalah penting, kita harus mengharapkan model yang ditentukan dengan tepat untuk mempelajari perilaku ini secara otomatis dari riwayat pengguna sebelumnya dan informasi kontekstual. Selain itu, sering kali tepat untuk merekomendasikan item yang sama beberapa kali (misalnya, serial TV yang selalu hijau atau item yang dibeli secara teratur).

Membuat prediksi

Sekarang kami memiliki model, kami ingin dapat membuat prediksi. Kita dapat menggunakan tfrs.layers.factorized_top_k.BruteForce lapisan untuk melakukan hal ini.

# Create a model that takes in raw query features, and
index = tfrs.layers.factorized_top_k.BruteForce(model.user_model)
# recommends movies out of the entire movies dataset.
index.index_from_dataset(
  tf.data.Dataset.zip((movies.batch(100), movies.batch(100).map(model.movie_model)))
)

# Get recommendations.
_, titles = index(tf.constant(["42"]))
print(f"Recommendations for user 42: {titles[0, :3]}")
Recommendations for user 42: [b'Bridges of Madison County, The (1995)'
 b'Father of the Bride Part II (1995)' b'Rudy (1993)']

Tentu saja, BruteForce lapisan akan menjadi terlalu lambat untuk melayani model dengan banyak kandidat. Bagian berikut menunjukkan cara mempercepat ini dengan menggunakan indeks pengambilan perkiraan.

Penyajian model

Setelah model dilatih, kita membutuhkan cara untuk menyebarkannya.

Dalam model pengambilan dua menara, melayani memiliki dua komponen:

  • model kueri penyajian, mengambil fitur kueri dan mengubahnya menjadi penyematan kueri, dan
  • model kandidat yang melayani. Ini paling sering mengambil bentuk indeks perkiraan tetangga terdekat (ANN) yang memungkinkan pencarian perkiraan cepat kandidat dalam menanggapi kueri yang dihasilkan oleh model kueri.

Di TFRS, kedua komponen dapat dikemas ke dalam satu model yang dapat diekspor, memberi kami model yang mengambil id pengguna mentah dan mengembalikan judul film teratas untuk pengguna tersebut. Hal ini dilakukan melalui mengekspor model untuk sebuah SavedModel format, yang memungkinkan untuk melayani menggunakan TensorFlow Melayani .

Untuk menyebarkan model seperti ini, kita hanya mengekspor BruteForce lapisan kita buat di atas:

# Export the query model.
with tempfile.TemporaryDirectory() as tmp:
  path = os.path.join(tmp, "model")

  # Save the index.
  tf.saved_model.save(index, path)

  # Load it back; can also be done in TensorFlow Serving.
  loaded = tf.saved_model.load(path)

  # Pass a user id in, get top predicted movie titles back.
  scores, titles = loaded(["42"])

  print(f"Recommendations: {titles[0][:3]}")
2021-10-02 11:05:54.109254: 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 query_with_exclusions while saving (showing 1 of 1). These functions will not be directly callable after loading.
INFO:tensorflow:Assets written to: /tmp/tmp7otg6id7/model/assets
INFO:tensorflow:Assets written to: /tmp/tmp7otg6id7/model/assets
Recommendations: [b'Bridges of Madison County, The (1995)'
 b'Father of the Bride Part II (1995)' b'Rudy (1993)']

Kami juga dapat mengekspor indeks pengambilan perkiraan untuk mempercepat prediksi. Ini akan memungkinkan untuk secara efisien memunculkan rekomendasi dari puluhan juta kandidat.

Untuk melakukannya, kita dapat menggunakan scann paket. Ini adalah ketergantungan opsional TFRS, dan kami diinstal secara terpisah pada awal tutorial ini dengan memanggil !pip install -q scann .

Setelah terinstal kita dapat menggunakan TFRS ScaNN lapisan:

scann_index = tfrs.layers.factorized_top_k.ScaNN(model.user_model)
scann_index.index_from_dataset(
  tf.data.Dataset.zip((movies.batch(100), movies.batch(100).map(model.movie_model)))
)
<tensorflow_recommenders.layers.factorized_top_k.ScaNN at 0x7f560caffc10>

Lapisan ini akan melakukan pencarian perkiraan: merek ini retrieval sedikit kurang akurat, tetapi lipat lebih cepat pada set kandidat besar.

# Get recommendations.
_, titles = scann_index(tf.constant(["42"]))
print(f"Recommendations for user 42: {titles[0, :3]}")
Recommendations for user 42: [b'Sleepless in Seattle (1993)' b'Father of the Bride Part II (1995)'
 b'Hunchback of Notre Dame, The (1996)']

Mengekspor untuk melayani semudah mengekspor BruteForce lapisan:

# Export the query model.
with tempfile.TemporaryDirectory() as tmp:
  path = os.path.join(tmp, "model")

  # Save the index.
  tf.saved_model.save(
      index,
      path,
      options=tf.saved_model.SaveOptions(namespace_whitelist=["Scann"])
  )

  # Load it back; can also be done in TensorFlow Serving.
  loaded = tf.saved_model.load(path)

  # Pass a user id in, get top predicted movie titles back.
  scores, titles = loaded(["42"])

  print(f"Recommendations: {titles[0][:3]}")
WARNING:absl:Found untraced functions such as query_with_exclusions while saving (showing 1 of 1). These functions will not be directly callable after loading.
INFO:tensorflow:Assets written to: /tmp/tmp_rde8grm/model/assets
INFO:tensorflow:Assets written to: /tmp/tmp_rde8grm/model/assets
Recommendations: [b'Bridges of Madison County, The (1995)'
 b'Father of the Bride Part II (1995)' b'Rudy (1993)']

Untuk mempelajari lebih lanjut tentang menggunakan dan tuning model pencarian cepat perkiraan, kita lihat kami efisien porsi tutorial.

Rekomendasi item-ke-item

Dalam model ini, kami membuat model film pengguna. Namun, untuk beberapa aplikasi (misalnya, halaman detail produk) biasanya melakukan rekomendasi item-ke-item (misalnya, film-ke-film atau produk-ke-produk).

Model pelatihan seperti ini akan mengikuti pola yang sama seperti yang ditunjukkan pada tutorial ini, tetapi dengan data pelatihan yang berbeda. Di sini, kami memiliki pengguna dan menara film, dan menggunakan pasangan (pengguna, film) untuk melatih mereka. Dalam model item-ke-item, kita akan memiliki dua menara item (untuk kueri dan item kandidat), dan melatih model menggunakan pasangan (item kueri, item kandidat). Ini dapat dibangun dari klik pada halaman detail produk.

Langkah selanjutnya

Ini menyimpulkan tutorial pengambilan.

Untuk memperluas apa yang disajikan di sini, lihat:

  1. Mempelajari model multi-tugas: bersama-sama mengoptimalkan peringkat dan klik.
  2. Menggunakan metadata film: membangun model film yang lebih kompleks untuk mengurangi cold-start.