特征交叉系列:DCN-Mix 混合低秩交叉网络理论和实践

DCN-Mix和DCN-V2的关系

DCN-Mix(a mixture of low-rank DCN)是基于DCN-V2的改进版,它提出使用矩阵分解降低DCN-V2的时间空间复杂度,又引入多次矩阵分解来达到类似混合专家网络MOE的效果从而提升交叉层的表征能力,若读者对DCN-V2不甚了解可以参考上一节[特征交叉系列:Deep&Cross(DCN-V2)理论和实践]做知识铺垫。


DCN-V2权重矩阵的低秩性和矩阵分解

在DCN-V2中核心的参数是交叉层的权重矩阵W,该参数是M×M的方阵,其中M是所有输入embedding拼接后的向量总长度,每一层交叉之间W不共享,W矩阵需要学习的参数数量能占到所有参数量的70%以上,而进一步作者发现随着网络的训练,W矩阵的奇异值出现快速下降呈现出低秩特性,代表该矩阵存在信息冗余,因此可以考虑通过矩阵分解来进行特征提取和信息压缩。
在PyTorch中可以通过torch.linalg.svd计算出矩阵的奇异值,例如

>>> a = torch.tensor([[1, 1], [1, 1.1]])
>>> u, s, v = torch.linalg.svd(a)
>>> print(s)
tensor([2.0512, 0.0488])

其中s是对角阵,斜对角线上的值就是奇异值,a矩阵的第二行几乎可以从第一行线性变换而来,因此s各位置上的奇异值差距极大,第一个奇异值基本携带了全部的矩阵信息。
在DCN-V2的训练代码里面,打印出第一个交叉层初始化的W矩阵和训练早停后W矩阵的奇异值,奇异值的长度和输入长度M一致,代码如下

# 初始化时
model = DCN(field_num=10, feat_dim=72, emb_num=16, order_num=2, dropout=0.1, method='parallel').to(DEVICE)
init_s = torch.linalg.svd(model.cross_net.cell_list[0].w)[1].cpu().detach().numpy().tolist()

# 早停时
if early_stop_flag:
    train_s = torch.linalg.svd(model.cross_net.cell_list[0].w)[1].cpu().detach().numpy().tolist()
    break

奇异值列表中元素大小逐个递减,对init_s和train_s分别做最大最小归一化,要求第一个奇异值归因化为1,

init_s = [(x - min(init_s)) / (max(init_s) - min(init_s)) for x in init_s]
train_s = [(x - min(train_s)) / (max(train_s) - min(train_s)) for x in train_s]

然后做图看一下初始矩阵的奇异值和收敛后的奇异值的各个位置元素的大小情况

import matplotlib.pylab as plt
plt.scatter(list(range(len(init_s))), init_s, label='init', s=3)
plt.scatter(list(range(len(train_s))), train_s, label='learned', s=3)
plt.legend(loc=0)
plt.show()

init和learned奇异值下降对比

相比于初始化阶段(蓝线),模型收敛后(橙线)的W矩阵奇异值急速下降,说明头部的奇异值已经携带了大部分矩阵信息,W矩阵可以考虑做压缩。
在论文中作者将W分解为U,V两个矩阵的相乘,其中U,V都是维度为[M, R]的二维矩阵,M和输入等长,R<=M/2,公式如下

矩阵分解

此时一个交叉权重的参数数量由M平方降低为2×MR。


DCN-Mix的混合专家网络

DCN-Mix使用矩阵UV分解来逼近原始的交叉矩阵W,受到MOE(Mixture of Experts)混合专家网络的启发,作者对W进行多次矩阵分解,单个矩阵分解相当于单个专家网络(Expert)在子空间学习特征交叉,再引入门控机制(Gate)对多个子空间的交叉结果进行自适应地融合,从而提高交叉层的表达能力,DCN结合MOE的示意图如下

MOE示意图

其中该层的输入Input x分别进入n个Expert专家网络,专家网络中包含UV矩阵相乘,同时Input x输入给一个门控网络Gate+Softmax输出n个权重标量,最后Input x会和加权求和的专家网络结果做残差连接。
将矩阵分解和MOE结合起来形成最终的交叉层公式如下

