【推荐算法】双塔模型代码(tensorflow)

【推荐算法】双塔模型介绍_MachineCYL的博客-CSDN博客

上文介绍了双塔模型的原理和结构,这篇介绍一下双塔模型的代码实现。我使用的是tensorflow来实现双塔模型和模型训练。

一、前期准备

  • tensorflow使用的版本是2.0.0
  • 数据格式(如果需要获取数据,可以见下方链接):

 不过由于是Demo,我只用了部分字段进行训练。

二、详细代码

  • DSSM模型代码
import tensorflow as tf

def dssm_model(feature_inputs, item_feature_columns, user_feature_columns, hidden_units):
    item_tower = tf.keras.layers.DenseFeatures(item_feature_columns)(feature_inputs)
    for num_nodes in hidden_units:
        item_tower = tf.keras.layers.Dense(num_nodes, activation='relu')(item_tower)

    user_tower = tf.keras.layers.DenseFeatures(user_feature_columns)(feature_inputs)
    for num_nodes in hidden_units:
        user_tower = tf.keras.layers.Dense(num_nodes, activation='relu')(user_tower)

    output = tf.keras.layers.Dot(axes=1)([item_tower, user_tower])
    output = tf.keras.layers.Dense(1, activation='sigmoid')(output)

    model = tf.keras.Model(feature_inputs, output)
    return model
  • 模型训练、预测与保存代码
def gen_dataset(data_df: pd.DataFrame, columns: dict):
    data_dict = dict()

    def _get_type(type_str):
        if type_str == "int32":
            return np.int32
        elif type_str == "float32":
            return np.float32
        elif type_str == "string" or type_str == "str":
            return np.str
        else:
            return np.int32

    for key in columns.keys():
        data_dict[key] = np.array(data_df[key]).astype(_get_type(columns[key]))

    return data_dict


def parse_argvs():
    parser = argparse.ArgumentParser(description='[DSSM]')
    parser.add_argument("--data_path", type=str, default='./data/')
    parser.add_argument("--model_path", type=str, default='./model_param')
    parser.add_argument("--epoch", type=int, default=10)
    parser.add_argument("--monitor", type=str, default="val_accuracy", choices=["val_accuracy", "val_auc"])
    parser.add_argument("--batch_size", type=int, default=12)
    args = parser.parse_args()
    print('[input params] {}'.format(args))

    return parser, args


