【Pytorch基础教程26】wide&deep推荐算法(tf2.0和torch版)

总结

一、tensorflow2.0的安装

学术界主流是pytorch,但在工业界中为了模型部署便捷,也会使用tensorflow2,TensorFlow 2.0 提供比1.0更简化的 API、注重 Keras、结合了 Eager execution。

下载过程参考官网:https://www.tensorflow.org/install/pip

张量的操作:

  • Tensorflow 和 PyTorch 张量初始化可以直接分别调用: tf.constent 方法,调用 torch.tensor 方法,填入张量数值即可。
  • 也可以: tf.Variable 创建的是Variable对象 ,不是Tensor对象,前者可以跟踪求梯度,后者 torch.Tensor 不能直接求梯度。
  • torch.tensor和 torch.Tensor 均创建的是 Tensor 对象,但前者输入具体数值,后者输入 Tensor shape(size),数值不可控,不推荐。

2.加载数据集

  • tensorflow用 tf.keras.datasets.mnist.load_data() 加载数据, numpy.ndarray 格式;pytorch使用 torchvison.datasets.MNIST 加载的数据集,数据格式为image(无法直接使用,需要设置 transform = transforms.ToTensor() 转换成tensor张量数据), transform.Compose() 还能通过 list 传参进行图片转换、正则化等操作。
  • tensorflow通过 tf.data.Dataset.from_tensor_slices() 构建数据集对象,通过 .map 自定义 preprocess 函数对数据预处理;而pytorch使用 torch.utils.data.DataLoader 构建数据集对象。处理后Tensorflow 中 image shape: [b, 28, 28], label shape: [b]。
  • PyTorch 的 DataLoader 可以设置训练数据的 Train = False 避免在测试数据库中对数据进行训练,而 Tensorflow 就只能在搭建网络的时候才能声明。
  • 如果tensorflow加载本地的数据集:train_dataset = get_dataset(路径),如果是从一个URL下载文件,可以用如下的 tf.keras.utils.get_file 。默认情况下,URL origin处的文件 被下载到缓存目录〜/.keras中, 放在缓存子目录 datasets 中,并命名为 fname。 文件 example.txt 的最终位置为 ~/.keras/datasets/example.txt 。
tf.keras.utils.get_file(fname, origin, untar=False, md5_hash=None, file_hash=None, cache_subdir='datasets', hash_algorithm='auto', extract=False, archive_format='auto', cache_dir=None)

3.模型的构建

3.1 继承的父对象

  • Tensorflow 继承 tf.keras.Model对象,PyTorch 继承 torch.nn.Module对象.
  • Tensorflow 模型对象中,前向传播调用 call() 函数,PyTorch 调用 forward() 函数.

3.2 处理的图片维度不同

tensorflow和pytorch存储图片的维度顺序不同:

  • Tensorflow 是bhwc,即[ batch_size , height , width , channel ];一个 filter 有四个维度 [input_channel, output_channel, (kernel__h, kernel_w)] ,其中 input_channel 如果是一张彩色图片则为值为3。
  • PyTorch 为bchw, [ batch_size , channel , height , width ];

3.3 keras.layers.Conv2D()和nn.Conv2d()区别

  • keras.layers.Conv2D()无需设置 input_channel 大小,然而 nn.Conv2d() input 和 output channel需要手动设置, input_channel 需等于上一层的 output_channel
  • keras.layers.Conv2D()中的 filters 参数相当于 nn.Conv2d() 的 output_channel 参数。另外注意 padding 为 valid 时表示不进行padding,而
    如果为 same 则表示边缘用0填充,使得输出的形状为height =width = P/strides。
  • keras.layers.Conv2D()中 kernel_size 和 strides 参数接收的是元组, nn.Conv2d() 中的 kernel_size 和 stride 参数接收的是 int 。
  • keras.layers.Conv2D()的 padding 参数只能选择 ‘ valid ’ 或 ‘ same ’ , 即没有padding, 或保证输出的图片尺寸不变(stride = 1的情况下)。 nn.Conv2d() 则需要手动设置 padding 的多少。