结合MOE的矩阵分解交叉层

相比于DCN-V2,等号左侧的哈达玛积部分改为了一个Σ加权求和的UV矩阵逼近,而右侧的残差连接放到最后和MOE的结果一起做残差连接。


DCN-Mix在PyTorch下的实践

本次实践的数据集和上一篇特征交叉系列:完全理解FM因子分解机原理和代码实战一致,采用用户的购买记录流水作为训练数据,用户侧特征是年龄,性别,会员年限等离散特征,商品侧特征采用商品的二级类目,产地,品牌三个离散特征,随机构造负样本,一共有10个特征域,全部是离散特征,对于枚举值过多的特征采用hash分箱,得到一共72个特征。
DCN-Mix的PyTorch代码实现如下

class Embedding(nn.Module):
    def __init__(self, feat_num, emb_num):
        super(Embedding, self).__init__()
        self.embedding = nn.Embedding(feat_num, emb_num)
        nn.init.xavier_normal_(self.embedding.weight.data)

    def forward(self, x):
        # [None, filed_num] => [None, filed_num, emb_num] => [None, filed_num * emb_num]
        return self.embedding(x).flatten(1)


class DNN(nn.Module):
    def __init__(self, input_num, hidden_nums, dropout=0.1):
        super(DNN, self).__init__()
        layers = []
        input_num = input_num
        for hidden_num in hidden_nums:
            layers.append(nn.Linear(input_num, hidden_num))
            layers.append(nn.BatchNorm1d(hidden_num))
            layers.append(nn.ReLU())
            layers.append(nn.Dropout(p=dropout))
            input_num = hidden_num
        self.mlp = nn.Sequential(*layers)
        for layer in self.mlp:
            if isinstance(layer, nn.Linear):
                nn.init.xavier_normal_(layer.weight.data)

    def forward(self, x):
        return self.mlp(x)


class CrossCell(nn.Module):
    """一个交叉单元"""

    def __init__(self, input_num, r):
        super(CrossCell, self).__init__()
        self.v = nn.Parameter(torch.randn(input_num, r))
        self.u = nn.Parameter(torch.randn(input_num, r))
        self.b = nn.Parameter(torch.randn(input_num, 1))
        nn.init.xavier_normal_(self.v.data)
        nn.init.xavier_normal_(self.u.data)

    def forward(self, x0, xi):
        # [None, emb_num] => [None, emb_num, 1]
        xi = xi.unsqueeze(2)
        x0 = x0.unsqueeze(2)
        # [r, input_num] * [None, emb_num, 1] => [None, r, 1]
        # [input_num, r] * [None, r, 1] => [None, emb_num, 1]
        xii = (torch.matmul(self.u, torch.matmul(self.v.t(), xi)) + self.b) * x0
        return xii  # [None, emb_num, 1]


class MOECrossCell(nn.Module):
    def __init__(self, input_num, r, k):
        super(MOECrossCell, self).__init__()
        self.k = k
        self.cross_cell = nn.ModuleList([CrossCell(input_num, r) for i in range(self.k)])
        self.gate = nn.Linear(input_num, self.k)
        nn.init.xavier_normal_(self.gate.weight.data)

    def forward(self, x0, xi):
        # [None, emb_num] => [None, emb_num, 1]
        xii = xi.unsqueeze(2)
        export_out = []
        for i in range(self.k):
            cross_out = self.cross_cell[i](x0, xi)
            # [[None, emb_num, 1], [None, emb_num, 1], [None, emb_num, 1], [None, emb_num, 1]]
            export_out.append(cross_out)
        export_out = torch.concat(export_out, dim=2)  # [None, emb_num, 4]
        # [None, k] => [None, 1, k]
        gate_out = self.gate(xi).softmax(dim=1).unsqueeze(dim=1)
        # [None, emb_num, 4] * [None, 1, k] = [None, emb_num, k] => [None, emb_num, 1]
        out = torch.sum(export_out * gate_out, dim=2, keepdim=True)
        out = out + xii  # [None, emb_num, 1]
        return out.squeeze(2)


