Đề xuất phim: truy xuất

Xem trên TensorFlow.org Xem nguồn trên GitHub Tải xuống sổ ghi chép

Hệ thống tư vấn trong thế giới thực thường bao gồm hai giai đoạn:

  1. Giai đoạn truy xuất có trách nhiệm chọn một tập hợp ban đầu gồm hàng trăm ứng viên từ tất cả các ứng viên có thể. Mục tiêu chính của mô hình này là loại bỏ hiệu quả tất cả các ứng viên mà người dùng không quan tâm. Bởi vì mô hình truy xuất có thể xử lý hàng triệu ứng viên, nên nó phải hiệu quả về mặt tính toán.
  2. Giai đoạn xếp hạng lấy kết quả đầu ra của mô hình truy xuất và tinh chỉnh chúng để chọn ra một số đề xuất tốt nhất có thể. Nhiệm vụ của nó là thu hẹp tập hợp các mục mà người dùng có thể quan tâm đến một danh sách rút gọn các ứng cử viên có khả năng.

Trong hướng dẫn này, chúng ta sẽ tập trung vào giai đoạn đầu tiên, truy xuất. Nếu bạn đang quan tâm trong giai đoạn thứ hạng, có một cái nhìn tại của chúng tôi xếp hạng hướng dẫn.

Các mô hình truy xuất thường bao gồm hai mô hình con:

  1. Mô hình truy vấn tính toán biểu diễn truy vấn (thường là vectơ nhúng chiều cố định) bằng cách sử dụng các tính năng truy vấn.
  2. Mô hình ứng cử viên tính toán đại diện ứng viên (một vectơ có kích thước bằng nhau) bằng cách sử dụng các tính năng ứng viên

Sau đó, kết quả đầu ra của hai mô hình sẽ được nhân với nhau để đưa ra điểm số mối quan hệ giữa ứng viên và truy vấn, với điểm số cao hơn thể hiện sự phù hợp tốt hơn giữa ứng viên và truy vấn.

Trong hướng dẫn này, chúng tôi sẽ xây dựng và đào tạo mô hình hai tháp như vậy bằng cách sử dụng tập dữ liệu Movielens.

Sắp tới:

  1. Nhận dữ liệu của chúng tôi và chia nó thành một tập hợp đào tạo và kiểm tra.
  2. Thực hiện một mô hình truy xuất.
  3. Phù hợp và đánh giá nó.
  4. Xuất nó để phục vụ hiệu quả bằng cách xây dựng chỉ số hàng xóm gần nhất (ANN).

Bộ dữ liệu

Các MovieLens tập dữ liệu là một tập dữ liệu cổ điển từ GroupLens nghiên cứu nhóm tại Đại học Minnesota. Nó chứa một tập hợp các xếp hạng do một nhóm người dùng đưa ra cho các bộ phim và là một tập hợp các nghiên cứu hệ thống giới thiệu.

Dữ liệu có thể được xử lý theo hai cách:

  1. Nó có thể được hiểu là thể hiện những bộ phim mà người dùng đã xem (và xếp hạng) và những bộ phim nào họ đã không xem. Đây là một dạng phản hồi ngầm, nơi đồng hồ của người dùng cho chúng tôi biết những thứ họ thích xem và những thứ họ không muốn xem.
  2. Nó cũng có thể được xem là thể hiện mức độ thích những bộ phim họ đã xem của người dùng. Đây là một dạng phản hồi rõ ràng: cho rằng một người dùng đã xem một bộ phim, chúng tôi có thể biết được họ thích bao nhiêu phần bằng cách xem xếp hạng mà họ đưa ra.

Trong hướng dẫn này, chúng tôi đang tập trung vào hệ thống truy xuất: một mô hình dự đoán một bộ phim từ danh mục mà người dùng có khả năng sẽ xem. Thông thường, dữ liệu ngầm sẽ hữu ích hơn ở đây và vì vậy chúng tôi sẽ coi Movielens như một hệ thống ngầm. Điều này có nghĩa là mọi bộ phim mà người dùng đã xem là một ví dụ tích cực và mọi bộ phim họ chưa xem đều là một ví dụ tiêu cực ngầm.

Nhập khẩu

Đầu tiên chúng ta hãy lấy hàng nhập khẩu của chúng ta ra khỏi con đường.

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