class CNN_model(keras.Model):
    def __init__(self):
        super().__init__()
    
        self.model = keras.Sequential(
        	# input=[b, 28, 28, 1]
            [layers.Conv2D(filters=3, kernel_size=(3,3), strides=(1,1),padding="same"),
            # conv后[b, 28, 28, 3]
            layers.MaxPool2D(pool_size=(2,2)),
            # pool后[b, 14, 14, 3]
            layers.ReLU(),
            layers.Conv2D(6,(3,3),(2,2),"same"),
            # conv后[b, 7, 7, 6]
            layers.ReLU(),
            layers.Flatten(),
            # 7*7*6->10
            layers.Dense(10)]
            )
    
    def call(self,x):
        x = self.model(x)
        
        return x
    
model = CNN_model()
model.build(input_shape = (None,28,28,1))
model.summary()
optimizer = tf.optimizers.Adam(learning_rate)
  • 具有【局部相关性】和【权重共享】的CNN能高效处理图片,滤波器filter将局部像素的“轮廓”过滤出来,filter的w是固定的,即共享了权重。
  • pytorch需要创建 device = torch.device(‘cuda:0’) 并将网络和参数搬到这个 device 上进行计算;但是tensorflow如果使用的是tensorflow-gpu版,则直接使用的GPU计算。

4. 模型训练和测试

accuracy的计算过程:

  • 将所有验证数据带入训练好的模型中,并给出预测值。
  • 将预测值与实际值进行比较。
  • 累积正确预测的样本数和样本总数。
  • 使用[正确率=正确预测样本数/所有样本数]计算正确率

自动求导的接口:tf.GradientTape()是一个自动求导的记录器,在其中的变量和计算步骤都会被自动记录。变量 x 和计算步骤y = tf.square(x)被自动记录,因此可以通过y_grad = tape.gradient(y, x)求张量y 对参数x的导数。

for epoch in range(epochs):
    
    for step, (x, y) in enumerate(ds_train):
        x = tf.reshape(x, [-1, 28,28,1])
        with tf.GradientTape() as tape:            
            logits = model(x)
            
            losses = tf.losses.sparse_categorical_crossentropy(y,logits,from_logits=True)
            loss = tf.reduce_mean(losses)
            
        grads = tape.gradient(loss, model.variables)
        
        optimizer.apply_gradients(zip(grads, model.variables))
        
        if(step%100==0):
            print("epoch:{}, step:{} loss:{}".
                  format(epoch, step, loss.numpy()))
            
            
#             test accuracy: 
            total_correct = 0
            total_num = 0
            
            for x_test, y_test in ds_test:
                x_test = tf.reshape(x_test, [-1, 28,28,1])
                y_pred = tf.argmax(model(x_test),axis=1)
                y_pred = tf.cast(y_pred, tf.int32)
                correct = tf.cast((y_pred == y_test), tf.int32)
                correct = tf.reduce_sum(correct)
                
                total_correct += int(correct)
                total_num += x_test.shape[0]
        
            
            accuracy = total_correct/total_num
            print('accuracy: ', accuracy)

为了与 PyTorch 中torch.nn.CrossEntropyLoss()求交叉熵的方法一致,Tensorflow 中并未对label 进行 One-Hot 编码,所以使用了tf.losses.sparse_categorical_crossentropy()方法计算交叉熵。结果为:

Model: "cnn_model_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
sequential_2 (Sequential)    multiple                  3148      
=================================================================
Total params: 3,148
Trainable params: 3,148
Non-trainable params: 0
_________________________________________________________________
epoch:0, step:0 loss:2.328885078430176
accuracy:  0.1409
epoch:0, step:100 loss:0.14413821697235107
accuracy:  0.8648
.......

五、模型构建对比

小结:为了方便比较和训练,我们用最简单的MINST数据集,比较两个框架的模型训练过程。可以看到TensorFlow 2.0 提供比1.0更简化的 API、注重 Keras、结合了 Eager execution。下面进一步使用tensorflow复现wide&deep模型。