class CrossNet(nn.Module):
    def __init__(self, order_num, input_num, r, k):
        super(CrossNet, self).__init__()
        self.order = order_num
        self.cell_list = nn.ModuleList([MOECrossCell(input_num, r, k) for i in range(order_num)])

    def forward(self, x0):
        xi = x0
        for i in range(self.order):
            xi = self.cell_list[i](x0=x0, xi=xi)
        return xi


class DCN(nn.Module):
    def __init__(self, field_num, feat_dim, emb_num, order_num, r=16, k=4, dropout=0.1, method='parallel',
                 hidden_nums=(128, 64, 32)):
        super(DCN, self).__init__()
        input_num = field_num * emb_num
        self.embedding = Embedding(feat_num=feat_dim, emb_num=emb_num)
        self.dnn = DNN(input_num=input_num, hidden_nums=hidden_nums, dropout=dropout)
        self.cross_net = CrossNet(order_num=order_num, input_num=input_num, r=r, k=k)
        if method not in ('parallel', 'stacked'):
            raise ValueError('unknown combine type: ' + method)
        self.method = method
        linear_dim = hidden_nums[-1]
        if self.method == 'parallel':
            linear_dim = linear_dim + input_num
        self.linear = nn.Linear(linear_dim, 1)
        nn.init.xavier_normal_(self.linear.weight.data)

    def forward(self, x):
        emb = self.embedding(x)  # [None, field * emb_num]
        cross_out = self.cross_net(emb)  # [None, input_num]
        if self.method == 'parallel':
            dnn_out = self.dnn(emb)  # [None, input_num]
            out = torch.concat([cross_out, dnn_out], dim=1)
        else:
            out = self.dnn(cross_out)  # [None, input_num]
        out = self.linear(out)
        return torch.sigmoid(out).squeeze(dim=1)

在CrossCell模块中完成了一个给予UV逼近的交叉操作,在MOECrossCell模块中完成了MOE和残差连接,其中export_out和gate_out分别为专家网络的输出和门控机制的权重。
本例全部是离散分箱变量,所有有值的特征都是1,因此只要输入有值位置的索引即可,一条输入例如

>>> train_data[0]
Out[120]: (tensor([ 2, 10, 14, 18, 34, 39, 47, 51, 58, 64]), tensor(0))

x的长度为10代表10个特征域,每个域的值是特征的全局位置索引,从0到71,一共72个特征。


DCN-Mix调参和效果对比

对阶数(order_num)和融合策略(method)这两个参数进行调参,分别尝试1~4层交叉层,stacked和parallel两种策略,采用10次验证集AUC不上升作为早停条件,验证集的平均AUC如下

DCN调参AUC并行parallel串行stacked
1层交叉(2阶)0.63450.6321
2层交叉(3阶)0.63280.6323
3层交叉(4阶)0.63310.6333
4层交叉(5阶)0.63400.6331

结论依旧是parallel效果好于stacked,其中一层交叉的并行parallel达到验证集最优AUC为0.6345。
再对比一下之前文章中实践的FM,FFM,PNN,DCN-V2等一系列算法,验证集AUC和参数规模如下

算法AUC参数量
FM0.6274361
FFM0.63172953
PNN*0.634229953
DeepFM0.632212746
NFM0.632910186
DCN-parallel-30.6348110017
DCN-stacked-30.6344109857
DCN-Mix-parallel-10.634554501
DCN-Mix-stacked-30.633397869

使用矩阵分解逼近策略的DCN-Mix略低于原生的DCN-V2,但是还是超越一众FM系列的算法,其中以同样是三层交叉的stacked DCN为例,DCN-Mix的参数量相比于DCN-V2有所降低,也印证了论文中提到的“在模型效果和部署延迟之间找到一个平衡”。

最后的最后

感谢你们的阅读和喜欢,我收藏了很多技术干货,可以共享给喜欢我文章的朋友们,如果你肯花时间沉下心去学习,它们一定能帮到你。

因为这个行业不同于其他行业,知识体系实在是过于庞大,知识更新也非常快。作为一个普通人,无法全部学完,所以我们在提升技术的时候,首先需要明确一个目标,然后制定好完整的计划,同时找到好的学习方法,这样才能更快的提升自己。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img

