个性化推荐系统——3. 模型搭建与训练

模型搭建

import pickle
import pandas as  pd
import numpy as np
from sklearn.model_selection import train_test_split

读取数据

title_count, title_set, genres2int, features, targets_values, ratings, users, movies, data, movies_orig, users_orig = pickle.load(open('preprocess.p', mode='rb'))

模型设计

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VOYn4LJz-1580741339497)(attachment:image.png)]

类别数据(UserID,MovieID,Geners,Age,Sex)的处理一般有两种方式:

  • onehot encode
  • label encode

在类别数据的种类过多时,onehot会使数据过于稀疏,因此只好使用label encode(虽然label encode处理后会出现大小的差异,这样也是不完美的)

所以在预处理数据时将这些字段转成了数字,我们用这个数字当做嵌入矩阵的索引,在网络的第一层使用了嵌入层,维度是(N,32)和(N,16)。
电影类型的处理要多一步,有时一个电影有多个电影类型,这样从嵌入矩阵索引出来是一个(n,32)的矩阵,因为有多个类型嘛,我们要将这个矩阵求和,变成(1,32)的向量。

电影名的处理比较特殊,没有使用循环神经网络,而是用了文本卷积网络,下文会进行说明。

从嵌入层索引出特征以后,将各特征传入全连接层,将输出再次传入全连接层,最终分别得到(1,200)的用户特征和电影特征两个特征向量。

我们的目的就是要训练出用户特征和电影特征,在实现推荐功能时使用。得到这两个特征以后,就可以选择任意的方式来拟合评分了。我使用了两种方式,一个是上图中画出的将两个特征做向量乘法,将结果与真实评分做回归,采用MSE优化损失。因为本质上这是一个回归问题,另一种方式是,将两个特征作为输入,再次传入全连接层,输出一个值,将输出值回归到真实评分,采用MSE优化损失。

实际上第二个方式的MSE loss在0.8附近,第一个方式在1附近,5次迭代的结果

文本卷积网络

CNN的卷积和池化过程就是一个抽取特征的过程,当我们可以准确抽取关键词的特征时,就能准确的提炼出文档或句子的中心思想。

卷积神经网络首次应用于文本分类可以说是在2004年Yoon Kim 在 “Convolutional Neural Networks for Sentence Classification” 一文中提出(虽然第一个用的并不是他,但是在这篇文章中提出了4种Model Variations,并有详细的调参),本文也是基于对这篇文章的理解。接下来将介绍text-CNN模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BDJBXWRP-1580741339498)(attachment:image.png)]
论文使用的模型主要包括五层,第一层是embedding layer,第二层是convolutional layer,第三层是max-pooling layer,第四层是fully connected layer,最后一层是softmax layer.

下图描述了更具体的步骤
在这里插入图片描述

输入层

首先输入一个一维的由7个单词构成的句子,为了使其可以进行卷积,首先需要将其转化为二维矩阵表示,通常使用word2vec、glove等word embedding实现。d=5表示每个词转化为5维的向量,矩阵的形状是[sentence_matrix × 5],即[7 × 5]。

卷积层

在处理图像数据时,CNN使用的卷积核的宽度和高度的一样的,但是在text-CNN中,卷积核的宽度是与词向量的维度一致。这是因为我们输入的每一行向量代表一个词,在抽取特征的过程中,词做为文本的最小粒度,如果我们使用卷积核的宽度小于词向量的维度就已经不是以词作为最小粒度了。而高度和CNN一样,可以自行设置(通常取值2,3,4,5)。由于我们的输入是一个句子,句子中相邻的词之间关联性很高,因此,当我们用卷积核进行卷积时,不仅考虑了词义而且考虑了词序及其上下文。(类似于skip-gram和CBOW模型的思想)。

本推荐系统模型所使用的网络

网络的第一层是词嵌入层,由每一个单词的嵌入向量组成的嵌入矩阵。下一层使用多个不同尺寸(窗口大小)的卷积核在嵌入矩阵上做卷积,窗口大小指的是每次卷积覆盖几个单词。这里跟对图像做卷积不太一样,图像的卷积通常用2x2、3x3、5x5之类的尺寸,而文本卷积要覆盖整个单词的嵌入向量,所以尺寸是(单词数,向量维度),比如每次滑动3个,4个或者5个单词。第三层网络是max pooling得到一个长向量,最后使用dropout做正则化,最终得到了电影Title的特征。

辅助函数

import tensorflow as tf
import os
import pickle
def save_params(params):
    pickle.dump(params,open('params.p','wb'))
def load_params():
    return pickle.load(open('params.p','rb'))

编码实现

#嵌入矩阵的维度
embed_dim = 32
#用户ID个数
uid_max = max(features.take(0,1)) + 1 # 6040
#性别个数
gender_max = max(features.take(2,1)) + 1 # 1 + 1 = 2
#年龄类别个数
age_max = max(features.take(3,1)) + 1 # 6 + 1 = 7
#职业个数
job_max = max(features.take(4,1)) + 1# 20 + 1 = 21

#电影ID个数
movie_id_max = max(features.take(1,1)) + 1 # 3952
#电影类型个数
movie_categories_max = max(genres2int.values()) + 1 # 18 + 1 = 19
#电影名单词个数
movie_title_max = len(title_set) # 5216

#对电影类型嵌入向量做加和操作的标志,考虑过使用mean做平均,但是没实现mean
combiner = "sum"

#电影名长度
sentences_size = title_count # = 15
#文本卷积滑动窗口,分别滑动2, 3, 4, 5个单词
window_sizes = {2, 3, 4, 5}
#文本卷积核数量
filter_num = 8

#电影ID转下标的字典,数据集中电影ID跟下标不一致,比如第5行的数据电影ID不一定是5
movieid2idx = {val[0]:i for i, val in enumerate(movies.values)}

超参

# Number of Epochs
num_epochs = 5
# Batch Size
batch_size = 256

dropout_keep = 0.5
# Learning Rate
learning_rate = 0.0001
# Show stats for every n number of batches
show_every_n_batches = 20

save_dir = './save'

输入

定义输入数据的占位符

def get_inputs():
    uid = tf.keras.layers.Input(shape=(1,), dtype='int32', name='uid')  
    user_gender = tf.keras.layers.Input(shape=(1,), dtype='int32', name='user_gender')  
    user_age = tf.keras.layers.Input(shape=(1,), dtype='int32', name='user_age') 
    user_job = tf.keras.layers.Input(shape=(1,), dtype='int32', name='user_job')

    movie_id = tf.keras.layers.Input(shape=(1,), dtype='int32', name='movie_id') 
    movie_categories = tf.keras.layers.Input(shape=(18,), dtype='int32', name='movie_categories') 
    movie_titles = tf.keras.layers.Input(shape=(15,), dtype='int32', name='movie_titles') 
    return uid, user_gender, user_age, user_job, movie_id, movie_categories, movie_titles

构建神经网络

定义User的嵌入矩阵

