推荐算法实战项目:DeepCross 原理以及案例实战(附完整 Python 代码)

news2024/11/15 5:13:13

本文要介绍的是由斯坦福大学联合Google的研究人员发表的论文《Deep & Cross Network for Ad Click Predictions》中提出的Deep&Cross模型,简称DCN。

DCN模型是Wide&Deep的改进版本,其中Deep部分的设计思路与Wide&Deep没有发生本质的变化,DCN主要是重新设计了Cross部分以增加特征之间的交互力度,使用了多层特征交叉层对输入向量进行特征交叉,以获得更加强壮的特征表达能力。

摘要

点击率(CTR)预估任务是一个大规模的问题,尤其是对于价值数百亿美元的在线广告业务。在广告界,广告商向发布商付款,以便在发布商的网站上展示其广告。

较为主流的付款方式是根据每次点击付款(cost-per-click),即当用户点击了一次广告之后,发布商就可以向广告商索取费用。因此,对于发布商而言,其预测广告点击率的能力直接决定了其营收。

做出较为准确的点击率预测的关键是要识别出经常预测的特征,并且同时挖掘出不常见的交叉特征信息。然而,用于Web级推荐系统的数据通常是离散的,且大多是类别数据,这就导致了一个非常庞大且稀疏的特征空间,对特征探索提出了巨大的挑战。这也使得大多数大型系统受限于使用简单的线性模型,比如逻辑回归。线性模型很简单,解释性很强,并且计算快速。

然而,这也限制了它的表达能力。交叉特征已经被证明对提高模型的表达能力很有效。然而它一般需要手工特征工程或者纷繁复杂的搜索才能找到;此外,它也很难推广到那些看不见的特征交互上。

作者在这篇论文中引入了一个新型的神经网络结构,即DCN。它避免了传统的针对特定任务的特征工程,依靠神经网络强大的学习能力,在一定程度上实现自动学习交叉特征组合。

Deep&Cross 网络模型

Deep&Cross模型,简称DCN。DCN模型的输入是稠密和稀疏向量,可以自动进行特征学习,有效捕捉有限度的特征交互,学习高度非线性的特征之间的交互,无需复杂繁琐的特征工程和详细的特征搜索,并且具备较低的计算成本。模型的整体结构图如下:

DCN模型整体结构比较简单,下面分别进行描述。

Embedding和Stack层

输入数据包含稠密和稀疏向量。在Web级的推荐系统任务中,比如点击率预估,其输入大都是类别向量,比如“国家=中国”。这样的特征通常被编码成one-hot向量,比如这样“[0,1,0]”;但是如果稀疏向量很多,且类别较大,那么这将导致一个超高维的特征空间,同时造成空间浪费以及计算复杂度高。

为了减少维度,通常采用embedding处理(即上图红色矩形框部分),将这些二值化特征转化为包含实数的稠密向量,也叫做嵌入向量(embedding vector)。转换公式如下:


Cross网络

Cross网络是DCN模型中最关键的部分,它以一种高效的方式来进行特征交叉。Cross网络包含若干个cross层,每一层都通过以下公式计算:


cross层的工作示意图如下:


现在大家应该可以理解cross layer计算公式的设计意图了。这个例子可以帮助我们更加深入理解cross层的设计:

  1. 有限高阶:叉乘阶数由网络深度决定,深度对应最高的阶的叉乘
  2. 自动叉乘: Cross输出包含了原始特征从一阶到n阶的所有叉乘组合,而模型的参数量仅仅随着输入维度成线性增加。
  3. 参数共享:不同叉乘项对应的权重不同,单并非每个叉乘组合对应独立的权重,通过参数共享,cross有效降低了参数量。此外,参数共享还使得模型具有更强的泛化性鲁棒性

复杂度计算

论文表示,cross网络之所以能够高效地学习组合特征,就是因为秩为1,使得我们不用计算并存储整个矩阵就可以得到所有的cross items。

我们再来观察一下cross层的计算迭代公式:


实际代码调试的时候,两种方法都实验了,在我的电脑上测试发现,使用优化过的计算方式大概可以将速度提升6倍左右。

Deep网络

Deep层比较简单,就是一个全连接前向神经网络,每一层的计算方式如下:

复杂度计算

出于简化目的,我们假设所有的Deep层都是通用的大小。