四、AI大模型商业化落地方案

img

五、面试资料

我们学习AI大模型必然是想找到高薪的工作,下面这些面试题都是总结当前最新、最热、最高频的面试题,并且每道题都有详细的答案,面试前刷完这套面试题资料,小小offer,不在话下。
在这里插入图片描述

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Faiss assertion ‘err == cudaSuccess‘ failed in void faiss::gpu:runL2Norm()

Faiss assertion ‘err cudaSuccess’ failed in void faiss::gpu:runL2Norm(). details:CUA error 209 no kernel image is available for execution on the device 本人使用的ubuntu 22.04系统&#xff0c;conda的环境。使用pip安装faiss-gpu出现的问题。 pip install fai…

38页 | 工商银行大数据平台助力全行数字化转型之路(免费下载)

【1】关注本公众号&#xff0c;转发当前文章到微信朋友圈 【2】私信发送 工商银行大数据平台 【3】获取本方案PDF下载链接&#xff0c;直接下载即可。 如需下载本方案PPT/WORD原格式&#xff0c;请加入微信扫描以下方案驿站知识星球&#xff0c;获取上万份PPT/WORD解决方案&a…

【C++】list的基本使用

&#x1f497;个人主页&#x1f497; ⭐个人专栏——C学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 导读 1. list基本介绍 2. list构造函数 3. list迭代器 4. list容量 5. list的修改操作 6. list排序 导读 今天我们来正式…

企业该如何选择GPU云服务器配置?

无论是个人开发者还是企业用户&#xff0c;对于如何选购最佳的云服务器配置&#xff0c;都是比较头疼与纠结的。因为GPU云服务器的配置众多&#xff0c;各种组合有各自优势与用途&#xff0c;很难一下子做出决策。接下来&#xff0c;我们来简单分析下各配置应该怎么选购。 1、地…

k8s和deepflow部署与测试

Ubuntu-22-LTS部署k8s和deepflow 环境详情&#xff1a; Static hostname: k8smaster.example.net Icon name: computer-vm Chassis: vm Machine ID: 22349ac6f9ba406293d0541bcba7c05d Boot ID: 605a74a509724a88940bbbb69cde77f2 Virtualization: vmware Operating System: U…

红海边的这座城,如何点亮人类可持续发展之梦

导读&#xff1a;造一座100%清洁能源供电的城市&#xff1f; 城市是人类最伟大的成就之一&#xff0c;数千年来城市承载了人类文明的跃迁。21世纪&#xff0c;在人类追求可持续发展的蓝图中&#xff0c;城市有了新的使命。 容纳全球50%以上人口&#xff0c;但碳排放量超过70%的…

植物大战僵尸杂交版 2.0 下载及配置图文教程

文章目录 Part.I IntroductionPart.II 下载Chap.I 下载地址Chap.II 网盘直链下载 Part.III 配置Chap.I 解压与安装Chap.II 加载存档Chap.III 其他设置 Reference Part.I Introduction 最近看大仙儿直播植物大战僵尸&#xff0c;觉得挺好玩的。它大概长这样&#xff1a; 就上网…

怎么取消Intellij IDEA中的项目和Git仓库的关联

这篇文章分享一种最简单的方法&#xff0c;取消已经开启代码控制的项目与git代码仓库的关联。 打开项目的位置&#xff0c;然后点击文件管理器上方的查看选项卡&#xff0c;勾选【隐藏的项目】。 然后可以看到项目的文件夹下显示了一个隐藏的.git文件夹&#xff0c;直接把这个.…

英伟达Blackwell芯片正式投入生产 | 百能云芯

在近日的一场公开活动中&#xff0c;英伟达公司的创始人和首席执行官黄仁勋正式宣布&#xff0c;备受瞩目的Blackwell芯片已成功投产。 黄仁勋在讲话中强调&#xff0c;英伟达将继续坚持其数据中心规模、一年节奏、技术限制、一个架构的战略方向。这意味着英伟达将继续运用业界…