六、经典wide&deep模型(tf2.0版)

6.0 模型提出的背景

Wide&Deep 模型是由 Google 的应用商店团队 Google Play 提出的,在 Google Play 为用户推荐 APP 这样的应用场景下。Wide&Deep 模型的推荐目标:尽量推荐那些用户可能喜欢,愿意安装的应用。

问题:具体到 Wide&Deep 模型中,Google Play 团队是如何为 Wide 部分和 Deep 部分挑选特征的。
【Pytorch基础教程26】wide&deep推荐算法(tf2.0和torch版)

图: Google Play Wide&Deep模型的细节 (出自Wide & Deep Learning for Recommender Systems )

上图补充google play团队这个模型的细节:从左边的wide的特征开始看起,只利用两个特征(“已安装应用”特征和“曝光应用”特征)的交叉,就是说wide想学的东西是希望记住“因为A所以B”的规则——如果安装了应用A,是否会安装B这样的规则。

6.1 Retrieval和Ranking

【Pytorch基础教程26】wide&deep推荐算法(tf2.0和torch版)
当一个用户访问app商店时,此时会产生一个请求,请求到达推荐系统后,推荐系统为该用户返回推荐的apps列表。
在实际的推荐系统中,通常将推荐的过程分为两个部分,即上图中的Retrieval和Ranking,Retrieval负责从数据库中检索出与用户相关的一些apps,Ranking负责对这些检索出的apps打分,最终,按照分数的高低返回相应的列表给用户。

其中在ranking中使用更细致的用户特征,如:

  • User features(年龄、性别、语言、民族等)
  • Contextual features(上下文特征:设备,时间等)
  • Impression features(展示特征:app age、app的历史统计信息等)

与一般的推荐系统不同的是,Google Pay是通过检索来实现推荐的召回,将大规模的App应用缩小到小规模(例如100)的相关应用。然后在通过用户特征、上下文特征、用户行为特征等来建立推荐模型,估计用户点击每个App的概率分数,按照分数进行排序,推荐Top K个App。

wide&deep模型最后是将wide部分和deep部分的输出进行加权求和(使用一个逻辑回归),通过sigmoid后输出概率值:
P%28Y%3D1%20%5Cmid%20%5Cmathbf%7Bx%7D%29%3D%5Csigma%5Cleft%28%5Cmathbf%7Bw%7D_%7B%5Ctext%20%7Bwide%20%7D%7D%5E%7BT%7D%5B%5Cmathbf%7Bx%7D%2C%20%5Cphi%28%5Cmathbf%7Bx%7D%29%5D%2B%5Cmathbf%7Bw%7D_%7B%5Ctext%20%7Bdeep%20%7D%7D%5E%7BT%7D%20a%5E%7B%5Cleft%28l_%7Bf%7D%5Cright%29%7D%2Bb%5Cright%29

  • 其中Y是二值分类标签;%5Csigma%28%5Ccdot%29%5Coperatorname%7Bsigmoid%7D函数,%5Cmathbf%7Bw%7D_%7B%5Ctext%20%7Bwide%20%7D%7D%2C%20%5Cmathbf%7Bw%7D_%7B%5Ctext%20%7Bdee%20%7D%7D分别是Wide部分和Deep部分的权重。
  • wide和deep使用的梯度下降方式不同,前者使用L1正则(有特征选择的作用),后者用普通的梯度下降方式(L2正则)。
  • wide&deep只是一种架构,可根据具体业务改,如某些特征不适合wide和deep,而是使用FM时,则将经过FM的特征和wide deep段的output进行拼接。
  • wide和deep模型的联合训练是通过使用小批量随机优化同时将输出的梯度反向传播到模型的wide和deep部分来完成的。 在实验中,我们使用带L1正则的FTRL算法作为wide部分的优化器,AdaGrad作为deep部分的优化器。

6.2 训练的方法:

  • Wide模型:FTRL(Follow-the-regularized-leader)
  • Deep模型:AdaGrad