聚合层

聚合的作用是将Deep和Cross网络的输出聚合到一个向量中,并且通过一个标准的逻辑层。计算公式如下:

损失函数是一个标准的交叉熵函数加上一个正则项:

主要贡献

DCN的主要贡献主要包含以下几点:

  • 提出一种新型的交叉网络结构,可以用来提取交叉组合特征,并不需要人为设计的特征工程
  • 这种网络结构足够简单同时也很有效,可以获得随网络层数增加而增加的多项式阶(polynomial degree)交叉特征
  • 十分节约内存(依赖于正确地实现),并且易于使用
  • 实验结果表明,DCN相比于其他模型有更出色的效果,与DNN模型相比,较少的参数却取得了较好的效果

完整源码

文章中的完整源码,添加微信号:mlc2060,备注:获取推荐资料

部分代码

模型部分代码,主要包含了Deep和Cross,以及DeepCross模型实现,特别要注意的就是Cross模型中的矩阵计算的时候,有两种方式,默认用的是优化过后的方法。

import torch
import torch.nn as nn
from BaseModel.basemodel import BaseModel

class Deep(nn.Module):
    def __init__(self, input_dim, deep_layers):
        super(Deep, self).__init__()

        deep_layers.insert(0, input_dim)
        deep_ayer_list = []
        for layer in list(zip(deep_layers[:-1], deep_layers[1:])):
            deep_ayer_list.append(nn.Linear(layer[0], layer[1]))
            deep_ayer_list.append(nn.BatchNorm1d(layer[1], affine=False))
            deep_ayer_list.append(nn.ReLU(inplace=True))
        self._deep = nn.Sequential(*deep_ayer_list)

    def forward(self, x):
        out = self._deep(x)
        return out

class Cross(nn.Module):
    """
    the operation is this module is x_0 * x_l^T * w_l + x_l + b_l for each layer, and x_0 is the init input
    """
    def __init__(self, input_dim, num_cross_layers):
        super(Cross, self).__init__()
        
        self.num_cross_layers = num_cross_layers
        weight_w = []
        weight_b = []
        batchnorm = []
        for i in range(num_cross_layers):
            weight_w.append(nn.Parameter(torch.nn.init.normal_(torch.empty(input_dim))))
            weight_b.append(nn.Parameter(torch.nn.init.normal_(torch.empty(input_dim))))
            batchnorm.append(nn.BatchNorm1d(input_dim, affine=False))

        self.weight_w = nn.ParameterList(weight_w)
        self.weight_b = nn.ParameterList(weight_b)
        self.bn = nn.ModuleList(batchnorm)

测试数据是criteo数据集的一个很小的子集,测试代码如下:

import torch
from DeepCross.trainer import Trainer
from DeepCross.network import DeepCross
from Utils.criteo_loader import getTestData, getTrainData
import torch.utils.data as Data

deepcross_config = \
{
    'deep_layers': [256,128,64,32], # 设置Deep模块的隐层大小
    'num_cross_layers': 4, # cross模块的层数
    'num_epoch': 2,
    'batch_size': 32,
    'lr': 1e-3,
    'l2_regularization': 1e-4,
    'device_id': 0,
    'use_cuda': False,
    'train_file': '../Data/criteo/processed_data/train_set.csv',
    'fea_file': '../Data/criteo/processed_data/fea_col.npy',
    'validate_file': '../Data/criteo/processed_data/val_set.csv',
    'test_file': '../Data/criteo/processed_data/test_set.csv',
    'model_name': '../TrainedModels/DeepCross.model'
}