Chuẩn bị tập dữ liệu

Đầu tiên chúng ta hãy xem dữ liệu.

Chúng tôi sử dụng dữ liệu MovieLens từ Tensorflow Datasets . Đang tải movielens/100k_ratings mang lại một tf.data.Dataset đối tượng chứa dữ liệu xếp hạng và tải movielens/100k_movies sản lượng một tf.data.Dataset đối tượng chỉ chứa các dữ liệu phim.

Lưu ý rằng kể từ khi MovieLens bộ dữ liệu không được xác định trước đã chia rẽ, tất cả dữ liệu đang được train chia rẽ.

# 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-08-24 11:23:07.684827: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected
2021-08-24 11:23:07.684881: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (kokoro-gcp-ubuntu-prod-1865084408): /proc/driver/nvidia/version does not exist
2021-08-24 11:23:07.686220: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 AVX512F FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.

Tập dữ liệu xếp hạng trả về một từ điển gồm id phim, id người dùng, xếp hạng được chỉ định, dấu thời gian, thông tin phim và thông tin người dùng:

for x in ratings.take(1).as_numpy_iterator():
  pprint.pprint(x)
2021-08-24 11:23:08.510902: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:185] None of the MLIR Optimization Passes are enabled (registered 2)
{'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-08-24 11:23:08.793892: 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.

Tập dữ liệu phim chứa id phim, tiêu đề phim và dữ liệu về thể loại phim đó thuộc về. Lưu ý rằng các thể loại được mã hóa bằng nhãn số nguyên.

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-08-24 11:23:09.008985: 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.

Trong ví dụ này, chúng tôi sẽ tập trung vào dữ liệu xếp hạng. Các hướng dẫn khác khám phá cách sử dụng dữ liệu thông tin phim cũng như để cải thiện chất lượng mô hình.

Chúng tôi tiếp tục chỉ user_id , và movie_title trường trong tập dữ liệu.

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

Để phù hợp và đánh giá mô hình, chúng ta cần chia nó thành một tập hợp đào tạo và đánh giá. Trong hệ thống khuyến nghị công nghiệp, điều này rất có thể sẽ được thực hiện theo thời gian: dữ liệu cho đến thời điểm $ T $ sẽ được sử dụng để dự đoán các tương tác sau $ T $.

Tuy nhiên, trong ví dụ đơn giản này, chúng ta hãy sử dụng phân tách ngẫu nhiên, đặt 80% xếp hạng vào nhóm tàu ​​và 20% trong nhóm thử nghiệm.

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)

Hãy cũng tìm ra id người dùng và tiêu đề phim duy nhất có trong dữ liệu.

Điều này rất quan trọng vì chúng ta cần có khả năng ánh xạ các giá trị thô của các đối tượng địa lý phân loại để nhúng vectơ vào các mô hình của chúng ta. Để làm được điều đó, chúng ta cần một từ vựng ánh xạ giá trị đối tượng địa lý thô thành một số nguyên trong một phạm vi liền kề: điều này cho phép chúng ta tra cứu các nhúng tương ứng trong bảng nhúng của chúng ta.

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)

Thực hiện một mô hình

Chọn kiến ​​trúc của mô hình của chúng tôi là một phần quan trọng của mô hình.

Bởi vì chúng tôi đang xây dựng mô hình truy xuất hai tháp, chúng tôi có thể xây dựng từng tháp riêng biệt và sau đó kết hợp chúng trong mô hình cuối cùng.

Tháp truy vấn

Hãy bắt đầu với tháp truy vấn.

Bước đầu tiên là quyết định về kích thước của truy vấn và các biểu diễn ứng viên:

embedding_dimension = 32

Giá trị cao hơn sẽ tương ứng với các mô hình có thể chính xác hơn, nhưng cũng sẽ chậm hơn để vừa vặn và dễ bị trang bị quá mức.

Thứ hai là xác định chính mô hình. Ở đây, chúng ta sẽ sử dụng Keras lớp tiền xử lý để id người dùng chuyển đổi đầu tiên để số nguyên, và sau đó chuyển đổi những để embeddings người dùng thông qua một Embedding lớp. Lưu ý rằng chúng tôi sử dụng danh sách id người dùng duy nhất mà chúng tôi đã tính toán trước đó làm từ vựng:

