TensorFlowでのレコメンダー【tensorflow-recommenders (TFRS)】


2020年9月23日GoogleはTensorFlow Recommenders (TFRS)のレコメンデーション システムのパッケージを発表しました。この記事は、TensorFlowレコメンダーのパッケージを紹介したいと思います。

目次

1. TensorFlowのレコメンダーとは
2. tensorflow-recommendersの特徴
3. 実験
_3.1 データロード
_3.2 レコメンデーションモデルの定義
_3.3 モデル評価の関数
_3.4 モデル学習
_3.5 モデル評価

1. TensorFlowのレコメンダーとは

TensorFlow Recommendationsは、TensorFlowを使用してレコメンダーシステムモデルを構築するためのオープンソースライブラリです。

これは、レコメンダーシステムを構築するための完全なワークフロー(データの準備、モデルの定式化、トレーニング、評価、および展開)に役立ちます。

Kerasに基づいて構築されており、複雑なモデルを構築する柔軟性を提供しながら、穏やかな学習曲線を持つことを目的としています。

2. tensorflow-recommendersの特徴

・柔軟な候補者指名モデルを構築して評価します。
・アイテム、ユーザー、およびコンテキスト情報を推奨モデルに自由に組み込みます。
・複数の推奨目標を共同で最適化するマルチタスクモデルをトレーニングします。
・TensorFlow Servingを使用する事が出来ます。

3. 実験

環境:Google Colab
データセット:MovieLens 100Kデータセット

TFRSをインポート

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

3.1 データロード

# Ratings data.
ratings = tfds.load("movie_lens/100k-ratings", split="train")

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

80%学習データセットと20%テストデータセットを分けます。

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)

特徴値を連続した範囲の整数にマップします

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

3.2 レコメンデーションのTFRSモデルを定義します。

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.experimental.preprocessing.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.experimental.preprocessing.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, user_id, movie_title):
    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))

3.3 モデル評価の関数

Loss and metrics
MeanSquaredError評価を予測するためのKeras損失を利用します。

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 compute_loss(self, features: Dict[Text, tf.Tensor], training=False) -> tf.Tensor:
   rating_predictions = self.ranking_model(
   features["user_id"], features["movie_title"])

   # The task computes the loss and the metrics.
   return self.task(labels=features["user_rating"], predictions=rating_predictions)

3.4 モデル学習

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

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

model.fit(cached_train, epochs=3)

Epoch 1/3
10/10 [==============================] – 0s 25ms/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 9ms/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

3.5 モデル評価

model.evaluate(cached_test, return_dict=True)

5/5 [==============================] – 0s 8ms/step – root_mean_squared_error: 1.1108 – loss: 1.2287 – regularization_loss: 0.0000e+00 – total_loss: 1.2287

{‘root_mean_squared_error’: 1.1108063459396362,
‘loss’: 1.2062581777572632,
‘regularization_loss’: 0,
‘total_loss’: 1.2062581777572632}

担当者:HM
香川県高松市出身 データ分析にて、博士(理学)を取得後、自動車メーカー会社にてデータ分析に関わる。その後コンサルティングファームでデータ分析プロジェクトを歴任後独立 気が付けばデータ分析プロジェクトだけで50以上担当
理化学研究所にて研究員を拝命中 応用数理学会所属