if __name__ == "__main__":
    ####################################################################################
    # DeepCross 模型
    ####################################################################################
    training_data, training_label, dense_features_col, sparse_features_col = getTrainData(deepcross_config['train_file'], deepcross_config['fea_file'])
    train_dataset = Data.TensorDataset(torch.tensor(training_data).float(), torch.tensor(training_label).float())
    test_data = getTestData(deepcross_config['test_file'])
    test_dataset = Data.TensorDataset(torch.tensor(test_data).float())

    deepCross = DeepCross(deepcross_config, dense_features_cols=dense_features_col, sparse_features_cols=sparse_features_col)

    ####################################################################################
    # 模型训练阶段
    ####################################################################################
    # # 实例化模型训练器
    trainer = Trainer(model=deepCross, config=deepcross_config)
    # 训练
    trainer.train(train_dataset)
    # 保存模型
    trainer.save()

    ####################################################################################
    # 模型测试阶段
    ####################################################################################
    deepCross.eval()
    if deepcross_config['use_cuda']:
        deepCross.loadModel(map_location=lambda storage, loc: storage.cuda(deepcross_config['device_id']))
        deepCross = deepCross.cuda()
    else:
        deepCross.loadModel(map_location=torch.device('cpu'))

    y_pred_probs = deepCross(torch.tensor(test_data).float())
    y_pred = torch.where(y_pred_probs>0.5, torch.ones_like(y_pred_probs), torch.zeros_like(y_pred_probs))
    print("Test Data CTR Predict...\n ", y_pred.view(-1))

测试代码就是对criteo的测试集中的每一个样本数据输出对应的点击率预测,0或者1。以下是部分测试结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/487921.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机视觉的应用3-批量图片风格迁移之素描图片生成的应用

大家好,我是微学AI,今天给大家介绍一下计算机视觉的应用3-批量图片生成素描图片的应用,将一张图像转换为素描风格的图像的其实是模拟了人类视觉在观察物体时受到的光照条件。素描风格的图像在灰度值上表现出明暗交替的效果,这种效…

【干货】一文说透分布式一致性协议(下)

本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注"慕课网"! 作者:大能老师 | 慕课网讲师 前情提示:如需阅读“一文说透分布式一致性协议(上)”&#…

对多个点进行直线拟合操作

在图像处理中,通常会遇到根据给定的点集(比如轮廓)拟合出一条直线的情形。 import numpy as np import matplotlib.pyplot as plt import cv2def Cal_kb_linear_fitline(pointLocs):loc np.array(pointLocs) # loc 必须为矩阵形式&#xff…

二分类结局变量Logistic回归临床模型预测(二)——基线特征及三线表绘制(二)

本节讲的是二分类结局变量的临床模型预测,与之前讲的Cox回归不同,https://lijingxian19961016.blog.csdn.net/article/details/124088364https://lijingxian19961016.blog.csdn.net/article/details/124088364https://lijingxian19961016.blog.csdn.net/article/details/1300…

蓝牙耳机哪款性价比高一些?2023年性价比最高的蓝牙耳机推荐

随着科技的进步,蓝牙耳机已然成为我们生活中的一部分,无论是通勤、追剧、运动或者玩游戏,大都会用到蓝牙耳机。那么,哪款蓝牙耳机的性价比高一些?相信大多数人在选择产品的时候,都会看性价比。接下来&#…

手把手带你写一份优秀的开发求职简历(五)技术能力如何凸显优势

前言 前面的几小节,把个人信息和教育背景的模块做了讲述,这两个模块处于简历的第一屏最顶部,可以说HR会第一眼看见,所以很重要,同时也通过一些讲述告诉求职者从这些方面如何扬长避短,抓住HR的招聘心理。 …

Android基于JNA集成调用第三方C/C++的so库

Android基于JNA集成调用第三方C/C的so库 (1)引入JNA。 基于JNA开源项目,JNA对Android NDK的封装,简化Android层JNI集成调用C/C的so库。 GitHub - java-native-access/jna: Java Native AccessJava Native Access. Contribute to…

为AI造“楚门世界” 人类围观对话机器人社交、谈恋爱

不满足于跟ChatGPT聊天,技术狂人开始为对话机器人创造“楚门的世界”,从上帝视角围观AI如何“吃饭”、社交、谈恋爱...... 最近,一位神秘人创建了一个AI社交网站Chirper,人类不能参与,只能围观上万名AI在这里的聊天和…

社交技能讲座笔记

作者:朱金灿 来源:clever101的专栏 为什么大多数人学不会人工智能编程?>>> 感谢张鹏老师做了一堂实用的社交技能讲座。我特地做了一些笔记(其中包含我的一些理解): 1.整理好外观,让别…

【大数据之Hadoop】二十三、Yarn命令行操作及生产环境下的配置

1 Yarn常用命令 Yarn状态查询可以在hadoop103:8088页面查看,也可以通过命令查看。 先运行案例再查看运行情况。 (1)yarn application 查看任务 yarn application -list //列出所有application yarn application -list -appStates 状态 …