user_model = tf.keras.Sequential([
  tf.keras.layers.experimental.preprocessing.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)
])

Một mô hình đơn giản như thế này tương ứng chính xác với một cổ điển thừa số ma trận phương pháp. Trong khi định nghĩa một lớp con của tf.keras.Model cho mô hình đơn giản này có thể là quá mức cần thiết, chúng ta có thể dễ dàng mở rộng nó đến một mô hình tùy tiện phức tạp sử dụng các thành phần Keras tiêu chuẩn, miễn là chúng ta trả lại một embedding_dimension đầu ra -wide ở cuối.

Tháp ứng cử viên

Chúng ta có thể làm điều tương tự với tháp ứng cử viên.

movie_model = tf.keras.Sequential([
  tf.keras.layers.experimental.preprocessing.StringLookup(
      vocabulary=unique_movie_titles, mask_token=None),
  tf.keras.layers.Embedding(len(unique_movie_titles) + 1, embedding_dimension)
])

Số liệu

Trong dữ liệu đào tạo của chúng tôi, chúng tôi có các cặp (người dùng, phim) tích cực. Để tìm ra mô hình của chúng ta tốt đến mức nào, chúng ta cần so sánh điểm quan hệ mà mô hình tính toán cho cặp này với điểm của tất cả các ứng viên có thể có khác: nếu điểm cho cặp tích cực cao hơn so với tất cả các ứng viên khác, mô hình của chúng tôi có độ chính xác cao.

Để làm điều này, chúng ta có thể sử dụng tfrs.metrics.FactorizedTopK mét. Chỉ số có một đối số bắt buộc: tập dữ liệu về các ứng cử viên được sử dụng làm phủ định ngầm để đánh giá.

Trong trường hợp của chúng tôi, đó là movies bộ dữ liệu, chuyển đổi thành embeddings qua mô hình bộ phim của chúng tôi:

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

Thua

Thành phần tiếp theo là tổn thất được sử dụng để đào tạo mô hình của chúng ta. TFRS có một số lớp tổn thất và các nhiệm vụ để thực hiện điều này dễ dàng.

Trong trường hợp này, chúng tôi sẽ tận dụng các Retrieval đối tượng nhiệm vụ: là một tiện nghi wrapper mà bó cùng hàm tổn thất và tính toán số liệu:

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

Bản thân tác vụ là một lớp Keras lấy truy vấn và nhúng ứng viên làm đối số và trả về tổn thất được tính toán: chúng tôi sẽ sử dụng điều đó để triển khai vòng lặp đào tạo của mô hình.

Mô hình đầy đủ

Bây giờ chúng ta có thể tập hợp tất cả lại thành một mô hình. TFR cho thấy một lớp mô hình cơ sở ( tfrs.models.Model ) mà sắp xếp hợp lý việc xây dựng mô hình: tất cả chúng ta cần làm là thiết lập các thành phần trong __init__ phương pháp, và thực hiện các compute_loss phương pháp, dùng trong các tính năng thô và trả về một giá trị thiệt hại .

Sau đó, mô hình cơ sở sẽ đảm nhận việc tạo ra vòng lặp đào tạo thích hợp để phù hợp với mô hình của chúng tôi.

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)

Các tfrs.Model lớp cơ sở là một lớp đơn giản tiện theo dõi: nó cho phép chúng ta tính cả đào tạo và kiểm tra thiệt hại bằng cách sử dụng phương pháp tương tự.

Dưới mui xe, nó vẫn là một mô hình Keras đơn giản. Bạn có thể đạt được các chức năng tương tự bằng cách kế thừa từ tf.keras.Model và trọng train_steptest_step chức năng (xem hướng dẫn để biết chi tiết):

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

Trong những hướng dẫn, tuy nhiên, chúng tôi dính vào sử dụng tfrs.Model lớp cơ sở để giữ tập trung của chúng tôi về mô hình hóa và trừu tượng đi một số bản mẫu.

Phù hợp và đánh giá

Sau khi xác định mô hình, chúng ta có thể sử dụng các quy trình đánh giá và lắp đặt tiêu chuẩn của Keras để điều chỉnh và đánh giá mô hình.