6.3 区别联合训练和集成学习的差别:

  • 集成学习是多个模型的独立训练,最后融合结果;
  • 联合训练会将wide和deep模型组合在一起,在训练时同时优化所有参数,并且进行加权求和,根据最终的loss计算出gradient,反向传播到Wide和Deep两部分中,分别训练自己的参数。也就是说,
    wide & deep 模型的权重更新会受到 wide 侧和 deep 侧对模型训练误差的共同影响
    。在论文中,wide部分是使用L1正则化的Follow-the-regularized-leader(FTRL)算法进行优化,deep部分使用的是AdaGrad完成优化。

6.4 代码部分

(0)了解我们的movielen数据集

数据来源:https://grouplens.org/datasets/movielens/
(1)movies.csv(电影基本信息数据)
movies 表是电影的基本信息表,它包含了电影 ID(movieId)、电影名(title)、发布年份以及电影类型(genres)等基本信息。
MovieLens 20M Dataset 包含了 2016 年前的约 13 万部电影,课程的实验数据集从中抽取了前 1000 部电影。电影数据集是我们推荐的主体,其中分类、发布年份、电影名称等信息也将是推荐模型可以利用的重要特征。
【Pytorch基础教程26】wide&deep推荐算法(tf2.0和torch版)

(2)ratings.csv(用户评分数据)
ratings 表包含了用户 ID(userId)、电影 ID(movieId)、评分(rating)和时间戳(timestamp)等信息。
MovieLens 20M Dataset 包含了 2000 万条评分数据,课程的实验数据集从中抽取了约 104 万条评论数据。评论数据集是之后推荐模型训练所需的训练样本来源,也是我们分析用户行为序列、电影统计型特征的原始数据。
【Pytorch基础教程26】wide&deep推荐算法(tf2.0和torch版)
(3)links.csv(外部链接数据)
links 表包含了电影 ID(movieId)、IMDB 对应电影 ID(imdbId)、TMDB 对应电影 ID(tmdbId)等信息。其中,imdb 和 tmdb 是全球最大的两个电影数据库。因为 links 表包含了 MovieLens 电影和这两个数据库 ID 之间的对应关系,所以,我们可以根据这个对应关系来抓取电影的其他相关信息,这也为我们大量拓展推荐系统特征提供了可能。
【Pytorch基础教程26】wide&deep推荐算法(tf2.0和torch版)

(1)导入数据集

通过get_dataset导入movielen数据集。

import tensorflow as tf

# load sample as tf dataset
def get_dataset(file_path):
    dataset = tf.data.experimental.make_csv_dataset(
        file_path,
        batch_size=12,
        label_name='label',
        na_value="0",
        num_epochs=1,
        ignore_errors=True)
    return dataset


# split as test dataset and training dataset
train_dataset = get_dataset('D:/wide&deep/trainingSamples.csv')
test_dataset = get_dataset('D:/wide&deep/testSamples.csv')

(2)特征处理

从广义上讲,所有功能都可以分为两大类:

1)类别型特征:利用 One-hot 编码处理

  • 第一类是类别、ID 型特征(以下简称类别型特征)。
    拿电影推荐来说,电影的风格、ID、标签、导演演员等信息,用户看过的电影 ID、用户的性别、地理位置信息、当前的季节、时间(上午,下午,晚上)、天气等等,这些无法用数字表示的信息全都可以被看作是类别、ID 类特征。——利用one hot编码。
# genre features vocabulary
genre_vocab = ['Film-Noir', 'Action', 'Adventure', 'Horror', 'Romance', 'War', 'Comedy', 'Western', 'Documentary',
               'Sci-Fi', 'Drama', 'Thriller',
               'Crime', 'Fantasy', 'Animation', 'IMAX', 'Mystery', 'Children', 'Musical']

GENRE_FEATURES = {
    'userGenre1': genre_vocab,
    'userGenre2': genre_vocab,
    'userGenre3': genre_vocab,
    'userGenre4': genre_vocab,
    'userGenre5': genre_vocab,
    'movieGenre1': genre_vocab,
    'movieGenre2': genre_vocab,
    'movieGenre3': genre_vocab
}

