CTR模型:WideDeep 网络

2023-10-15 13:58
文章标签 模型 网络 ctr widedeep

本文主要是介绍CTR模型:WideDeep 网络,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0. 简介

Wide and Deep网络(Wide & Deep Learning for Recommender Systems)是2016年被提出的。
出发点:
推荐系统需要同时实现 memorization 和generalization。

memorization, 学习 item 或者 feature的共现关系,并基于历史数据中的这种相关性来推荐。
通过特征交叉可以实现 memorization, 比如 性别 和是否购买汽车作为交叉特征。

generalization: 探索过去从未发生后者很少发生的新特征组合。

提升泛化能力,需要提升特征的粒度, 比如,性别+ 曾经购买汽车的价格<= 10万。
这种方式的限制无法推广到训练集没有出现过的query-item或者 feature pair。

解决方案:

(1)基于Embedding的模型,为query 和item学习一个低维的dense Embedding, 通过Embedding向量来泛化训练集未见过的 query-item feature pair。

当query-item 矩阵非常稀疏,且矩阵的秩较高时,很难学到有效的query-item的低维表达。

Wide网络,通过大量的人工构建交叉特征来提高memorization;缺点是模型表达能力不强,容易欠拟合。

Deep网络:通过特征工程,可泛化未出现的特征组合。即generalization。优点是泛化能力强,缺点是容易过拟合。缺点是表达能力太强,容易过拟合。

1. 总体网络

一个典型的推荐系统整体架构是:
在这里插入图片描述
当用户访问 app store 时产生一个query, 包含用户特征(如用户画像)和上下文特征(如 当前时刻LBS信息,设备信息,页面信息)。
检索retrieval 模块根据用户query 返回一组相关app 组成的app list. (召回阶段)
精排 ranking 模块对候选 app list 根据用户的行为(如下载等)概率进行排名,返回概率最高的10几个app组成的推荐结果。

Wide&Deep 模型主要用于ranking 精排模块,包含一个 线性模型和一个神经网络模型。

Wide & Deep模型结合了LR和DNN,其框架图如下所示。

在这里插入图片描述

2. Wide网络

这部分特征包括原始的输入特征和转换后特征。

ϕ k ( x ) \phi_k{(x)} ϕk(x) 定义:
x = [ x 1 , x 2 , … , x d ] \mathbf{x}=\left[x_{1}, x_{2}, \ldots, x_{d}\right] x=[x1,x2,,xd] 是一个特征维度为d的向量(经过one-hot),仅包含原始特征。

定义交叉积转换函数(cross-product transformation)
在这里插入图片描述
在这里插入图片描述
特征交叉

假设将所有categorical特征都按照One-Hot-Encoding(OHE)展开后,一共有n个特征,根据经验对特征进行两两交叉,并和原始特征,作为Wide部分的输入。

所以,Wide 网络输入了one-hot的类别特征,及交叉特征,以及原来的一些连续特征(连续特征可能不需要输入?)。

3. Deep网络

Deep网络使用了 类别特征 + 连续特征

输入层:DNN的所有离散特征,未经过one-hot.
第一层Embedding层:将高维稀疏的类别特征转换成低维的Embedding向量,Embedding向量维度是32维。(一般是10-100之间)
第二层特征拼接层:将所有的Embedding向量拼接成一个dense feature 向量。 论文是 1200 维。
后续是全连接层。

在这里插入图片描述

4. Wide&Deep整体

Wide & Deep model structure for apps recommendation:在这里插入图片描述
Wide网络:以类别特征为主,输入到 LR进行学习;
Deep网络:以连续特征以及类别特征的Embeddings表示为输入,最后,和Wide网络连接同一个LR。
两个网络联合训练。

在共同的LR模型中:
y ^ = P ( Y = 1 ∣ x ) = σ ( w w i d e T [ x , ϕ ( x ) ] + w d e c p T a ( l f ) + b ) \hat y = P(Y=1 | \mathbf{x})=\sigma\left(\mathbf{w}_{w i d e}^{T}[\mathbf{x}, \phi(\mathbf{x})]+\mathbf{w}_{d e c p}^{T} a^{\left(l_{f}\right)}+b\right) y^=P(Y=1x)=σ(wwideT[x,ϕ(x)]+wdecpTa(lf)+b)