Đầu tiên hãy tạo mô hình.

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

Sau đó trộn, trộn và lưu vào bộ đệm dữ liệu đào tạo và đánh giá.

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

Sau đó đào tạo mô hình:

model.fit(cached_train, epochs=3)
Epoch 1/3
10/10 [==============================] - 6s 308ms/step - factorized_top_k/top_1_categorical_accuracy: 7.6250e-04 - factorized_top_k/top_5_categorical_accuracy: 0.0072 - factorized_top_k/top_10_categorical_accuracy: 0.0167 - factorized_top_k/top_50_categorical_accuracy: 0.0915 - factorized_top_k/top_100_categorical_accuracy: 0.1698 - loss: 69885.1129 - regularization_loss: 0.0000e+00 - total_loss: 69885.1129
Epoch 2/3
10/10 [==============================] - 3s 287ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0028 - factorized_top_k/top_5_categorical_accuracy: 0.0184 - factorized_top_k/top_10_categorical_accuracy: 0.0375 - factorized_top_k/top_50_categorical_accuracy: 0.1682 - factorized_top_k/top_100_categorical_accuracy: 0.2917 - loss: 67523.3707 - regularization_loss: 0.0000e+00 - total_loss: 67523.3707
Epoch 3/3
10/10 [==============================] - 3s 280ms/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 0x7f95f02a2390>

Khi mô hình đào tạo, khoản lỗ sẽ giảm xuống và một tập hợp các chỉ số truy xuất hàng đầu được cập nhật. Những điều này cho chúng ta biết liệu giá trị dương thực sự có nằm trong k mục được truy xuất hàng đầu từ toàn bộ tập hợp ứng viên hay không. Ví dụ: số liệu về độ chính xác phân loại của 5 mục hàng đầu là 0,2 sẽ cho chúng ta biết rằng, trung bình, giá trị dương thực sự nằm trong 5 mục hàng đầu được truy xuất 20% thời gian.

Lưu ý rằng, trong ví dụ này, chúng tôi đánh giá các chỉ số trong quá trình đào tạo cũng như đánh giá. Bởi vì điều này có thể khá chậm với các tập hợp ứng viên lớn, có thể cần thận trọng khi tắt tính toán số liệu trong đào tạo và chỉ chạy nó khi đánh giá.

Cuối cùng, chúng ta có thể đánh giá mô hình của mình trên bộ thử nghiệm:

model.evaluate(cached_test, return_dict=True)
5/5 [==============================] - 2s 155ms/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}

Hiệu suất bộ kiểm tra kém hơn nhiều so với hiệu suất đào tạo. Điều này là do hai yếu tố:

  1. Mô hình của chúng tôi có khả năng hoạt động tốt hơn trên dữ liệu mà nó đã thấy, đơn giản vì nó có thể ghi nhớ nó. Hiện tượng overfitting này đặc biệt mạnh khi các mô hình có nhiều thông số. Nó có thể được dàn xếp bằng cách điều chỉnh mô hình và sử dụng các tính năng của người dùng và phim để giúp mô hình tổng quát hóa tốt hơn đối với dữ liệu không nhìn thấy.
  2. Mô hình đang giới thiệu lại một số bộ phim đã xem của người dùng. Những chiếc đồng hồ tích cực được biết đến này có thể loại bỏ các phim thử nghiệm ngoài các đề xuất K hàng đầu.

Hiện tượng thứ hai có thể được giải quyết bằng cách loại trừ các phim đã xem trước đó khỏi các đề xuất thử nghiệm. Cách tiếp cận này tương đối phổ biến trong tài liệu về hệ thống khuyến nghị, nhưng chúng tôi không làm theo cách này trong các hướng dẫn này. Nếu việc đề xuất đồng hồ trong quá khứ không quan trọng, chúng ta nên mong đợi các mô hình được chỉ định phù hợp sẽ tự động tìm hiểu hành vi này từ lịch sử người dùng trong quá khứ và thông tin ngữ cảnh. Ngoài ra, việc giới thiệu cùng một mặt hàng nhiều lần là điều thích hợp (giả sử như một bộ phim truyền hình mới hay một mặt hàng được mua thường xuyên).

Đưa ra dự đoán