一个简单好用的 C# Animation Easing 缓动动画类库

文章目录 1.类库说明2.使用步骤2.1 创建一个Windows Form 项目2.2 安装类库2.3 编码2.4 效果 3.该库支持的缓动函数4.代码下载 1.类库说明 App.Animations 类库是一个很精炼、好用的 csharp easing 动画库 基于 net-standard 2.0提供 Fluent API&#xff0c;写代码非常舒服。…

项目3:从0开始的RPC框架

一. 基本概念 区别于传统的增删改查型的业务项目&#xff0c;本项目侧重于开发框架&#xff0c;并且涉及架构方面的技术知识点。 1. 什么是RPC&#xff1f; 远程过程调用&#xff08;Remote Procedure Call&#xff09;&#xff0c;是一种计算机通信协议&#xff0c;它允许程…

02眼电识别眼动--软件V1.0

对应视频链接点击直达 01项目点击下载&#xff0c;可直接运行&#xff08;含数据库&#xff09; 02眼电识别眼动--软件V1.0 对应视频链接点击直达构思结语其他以下是废话 构思 对于软件&#xff0c;主要就是接收数据、处理数据、储存和显示数据。 这是主要页面&#xff0c;…

爬取股票数据python

最近在搜集数据要做分析&#xff0c;一般的数据来源是一手数据&#xff08;生产的&#xff09;和二手数据&#xff08;来自其他地方的&#xff09;。 今天我们爬取同花顺这个网站的数据。url为&#xff1a;https://data.10jqka.com.cn/ipo/xgsgyzq/ 话不多说直接上代码。有帮…

QT项目实战: 五子棋小游戏

目录 内容介绍 一.添加头文件 二.画棋盘 1.宏定义 2.棋盘 三.画棋子 四.获取棋子摆放位置 五.判断棋子存在 六.判断胜利 1.变量定义和初始化 2.检查获胜条件 3.游戏结束处理 七.重绘 八.效果展示 九.代码 1.mainwindow.h 2.mainwindow.cpp 3.chessitem.h 4…

部署kubesphere报错

安装kubesphere报错命名空间terminted [rootk8smaster ~]# kubectl apply -f kubesphere-installer.yaml Warning: apiextensions.k8s.io/v1beta1 CustomResourceDefinition is deprecated in v1.16, unavailable in v1.22; use apiextensions.k8s.io/v1 CustomResourceDefini…

【Oracle篇】rman全库异机恢复:从单机环境到RAC测试环境的转移(第五篇,总共八篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…

车载以太网测试要测些什么呢?

车载以太网测试大致可以分成两块&#xff1a;TC8测试和以太网通信测试。 TC8测试全称TC8一致性测试&#xff0c;其规范由OPEN联盟制定&#xff0c;包括车载以太网ECU从物理层到应用层的各层互操作性以及常规基础功能服务。目的在于提高不同ECU之间的兼容性。 TC8测试规范可以…

C++STL---stack queue知识汇总

前言 C将stack和queue划归到了Containers中&#xff0c;但严格的说这并不准确&#xff0c;stack和queue实际上已经不再是容器了&#xff0c;而是属于容器适配器&#xff0c;适配器做的功能是转换&#xff0c;即&#xff1a;它不是直接实现的&#xff0c;而是由其他容器封装转换…

ruoyi若依二次开发怎么添加扫描自己的controller和mapper,配置三个地方即可。

概要 首先&#xff0c;添加在com.ruoyi外的类&#xff0c;项目启动后&#xff0c;调用接口&#xff0c;是会返回404找不到的。 必须要对这以外的接口类进行配置。目录结构如下&#xff1a; 解决步骤 一、添加 com.ruoyi.framework.config 下&#xff1a; // 指定要扫描的M…

深度学习革命-AI发展详解

深度学习革命 《深度学习革命》是一部引人深思的作品&#xff0c;详细讲述了深度学习技术的发展历程及其对各个行业的深远影响。由杰出的计算机科学家、深度学习专家撰写&#xff0c;这本书不仅适合科技领域的专业人士阅读&#xff0c;也为普通读者提供了一个理解人工智能革命…