Wide 线性模型可以有效地通过叉乘的转换记住稀疏特征的交叉,Deep 神经网络可以通过低维的Embedding获得无法看到的特征交叉,具有泛化性能。

模型使用负的对数似然,并用随机梯度下降来训练,和LogisticRegression 模型相似,可以得到损失函数:
loss ⁡ ( θ ) = − log ⁡ ( L ( θ ) ) = − 1 N ∑ i = 1 N y ( i ) log ⁡ P ( Y = 1 ∣ x ) + ( 1 − y ( i ) ) log ⁡ ( 1 − P ( Y = 1 ∣ x ) ) \operatorname{loss}(\theta)= - \log (L(\theta))=-\frac{1}{N} \sum_{i=1}^{N} y^{(i)} \log P(Y=1 | \mathbf{x})+\left(1-y^{(i)}\right) \log(1-P(Y=1 | \mathbf{x})) loss(θ)=log(L(θ))=N1i=1Ny(i)logP(Y=1x)+(1y(i))log1P(Y=1x)

4.1 模型细节

在 Wide&Deep 模型中,每个子模型在训练期间就结合在一起,共同训练。
在 Wide&Deep 模型中,每个子模型都可以比较小,尤其是 wide 部分只需要少量的特征交叉即可

数据生成

  • 离散的字符串特征(如app name)映射成为整数ID ,同时生成映射字典vocabulary 。对于出现次数低于指定阈值(如 10此)的字符串直接丢弃,这能够丢弃一些长尾的、罕见的字符串,降低字典规模。
  • 连续特征离散化:
    首先将连续特征归一化到 0~1 之间,它通过累积分布函数来归一化,计算特征的整体排名(1.0表示排名最高,0.0表示排名最低)
    在这里插入图片描述
    然后将 f(x) 映射到 q 分位。如映射到10分位时,假设 f(x)=0.95 (即排名在最高的 5%),则映射为 9 这个等级。

模型训练阶段:
wide 部分的特征由:用户已经安装的 app 、给用户曝光的 app 的两个特征的交叉组成。
deep 部分从每个离散特征中学习。
增量学习:
每次有新的训练数据到达时,模型会利用该部分数据重新训练。
由于重新训练模型的代价太大,因此我们实现了一个 warm-starting 系统:基于前一个模型的 embedding 和 w w i d e w_{wide} wwide参数来初始化当前模型的这两个参数。
模型预测阶段
将模型部署到服务器上来提供预测服务。
为满足 10ms 量级的响应速度,采用多线程并行来优化性能。方法为:
假设一个 batch 有 500 个候选 app,先将其拆分为更小的一组 batch:如 50 个 batch,每个 batch 有 10 个候选 app。
每个子线程并行的执行推断;
将所有子线程的推断结果收集在一起,拼接成整个 batch 的推断结果并返回。
在这里插入图片描述
实验
谷歌应用商店 app下载量:
在这里插入图片描述
性能评估:
在这里插入图片描述

5. 代码