Bây giờ chúng tôi có một mô hình, chúng tôi muốn có thể đưa ra dự đoán. Chúng tôi có thể sử dụng tfrs.layers.factorized_top_k.BruteForce lớp để làm điều này.

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

Tất nhiên, BruteForce lớp sẽ là quá chậm để phục vụ cho một mô hình với nhiều ứng cử viên có thể. Các phần sau đây cho biết cách tăng tốc độ này bằng cách sử dụng chỉ số truy xuất gần đúng.

Mô hình phục vụ

Sau khi mô hình được đào tạo, chúng tôi cần một cách để triển khai nó.

Trong mô hình truy xuất hai tháp, việc phân phát có hai thành phần:

  • một mô hình truy vấn phục vụ, sử dụng các tính năng của truy vấn và chuyển đổi chúng thành một nhúng truy vấn, và
  • một mô hình ứng viên đang phục vụ. Điều này thường có dạng một chỉ mục gần đúng gần nhất (ANN) cho phép tra cứu gần đúng nhanh chóng các ứng cử viên để phản hồi một truy vấn do mô hình truy vấn tạo ra.

Trong TFRS, cả hai thành phần có thể được đóng gói thành một mô hình có thể xuất duy nhất, cung cấp cho chúng tôi một mô hình lấy id người dùng thô và trả về tiêu đề của các bộ phim hàng đầu cho người dùng đó. Này được thực hiện thông qua xuất khẩu mô hình để một SavedModel định dạng, mà làm cho nó có thể để phục vụ sử dụng TensorFlow Phục vụ .

Để triển khai một mô hình như thế này, chúng tôi chỉ đơn giản là xuất BruteForce lớp chúng ta đã tạo ở trên:

# 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-08-24 11:23:28.077112: 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/tmprdeui3rt/model/assets
INFO:tensorflow:Assets written to: /tmp/tmprdeui3rt/model/assets
Recommendations: [b'Bridges of Madison County, The (1995)'
 b'Father of the Bride Part II (1995)' b'Rudy (1993)']

Chúng tôi cũng có thể xuất chỉ số truy xuất gần đúng để tăng tốc độ dự đoán. Điều này sẽ giúp bạn có thể hiển thị hiệu quả các đề xuất từ ​​hàng chục triệu ứng viên.

Để làm như vậy, chúng ta có thể sử dụng scann gói. Đây là một sự phụ thuộc tùy chọn của TFR, và chúng tôi cài đặt nó riêng biệt ở phần đầu của hướng dẫn này bằng cách gọi !pip install -q scann .

Sau khi cài đặt, chúng tôi có thể sử dụng TFR ScaNN lớp:

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)))
)
2021-08-24 11:23:28.652143: I scann/partitioning/partitioner_factory_base.cc:71] Size of sampled dataset for training partition: 1682
2021-08-24 11:23:28.661092: I ./scann/partitioning/kmeans_tree_partitioner_utils.h:102] PartitionerFactory ran in 8.895297ms.
<tensorflow_recommenders.layers.factorized_top_k.ScaNN at 0x7f95375bfe10>

Lớp này sẽ thực hiện tra cứu gần đúng: làm cho này hồi hơi kém chính xác, nhưng thứ tự độ lớn nhanh hơn trên bộ ứng cử viên lớn.

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

Xuất khẩu nó phục vụ dễ dàng như xuất khẩu BruteForce lớp:

# 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/tmpxlk0mik6/model/assets
INFO:tensorflow:Assets written to: /tmp/tmpxlk0mik6/model/assets
Recommendations: [b'Bridges of Madison County, The (1995)'
 b'Father of the Bride Part II (1995)' b'Rudy (1993)']

Để tìm hiểu thêm về việc sử dụng và điều chỉnh mô hình hồi nhanh xấp xỉ, có một cái nhìn tại của chúng tôi phục vụ hiệu quả hướng dẫn.

Bước tiếp theo

Điều này kết thúc hướng dẫn truy xuất.

Để mở rộng những gì được trình bày ở đây, hãy xem:

  1. Học các mô hình đa tác vụ: cùng tối ưu hóa cho xếp hạng và nhấp chuột.
  2. Sử dụng siêu dữ liệu phim: xây dựng một mô hình phim phức tạp hơn để giảm bớt tình trạng bắt đầu nguội.