def get_user_embedding(uid, user_gender, user_age, user_job):
    uid_embed_layer = tf.keras.layers.Embedding(uid_max, embed_dim, input_length=1, name='uid_embed_layer')(uid)
    gender_embed_layer = tf.keras.layers.Embedding(gender_max, embed_dim // 2, input_length=1, name='gender_embed_layer')(user_gender)
    age_embed_layer = tf.keras.layers.Embedding(age_max, embed_dim // 2, input_length=1, name='age_embed_layer')(user_age)
    job_embed_layer = tf.keras.layers.Embedding(job_max, embed_dim // 2, input_length=1, name='job_embed_layer')(user_job)
    return uid_embed_layer, gender_embed_layer, age_embed_layer, job_embed_layer

将User的嵌入矩阵一起全连接生成User的特征

def get_user_feature_layer(uid_embed_layer, gender_embed_layer, age_embed_layer, job_embed_layer):
    #第一层全连接
    uid_fc_layer = tf.keras.layers.Dense(embed_dim, name="uid_fc_layer", activation='relu')(uid_embed_layer)
    gender_fc_layer = tf.keras.layers.Dense(embed_dim, name="gender_fc_layer", activation='relu')(gender_embed_layer)
    age_fc_layer = tf.keras.layers.Dense(embed_dim, name="age_fc_layer", activation='relu')(age_embed_layer)
    job_fc_layer = tf.keras.layers.Dense(embed_dim, name="job_fc_layer", activation='relu')(job_embed_layer)

    #第二层全连接
    user_combine_layer = tf.keras.layers.concatenate([uid_fc_layer, gender_fc_layer, age_fc_layer, job_fc_layer], 2)  #(?, 1, 128)
    user_combine_layer = tf.keras.layers.Dense(200, activation='tanh')(user_combine_layer)  #(?, 1, 200)

    user_combine_layer_flat = tf.keras.layers.Reshape([200], name="user_combine_layer_flat")(user_combine_layer)
    return user_combine_layer, user_combine_layer_flat

定义Movie ID的嵌入矩阵

def get_movie_id_embed_layer(movie_id):
    movie_id_embed_layer = tf.keras.layers.Embedding(movie_id_max, embed_dim, input_length=1, name='movie_id_embed_layer')(movie_id)
    return movie_id_embed_layer

合并电影类型的多个嵌入向量

def get_movie_categories_layers(movie_categories):
    movie_categories_embed_layer = tf.keras.layers.Embedding(movie_categories_max, embed_dim, input_length=18, name='movie_categories_embed_layer')(movie_categories)
    movie_categories_embed_layer = tf.keras.layers.Lambda(lambda layer: tf.reduce_sum(layer, axis=1, keepdims=True))(movie_categories_embed_layer)
#     movie_categories_embed_layer = tf.keras.layers.Reshape([1, 18 * embed_dim])(movie_categories_embed_layer)

    return movie_categories_embed_layer

Movie Title的文本卷积网络实现

def get_movie_cnn_layer(movie_titles):
    #从嵌入矩阵中得到电影名对应的各个单词的嵌入向量
    movie_title_embed_layer = tf.keras.layers.Embedding(movie_title_max, embed_dim, input_length=15, name='movie_title_embed_layer')(movie_titles)
    sp=movie_title_embed_layer.shape
    movie_title_embed_layer_expand = tf.keras.layers.Reshape([sp[1], sp[2], 1])(movie_title_embed_layer)
    #对文本嵌入层使用不同尺寸的卷积核做卷积和最大池化
    pool_layer_lst = []
    for window_size in window_sizes:
        conv_layer = tf.keras.layers.Conv2D(filter_num, (window_size, embed_dim), 1, activation='relu')(movie_title_embed_layer_expand)
        maxpool_layer = tf.keras.layers.MaxPooling2D(pool_size=(sentences_size - window_size + 1 ,1), strides=1)(conv_layer)
        pool_layer_lst.append(maxpool_layer)
    #Dropout层
    pool_layer = tf.keras.layers.concatenate(pool_layer_lst, 3, name ="pool_layer")  
    max_num = len(window_sizes) * filter_num
    pool_layer_flat = tf.keras.layers.Reshape([1, max_num], name = "pool_layer_flat")(pool_layer)

    dropout_layer = tf.keras.layers.Dropout(dropout_keep, name = "dropout_layer")(pool_layer_flat)
    return pool_layer_flat, dropout_layer

将Movie的各个层一起做全连接

def get_movie_feature_layer(movie_id_embed_layer, movie_categories_embed_layer, dropout_layer):
    #第一层全连接
    movie_id_fc_layer = tf.keras.layers.Dense(embed_dim, name="movie_id_fc_layer", activation='relu')(movie_id_embed_layer)
    movie_categories_fc_layer = tf.keras.layers.Dense(embed_dim, name="movie_categories_fc_layer", activation='relu')(movie_categories_embed_layer)

    #第二层全连接
    movie_combine_layer = tf.keras.layers.concatenate([movie_id_fc_layer, movie_categories_fc_layer, dropout_layer], 2)  
    movie_combine_layer = tf.keras.layers.Dense(200, activation='tanh')(movie_combine_layer)

    movie_combine_layer_flat = tf.keras.layers.Reshape([200], name="movie_combine_layer_flat")(movie_combine_layer)
    return movie_combine_layer, movie_combine_layer_flat

构建计算图

import tensorflow as tf
import datetime
from tensorflow import keras
from tensorflow.python.ops import summary_ops_v2
import time

MODEL_DIR = "./models"


class mv_network(object):
    def __init__(self, batch_size=256):
        self.batch_size = batch_size
        self.best_loss = 9999
        self.losses = {'train': [], 'test': []}

        # 获取输入占位符
        uid, user_gender, user_age, user_job, movie_id, movie_categories, movie_titles = get_inputs()
        # 获取User的4个嵌入向量
        uid_embed_layer, gender_embed_layer, age_embed_layer, job_embed_layer = get_user_embedding(uid, user_gender,
                                                                                                   user_age, user_job)
        # 得到用户特征
        user_combine_layer, user_combine_layer_flat = get_user_feature_layer(uid_embed_layer, gender_embed_layer,
                                                                             age_embed_layer, job_embed_layer)
        # 获取电影ID的嵌入向量
        movie_id_embed_layer = get_movie_id_embed_layer(movie_id)
        # 获取电影类型的嵌入向量
        movie_categories_embed_layer = get_movie_categories_layers(movie_categories)
        # 获取电影名的特征向量
        pool_layer_flat, dropout_layer = get_movie_cnn_layer(movie_titles)
        # 得到电影特征
        movie_combine_layer, movie_combine_layer_flat = get_movie_feature_layer(movie_id_embed_layer,
                                                                                movie_categories_embed_layer,
                                                                                dropout_layer)
        # 计算出评分
        # 将用户特征和电影特征做矩阵乘法得到一个预测评分的方案
        inference = tf.keras.layers.Lambda(lambda layer: 
            tf.reduce_sum(layer[0] * layer[1], axis=1), name="inference")((user_combine_layer_flat, movie_combine_layer_flat))
        inference = tf.keras.layers.Lambda(lambda layer: tf.expand_dims(layer, axis=1))(inference)
        
        # 将用户特征和电影特征作为输入,经过全连接,输出一个值的方案
#         inference_layer = tf.keras.layers.concatenate([user_combine_layer_flat, movie_combine_layer_flat],
#                                                       1)  # (?, 400)
        # 你可以使用下面这个全连接层,试试效果
        #inference_dense = tf.keras.layers.Dense(64, kernel_regularizer=tf.nn.l2_loss, activation='relu')(
        #    inference_layer)
#         inference = tf.keras.layers.Dense(1, name="inference")(inference_layer)  # inference_dense

        self.model = tf.keras.Model(
            inputs=[uid, user_gender, user_age, user_job, movie_id, movie_categories, movie_titles],
            outputs=[inference])

        self.model.summary()

        self.optimizer = tf.keras.optimizers.Adam(learning_rate)
        # MSE损失,将计算值回归到评分
        self.ComputeLoss = tf.keras.losses.MeanSquaredError()
        self.ComputeMetrics = tf.keras.metrics.MeanAbsoluteError()

        if tf.io.gfile.exists(MODEL_DIR):
            #             print('Removing existing model dir: {}'.format(MODEL_DIR))
            #             tf.io.gfile.rmtree(MODEL_DIR)
            pass
        else:
            tf.io.gfile.makedirs(MODEL_DIR)

        train_dir = os.path.join(MODEL_DIR, 'summaries', 'train')
        test_dir = os.path.join(MODEL_DIR, 'summaries', 'eval')

        #         self.train_summary_writer = summary_ops_v2.create_file_writer(train_dir, flush_millis=10000)
        #         self.test_summary_writer = summary_ops_v2.create_file_writer(test_dir, flush_millis=10000, name='test')

        checkpoint_dir = os.path.join(MODEL_DIR, 'checkpoints')
        self.checkpoint_prefix = os.path.join(checkpoint_dir, 'ckpt')
        self.checkpoint = tf.train.Checkpoint(model=self.model, optimizer=self.optimizer)

        # Restore variables on creation if a checkpoint exists.
        self.checkpoint.restore(tf.train.latest_checkpoint(checkpoint_dir))

    def compute_loss(self, labels, logits):
        return tf.reduce_mean(tf.keras.losses.mse(labels, logits))

    def compute_metrics(self, labels, logits):
        return tf.keras.metrics.mae(labels, logits)  #

    @tf.function
    def train_step(self, x, y):
        # Record the operations used to compute the loss, so that the gradient
        # of the loss with respect to the variables can be computed.
        #         metrics = 0
        with tf.GradientTape() as tape:
            logits = self.model([x[0],
                                 x[1],
                                 x[2],
                                 x[3],
                                 x[4],
                                 x[5],
                                 x[6]], training=True)
            loss = self.ComputeLoss(y, logits)
            # loss = self.compute_loss(labels, logits)
            self.ComputeMetrics(y, logits)
            # metrics = self.compute_metrics(labels, logits)
        grads = tape.gradient(loss, self.model.trainable_variables)
        self.optimizer.apply_gradients(zip(grads, self.model.trainable_variables))
        return loss, logits

    def training(self, features, targets_values, epochs=5, log_freq=50):

        for epoch_i in range(epochs):
            # 将数据集分成训练集和测试集,随机种子不固定
            train_X, test_X, train_y, test_y = train_test_split(features,
                                                                targets_values,
                                                                test_size=0.2,
                                                                random_state=0)

            train_batches = get_batches(train_X, train_y, self.batch_size)
            batch_num = (len(train_X) // self.batch_size)

            train_start = time.time()
            #             with self.train_summary_writer.as_default():
            if True:
                start = time.time()
                # Metrics are stateful. They accumulate values and return a cumulative
                # result when you call .result(). Clear accumulated values with .reset_states()
                avg_loss = tf.keras.metrics.Mean('loss', dtype=tf.float32)
                #                 avg_mae = tf.keras.metrics.Mean('mae', dtype=tf.float32)

                # Datasets can be iterated over like any other Python iterable.
                for batch_i in range(batch_num):
                    x, y = next(train_batches)
                    categories = np.zeros([self.batch_size, 18])
                    for i in range(self.batch_size):
                        categories[i] = x.take(6, 1)[i]

                    titles = np.zeros([self.batch_size, sentences_size])
                    for i in range(self.batch_size):
                        titles[i] = x.take(5, 1)[i]

                    loss, logits = self.train_step([np.reshape(x.take(0, 1), [self.batch_size, 1]).astype(np.float32),
                                                    np.reshape(x.take(2, 1), [self.batch_size, 1]).astype(np.float32),
                                                    np.reshape(x.take(3, 1), [self.batch_size, 1]).astype(np.float32),
                                                    np.reshape(x.take(4, 1), [self.batch_size, 1]).astype(np.float32),
                                                    np.reshape(x.take(1, 1), [self.batch_size, 1]).astype(np.float32),
                                                    categories.astype(np.float32),
                                                    titles.astype(np.float32)],
                                                   np.reshape(y, [self.batch_size, 1]).astype(np.float32))
                    avg_loss(loss)
                    #                     avg_mae(metrics)
                    self.losses['train'].append(loss)

                    if tf.equal(self.optimizer.iterations % log_freq, 0):
                        #                         summary_ops_v2.scalar('loss', avg_loss.result(), step=self.optimizer.iterations)
                        #                         summary_ops_v2.scalar('mae', self.ComputeMetrics.result(), step=self.optimizer.iterations)
                        # summary_ops_v2.scalar('mae', avg_mae.result(), step=self.optimizer.iterations)

                        rate = log_freq / (time.time() - start)
                        print('Step #{}\tEpoch {:>3} Batch {:>4}/{}   Loss: {:0.6f} mae: {:0.6f} ({} steps/sec)'.format(
                            self.optimizer.iterations.numpy(),
                            epoch_i,
                            batch_i,
                            batch_num,
                            loss, (self.ComputeMetrics.result()), rate))
                        # print('Step #{}\tLoss: {:0.6f} mae: {:0.6f} ({} steps/sec)'.format(
                        #     self.optimizer.iterations.numpy(), loss, (avg_mae.result()), rate))
                        avg_loss.reset_states()
                        self.ComputeMetrics.reset_states()
                        # avg_mae.reset_states()
                        start = time.time()

            train_end = time.time()
            print(
                '\nTrain time for epoch #{} ({} total steps): {}'.format(epoch_i + 1, self.optimizer.iterations.numpy(),
                                                                         train_end - train_start))
            #             with self.test_summary_writer.as_default():
            self.testing((test_X, test_y), self.optimizer.iterations)
            # self.checkpoint.save(self.checkpoint_prefix)
        self.export_path = os.path.join(MODEL_DIR, 'export')
        tf.saved_model.save(self.model, self.export_path)

    def testing(self, test_dataset, step_num):
        test_X, test_y = test_dataset
        test_batches = get_batches(test_X, test_y, self.batch_size)

        """Perform an evaluation of `model` on the examples from `dataset`."""
        avg_loss = tf.keras.metrics.Mean('loss', dtype=tf.float32)
        #         avg_mae = tf.keras.metrics.Mean('mae', dtype=tf.float32)

        batch_num = (len(test_X) // self.batch_size)
        for batch_i in range(batch_num):
            x, y = next(test_batches)
            categories = np.zeros([self.batch_size, 18])
            for i in range(self.batch_size):
                categories[i] = x.take(6, 1)[i]

            titles = np.zeros([self.batch_size, sentences_size])
            for i in range(self.batch_size):
                titles[i] = x.take(5, 1)[i]

            logits = self.model([np.reshape(x.take(0, 1), [self.batch_size, 1]).astype(np.float32),
                                 np.reshape(x.take(2, 1), [self.batch_size, 1]).astype(np.float32),
                                 np.reshape(x.take(3, 1), [self.batch_size, 1]).astype(np.float32),
                                 np.reshape(x.take(4, 1), [self.batch_size, 1]).astype(np.float32),
                                 np.reshape(x.take(1, 1), [self.batch_size, 1]).astype(np.float32),
                                 categories.astype(np.float32),
                                 titles.astype(np.float32)], training=False)
            test_loss = self.ComputeLoss(np.reshape(y, [self.batch_size, 1]).astype(np.float32), logits)
            avg_loss(test_loss)
            # 保存测试损失
            self.losses['test'].append(test_loss)
            self.ComputeMetrics(np.reshape(y, [self.batch_size, 1]).astype(np.float32), logits)
            # avg_loss(self.compute_loss(labels, logits))
            # avg_mae(self.compute_metrics(labels, logits))

        print('Model test set loss: {:0.6f} mae: {:0.6f}'.format(avg_loss.result(), self.ComputeMetrics.result()))
        # print('Model test set loss: {:0.6f} mae: {:0.6f}'.format(avg_loss.result(), avg_mae.result()))
        #         summary_ops_v2.scalar('loss', avg_loss.result(), step=step_num)
        #         summary_ops_v2.scalar('mae', self.ComputeMetrics.result(), step=step_num)
        # summary_ops_v2.scalar('mae', avg_mae.result(), step=step_num)

        if avg_loss.result() < self.best_loss:
            self.best_loss = avg_loss.result()
            print("best loss = {}".format(self.best_loss))
            self.checkpoint.save(self.checkpoint_prefix)

    def forward(self, xs):
        predictions = self.model(xs)
        # logits = tf.nn.softmax(predictions)

        return predictions

取得batch

def get_batches(Xs, ys, batch_size):
    for start in range(0, len(Xs), batch_size):
        end = min(start + batch_size, len(Xs))
        yield Xs[start:end], ys[start:end]

训练网络

将用户特征和电影特征作为输入,经过全连接,输出一个值的训练

mv_net=mv_network()
mv_net.training(features, targets_values, epochs=5)
Model: "model_3"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
movie_titles (InputLayer)       [(None, 15)]         0                                            
__________________________________________________________________________________________________
movie_title_embed_layer (Embedd (None, 15, 32)       166880      movie_titles[0][0]               
__________________________________________________________________________________________________
reshape_3 (Reshape)             (None, 15, 32, 1)    0           movie_title_embed_layer[0][0]    
__________________________________________________________________________________________________
conv2d_12 (Conv2D)              (None, 14, 1, 8)     520         reshape_3[0][0]                  
__________________________________________________________________________________________________
conv2d_13 (Conv2D)              (None, 13, 1, 8)     776         reshape_3[0][0]                  
__________________________________________________________________________________________________
conv2d_14 (Conv2D)              (None, 12, 1, 8)     1032        reshape_3[0][0]                  
__________________________________________________________________________________________________
conv2d_15 (Conv2D)              (None, 11, 1, 8)     1288        reshape_3[0][0]                  
__________________________________________________________________________________________________
movie_categories (InputLayer)   [(None, 18)]         0                                            
__________________________________________________________________________________________________
max_pooling2d_12 (MaxPooling2D) (None, 1, 1, 8)      0           conv2d_12[0][0]                  
__________________________________________________________________________________________________
max_pooling2d_13 (MaxPooling2D) (None, 1, 1, 8)      0           conv2d_13[0][0]                  
__________________________________________________________________________________________________
max_pooling2d_14 (MaxPooling2D) (None, 1, 1, 8)      0           conv2d_14[0][0]                  
__________________________________________________________________________________________________
max_pooling2d_15 (MaxPooling2D) (None, 1, 1, 8)      0           conv2d_15[0][0]                  
__________________________________________________________________________________________________
uid (InputLayer)                [(None, 1)]          0                                            
__________________________________________________________________________________________________
user_gender (InputLayer)        [(None, 1)]          0                                            
__________________________________________________________________________________________________
user_age (InputLayer)           [(None, 1)]          0                                            
__________________________________________________________________________________________________
user_job (InputLayer)           [(None, 1)]          0                                            
__________________________________________________________________________________________________
movie_id (InputLayer)           [(None, 1)]          0                                            
__________________________________________________________________________________________________
movie_categories_embed_layer (E (None, 18, 32)       608         movie_categories[0][0]           
__________________________________________________________________________________________________
pool_layer (Concatenate)        (None, 1, 1, 32)     0           max_pooling2d_12[0][0]           
                                                                 max_pooling2d_13[0][0]           
                                                                 max_pooling2d_14[0][0]           
                                                                 max_pooling2d_15[0][0]           
__________________________________________________________________________________________________
uid_embed_layer (Embedding)     (None, 1, 32)        193312      uid[0][0]                        
__________________________________________________________________________________________________
gender_embed_layer (Embedding)  (None, 1, 16)        32          user_gender[0][0]                
__________________________________________________________________________________________________
age_embed_layer (Embedding)     (None, 1, 16)        112         user_age[0][0]                   
__________________________________________________________________________________________________
job_embed_layer (Embedding)     (None, 1, 16)        336         user_job[0][0]                   
__________________________________________________________________________________________________
movie_id_embed_layer (Embedding (None, 1, 32)        126496      movie_id[0][0]                   
__________________________________________________________________________________________________
lambda_6 (Lambda)               (None, 1, 32)        0           movie_categories_embed_layer[0][0
__________________________________________________________________________________________________
pool_layer_flat (Reshape)       (None, 1, 32)        0           pool_layer[0][0]                 
__________________________________________________________________________________________________
uid_fc_layer (Dense)            (None, 1, 32)        1056        uid_embed_layer[0][0]            
__________________________________________________________________________________________________
gender_fc_layer (Dense)         (None, 1, 32)        544         gender_embed_layer[0][0]         
__________________________________________________________________________________________________
age_fc_layer (Dense)            (None, 1, 32)        544         age_embed_layer[0][0]            
__________________________________________________________________________________________________
job_fc_layer (Dense)            (None, 1, 32)        544         job_embed_layer[0][0]            
__________________________________________________________________________________________________
movie_id_fc_layer (Dense)       (None, 1, 32)        1056        movie_id_embed_layer[0][0]       
__________________________________________________________________________________________________
movie_categories_fc_layer (Dens (None, 1, 32)        1056        lambda_6[0][0]                   
__________________________________________________________________________________________________
dropout_layer (Dropout)         (None, 1, 32)        0           pool_layer_flat[0][0]            
__________________________________________________________________________________________________
concatenate_6 (Concatenate)     (None, 1, 128)       0           uid_fc_layer[0][0]               
                                                                 gender_fc_layer[0][0]            
                                                                 age_fc_layer[0][0]               
                                                                 job_fc_layer[0][0]               
__________________________________________________________________________________________________
concatenate_7 (Concatenate)     (None, 1, 96)        0           movie_id_fc_layer[0][0]          
                                                                 movie_categories_fc_layer[0][0]  
                                                                 dropout_layer[0][0]              
__________________________________________________________________________________________________
dense_6 (Dense)                 (None, 1, 200)       25800       concatenate_6[0][0]              
__________________________________________________________________________________________________
dense_7 (Dense)                 (None, 1, 200)       19400       concatenate_7[0][0]              
__________________________________________________________________________________________________
user_combine_layer_flat (Reshap (None, 200)          0           dense_6[0][0]                    
__________________________________________________________________________________________________
movie_combine_layer_flat (Resha (None, 200)          0           dense_7[0][0]                    
__________________________________________________________________________________________________
inference (Lambda)              (None,)              0           user_combine_layer_flat[0][0]    
                                                                 movie_combine_layer_flat[0][0]   
__________________________________________________________________________________________________
lambda_7 (Lambda)               (None, 1)            0           inference[0][0]                  
==================================================================================================
Total params: 541,392
Trainable params: 541,392
Non-trainable params: 0
__________________________________________________________________________________________________
Step #18800	Epoch   0 Batch   49/3125   Loss: 0.848101 mae: 0.691804 (27.637772944410063 steps/sec)
Step #18850	Epoch   0 Batch   99/3125   Loss: 0.947761 mae: 0.682926 (97.27970550089155 steps/sec)
Step #18900	Epoch   0 Batch  149/3125   Loss: 0.746948 mae: 0.693619 (94.22213516055017 steps/sec)
Step #18950	Epoch   0 Batch  199/3125   Loss: 0.792230 mae: 0.693281 (94.88800226592596 steps/sec)
Step #19000	Epoch   0 Batch  249/3125   Loss: 0.853272 mae: 0.691730 (94.83132146030555 steps/sec)
Step #19050	Epoch   0 Batch  299/3125   Loss: 0.751092 mae: 0.691599 (101.01586561480342 steps/sec)
Step #19100	Epoch   0 Batch  349/3125   Loss: 0.843071 mae: 0.694882 (101.83058405828346 steps/sec)
Step #19150	Epoch   0 Batch  399/3125   Loss: 0.874644 mae: 0.695321 (101.51983099649716 steps/sec)
Step #19200	Epoch   0 Batch  449/3125   Loss: 0.786772 mae: 0.698967 (98.81082232255979 steps/sec)
Step #19250	Epoch   0 Batch  499/3125   Loss: 0.760961 mae: 0.686922 (97.884092537404 steps/sec)
Step #19300	Epoch   0 Batch  549/3125   Loss: 0.752310 mae: 0.686976 (98.99852103058629 steps/sec)
Step #19350	Epoch   0 Batch  599/3125   Loss: 0.685646 mae: 0.697807 (96.76298892450912 steps/sec)
Step #19400	Epoch   0 Batch  649/3125   Loss: 0.715844 mae: 0.693816 (96.13379460763798 steps/sec)
Step #19450	Epoch   0 Batch  699/3125   Loss: 0.768952 mae: 0.693204 (97.33149111525822 steps/sec)
Step #19500	Epoch   0 Batch  749/3125   Loss: 0.745624 mae: 0.683436 (95.30070259292735 steps/sec)
Step #19550	Epoch   0 Batch  799/3125   Loss: 0.821963 mae: 0.691857 (102.57208871915968 steps/sec)
Step #19600	Epoch   0 Batch  849/3125   Loss: 0.850824 mae: 0.691828 (103.89249070757201 steps/sec)
Step #19650	Epoch   0 Batch  899/3125   Loss: 0.845563 mae: 0.689795 (97.78815221765309 steps/sec)
Step #19700	Epoch   0 Batch  949/3125   Loss: 0.674638 mae: 0.691894 (103.42582459718882 steps/sec)
Step #19750	Epoch   0 Batch  999/3125   Loss: 0.847141 mae: 0.687374 (105.39066598857019 steps/sec)
Step #19800	Epoch   0 Batch 1049/3125   Loss: 0.838690 mae: 0.698633 (103.69963799235833 steps/sec)
Step #19850	Epoch   0 Batch 1099/3125   Loss: 0.739785 mae: 0.690680 (104.66621782071482 steps/sec)
Step #19900	Epoch   0 Batch 1149/3125   Loss: 0.703950 mae: 0.697995 (105.42616329866972 steps/sec)
Step #19950	Epoch   0 Batch 1199/3125   Loss: 0.824220 mae: 0.687212 (103.49937766687756 steps/sec)
Step #20000	Epoch   0 Batch 1249/3125   Loss: 0.868953 mae: 0.693830 (97.82332065811619 steps/sec)
Step #20050	Epoch   0 Batch 1299/3125   Loss: 0.730640 mae: 0.699454 (93.00487297794476 steps/sec)
Step #20100	Epoch   0 Batch 1349/3125   Loss: 0.803740 mae: 0.677289 (98.04966835245015 steps/sec)
Step #20150	Epoch   0 Batch 1399/3125   Loss: 0.786500 mae: 0.693733 (97.83203685346085 steps/sec)
Step #20200	Epoch   0 Batch 1449/3125   Loss: 0.737920 mae: 0.692194 (100.51230239884435 steps/sec)
Step #20250	Epoch   0 Batch 1499/3125   Loss: 0.805032 mae: 0.691858 (97.52258504938787 steps/sec)
Step #20300	Epoch   0 Batch 1549/3125   Loss: 0.854445 mae: 0.691005 (98.68922723041723 steps/sec)
Step #20350	Epoch   0 Batch 1599/3125   Loss: 0.768004 mae: 0.687592 (96.64294930875576 steps/sec)
Step #20400	Epoch   0 Batch 1649/3125   Loss: 0.820738 mae: 0.693461 (97.56441599344966 steps/sec)
Step #20450	Epoch   0 Batch 1699/3125   Loss: 0.810527 mae: 0.687126 (104.0909700059065 steps/sec)
Step #20500	Epoch   0 Batch 1749/3125   Loss: 0.785807 mae: 0.689348 (104.86331505067027 steps/sec)
Step #20550	Epoch   0 Batch 1799/3125   Loss: 0.852628 mae: 0.690730 (100.98035816778955 steps/sec)
Step #20600	Epoch   0 Batch 1849/3125   Loss: 0.745395 mae: 0.692310 (100.04140660330376 steps/sec)
Step #20650	Epoch   0 Batch 1899/3125   Loss: 0.860758 mae: 0.689794 (103.83014876291656 steps/sec)
Step #20700	Epoch   0 Batch 1949/3125   Loss: 0.729740 mae: 0.682986 (104.72894049659993 steps/sec)
Step #20750	Epoch   0 Batch 1999/3125   Loss: 0.843179 mae: 0.691823 (104.53922578786306 steps/sec)
Step #20800	Epoch   0 Batch 2049/3125   Loss: 0.728389 mae: 0.698972 (105.46375291990717 steps/sec)
Step #20850	Epoch   0 Batch 2099/3125   Loss: 0.808849 mae: 0.679972 (104.75865544992755 steps/sec)
Step #20900	Epoch   0 Batch 2149/3125   Loss: 0.742408 mae: 0.680288 (98.92170421676859 steps/sec)
Step #20950	Epoch   0 Batch 2199/3125   Loss: 0.676885 mae: 0.686084 (95.43749024419213 steps/sec)
Step #21000	Epoch   0 Batch 2249/3125   Loss: 0.738224 mae: 0.685648 (102.49558914808244 steps/sec)
Step #21050	Epoch   0 Batch 2299/3125   Loss: 0.811326 mae: 0.699091 (104.40786312956938 steps/sec)
Step #21100	Epoch   0 Batch 2349/3125   Loss: 0.744082 mae: 0.691439 (98.69243182268463 steps/sec)
Step #21150	Epoch   0 Batch 2399/3125   Loss: 0.715450 mae: 0.689829 (98.54250365337356 steps/sec)
Step #21200	Epoch   0 Batch 2449/3125   Loss: 0.733722 mae: 0.681757 (97.19778292029201 steps/sec)
Step #21250	Epoch   0 Batch 2499/3125   Loss: 0.895794 mae: 0.691461 (93.82907166061841 steps/sec)
Step #21300	Epoch   0 Batch 2549/3125   Loss: 0.594887 mae: 0.695868 (91.97760768538483 steps/sec)
Step #21350	Epoch   0 Batch 2599/3125   Loss: 0.896662 mae: 0.690421 (99.11315046856753 steps/sec)
Step #21400	Epoch   0 Batch 2649/3125   Loss: 0.857583 mae: 0.692567 (102.56140400640265 steps/sec)
Step #21450	Epoch   0 Batch 2699/3125   Loss: 0.758102 mae: 0.687871 (98.85618904722645 steps/sec)
Step #21500	Epoch   0 Batch 2749/3125   Loss: 0.856856 mae: 0.685238 (99.84911830144058 steps/sec)
Step #21550	Epoch   0 Batch 2799/3125   Loss: 0.798290 mae: 0.694276 (100.47767755758721 steps/sec)
Step #21600	Epoch   0 Batch 2849/3125   Loss: 0.779489 mae: 0.686759 (88.33807145471769 steps/sec)
Step #21650	Epoch   0 Batch 2899/3125   Loss: 0.822600 mae: 0.685006 (94.11055146491282 steps/sec)
Step #21700	Epoch   0 Batch 2949/3125   Loss: 0.837273 mae: 0.689872 (99.90215348088753 steps/sec)
Step #21750	Epoch   0 Batch 2999/3125   Loss: 0.706622 mae: 0.687190 (103.2946995484817 steps/sec)
Step #21800	Epoch   0 Batch 3049/3125   Loss: 0.730821 mae: 0.679799 (95.09064923570253 steps/sec)
Step #21850	Epoch   0 Batch 3099/3125   Loss: 0.830290 mae: 0.684865 (100.44442358323519 steps/sec)

Train time for epoch #1 (21875 total steps): 32.83831572532654
Model test set loss: 0.788444 mae: 0.700780
best loss = 0.7884443998336792
Step #21900	Epoch   1 Batch   24/3125   Loss: 0.678443 mae: 0.700345 (170.22752177406917 steps/sec)
Step #21950	Epoch   1 Batch   74/3125   Loss: 0.812340 mae: 0.681441 (95.51281700943126 steps/sec)
Step #22000	Epoch   1 Batch  124/3125   Loss: 0.659081 mae: 0.690085 (91.39661512741866 steps/sec)
Step #22050	Epoch   1 Batch  174/3125   Loss: 0.768032 mae: 0.687947 (95.5915741473845 steps/sec)
Step #22100	Epoch   1 Batch  224/3125   Loss: 0.636173 mae: 0.691459 (95.35816285375337 steps/sec)
Step #22150	Epoch   1 Batch  274/3125   Loss: 0.764309 mae: 0.687606 (96.18635225136346 steps/sec)
Step #22200	Epoch   1 Batch  324/3125   Loss: 0.744969 mae: 0.689999 (94.08859569153022 steps/sec)
Step #22250	Epoch   1 Batch  374/3125   Loss: 0.763131 mae: 0.691957 (97.47227214777158 steps/sec)
Step #22300	Epoch   1 Batch  424/3125   Loss: 0.831872 mae: 0.693085 (97.65564282511221 steps/sec)
Step #22350	Epoch   1 Batch  474/3125   Loss: 0.763018 mae: 0.689512 (94.82304598200075 steps/sec)
Step #22400	Epoch   1 Batch  524/3125   Loss: 0.835540 mae: 0.683687 (91.60585169139671 steps/sec)
Step #22450	Epoch   1 Batch  574/3125   Loss: 0.818543 mae: 0.689819 (94.79642846326554 steps/sec)
Step #22500	Epoch   1 Batch  624/3125   Loss: 0.592940 mae: 0.686780 (94.30895478894674 steps/sec)
Step #22550	Epoch   1 Batch  674/3125   Loss: 0.791231 mae: 0.690431 (94.42547366904402 steps/sec)
Step #22600	Epoch   1 Batch  724/3125   Loss: 0.644314 mae: 0.690026 (84.83425550695009 steps/sec)
Step #22650	Epoch   1 Batch  774/3125   Loss: 0.718745 mae: 0.681867 (89.78514349811302 steps/sec)
Step #22700	Epoch   1 Batch  824/3125   Loss: 0.786647 mae: 0.688625 (86.77908647320926 steps/sec)
Step #22750	Epoch   1 Batch  874/3125   Loss: 0.692773 mae: 0.686636 (88.38308191426324 steps/sec)
Step #22800	Epoch   1 Batch  924/3125   Loss: 0.861632 mae: 0.693288 (84.86120311272774 steps/sec)
Step #22850	Epoch   1 Batch  974/3125   Loss: 0.712722 mae: 0.687713 (85.69058664990843 steps/sec)
Step #22900	Epoch   1 Batch 1024/3125   Loss: 0.716715 mae: 0.684843 (81.83209442981173 steps/sec)
Step #22950	Epoch   1 Batch 1074/3125   Loss: 0.780225 mae: 0.689261 (85.32402879243311 steps/sec)
Step #23000	Epoch   1 Batch 1124/3125   Loss: 0.770114 mae: 0.693500 (87.99868074487561 steps/sec)
Step #23050	Epoch   1 Batch 1174/3125   Loss: 0.700080 mae: 0.690776 (89.22923358196857 steps/sec)
Step #23100	Epoch   1 Batch 1224/3125   Loss: 0.753743 mae: 0.682393 (86.86851950651322 steps/sec)
Step #23150	Epoch   1 Batch 1274/3125   Loss: 0.858793 mae: 0.697203 (85.37411670451299 steps/sec)
Step #23200	Epoch   1 Batch 1324/3125   Loss: 0.666164 mae: 0.684622 (98.41385446504661 steps/sec)
Step #23250	Epoch   1 Batch 1374/3125   Loss: 0.701718 mae: 0.682613 (94.23792790444777 steps/sec)
Step #23300	Epoch   1 Batch 1424/3125   Loss: 0.767711 mae: 0.688312 (95.42172709453028 steps/sec)
Step #23350	Epoch   1 Batch 1474/3125   Loss: 0.666887 mae: 0.689093 (91.94046968222995 steps/sec)
Step #23400	Epoch   1 Batch 1524/3125   Loss: 0.686597 mae: 0.683916 (96.19791205570175 steps/sec)
Step #23450	Epoch   1 Batch 1574/3125   Loss: 0.724204 mae: 0.691114 (97.00158697340443 steps/sec)
Step #23500	Epoch   1 Batch 1624/3125   Loss: 0.796998 mae: 0.682731 (93.58855526612791 steps/sec)
Step #23550	Epoch   1 Batch 1674/3125   Loss: 0.655430 mae: 0.689436 (94.92743126973551 steps/sec)
Step #23600	Epoch   1 Batch 1724/3125   Loss: 0.860071 mae: 0.685661 (93.87716367373761 steps/sec)
Step #23650	Epoch   1 Batch 1774/3125   Loss: 0.728770 mae: 0.689083 (92.59697361861907 steps/sec)
Step #23700	Epoch   1 Batch 1824/3125   Loss: 0.701443 mae: 0.686881 (87.97590381662738 steps/sec)
Step #23750	Epoch   1 Batch 1874/3125   Loss: 0.818099 mae: 0.689917 (95.95046990361269 steps/sec)
Step #23800	Epoch   1 Batch 1924/3125   Loss: 0.952441 mae: 0.684022 (87.49854492580687 steps/sec)
Step #23850	Epoch   1 Batch 1974/3125   Loss: 0.757475 mae: 0.680573 (90.24557755565387 steps/sec)
Step #23900	Epoch   1 Batch 2024/3125   Loss: 0.863990 mae: 0.692241 (97.66546623380917 steps/sec)
Step #23950	Epoch   1 Batch 2074/3125   Loss: 0.795743 mae: 0.682051 (97.1957557685231 steps/sec)
Step #24000	Epoch   1 Batch 2124/3125   Loss: 0.638063 mae: 0.685234 (88.90075842069096 steps/sec)
Step #24050	Epoch   1 Batch 2174/3125   Loss: 0.725783 mae: 0.679442 (95.6616023365831 steps/sec)
Step #24100	Epoch   1 Batch 2224/3125   Loss: 0.682556 mae: 0.684956 (90.38552212496175 steps/sec)
Step #24150	Epoch   1 Batch 2274/3125   Loss: 0.759051 mae: 0.685392 (86.45735636112232 steps/sec)
Step #24200	Epoch   1 Batch 2324/3125   Loss: 0.616159 mae: 0.694101 (90.38918408231241 steps/sec)
Step #24250	Epoch   1 Batch 2374/3125   Loss: 0.709371 mae: 0.683894 (99.02656902293784 steps/sec)
Step #24300	Epoch   1 Batch 2424/3125   Loss: 0.721422 mae: 0.684375 (87.43470493447042 steps/sec)
Step #24350	Epoch   1 Batch 2474/3125   Loss: 0.785628 mae: 0.680045 (84.47830672143998 steps/sec)
Step #24400	Epoch   1 Batch 2524/3125   Loss: 0.719284 mae: 0.689088 (83.60163380115495 steps/sec)
Step #24450	Epoch   1 Batch 2574/3125   Loss: 0.821281 mae: 0.693504 (90.1592526051642 steps/sec)
Step #24500	Epoch   1 Batch 2624/3125   Loss: 0.933031 mae: 0.688952 (93.38447659056034 steps/sec)
Step #24550	Epoch   1 Batch 2674/3125   Loss: 0.743384 mae: 0.689125 (87.3659350872742 steps/sec)
Step #24600	Epoch   1 Batch 2724/3125   Loss: 0.726583 mae: 0.679906 (96.08274704350488 steps/sec)
Step #24650	Epoch   1 Batch 2774/3125   Loss: 0.687935 mae: 0.684948 (94.66373562881144 steps/sec)
Step #24700	Epoch   1 Batch 2824/3125   Loss: 0.790933 mae: 0.695512 (101.71669031962044 steps/sec)
Step #24750	Epoch   1 Batch 2874/3125   Loss: 0.799906 mae: 0.676791 (92.94580504423803 steps/sec)
Step #24800	Epoch   1 Batch 2924/3125   Loss: 0.771244 mae: 0.685280 (100.01435485878586 steps/sec)
Step #24850	Epoch   1 Batch 2974/3125   Loss: 0.672207 mae: 0.686887 (102.39780004726461 steps/sec)
Step #24900	Epoch   1 Batch 3024/3125   Loss: 0.702219 mae: 0.677694 (102.82883843215284 steps/sec)
Step #24950	Epoch   1 Batch 3074/3125   Loss: 0.751962 mae: 0.680351 (100.43942054917271 steps/sec)
Step #25000	Epoch   1 Batch 3124/3125   Loss: 0.800776 mae: 0.680315 (98.22224532799028 steps/sec)

Train time for epoch #2 (25000 total steps): 33.96665096282959
Model test set loss: 0.784036 mae: 0.699112
best loss = 0.7840359210968018
Step #25050	Epoch   2 Batch   49/3125   Loss: 0.841394 mae: 0.698265 (90.52476819008047 steps/sec)
Step #25100	Epoch   2 Batch   99/3125   Loss: 0.917930 mae: 0.675593 (94.70960760909671 steps/sec)
Step #25150	Epoch   2 Batch  149/3125   Loss: 0.731097 mae: 0.686770 (95.71019392574121 steps/sec)
Step #25200	Epoch   2 Batch  199/3125   Loss: 0.766869 mae: 0.686221 (93.53821341134608 steps/sec)
Step #25250	Epoch   2 Batch  249/3125   Loss: 0.841341 mae: 0.686227 (89.86593933524594 steps/sec)
Step #25300	Epoch   2 Batch  299/3125   Loss: 0.738986 mae: 0.685498 (87.32911779831642 steps/sec)
Step #25350	Epoch   2 Batch  349/3125   Loss: 0.825709 mae: 0.688310 (87.90694360027665 steps/sec)
Step #25400	Epoch   2 Batch  399/3125   Loss: 0.866955 mae: 0.689053 (90.68918351487874 steps/sec)
Step #25450	Epoch   2 Batch  449/3125   Loss: 0.759929 mae: 0.692852 (88.27745989812416 steps/sec)
Step #25500	Epoch   2 Batch  499/3125   Loss: 0.751120 mae: 0.680172 (85.08168182568728 steps/sec)
Step #25550	Epoch   2 Batch  549/3125   Loss: 0.749131 mae: 0.679911 (86.89378677801966 steps/sec)
Step #25600	Epoch   2 Batch  599/3125   Loss: 0.662256 mae: 0.690591 (88.49661188460912 steps/sec)
Step #25650	Epoch   2 Batch  649/3125   Loss: 0.713749 mae: 0.686868 (91.26206240793404 steps/sec)
Step #25700	Epoch   2 Batch  699/3125   Loss: 0.751382 mae: 0.687611 (84.17108328801321 steps/sec)
Step #25750	Epoch   2 Batch  749/3125   Loss: 0.730248 mae: 0.677658 (86.24945301164387 steps/sec)
Step #25800	Epoch   2 Batch  799/3125   Loss: 0.792215 mae: 0.685663 (89.12756515360535 steps/sec)
Step #25850	Epoch   2 Batch  849/3125   Loss: 0.839750 mae: 0.686164 (93.40710341381113 steps/sec)
Step #25900	Epoch   2 Batch  899/3125   Loss: 0.845688 mae: 0.684292 (94.12170216432808 steps/sec)
Step #25950	Epoch   2 Batch  949/3125   Loss: 0.682219 mae: 0.686044 (91.55478176441261 steps/sec)
Step #26000	Epoch   2 Batch  999/3125   Loss: 0.835548 mae: 0.679832 (94.26893602943028 steps/sec)
Step #26050	Epoch   2 Batch 1049/3125   Loss: 0.825394 mae: 0.691863 (94.50261744715425 steps/sec)
Step #26100	Epoch   2 Batch 1099/3125   Loss: 0.727683 mae: 0.684240 (91.55422219040152 steps/sec)
Step #26150	Epoch   2 Batch 1149/3125   Loss: 0.683049 mae: 0.692138 (95.7884894971446 steps/sec)
Step #26200	Epoch   2 Batch 1199/3125   Loss: 0.796000 mae: 0.680490 (96.30658635117257 steps/sec)
Step #26250	Epoch   2 Batch 1249/3125   Loss: 0.838705 mae: 0.687717 (95.88821625180606 steps/sec)
Step #26300	Epoch   2 Batch 1299/3125   Loss: 0.705656 mae: 0.692004 (94.1591439098221 steps/sec)
Step #26350	Epoch   2 Batch 1349/3125   Loss: 0.779030 mae: 0.671063 (93.87880261051 steps/sec)
Step #26400	Epoch   2 Batch 1399/3125   Loss: 0.785823 mae: 0.688031 (95.40644658809057 steps/sec)
Step #26450	Epoch   2 Batch 1449/3125   Loss: 0.720694 mae: 0.684680 (97.78701228940247 steps/sec)
Step #26500	Epoch   2 Batch 1499/3125   Loss: 0.790368 mae: 0.685548 (98.16642895292519 steps/sec)
Step #26550	Epoch   2 Batch 1549/3125   Loss: 0.831634 mae: 0.684100 (98.15678016674678 steps/sec)
Step #26600	Epoch   2 Batch 1599/3125   Loss: 0.749523 mae: 0.680817 (96.42956002431485 steps/sec)
Step #26650	Epoch   2 Batch 1649/3125   Loss: 0.801523 mae: 0.686970 (97.63850207228171 steps/sec)
Step #26700	Epoch   2 Batch 1699/3125   Loss: 0.794450 mae: 0.680057 (96.53382604825053 steps/sec)
Step #26750	Epoch   2 Batch 1749/3125   Loss: 0.770107 mae: 0.683221 (97.93469438837982 steps/sec)
Step #26800	Epoch   2 Batch 1799/3125   Loss: 0.822275 mae: 0.684085 (97.58307454210937 steps/sec)
Step #26850	Epoch   2 Batch 1849/3125   Loss: 0.747708 mae: 0.684700 (97.58311994874117 steps/sec)
Step #26900	Epoch   2 Batch 1899/3125   Loss: 0.846560 mae: 0.683030 (94.89822145476529 steps/sec)
Step #26950	Epoch   2 Batch 1949/3125   Loss: 0.708278 mae: 0.677219 (98.29447772247063 steps/sec)
Step #27000	Epoch   2 Batch 1999/3125   Loss: 0.830324 mae: 0.685146 (95.49789869759779 steps/sec)
Step #27050	Epoch   2 Batch 2049/3125   Loss: 0.713161 mae: 0.692587 (92.06534980760746 steps/sec)
Step #27100	Epoch   2 Batch 2099/3125   Loss: 0.784691 mae: 0.674547 (97.8175259323592 steps/sec)
Step #27150	Epoch   2 Batch 2149/3125   Loss: 0.721927 mae: 0.674004 (98.35274607977578 steps/sec)
Step #27200	Epoch   2 Batch 2199/3125   Loss: 0.668375 mae: 0.680332 (98.05874588353784 steps/sec)
Step #27250	Epoch   2 Batch 2249/3125   Loss: 0.726950 mae: 0.678826 (96.12066416994112 steps/sec)
Step #27300	Epoch   2 Batch 2299/3125   Loss: 0.793177 mae: 0.692385 (99.10612471155214 steps/sec)
Step #27350	Epoch   2 Batch 2349/3125   Loss: 0.729357 mae: 0.683784 (97.88272194126995 steps/sec)
Step #27400	Epoch   2 Batch 2399/3125   Loss: 0.697055 mae: 0.682630 (97.50073108625237 steps/sec)
Step #27450	Epoch   2 Batch 2449/3125   Loss: 0.719842 mae: 0.675641 (96.70765876521986 steps/sec)
Step #27500	Epoch   2 Batch 2499/3125   Loss: 0.885442 mae: 0.685140 (96.35760646123506 steps/sec)
Step #27550	Epoch   2 Batch 2549/3125   Loss: 0.569982 mae: 0.688982 (96.15085190724339 steps/sec)
Step #27600	Epoch   2 Batch 2599/3125   Loss: 0.883556 mae: 0.683297 (98.5813215802705 steps/sec)
Step #27650	Epoch   2 Batch 2649/3125   Loss: 0.838301 mae: 0.684033 (96.97592979396074 steps/sec)
Step #27700	Epoch   2 Batch 2699/3125   Loss: 0.747114 mae: 0.682756 (98.4129769949943 steps/sec)
Step #27750	Epoch   2 Batch 2749/3125   Loss: 0.826727 mae: 0.678213 (96.69597613437784 steps/sec)
Step #27800	Epoch   2 Batch 2799/3125   Loss: 0.792681 mae: 0.686795 (98.76154371423863 steps/sec)
Step #27850	Epoch   2 Batch 2849/3125   Loss: 0.787148 mae: 0.681075 (95.59837189128376 steps/sec)
Step #27900	Epoch   2 Batch 2899/3125   Loss: 0.817012 mae: 0.678875 (97.75852271800272 steps/sec)
Step #27950	Epoch   2 Batch 2949/3125   Loss: 0.821596 mae: 0.682126 (98.38209078456025 steps/sec)
Step #28000	Epoch   2 Batch 2999/3125   Loss: 0.700930 mae: 0.679892 (99.07686144228825 steps/sec)
Step #28050	Epoch   2 Batch 3049/3125   Loss: 0.721152 mae: 0.673013 (97.36936063563608 steps/sec)
Step #28100	Epoch   2 Batch 3099/3125   Loss: 0.804983 mae: 0.677583 (95.00479519728262 steps/sec)

Train time for epoch #3 (28125 total steps): 33.18755841255188
Model test set loss: 0.779327 mae: 0.696082
best loss = 0.7793265581130981
Step #28150	Epoch   3 Batch   24/3125   Loss: 0.671083 mae: 0.695564 (171.26934296793078 steps/sec)
Step #28200	Epoch   3 Batch   74/3125   Loss: 0.792037 mae: 0.674184 (97.14375446136373 steps/sec)
Step #28250	Epoch   3 Batch  124/3125   Loss: 0.655678 mae: 0.682189 (92.6364035120655 steps/sec)
Step #28300	Epoch   3 Batch  174/3125   Loss: 0.774118 mae: 0.681569 (97.98278487352634 steps/sec)
Step #28350	Epoch   3 Batch  224/3125   Loss: 0.640327 mae: 0.683743 (96.37979250203936 steps/sec)
Step #28400	Epoch   3 Batch  274/3125   Loss: 0.750146 mae: 0.681639 (96.8823424517171 steps/sec)
Step #28450	Epoch   3 Batch  324/3125   Loss: 0.732256 mae: 0.683736 (96.14340236788117 steps/sec)
Step #28500	Epoch   3 Batch  374/3125   Loss: 0.743042 mae: 0.684646 (97.48745120170025 steps/sec)
Step #28550	Epoch   3 Batch  424/3125   Loss: 0.815393 mae: 0.686061 (96.54751409321202 steps/sec)
Step #28600	Epoch   3 Batch  474/3125   Loss: 0.765601 mae: 0.681953 (97.42124177298454 steps/sec)
Step #28650	Epoch   3 Batch  524/3125   Loss: 0.817163 mae: 0.675836 (97.35236541674423 steps/sec)
Step #28700	Epoch   3 Batch  574/3125   Loss: 0.789274 mae: 0.682267 (96.4514686971671 steps/sec)
Step #28750	Epoch   3 Batch  624/3125   Loss: 0.581383 mae: 0.680147 (95.3692642182902 steps/sec)
Step #28800	Epoch   3 Batch  674/3125   Loss: 0.782234 mae: 0.684234 (97.92870354502362 steps/sec)
Step #28850	Epoch   3 Batch  724/3125   Loss: 0.629306 mae: 0.682857 (95.06513098726391 steps/sec)
Step #28900	Epoch   3 Batch  774/3125   Loss: 0.693846 mae: 0.676542 (96.86851456409788 steps/sec)
Step #28950	Epoch   3 Batch  824/3125   Loss: 0.773958 mae: 0.682875 (95.78157719860334 steps/sec)
Step #29000	Epoch   3 Batch  874/3125   Loss: 0.684647 mae: 0.680135 (97.5185490366033 steps/sec)
Step #29050	Epoch   3 Batch  924/3125   Loss: 0.850243 mae: 0.686539 (94.78147606138972 steps/sec)
Step #29100	Epoch   3 Batch  974/3125   Loss: 0.696704 mae: 0.681376 (97.06808066295888 steps/sec)
Step #29150	Epoch   3 Batch 1024/3125   Loss: 0.723475 mae: 0.677778 (94.13716546022421 steps/sec)
Step #29200	Epoch   3 Batch 1074/3125   Loss: 0.757530 mae: 0.681978 (97.67006026509189 steps/sec)
Step #29250	Epoch   3 Batch 1124/3125   Loss: 0.748991 mae: 0.687987 (95.03368307906754 steps/sec)
Step #29300	Epoch   3 Batch 1174/3125   Loss: 0.664798 mae: 0.683524 (96.86860405229694 steps/sec)
Step #29350	Epoch   3 Batch 1224/3125   Loss: 0.742110 mae: 0.675986 (95.62334882711438 steps/sec)
Step #29400	Epoch   3 Batch 1274/3125   Loss: 0.842598 mae: 0.690012 (97.26982418953486 steps/sec)
Step #29450	Epoch   3 Batch 1324/3125   Loss: 0.642632 mae: 0.678084 (94.8816056586419 steps/sec)
Step #29500	Epoch   3 Batch 1374/3125   Loss: 0.706632 mae: 0.676122 (95.79640924256432 steps/sec)
Step #29550	Epoch   3 Batch 1424/3125   Loss: 0.742016 mae: 0.680312 (95.7289801791011 steps/sec)
Step #29600	Epoch   3 Batch 1474/3125   Loss: 0.641970 mae: 0.682409 (98.22155528203514 steps/sec)
Step #29650	Epoch   3 Batch 1524/3125   Loss: 0.659349 mae: 0.675746 (95.23033672405047 steps/sec)
Step #29700	Epoch   3 Batch 1574/3125   Loss: 0.703235 mae: 0.683202 (96.5951413908508 steps/sec)
Step #29750	Epoch   3 Batch 1624/3125   Loss: 0.772652 mae: 0.675448 (95.40458027074376 steps/sec)
Step #29800	Epoch   3 Batch 1674/3125   Loss: 0.632780 mae: 0.681941 (97.03668572248223 steps/sec)
Step #29850	Epoch   3 Batch 1724/3125   Loss: 0.851819 mae: 0.678916 (96.02089321803724 steps/sec)
Step #29900	Epoch   3 Batch 1774/3125   Loss: 0.684029 mae: 0.680845 (98.01236726409218 steps/sec)
Step #29950	Epoch   3 Batch 1824/3125   Loss: 0.680554 mae: 0.679434 (95.80441783048187 steps/sec)
Step #30000	Epoch   3 Batch 1874/3125   Loss: 0.798749 mae: 0.682511 (96.41745686930335 steps/sec)
Step #30050	Epoch   3 Batch 1924/3125   Loss: 0.929966 mae: 0.677670 (97.07050686850191 steps/sec)
Step #30100	Epoch   3 Batch 1974/3125   Loss: 0.737366 mae: 0.674866 (96.14053746779503 steps/sec)
Step #30150	Epoch   3 Batch 2024/3125   Loss: 0.855838 mae: 0.684689 (93.99531357288971 steps/sec)
Step #30200	Epoch   3 Batch 2074/3125   Loss: 0.774386 mae: 0.675527 (96.28850113040109 steps/sec)
Step #30250	Epoch   3 Batch 2124/3125   Loss: 0.626055 mae: 0.677924 (95.61227541634145 steps/sec)
Step #30300	Epoch   3 Batch 2174/3125   Loss: 0.723549 mae: 0.672728 (97.72176152958653 steps/sec)
Step #30350	Epoch   3 Batch 2224/3125   Loss: 0.681627 mae: 0.678353 (95.19955731101851 steps/sec)
Step #30400	Epoch   3 Batch 2274/3125   Loss: 0.736302 mae: 0.677233 (96.37434468357316 steps/sec)
Step #30450	Epoch   3 Batch 2324/3125   Loss: 0.584631 mae: 0.686699 (94.81027113681799 steps/sec)
Step #30500	Epoch   3 Batch 2374/3125   Loss: 0.698571 mae: 0.677499 (95.78105225466504 steps/sec)
Step #30550	Epoch   3 Batch 2424/3125   Loss: 0.706093 mae: 0.677204 (95.26126586096406 steps/sec)
Step #30600	Epoch   3 Batch 2474/3125   Loss: 0.777790 mae: 0.673271 (95.12079737835785 steps/sec)
Step #30650	Epoch   3 Batch 2524/3125   Loss: 0.703747 mae: 0.681530 (95.3811056311252 steps/sec)
Step #30700	Epoch   3 Batch 2574/3125   Loss: 0.807804 mae: 0.685983 (97.28015675025257 steps/sec)
Step #30750	Epoch   3 Batch 2624/3125   Loss: 0.912028 mae: 0.681242 (92.45042886924612 steps/sec)
Step #30800	Epoch   3 Batch 2674/3125   Loss: 0.733961 mae: 0.680752 (95.10548370127161 steps/sec)
Step #30850	Epoch   3 Batch 2724/3125   Loss: 0.720733 mae: 0.672703 (94.2092254559405 steps/sec)
Step #30900	Epoch   3 Batch 2774/3125   Loss: 0.668025 mae: 0.678066 (96.03896600503653 steps/sec)
Step #30950	Epoch   3 Batch 2824/3125   Loss: 0.771790 mae: 0.687630 (94.54270703442332 steps/sec)
Step #31000	Epoch   3 Batch 2874/3125   Loss: 0.795335 mae: 0.669771 (95.89514395117887 steps/sec)
Step #31050	Epoch   3 Batch 2924/3125   Loss: 0.768766 mae: 0.678650 (95.54924074157603 steps/sec)
Step #31100	Epoch   3 Batch 2974/3125   Loss: 0.657581 mae: 0.679598 (86.63522356836064 steps/sec)
Step #31150	Epoch   3 Batch 3024/3125   Loss: 0.710757 mae: 0.669819 (81.81546157234253 steps/sec)
Step #31200	Epoch   3 Batch 3074/3125   Loss: 0.752866 mae: 0.671728 (85.46792026832618 steps/sec)
Step #31250	Epoch   3 Batch 3124/3125   Loss: 0.789243 mae: 0.671955 (84.97295203488784 steps/sec)

Train time for epoch #4 (31250 total steps): 32.9474937915802
Model test set loss: 0.774264 mae: 0.693687
best loss = 0.7742644548416138
Step #31300	Epoch   4 Batch   49/3125   Loss: 0.849005 mae: 0.692671 (86.63508040945638 steps/sec)
Step #31350	Epoch   4 Batch   99/3125   Loss: 0.887145 mae: 0.667644 (93.65070150321479 steps/sec)
Step #31400	Epoch   4 Batch  149/3125   Loss: 0.715392 mae: 0.678084 (88.70357093762226 steps/sec)
Step #31450	Epoch   4 Batch  199/3125   Loss: 0.755828 mae: 0.678409 (93.64146002219191 steps/sec)
Step #31500	Epoch   4 Batch  249/3125   Loss: 0.835472 mae: 0.677886 (94.04458834371097 steps/sec)
Step #31550	Epoch   4 Batch  299/3125   Loss: 0.707785 mae: 0.678733 (94.06112318871456 steps/sec)
Step #31600	Epoch   4 Batch  349/3125   Loss: 0.784751 mae: 0.680859 (93.25856586992774 steps/sec)
Step #31650	Epoch   4 Batch  399/3125   Loss: 0.846286 mae: 0.681717 (97.06237506496969 steps/sec)
Step #31700	Epoch   4 Batch  449/3125   Loss: 0.738571 mae: 0.684823 (95.92308413587432 steps/sec)
Step #31750	Epoch   4 Batch  499/3125   Loss: 0.726846 mae: 0.673212 (92.13661943304719 steps/sec)
Step #31800	Epoch   4 Batch  549/3125   Loss: 0.719152 mae: 0.671284 (94.35966288550462 steps/sec)
Step #31850	Epoch   4 Batch  599/3125   Loss: 0.642589 mae: 0.682743 (94.95674506256186 steps/sec)
Step #31900	Epoch   4 Batch  649/3125   Loss: 0.702127 mae: 0.679642 (91.53791760875069 steps/sec)
Step #31950	Epoch   4 Batch  699/3125   Loss: 0.724501 mae: 0.679958 (94.65625839240458 steps/sec)
Step #32000	Epoch   4 Batch  749/3125   Loss: 0.717045 mae: 0.669120 (93.81786427502881 steps/sec)
Step #32050	Epoch   4 Batch  799/3125   Loss: 0.745565 mae: 0.679389 (91.53775778865695 steps/sec)
Step #32100	Epoch   4 Batch  849/3125   Loss: 0.828537 mae: 0.678774 (89.95494428945463 steps/sec)
Step #32150	Epoch   4 Batch  899/3125   Loss: 0.828524 mae: 0.676391 (85.42294122007868 steps/sec)
Step #32200	Epoch   4 Batch  949/3125   Loss: 0.674728 mae: 0.677796 (82.50033831735112 steps/sec)
Step #32250	Epoch   4 Batch  999/3125   Loss: 0.814002 mae: 0.672747 (87.36775492808826 steps/sec)
Step #32300	Epoch   4 Batch 1049/3125   Loss: 0.822413 mae: 0.683690 (92.12876708838405 steps/sec)
Step #32350	Epoch   4 Batch 1099/3125   Loss: 0.714512 mae: 0.676341 (92.99031543026298 steps/sec)
Step #32400	Epoch   4 Batch 1149/3125   Loss: 0.665886 mae: 0.684505 (92.53727918640166 steps/sec)
Step #32450	Epoch   4 Batch 1199/3125   Loss: 0.769309 mae: 0.671976 (91.53392227382241 steps/sec)
Step #32500	Epoch   4 Batch 1249/3125   Loss: 0.829105 mae: 0.680787 (91.2518171806407 steps/sec)
Step #32550	Epoch   4 Batch 1299/3125   Loss: 0.703187 mae: 0.684143 (89.1962161769028 steps/sec)
Step #32600	Epoch   4 Batch 1349/3125   Loss: 0.762131 mae: 0.663012 (90.23563692190127 steps/sec)
Step #32650	Epoch   4 Batch 1399/3125   Loss: 0.782941 mae: 0.680012 (92.17347046860901 steps/sec)
Step #32700	Epoch   4 Batch 1449/3125   Loss: 0.717813 mae: 0.676620 (90.84884445786405 steps/sec)
Step #32750	Epoch   4 Batch 1499/3125   Loss: 0.771077 mae: 0.677188 (91.24991134562761 steps/sec)
Step #32800	Epoch   4 Batch 1549/3125   Loss: 0.822044 mae: 0.674737 (90.50785164520731 steps/sec)
Step #32850	Epoch   4 Batch 1599/3125   Loss: 0.730982 mae: 0.672091 (86.22594164279556 steps/sec)
Step #32900	Epoch   4 Batch 1649/3125   Loss: 0.787307 mae: 0.678850 (89.30420163486811 steps/sec)
Step #32950	Epoch   4 Batch 1699/3125   Loss: 0.769659 mae: 0.672791 (80.95036639255419 steps/sec)
Step #33000	Epoch   4 Batch 1749/3125   Loss: 0.754821 mae: 0.674748 (83.31689231843737 steps/sec)
Step #33050	Epoch   4 Batch 1799/3125   Loss: 0.808317 mae: 0.675786 (81.94253419690415 steps/sec)
Step #33100	Epoch   4 Batch 1849/3125   Loss: 0.736969 mae: 0.676992 (88.07533023755097 steps/sec)
Step #33150	Epoch   4 Batch 1899/3125   Loss: 0.830447 mae: 0.676006 (90.29686872983861 steps/sec)
Step #33200	Epoch   4 Batch 1949/3125   Loss: 0.698865 mae: 0.670767 (90.06763816993418 steps/sec)
Step #33250	Epoch   4 Batch 1999/3125   Loss: 0.810068 mae: 0.675959 (89.52894623486988 steps/sec)
Step #33300	Epoch   4 Batch 2049/3125   Loss: 0.690710 mae: 0.684732 (91.52852912486824 steps/sec)
Step #33350	Epoch   4 Batch 2099/3125   Loss: 0.761189 mae: 0.667424 (89.95930462250931 steps/sec)
Step #33400	Epoch   4 Batch 2149/3125   Loss: 0.703904 mae: 0.666731 (92.74853656336074 steps/sec)
Step #33450	Epoch   4 Batch 2199/3125   Loss: 0.654756 mae: 0.673259 (90.60009029111323 steps/sec)
Step #33500	Epoch   4 Batch 2249/3125   Loss: 0.700377 mae: 0.670951 (88.25873548749843 steps/sec)
Step #33550	Epoch   4 Batch 2299/3125   Loss: 0.786276 mae: 0.683020 (90.4601443461547 steps/sec)
Step #33600	Epoch   4 Batch 2349/3125   Loss: 0.714943 mae: 0.675117 (93.2993914847008 steps/sec)
Step #33650	Epoch   4 Batch 2399/3125   Loss: 0.673051 mae: 0.675196 (91.91455940309393 steps/sec)
Step #33700	Epoch   4 Batch 2449/3125   Loss: 0.709089 mae: 0.667099 (92.24308183044161 steps/sec)
Step #33750	Epoch   4 Batch 2499/3125   Loss: 0.864663 mae: 0.676928 (92.42276405565941 steps/sec)
Step #33800	Epoch   4 Batch 2549/3125   Loss: 0.557530 mae: 0.679273 (92.74340948178455 steps/sec)
Step #33850	Epoch   4 Batch 2599/3125   Loss: 0.870227 mae: 0.675846 (90.21265759185366 steps/sec)
Step #33900	Epoch   4 Batch 2649/3125   Loss: 0.823046 mae: 0.675030 (93.99535570203884 steps/sec)
Step #33950	Epoch   4 Batch 2699/3125   Loss: 0.734765 mae: 0.674813 (88.93148319499136 steps/sec)
Step #34000	Epoch   4 Batch 2749/3125   Loss: 0.804615 mae: 0.669130 (95.49102827322206 steps/sec)
Step #34050	Epoch   4 Batch 2799/3125   Loss: 0.764164 mae: 0.678259 (90.9379151966753 steps/sec)
Step #34100	Epoch   4 Batch 2849/3125   Loss: 0.777574 mae: 0.673345 (90.35281141887147 steps/sec)
Step #34150	Epoch   4 Batch 2899/3125   Loss: 0.807234 mae: 0.671131 (94.95287563659545 steps/sec)
Step #34200	Epoch   4 Batch 2949/3125   Loss: 0.789137 mae: 0.675352 (96.48173144782037 steps/sec)
Step #34250	Epoch   4 Batch 2999/3125   Loss: 0.685636 mae: 0.670751 (97.09055016768549 steps/sec)
Step #34300	Epoch   4 Batch 3049/3125   Loss: 0.707665 mae: 0.663872 (97.26644064023301 steps/sec)
Step #34350	Epoch   4 Batch 3099/3125   Loss: 0.765113 mae: 0.668804 (95.97462096891188 steps/sec)

Train time for epoch #5 (34375 total steps): 34.385642290115356
Model test set loss: 0.769376 mae: 0.690253
best loss = 0.769376277923584
INFO:tensorflow:Assets written to: ./models/export/assets

将用户特征和电影特征做矩阵乘法得到一个预测评分的训练

显示训练Loss

%matplotlib inline
%config InlineBackend.figure_format = 'retina'
import matplotlib.pyplot as plt

plt.plot(mv_net.losses['train'], label='Training loss')
plt.legend()
_ = plt.ylim()

在这里插入图片描述

显示测试Loss

迭代次数再增加一些,下降的趋势会明显一些

plt.plot(mv_net.losses['test'], label='Test loss')
plt.legend()
_ = plt.ylim()

在这里插入图片描述## 指定用户和电影进行评分

这部分就是对网络做正向传播,计算得到预测的评分

def rating_movie(mv_net, user_id_val, movie_id_val):
    categories = np.zeros([1, 18])
    categories[0] = movies.values[movieid2idx[movie_id_val]][2]
    
    titles = np.zeros([1, sentences_size])
    titles[0] = movies.values[movieid2idx[movie_id_val]][1]
    
    inference_val = mv_net.model([np.reshape(users.values[user_id_val-1][0], [1, 1]),
              np.reshape(users.values[user_id_val-1][1], [1, 1]),
              np.reshape(users.values[user_id_val-1][2], [1, 1]),
              np.reshape(users.values[user_id_val-1][3], [1, 1]),
              np.reshape(movies.values[movieid2idx[movie_id_val]][0], [1, 1]),
              categories,  
              titles])

    return (inference_val.numpy())
rating_movie(mv_net, 234, 1401)
array([[4.4249763]], dtype=float32)

生成Movie特征矩阵

将训练好的电影特征组合成电影特征矩阵并保存到本地

movie_layer_model = keras.models.Model(inputs=[mv_net.model.input[4], mv_net.model.input[5], mv_net.model.input[6]], 
                                 outputs=mv_net.model.get_layer("movie_combine_layer_flat").output)
movie_matrics = []

for item in movies.values:
    categories = np.zeros([1, 18])
    categories[0] = item.take(2)

    titles = np.zeros([1, sentences_size])
    titles[0] = item.take(1)

    movie_combine_layer_flat_val = movie_layer_model([np.reshape(item.take(0), [1, 1]), categories, titles])  
    movie_matrics.append(movie_combine_layer_flat_val)

pickle.dump((np.array(movie_matrics).reshape(-1, 200)), open('movie_matrics.p', 'wb'))
movie_matrics = pickle.load(open('movie_matrics.p', mode='rb'))
movie_matrics = pickle.load(open('movie_matrics.p', mode='rb'))

生成User特征矩阵

将训练好的用户特征组合成用户特征矩阵并保存到本地

user_layer_model = keras.models.Model(inputs=[mv_net.model.input[0], mv_net.model.input[1], mv_net.model.input[2], mv_net.model.input[3]], 
                                 outputs=mv_net.model.get_layer("user_combine_layer_flat").output)
users_matrics = []

for item in users.values:

    user_combine_layer_flat_val = user_layer_model([np.reshape(item.take(0), [1, 1]), 
                                                    np.reshape(item.take(1), [1, 1]), 
                                                    np.reshape(item.take(2), [1, 1]), 
                                                    np.reshape(item.take(3), [1, 1])])  
    users_matrics.append(user_combine_layer_flat_val)

pickle.dump((np.array(users_matrics).reshape(-1, 200)), open('users_matrics.p', 'wb'))
users_matrics = pickle.load(open('users_matrics.p', mode='rb'))
users_matrics = pickle.load(open('users_matrics.p', mode='rb'))

开始推荐电影

使用生产的用户特征矩阵和电影特征矩阵做电影推荐

推荐同类型的电影

思路是计算当前看的电影特征向量与整个电影特征矩阵的余弦相似度,取相似度最大的top_k个,这里加了些随机选择在里面,保证每次的推荐稍稍有些不同。

def recommend_same_type_movie(movie_id_val, top_k = 20):
   
    norm_movie_matrics = tf.sqrt(tf.reduce_sum(tf.square(movie_matrics), 1, keepdims=True))
    normalized_movie_matrics = movie_matrics / norm_movie_matrics

    #推荐同类型的电影
    probs_embeddings = (movie_matrics[movieid2idx[movie_id_val]]).reshape([1, 200])
    probs_similarity = tf.matmul(probs_embeddings, tf.transpose(normalized_movie_matrics))
    sim = (probs_similarity.numpy())
    #     results = (-sim[0]).argsort()[0:top_k]
    #     print(results)
        
    print("您看的电影是:{}".format(movies_orig[movieid2idx[movie_id_val]]))
    print("以下是给您的推荐:")
    p = np.squeeze(sim)
    p[np.argsort(p)[:-top_k]] = 0
    p = p / np.sum(p)
    results = set()
    while len(results) != 5:
        c = np.random.choice(3883, 1, p=p)[0]
        results.add(c)
    for val in (results):
        print(val)
        print(movies_orig[val])
        
    return results
recommend_same_type_movie(1401, 20)
您看的电影是:[1401 'Ghosts of Mississippi (1996)' 'Drama']
以下是给您的推荐:
3040
[3109 'River, The (1984)' 'Drama']
1383
[1406 'C�r�monie, La (1995)' 'Drama']
1611
[1657 'Wonderland (1997)' 'Documentary']
2482
[2551 'Dead Ringers (1988)' 'Drama|Thriller']
3572
[3641 'Woman of Paris, A (1923)' 'Drama']





{1383, 1611, 2482, 3040, 3572}

推荐您喜欢的电影

思路是使用用户特征向量与电影特征矩阵计算所有电影的评分,取评分最高的top_k个,同样加了些随机选择部分。

def recommend_your_favorite_movie(user_id_val, top_k = 10):

    #推荐您喜欢的电影
    probs_embeddings = (users_matrics[user_id_val-1]).reshape([1, 200])

    probs_similarity = tf.matmul(probs_embeddings, tf.transpose(movie_matrics))
    sim = (probs_similarity.numpy())
    #     print(sim.shape)
    #     results = (-sim[0]).argsort()[0:top_k]
    #     print(results)
        
    #     sim_norm = probs_norm_similarity.eval()
    #     print((-sim_norm[0]).argsort()[0:top_k])
    
    print("以下是给您的推荐:")
    p = np.squeeze(sim)
    p[np.argsort(p)[:-top_k]] = 0
    p = p / np.sum(p)
    results = set()
    while len(results) != 5:
        c = np.random.choice(3883, 1, p=p)[0]
        results.add(c)
    for val in (results):
        print(val)
        print(movies_orig[val])

    return results
recommend_your_favorite_movie(234, 10)
以下是给您的推荐:
2434
[2503 'Apple, The (Sib) (1998)' 'Drama']
3366
[3435 'Double Indemnity (1944)' 'Crime|Film-Noir']
1194
[1212 'Third Man, The (1949)' 'Mystery|Thriller']
589
[593 'Silence of the Lambs, The (1991)' 'Drama|Thriller']
942
[954 'Mr. Smith Goes to Washington (1939)' 'Drama']





{589, 942, 1194, 2434, 3366}

看过这个电影的人还看了(喜欢)哪些电影

  • 首先选出喜欢某个电影的top_k个人,得到这几个人的用户特征向量。
  • 然后计算这几个人对所有电影的评分
  • 选择每个人评分最高的电影作为推荐
  • 同样加入了随机选择
import random

def recommend_other_favorite_movie(movie_id_val, top_k = 20):

    probs_movie_embeddings = (movie_matrics[movieid2idx[movie_id_val]]).reshape([1, 200])
    probs_user_favorite_similarity = tf.matmul(probs_movie_embeddings, tf.transpose(users_matrics))
    favorite_user_id = np.argsort(probs_user_favorite_similarity.numpy())[0][-top_k:]
    #     print(normalized_users_matrics.numpy().shape)
    #     print(probs_user_favorite_similarity.numpy()[0][favorite_user_id])
    #     print(favorite_user_id.shape)
    
    print("您看的电影是:{}".format(movies_orig[movieid2idx[movie_id_val]]))
        
    print("喜欢看这个电影的人是:{}".format(users_orig[favorite_user_id-1]))
    probs_users_embeddings = (users_matrics[favorite_user_id-1]).reshape([-1, 200])
    probs_similarity = tf.matmul(probs_users_embeddings, tf.transpose(movie_matrics))
    sim = (probs_similarity.numpy())
    #     results = (-sim[0]).argsort()[0:top_k]
    #     print(results)
    
    #     print(sim.shape)
    #     print(np.argmax(sim, 1))
    p = np.argmax(sim, 1)
    print("喜欢看这个电影的人还喜欢看:")

    if len(set(p)) < 5:
        results = set(p)
    else:
        results = set()
        while len(results) != 5:
            c = p[random.randrange(top_k)]
            results.add(c)
    for val in (results):
        print(val)
        print(movies_orig[val])
        
    return results
recommend_other_favorite_movie(1401, 20)
您看的电影是:[1401 'Ghosts of Mississippi (1996)' 'Drama']
喜欢看这个电影的人是:[[209 'M' 35 1]
 [1110 'F' 56 6]
 [2921 'M' 50 1]
 [287 'M' 50 13]
 [74 'M' 35 14]
 [64 'M' 18 1]
 [5728 'F' 35 20]
 [4253 'M' 45 11]
 [5099 'M' 18 0]
 [978 'M' 18 0]
 [5996 'F' 25 0]
 [4504 'F' 25 0]
 [2338 'M' 45 17]
 [277 'F' 35 1]
 [4506 'M' 50 16]
 [1636 'F' 25 19]
 [2496 'M' 50 1]
 [1985 'M' 45 12]
 [1855 'M' 18 4]
 [2154 'M' 25 12]]
喜欢看这个电影的人还喜欢看:
2434
[2503 'Apple, The (Sib) (1998)' 'Drama']
589
[593 'Silence of the Lambs, The (1991)' 'Drama|Thriller']





{589, 2434}

这个结果里面20个人最喜欢这两个电影,所以只输出了两个结果

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值