class WideDeep(nn.Module):def __init__(self,wide_dim,embeddings_input,continuous_cols,deep_column_idx,hidden_layers,dropout,encoding_dict,n_class):super(WideDeep, self).__init__()self.wide_dim = wide_dimself.deep_column_idx = deep_column_idxself.embeddings_input = embeddings_inputself.continuous_cols = continuous_colsself.hidden_layers = hidden_layersself.dropout = dropoutself.encoding_dict = encoding_dictself.n_class = n_class# Build the embedding layers to be passed through the deep-sidefor col,val,dim in self.embeddings_input:setattr(self, 'emb_layer_'+col, nn.Embedding(val, dim))# Build the deep-side hidden layers with dropout if specifiedinput_emb_dim = np.sum([emb[2] for emb in self.embeddings_input])self.linear_1 = nn.Linear(input_emb_dim+len(continuous_cols), self.hidden_layers[0])if self.dropout:self.linear_1_drop = nn.Dropout(self.dropout[0])for i,h in enumerate(self.hidden_layers[1:],1):setattr(self, 'linear_'+str(i+1), nn.Linear( self.hidden_layers[i-1], self.hidden_layers[i] ))if self.dropout:setattr(self, 'linear_'+str(i+1)+'_drop', nn.Dropout(self.dropout[i]))# Connect the wide- and dee-side of the model to the output neuron(s)self.output = nn.Linear(self.hidden_layers[-1]+self.wide_dim, self.n_class)def compile(self, method="logistic", optimizer="Adam", learning_rate=0.001, momentum=0.0):"""Wrapper to set the activation, loss and the optimizer.Parameters:----------method (str) : regression, logistic or multiclassoptimizer (str): SGD, Adam, or RMSprop"""if method == 'regression':self.activation, self.criterion = None, F.mse_lossif method == 'logistic':self.activation, self.criterion = F.sigmoid, F.binary_cross_entropyif method == 'multiclass':self.activation, self.criterion = F.softmax, F.cross_entropyif optimizer == "Adam":self.optimizer = torch.optim.Adam(self.parameters(), lr=learning_rate)if optimizer == "RMSprop":self.optimizer = torch.optim.RMSprop(self.parameters(), lr=learning_rate)if optimizer == "SGD":self.optimizer = torch.optim.SGD(self.parameters(), lr=learning_rate, momentum=momentum)self.method = methoddef forward(self, X_w, X_d):"""Implementation of the forward pass.Parameters:----------X_w (torch.tensor) : wide-side input tensorX_d (torch.tensor) : deep-side input tensorReturns:--------out (torch.tensor) : result of the output neuron(s)"""# Deep Sideemb = [getattr(self, 'emb_layer_'+col)(X_d[:,self.deep_column_idx[col]].long())for col,_,_ in self.embeddings_input]if self.continuous_cols:cont_idx = [self.deep_column_idx[col] for col in self.continuous_cols]cont = [X_d[:, cont_idx].float()]deep_inp = torch.cat(emb+cont, 1)else:deep_inp = torch.cat(emb, 1)x_deep = F.relu(self.linear_1(deep_inp))if self.dropout:x_deep = self.linear_1_drop(x_deep)for i in range(1,len(self.hidden_layers)):x_deep = F.relu( getattr(self, 'linear_'+str(i+1))(x_deep) )if self.dropout:x_deep = getattr(self, 'linear_'+str(i+1)+'_drop')(x_deep)# Deep + Wide sideswide_deep_input = torch.cat([x_deep, X_w.float()], 1)if not self.activation:out = self.output(wide_deep_input)else:out = self.activation(self.output(wide_deep_input))return outdef fit(self, dataset, n_epochs, batch_size):"""Run the model for the training set at dataset.Parameters:----------dataset (dict): dictionary with the training sets -X_wide_train, X_deep_train, targetn_epochs (int)batch_size (int)"""widedeep_dataset = WideDeepLoader(dataset)train_loader = torch.utils.data.DataLoader(dataset=widedeep_dataset,batch_size=batch_size,shuffle=True)# set the model in training modenet = self.train()for epoch in range(n_epochs):total=0correct=0for i, (X_wide, X_deep, target) in enumerate(train_loader):X_w = Variable(X_wide)X_d = Variable(X_deep)y = (Variable(target).float() if self.method != 'multiclass' else Variable(target))if use_cuda:X_w, X_d, y = X_w.cuda(), X_d.cuda(), y.cuda()self.optimizer.zero_grad()y_pred =  net(X_w, X_d)loss = self.criterion(y_pred, y)loss.backward()self.optimizer.step()if self.method != "regression":total+= y.size(0)if self.method == 'logistic':y_pred_cat = (y_pred > 0.5).squeeze(1).float()if self.method == "multiclass":_, y_pred_cat = torch.max(y_pred, 1)correct+= float((y_pred_cat == y).sum().data[0])if self.method != "regression":print ('Epoch {} of {}, Loss: {}, accuracy: {}'.format(epoch+1,n_epochs, round(loss.data[0],3), round(correct/total,4)))else:print ('Epoch {} of {}, Loss: {}'.format(epoch+1, n_epochs,round(loss.data[0],3)))def predict(self, dataset):"""Predict target for dataset.Parameters:----------dataset (dict): dictionary with the testing dataset -X_wide_test, X_deep_test, targetReturns:--------array-like with the target for dataset"""X_w = Variable(torch.from_numpy(dataset.wide)).float()X_d = Variable(torch.from_numpy(dataset.deep))if use_cuda:X_w, X_d = X_w.cuda(), X_d.cuda()# set the model in evaluation mode so dropout is not appliednet = self.eval()pred = net(X_w,X_d).cpu()if self.method == "regression":return pred.squeeze(1).data.numpy()if self.method == "logistic":return (pred > 0.5).squeeze(1).data.numpy()if self.method == "multiclass":_, pred_cat = torch.max(pred, 1)return pred_cat.data.numpy()def predict_proba(self, dataset):"""Predict predict probability for dataset.This method will only work with method logistic/multiclassParameters:----------dataset (dict): dictionary with the testing dataset -X_wide_test, X_deep_test, targetReturns:--------array-like with the probability for dataset."""X_w = Variable(torch.from_numpy(dataset.wide)).float()X_d = Variable(torch.from_numpy(dataset.deep))if use_cuda:X_w, X_d = X_w.cuda(), X_d.cuda()# set the model in evaluation mode so dropout is not appliednet = self.eval()pred = net(X_w,X_d).cpu()if self.method == "logistic":pred = pred.squeeze(1).data.numpy()probs = np.zeros([pred.shape[0],2])probs[:,0] = 1-predprobs[:,1] = predreturn probsif self.method == "multiclass":return pred.data.numpy()def get_embeddings(self, col_name):"""Extract the embeddings for the embedding columns.Parameters:-----------col_name (str) : column we want the embedding forReturns:--------embeddings_dict (dict): dictionary with the column values and the embeddings"""params = list(self.named_parameters())emb_layers = [p for p in params if 'emb_layer' in p[0]]emb_layer  = [layer for layer in emb_layers if col_name in layer[0]][0]embeddings = emb_layer[1].cpu().data.numpy()col_label_encoding = self.encoding_dict[col_name]inv_dict = {v:k for k,v in col_label_encoding.iteritems()}embeddings_dict = {}for idx,value in inv_dict.iteritems():embeddings_dict[value] = embeddings[idx]return embeddings_dict