# all categorical features

# genre类别型特征转为one-hot特征,此处用到词表
categorical_columns = []
for feature, vocab in GENRE_FEATURES.items():
    cat_col = tf.feature_column.categorical_column_with_vocabulary_list(
        key=feature, vocabulary_list=vocab)
    emb_col = tf.feature_column.embedding_column(cat_col, 10)
    categorical_columns.append(emb_col)
    
# 用户id和电影id转为one-hot特征,此处不用词表
# movie id embedding feature
movie_col = tf.feature_column.categorical_column_with_identity(key='movieId', num_buckets=1001)
movie_emb_col = tf.feature_column.embedding_column(movie_col, 10)
categorical_columns.append(movie_emb_col)

# user id embedding feature
user_col = tf.feature_column.categorical_column_with_identity(key='userId', num_buckets=30001)
# 为了将得到的one-hot转为稠密向量,所以要加一层embedding
user_emb_col = tf.feature_column.embedding_column(user_col, 10)
categorical_columns.append(user_emb_col)

2)数值型特征:归一化和分桶

  • 第二类是数值特征。可以直接用数字表示的特征是数值特征。如:用户年龄、收入、电影播放时长、点击次数、点击率等——为了解决特征规模差异较大(使用归一化);解决特征分布不均匀的问题(使用bucketing策略)
  • 在经典的 YouTube 深度推荐模型中,可以看到一些很有意思的处理方法。比如,在处理观看时间间隔(time since last watch)和视频曝光量(previous impressions)这两个特征时,YouTube 模型对它们进行归一化后,又将它们各自处理成了三个特征(图 6 中红框内的部分),分别是原特征值 x,特征值的平方x^2,以及特征值的开方。

分桶(Bucketing):将样本按照某特征的值从高到低排序,然后按照桶的数量找到分位数,将样本分到各自的桶中,再用桶 ID 作为特征值。

【Pytorch基础教程26】wide&deep推荐算法(tf2.0和torch版)
无论是平方还是平方根运算,都会改变特征值的分布。这些操作与分桶操作相同。希望通过改变特征的分布,模型能够更好地学习到特征中包含的有价值的信息。但由于我们无法通过人工经验判断哪种特征处理方式更好,所以我们简单地将它们全部输入到模型中,让模型做出选择。

# all numerical features
numerical_columns = [tf.feature_column.numeric_column('releaseYear'),
                     tf.feature_column.numeric_column('movieRatingCount'),
                     tf.feature_column.numeric_column('movieAvgRating'),
                     tf.feature_column.numeric_column('movieRatingStddev'),
                     tf.feature_column.numeric_column('userRatingCount'),
                     tf.feature_column.numeric_column('userAvgRating'),
                     tf.feature_column.numeric_column('userRatingStddev')]

# cross feature between current movie and user historical movie
rated_movie = tf.feature_column.categorical_column_with_identity(key='userRatedMovie1', num_buckets=1001)
crossed_feature = tf.feature_column.indicator_column(tf.feature_column.crossed_column([movie_col, rated_movie], 10000))