c++ 11标准模板(STL) std::vector (五)

定义于头文件 <vector> template< class T, class Allocator std::allocator<T> > class vector;(1)namespace pmr { template <class T> using vector std::vector<T, std::pmr::polymorphic_allocator<T>>; }(2)(C17…

Qt音视频开发43-采集屏幕桌面并推流(支持分辨率/矩形区域/帧率等设置/实时性极高)

一、前言 采集电脑屏幕桌面并推流一般是用来做共享桌面、远程协助、投屏之类的应用&#xff0c;最简单入门的做法可能会采用开个定时器或者线程抓图&#xff0c;将整个屏幕截图下来&#xff0c;然后将图片传出去&#xff0c;这种方式很简单但是性能要低不少&#xff0c;一般采…

R语言的贝叶斯时空数据模型

时间&#xff0d;空间数据&#xff08;以下简称“时空数据”&#xff09;是最重要的观测数据形式之一&#xff0c;很多科学研究的数据都以时空数据的形式得以呈现&#xff0c;而科学研究目的可以归结为挖掘时空数据中的规律。另一方面&#xff0c;贝叶斯统计学作为与传统统计学…

FCOS3D Fully Convolutional One-Stage Monocular 3D Object Detection 论文学习

论文地址&#xff1a;Fully Convolutional One-Stage Monocular 3D Object Detection Github地址&#xff1a;Fully Convolutional One-Stage Monocular 3D Object Detection 1. 解决了什么问题&#xff1f; 单目 3D 目标检测由于成本很低&#xff0c;对于自动驾驶任务非常重…

可视化工作流管理

​本场景是可视化工作流&#xff0c;通过可视化的精益看板将价值流进行可视化&#xff0c;通过精益思维消除瓶颈、加速流动&#xff0c;提升效率。 创建工作流任务看板 •通过Leangoo可视化工作流项目模板&#xff0c;创建一个工作流看板。 •通过看板&#xff0c;我们可以将…

K_A35_017 基于STM32等单片机驱动TTP229矩阵触摸传感器 串口与OLED0.96双显示

K_A35_017 基于STM32等单片机驱动TTP229矩阵触摸传感器 串口与OLED0.96双显示 所有资源导航一、资源说明二、基本参数参数引脚说明 三、驱动说明时序:对应程序: 四、部分代码说明1、接线引脚定义1.1、STC89C52RCTTP229矩阵触摸模块1.2、STM32F103C8T6TTP229矩阵触摸模块 五、基…

医院安全(不良)事件报告系统 PHP语言实现

医院安全&#xff08;不良&#xff09;事件报告制度 一、目的 规范医院安全&#xff08;不良&#xff09;事件的主动报告&#xff0c;增强风险防范意识&#xff0c;及时发现医疗不良事件和安全隐患&#xff0c;将获取的医疗安全信息进行分析反馈&#xff0c;并从医院管理体系…

UG NX二次开发(C++)-UF_OBJ_cycle_all获取所有的体对象

文章目录 1、前言2、在UG NX创建多个体对象3、用UF_OBJ_cycle_all来创建一个新的方法4、测试结果4.1 用UF_OBJ_cycle_objs_in_part&#xff08;&#xff09;结果4.2 用 UF_OBJ_cycle_all&#xff08;&#xff09;结果 5、结论 1、前言 在前面的一篇博客中&#xff0c;我们介绍…

Linux线程:概念、特点、线程间资源共享情况

1. 线程概念 线程是轻量级的进程&#xff1b;Linux中&#xff0c;线程本质上仍是进程。 进程是OS分配资源的最小单位&#xff0c;线程是OS调度的最小单位。 NPTL 当前Linux线程库为redHat开发的NPTL&#xff0c;查看本地线程库版本&#xff1a; getconf GNU_LIBPTHREAD_VE…

在VM VirtualBox6.1中安装redhat7.3过程实录

最近试用皕杰报表工具&#xff0c;需要把报表部署到linux系统&#xff0c;因而在VM VirtualBox虚拟机上安装linux操作系统&#xff0c;现把过程记录下来&#xff0c;作为今后的备忘。 打开VM VirtualBox虚拟机&#xff0c;见下图&#xff1a; 点击控制菜单选择新建&#xff1…