if __name__ == '__main__':
    parser, args = parse_argvs()
    data_path = args.data_path
    model_path = args.model_path
    monitor = args.monitor
    epoch = args.epoch
    batch_size = args.batch_size

    # ====================================================================================
    # read data
    data_path = os.path.abspath(data_path)
    print("[DSSM] read file path: {}".format(data_path))
    train_data = pd.read_csv(os.path.join(data_path, "trainingSamples.csv"), sep=",")
    test_data = pd.read_csv(os.path.join(data_path, "testSamples.csv"), sep=",")
    data_pd = pd.concat([train_data, test_data])

    # ====================================================================================
    # define input for keras model
    columns_dict = {
        'movieId': 'int32',
        'movieGenre1': 'string',
        'movieAvgRating': 'float32',
        'userId': 'int32',
        'userGenre1': 'string',
        'userAvgRating': 'float32'
    }

    inputs = dict()
    for key in columns_dict.keys():
        inputs[key] = tf.keras.layers.Input(name=key, shape=(), dtype=columns_dict[key])
    print("[DSSM] input for keras model: \n {}".format(inputs))

    # ====================================================================================
    # movie 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)

    movie_genre_1_vocab = data_pd['movieGenre1'].dropna().unique()
    movie_genre_1_col = tf.feature_column.categorical_column_with_vocabulary_list(key='movieGenre1',
                                                                                  vocabulary_list=movie_genre_1_vocab)
    movie_genre_1_emb_col = tf.feature_column.embedding_column(movie_genre_1_col, 10)

    movie_avg_rating = tf.feature_column.numeric_column(key='movieAvgRating')

    # user embedding feature
    user_col = tf.feature_column.categorical_column_with_identity(key='userId', num_buckets=30001)
    user_emb_col = tf.feature_column.embedding_column(user_col, 10)

    user_genre_1_vocab = data_pd['userGenre1'].dropna().unique()
    user_genre_1_col = tf.feature_column.categorical_column_with_vocabulary_list(key='userGenre1',
                                                                                 vocabulary_list=user_genre_1_vocab)
    user_genre_1_emb_col = tf.feature_column.embedding_column(user_genre_1_col, 100)

    user_avg_rating = tf.feature_column.numeric_column(key='userAvgRating')

    # ====================================================================================
    # train model
    model = dssm_model(feature_inputs=inputs,
                       item_feature_columns=[movie_emb_col, movie_genre_1_emb_col, movie_avg_rating],
                       user_feature_columns=[user_emb_col, user_genre_1_emb_col, user_avg_rating],
                       hidden_units=[30, 10])

    model.compile(
        loss='binary_crossentropy',
        optimizer='adam',
        metrics=['accuracy', tf.keras.metrics.AUC(curve='ROC')])

    filepath = os.path.join(model_path, "checkpoint", "dssm-weights-best.hdf5")
    checkpoint = tf.keras.callbacks.ModelCheckpoint(
        filepath, monitor=monitor, verbose=1, save_best_only=True, mode='max')

    train_data_input = gen_dataset(data_df=train_data, columns=columns_dict)
    model.fit(x=train_data_input, y=train_data["label"].values,
              epochs=epoch, callbacks=[checkpoint], verbose=2, batch_size=batch_size, validation_split=0.1)

    # ====================================================================================
    # predict, use best model.
    test_data_input = gen_dataset(data_df=test_data, columns=columns_dict)
    model.load_weights(filepath=filepath)

    pred_ans = model.predict(x=test_data_input, batch_size=batch_size)
    print("\n[BEST] ===============================================================")
    print("[test] LogLoss: {} ".format(round(log_loss(test_data["label"].values, pred_ans), 4)))
    print("[test] Accuracy: {} ".format(round(accuracy_score(test_data["label"].values, pred_ans >= 0.5), 4)))
    print("[test] AUC: {} ".format(round(roc_auc_score(test_data["label"].values, pred_ans), 4)))
    print("[test] classification_report: \n{} ".format(classification_report(test_data["label"].values, pred_ans >= 0.5, digits=4)))

    # ====================================================================================
    # save model
    model_path = os.path.abspath(model_path)
    print("[DSSM] save model path: {}".format(model_path))

    model.summary()
    tf.keras.models.save_model(
        model,
        os.path.join(model_path, "dssm"),
        overwrite=True,
        include_optimizer=True,
        save_format=None,
        signatures=None,
        options=None
    )
  • 运行结果展示(部分)

需要获取训练数据和代码可以访问我的github,如果觉得有帮助,请star收藏,谢谢~

DSSM代码

  • 8
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
双塔模型是一种推荐算法中常用的模型,它由两个塔组成,一个是用户塔,另一个是物品塔。这两个塔都是由深度神经网络(DNN)构成的,最后一层的隐藏单元个数相同,以确保用户嵌入和物品嵌入的维度相同。在双塔模型中,使用二分类交叉熵损失函数进行相似度计算,例如使用余弦内积计算相似度。与其他模型不同的是,DSSM模型无法像deepFM一样使用用户和物品的交叉特征。\[2\] 在Python中实现双塔模型时,可以使用torch.nn.CrossEntropyLoss作为损失函数。这个函数已经包括了softmax激活函数,因此在最后一层网络不需要再使用激活函数。交叉熵损失函数的计算可以通过手写代码实现,也可以直接使用torch.nn.CrossEntropyLoss函数进行计算。\[3\] 双塔模型在推荐系统中有广泛的应用,可以用于生成用户和物品的嵌入向量,并通过计算相似度来进行推荐。它的简单结构和有效性使其成为推荐算法中的一种重要模型。\[9\]\[10\]\[11\] #### 引用[.reference_title] - *1* *2* *3* [【PyTorch基础教程30】DSSM双塔模型(线上召回 | 模型更新)](https://blog.csdn.net/qq_35812205/article/details/125383309)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值