最近开通了个公众号,主要分享推荐系统,风控等算法相关的内容,感兴趣的伙伴可以关注下。
在这里插入图片描述


参考:

  1. zhihu Wide and Deep Network;
  2. 论文2016 Wide & Deep Learning for Recommender Systems;
  3. 论文笔记 - Wide and Deep Learning for Recommender Systems;
  4. wide and deep github;
  5. ctr模型汇总;

这篇关于CTR模型:WideDeep 网络的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/218160

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

图神经网络模型介绍(1)

我们将图神经网络分为基于谱域的模型和基于空域的模型,并按照发展顺序详解每个类别中的重要模型。 1.1基于谱域的图神经网络         谱域上的图卷积在图学习迈向深度学习的发展历程中起到了关键的作用。本节主要介绍三个具有代表性的谱域图神经网络:谱图卷积网络、切比雪夫网络和图卷积网络。 (1)谱图卷积网络 卷积定理:函数卷积的傅里叶变换是函数傅里叶变换的乘积,即F{f*g}

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

AI Toolkit + H100 GPU,一小时内微调最新热门文生图模型 FLUX

上个月,FLUX 席卷了互联网,这并非没有原因。他们声称优于 DALLE 3、Ideogram 和 Stable Diffusion 3 等模型,而这一点已被证明是有依据的。随着越来越多的流行图像生成工具(如 Stable Diffusion Web UI Forge 和 ComyUI)开始支持这些模型,FLUX 在 Stable Diffusion 领域的扩展将会持续下去。 自 FLU