# define input for keras model
inputs = {
    'movieAvgRating': tf.keras.layers.Input(name='movieAvgRating', shape=(), dtype='float32'),
    'movieRatingStddev': tf.keras.layers.Input(name='movieRatingStddev', shape=(), dtype='float32'),
    'movieRatingCount': tf.keras.layers.Input(name='movieRatingCount', shape=(), dtype='int32'),
    'userAvgRating': tf.keras.layers.Input(name='userAvgRating', shape=(), dtype='float32'),
    'userRatingStddev': tf.keras.layers.Input(name='userRatingStddev', shape=(), dtype='float32'),
    'userRatingCount': tf.keras.layers.Input(name='userRatingCount', shape=(), dtype='int32'),
    'releaseYear': tf.keras.layers.Input(name='releaseYear', shape=(), dtype='int32'),

    'movieId': tf.keras.layers.Input(name='movieId', shape=(), dtype='int32'),
    'userId': tf.keras.layers.Input(name='userId', shape=(), dtype='int32'),
    'userRatedMovie1': tf.keras.layers.Input(name='userRatedMovie1', shape=(), dtype='int32'),

    'userGenre1': tf.keras.layers.Input(name='userGenre1', shape=(), dtype='string'),
    'userGenre2': tf.keras.layers.Input(name='userGenre2', shape=(), dtype='string'),
    'userGenre3': tf.keras.layers.Input(name='userGenre3', shape=(), dtype='string'),
    'userGenre4': tf.keras.layers.Input(name='userGenre4', shape=(), dtype='string'),
    'userGenre5': tf.keras.layers.Input(name='userGenre5', shape=(), dtype='string'),
    'movieGenre1': tf.keras.layers.Input(name='movieGenre1', shape=(), dtype='string'),
    'movieGenre2': tf.keras.layers.Input(name='movieGenre2', shape=(), dtype='string'),
    'movieGenre3': tf.keras.layers.Input(name='movieGenre3', shape=(), dtype='string'),
}

这里也来学习下tf提供的特征列类型:
【Pytorch基础教程26】wide&deep推荐算法(tf2.0和torch版)
常见的特征预处理方法包括:连续变量分箱化、离散变量one-hot、离散指标embedding等,tensorflow给我们提供了一个功能强大的特征处理函数tf.feature_column,它通过对特征处理将数据输入网络并交由estimator来进行训练:

  • 整数连续值的特征直接映射成离散特征 tf.feature_column.categorical_column_with_identity() 函数:把numerical data转乘one hot encoding,只适用于值为整数的类别型变量。
  • key:特征名
  • num_buckets:离散特征的离散取值规模
  • default_value=None:出现新值的默认填充值
  • tf.feature_column.crossed_column:将多个特征进行组合,比如将经度和纬度表示单独的特征时对确定房子的位置用处不大,可以将经度和纬度组合为一个特征。

(3)模型部分

  • deep模块:embedding+MLP,让模型具有较强泛化能力。和上个task的特征是一样的,输入层加两层 128 维隐层的结构,它的输入是类别型 Embedding 向量和数值型特征。
  • wide模块:将输入层直接连接到输出层(中间没有做任何处理)
    ——让模型具有较强的记忆力。把输入特征连接到输出层,注意Wide 部分所用的特征 crossed_feature 。如下面我们用movielen电影数据集,生成了一个由【用户已好评电影】和【当前评价电影】组成的一个交叉特征 crossed_feature 。其交叉的代码:
# movie id 转为 one-hot特征,movie id embedding feature
movie_col = tf.feature_column.categorical_column_with_identity(key='movieId', num_buckets=1001)
rated_movie = tf.feature_column.categorical_column_with_identity(key='userRatedMovie1', 
                                                                 num_buckets=1001)
# cross feature between current movie and user historical movie
crossed_feature = tf.feature_column.indicator_column(tf.feature_column.crossed_column([movie_col, rated_movie], 
                                                                                      10000))

【Pytorch基础教程26】wide&deep推荐算法(tf2.0和torch版)
注意:在tensorflow中模型的训练可以使用keras封装好的compilefit方法,也可以使用tf2.0更加灵活的tf.GradientTape()方式。

# wide and deep model architecture
# deep part for all input features
deep = tf.keras.layers.DenseFeatures(numerical_columns + categorical_columns)(inputs)
deep = tf.keras.layers.Dense(128, activation='relu')(deep)
deep = tf.keras.layers.Dense(128, activation='relu')(deep)
# wide part for cross feature
wide = tf.keras.layers.DenseFeatures(crossed_feature)(inputs)
both = tf.keras.layers.concatenate([deep, wide])
output_layer = tf.keras.layers.Dense(1, activation='sigmoid')(both)
model = tf.keras.Model(inputs, output_layer)

# compile the model, set loss function, optimizer and evaluation metrics
model.compile(
    loss='binary_crossentropy',
    optimizer='adam',
    metrics=['accuracy', tf.keras.metrics.AUC(curve='ROC'), tf.keras.metrics.AUC(curve='PR')])

# train the model
model.fit(train_dataset, epochs=5)

# evaluate the model
test_loss, test_accuracy, test_roc_auc, test_pr_auc = model.evaluate(test_dataset)
print('\n\nTest Loss {}, Test Accuracy {}, Test ROC AUC {}, Test PR AUC {}'.format(test_loss, test_accuracy,
                                                                                   test_roc_auc, test_pr_auc))

# print some predict results
predictions = model.predict(test_dataset)
for prediction, goodRating in zip(predictions[:12], list(test_dataset)[0][1][:12]):
    print("Predicted good rating: {:.2%}".format(prediction[0]),
          " | Actual rating label: ",
          ("Good Rating" if bool(goodRating) else "Bad Rating"))

(4)训练结果

2022-03-26 20:32:48.370872: 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:  AVX AVX2
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
Epoch 1/5
D:\anaconda1\envs\tensorflow\lib\site-packages\tensorflow\python\keras\engine\functional.py:540: UserWarning: Input dict contained keys ['rating', 'timestamp', 'userRatedMovie2', 'userRatedMovie3', 'userRatedMovie4', 'userRatedMovie5', 'userAvgReleaseYear', 'userReleaseYearStddev'] which did not match any model input. They will be ignored by the model.
  warnings.warn(
7403/7403 [==============================] - 48s 6ms/step - loss: 0.7353 - accuracy: 0.6156 - auc: 0.6373 - auc_1: 0.6713
Epoch 2/5
7403/7403 [==============================] - 48s 6ms/step - loss: 0.5968 - accuracy: 0.6854 - auc: 0.7384 - auc_1: 0.7648
Epoch 3/5
7403/7403 [==============================] - 45s 6ms/step - loss: 0.5417 - accuracy: 0.7283 - auc: 0.7948 - auc_1: 0.8157
Epoch 4/5
7403/7403 [==============================] - 40s 5ms/step - loss: 0.5024 - accuracy: 0.7552 - auc: 0.8288 - auc_1: 0.8492
Epoch 5/5
7403/7403 [==============================] - 40s 5ms/step - loss: 0.4774 - accuracy: 0.7708 - auc: 0.8482 - auc_1: 0.8704
1870/1870 [==============================] - 4s 2ms/step - loss: 0.6218 - accuracy: 0.6893 - auc: 0.7536 - auc_1: 0.7819


Test Loss 0.6217975616455078, Test Accuracy 0.6893048286437988, Test ROC AUC 0.7535525560379028, Test PR AUC 0.7818983793258667
Predicted good rating: 82.82%  | Actual rating label:  Good Rating
Predicted good rating: 49.24%  | Actual rating label:  Good Rating
Predicted good rating: 77.08%  | Actual rating label:  Bad Rating
Predicted good rating: 74.62%  | Actual rating label:  Good Rating
Predicted good rating: 39.94%  | Actual rating label:  Bad Rating
Predicted good rating: 71.07%  | Actual rating label:  Good Rating
Predicted good rating: 65.24%  | Actual rating label:  Good Rating
Predicted good rating: 4.88%  | Actual rating label:  Good Rating
Predicted good rating: 94.61%  | Actual rating label:  Bad Rating
Predicted good rating: 39.97%  | Actual rating label:  Bad Rating
Predicted good rating: 75.85%  | Actual rating label:  Bad Rating
Predicted good rating: 30.80%  | Actual rating label:  Good Rating

Reference

[1] tensorflow官网:https://www.tensorflow.org/
[2]Tensorflow2 和 Pytorch的基本操作对比(二)
[3]PyTorch与TensorFlow 2.x各有什么优势?
[4]TensorFlow 2.x —— tf.keras.util.get_file
[5]tensorflow特征列的学习
[6] https://www.tensorflow.org/api_docs/python/tf/feature_column

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2022年3月28日 下午1:50
下一篇 2022年3月28日 下午2:08

相关推荐