深度学习模型复杂度分析大杂烩

news2024/11/19 19:42:28

深度学习模型复杂度分析大杂烩

时间复杂度和空间复杂度是衡量一个算法的两个重要指标,用于表示算法的最差状态所需的时间增长量和所需辅助空间.

在深度学习神经网络模型中我们也通过:

计算量/FLOPS(时间复杂度)即模型的运算次数
访存量/Bytes(空间复杂度)即模型的参数数量

这两个指标来评判深度学习模型的性能

在这里插入图片描述

复杂度对模型的影响:
时间复杂度决定了模型的训练/预测时间。如果复杂度过高,会导致模型训练和预测耗费大量时间,既无法快速的验证想法和改善模型,也无法做到快速的预测。

空间复杂度决定了模型的参数数量。由于维度灾难的限制,模型的参数越多,训练模型所需的数据量就越大,而现实生活中的数据集通常不会太大,这会导致模型的训练更容易过拟合。

经典模型复杂度分析

基本模型框架

模型框架的选择影响模型的复杂性。影响因素包括模型类型(如CNN、GAN)、激活函数(如Sigmoid、ReLU)等。不同的模型框架可能需要不同的复杂性度量和方法,这些度量和方法可能彼此之间无法直接比较。

模型大小

深度模型的大小会影响模型的复杂性。用于测量模型大小的一些常见方法包括参数的数量、隐藏层的数量、隐蔽层的宽度、过滤器的数量和过滤器的大小。在相同的模型框架下,模型的复杂度可以通过相同的复杂度度量对不同大小的模型进行量化,以成为可比较的标准。

优化过程

优化过程影响模型的复杂度,包括目标函数的形式、学习算法的选择和超参数的设置。

数据复杂度

网络模型的主要任务是拟合真实世界中的数据分布问题。而真实世界中的数据规模一般比较大,所以我们一般需要比较复杂的模型才能比较好地拟合。训练模型的数据也会影响模型的复杂性。主要影响因素包括数据维度、数据类型和数据类型分布、由Kolmogorov复杂性度量的信息量等。

img

通常来说,复杂度的研究模型选取有如下两种:

一是指定模型(model-specific)的方法关注于特定类型的模型,并基于结构特征探索复杂性。例如,Bianchini等人和Hanin等人研究了FCNNs的模型复杂性,Bengio和Delalleau关注和积网络的模型复杂性。此外,一些研究进一步提出了激活的限制条件约束非线性特性的函数。

还有一种方法是跨模型(cross-model),当它涵盖多种类型的模型时,而不是多个特定类型的模型,因此可以应用于比较两个或多个更多不同类型的模型。例如,Khrulkov等人比较了建筑物连接对一般RNN、CNN和浅层FCNN复杂性的影响在这些网络结构和张量分解中。

「表达能力」与「有效模型复杂度」

模型的表达能力

模型的表达能力意味着这个模型在不同数据上的表达能力,即性能,综述主要分析方法是从下面四个角度分析。

深度效率(depth efficiency)分析深度学习模型如何从架构的深度获得更好地性能(例如,精确度)。

img

宽度效率(width efficiency)分析深度学习中各层的宽度对模型影响程度。

可表达功能空间(expressible functional space)研究可表达的功能由具有特定框架和指定大小的深模型表示,在不同参数的情况下。

img

最后,VC维度和Rademacher复杂性是机器学习中表达能力的两个经典度量。

模型的有效复杂度

深度学习模型的有效复杂性也称为实际复杂性、实际表达能力和可用容量。

它反映了复杂性具有特定参数化的深部模型所代表的函数。深度学习模型的有效复杂性主要从以下两个方面进行了探讨。

有效复杂性的一般度量(general measures of effective complexity)设计深度学习模型有效复杂性的量化度量。

对高容量低现实现象的调查发现深度学习模型的有效复杂性可能远低于他们的表达能力。一些研究探讨了深度学习模型的有效复杂性和表达能力之间的差距。

img

模型复杂度的应用

这篇论文主要介绍了三个应用,理解模型泛化能力、模型优化、模型选择和设计。

理解模型泛化能力

深度学习模型总是过于参数化,也就是说,它们的参数要多得多,模型参数比最优解和训练样本数多。然而,人们经常发现大型的过参数化神经网络具有良好的泛化能力。一些研究甚至发现更大、更复杂的网络通常更具通用性。这一观察结果与函数复杂性的经典概念相矛盾,例如著名的奥卡姆剃须刀原则,更喜欢简单的定理。

什么导致过度参数化深度学习模型的良好泛化能力?

1、在训练误差为零的情况下,一个网络训练在真实的标签上,导致良好的泛化能力,其复杂度比在随机标签上训练的网络要低得多。

2、增加隐藏单元的数量或参数的数量,从而减少了泛化误差,有望降低复杂度。

3、使用两种不同的优化算法,如果都导致零训练误差,具有较好泛化能力的模型具有较低的复杂度。

优化策略

模型优化关注的是神经网络模型如何建立以及为什么建立,为什么可以成功训练。具体来说,优化一个深度学习模型一般是确定模型参数,使损失函数最小化非凸的。损失函数的设计通常基于一个问题和模型的要求,因此一般包括在训练集上评估的性能度量和其他约束条件。

模型复杂度被广泛用于提供一个度量来进行优化可追踪。例如,有效模型复杂性的度量指标神经网络有助于监测优化过程中模型的变化处理并理解优化过程是如何进行的。这样的度量也有助于验证优化算法新改进的有效性。

Nakkiran等人研究了训练过程中的双下降现象利用有效复杂度度量数据集的最大大小,在该数据集上可以得到零训练误差实现。结果表明,双下降现象是可以表示的作为有效复杂性的函数。Raghu等人和Hu等人提出了新的正则化方法,并证明了这些方法对减小复杂度是有效的。

模型选择和设计

给定一个具体的学习任务,研究人员如何为这个任务确定一个可行的模型结构。给出了各种不同体系结构和不同性能的模型复杂性,研究人员如何从中挑选出最好的模型?这就是模型选择和设计问题。

一般来说,模型的选择和设计是基于两者之间的权衡,预测性能和模型复杂性。

img

一方面,高精度的预测是学习模型的基本目标。模型应该能够捕获隐藏在模型中的底层模式训练数据和实现预测的精度尽可能高。为了表示大量的知识并获得较高的准确度,一个模型具有较高的表达能力,自由度大,体积大,需要更大训练集。在这个程度上,一个具有更多参数和更高的复杂性是有利的。

另一方面,过于复杂的模型可能很难进行训练,可能会导致不必要的资源消耗,例如存储、计算和时间成本。不必要的资源消耗特别是在实际的大规模应用中,应避免使用。为了这个目标,一个更简单的模型比一个更精确的模型更可取。

大模型分析

大模型火出圈已经好久,然而为什么能拿出手的大模型还就是那几个。无论国内还是国外真正的拿的出手的大模型,能打的大模型都不会超过一只手。国内更是如此基本都是基于LLama或者GLM开源的参数在调,百度基本是闭源的算是一个独立自主从零开始训练模型。

理论上讲大模型需要训练的数据是知道的、模型架构也是知道的、最后的效果也是知道,甚至还有论文介绍一些思苦。对于输入输出、架构约束都是知道的这么一个系统,逆向出来应该就是一个半开卷的题目了。但为什么却一直后无来者,这个事情到底难在哪,复杂度在哪,有哪些因素带来了复现复杂度呢?

首先我们可以来分析下复杂度的来源(与工艺流程实际差不多):

1.原料:配比、不同步骤配比

2.流程:需要多少步工艺、每步需要哪些工序组合

3.每阶段如何测评

4.工序之间重复多少次

大模型训练用的就是系统性工程的打法,但是我们大部分人的思考思路还在用单一模块的思路,思维的惯性导致把问题考虑的简单了。国内大部分参与大模型训练的同学还是用单一模块训练的思路在做实验实践,而没有认真的思考考虑如何更上一个层次系统工程的构建这件事情,如何做好实验设计和规划来持续的推进这件事情。个人的建议是这块实验设计应该有宏观的长期的规划和设计,我觉得甚至可以参考系统工程管理做的非常出色的航空航天行业学习(需不需要做的这么重,可以结合实际情况考虑,但是这种系统工程管理设计思路是值得引入的)。

大模型的基础能力

衡量大模型的基础能力最重要的3个要素是:算法、算力、数据

1.参数尺度:可能有更多的维度来衡量算法的强度,可以简单地用参数尺度来衡量,参数尺度是衡量模型复杂性和能力的量化指标。参数规模越大,模型所能支持的复杂问题就越多,所能考虑的维度就越多,简而言之,它就越强大;
2.数据量:该模型是在数据的基础上运行的。模型背后的数据量值越大,模型的性能可能越好;
3.数据质量:数据质量包括数据本身的价值和业务对数据的清理;数据本身在质量上是分层的。例如,用户消费的数据比用户的一般社交属性信息具有更高的价值。数据的值越高,模型的性能就越好;二是业务对数据的清理,体现在数据标注的精细度上;
4.训练次数:模型训练次数越多,模型的经验越多,性能越好;
5.算力:算力的衡量主要是芯片数量、服务器数量和网络能力。计算能力代表了模型的计算量,计算能力是模型发展速度的重要制约因素之一。

在这里插入图片描述

显存优化复杂

显存消耗估计

模型训练时消耗的显存,往往是参数量的几倍还多。不说特别大的,仅以100B模型为例,我们大致估算一下 不做任何显存优化 时,使用AdamOptimizer训练的固定消耗:

Section参数量存储消耗
模型参数本身100B400GB
Adam辅助变量(两份)200B800GB
总计300B1200GB

即使没有列出Activations的消耗,上面的部分应该也比较吓人了。这得堆多少GPU卡,多少台机器?

  • 16GB显卡:75张GPU卡,约等于单机八卡服务器10台;
  • 32GB显卡:38张GPU显卡,约等于单机八卡服务器,5台。

也就是说,即使抠抠索索的使用,也得消耗这么多资源,显存优化不做不行。于是,大量的显存优化工作就必须得上了。

显存优化方法
  1. 合理的计算调度:如DAPPLE中提到的early backward;
  2. Gradient Checkpointing:习惯上称之为重算(Re-computation)
  3. CPU-offload:ZeRO中提到的借用Host memory做辅助变量的offload
  4. Optimization-state优化:切分辅助变量分片存储

上面的有些优化,在目前流行的一些框架上,是需要手动做的。目前也有一些框架在自动化托管这些工作,但是上面这些优化组合,全自动化方案能否做到性能最优,并不容易。

这是第一个难点。

分布式复杂

即使做了显存优化,单卡也绝对不够,分布式方案是必然选择。但这里问题在于:Dense巨无霸模型很难用Naive Data Parallelism训练(单卡放不下一份完整的replica),迫使必须叠加各种各样的并行模式,所以只能是所谓的Hybrid Parallelism。例如可以是如下这种组合方案:

数据并行 + 算子拆分 + 流水并行

大家对数据并行比较熟悉,所以下面只展开后面两项、

算子拆分

算子拆分并不是什么新鲜想法。我用矩阵乘法举个最简单的例子。例如我们有如下变量和矩阵运算:

  • variable矩阵: WWW
  • batch input矩阵 XXX :
  • 输出: Y=WXY=WXY=WX 。

单个矩阵乘法可以分到两个device上计算。我们在工程上要做的就是:将 WWW 切分到两个device上,将 XXX 复制到两个device上,然后两个device分别做矩阵乘法即可。有的时候,切分会带来额外的通信,比如矩阵乘法切到了reduction维度上,为了保持语义正确,就必须再紧跟一个AllReduce通信。

在Megatron-LM中,对Attention Block就做了这样的算子拆分(拆K,Q,V的head维度),像下面这样。

img

Megatron-LM的算子拆分方案

这里复杂之处在于,你不能无脑地将所有算子全部做拆分,因为拆分可能会引入一些额外通信,降低总体吞吐。所以你得做些分析,决定哪些算子被拆分,这得考虑以下因素:

  • Workload的特点:计算量、参数量、Tensor shape等;
  • 硬件拓扑:GPU算力,通信带宽等。

写个程序自动化行不行?能不能让程序自动搜索出来最佳的拆分方案?这取决于你在什么层次上做搜索。以TensorFlow为例,如果在GraphDef上的Operator这个粒度上做,搜索空间肯定爆炸。如果在Layer这个粗粒度上搜索,则是有可能的。但自动化方案也有一定的工作量:

  1. 拆分规则定制:为每种算子都需要定制一个完备的推导方案;
  2. 推导传播算法:推导影响链以及通信的引入(比如引入Reshard);
  3. Cost model:快速评估每种方案的性能;
  4. 高效地搜索算法:在巨大的空间里快速搜索出较好的方案。

现在大部分框架都不支持这种全自动化策略,要么是半自动或纯手工,要么是针对某种模型把它的拆分方案写死。所以只能造轮子解决这个事。

流水并行

不切算子,而是将不同的Layer切分到不同的Device上,就可以形成Pipeline方案。GPipe就是这样一种方案,提出了将一个batch拆分成若干个micro-batch,依次推入到Pipeline系统中,即可消除Bubble time(打时间差:Device 1计算micro-batch 1时,Device 0为空闲状态,正好推入下一个micro-batch)。下面这个图应该能看明白,就不过多解释了。

img

GPipe流水并行方案:F代表forward,B代表Backward。拆分多个micro-batch推入系统,有效地消除了Bubble time

然而,这种方案有显存压力。上图(a)中看到,B0的计算依赖于B1和F0,也就是说F0计算完成后,其Activations不能立即释放,直到B0算完才能丢掉。所以针对F0来说,推N个micro-batch时,我们要保存N份这样的Activations,直到他们的反向计算完成才能释放,显存峰值是很大的。

因此我们又要做显存优化了,我们在DAPPLE中提出了Early Backward方案,通过合理调度计算顺序,及早释放Activations,如下图所示。

img

DAPPLE early backward调度方案。同个数字代表同个micro-batch,蓝色和绿色分别代表前向和反向计算。

和算子拆分类似,全自动化方案工作量不小,比如Pipeline怎么切,才能让通信量小,计算还能均匀,这需要一定的算法和工程量。

而且,在TensorFlow这样的框架上实现Early backward方案,除了让用户在编写模型时强行加上control flow严格控制,没有别的办法。大家自己可以试一试,用TF的Graph mode写这样的调度顺序,是有多么的噩梦,最好的解决方案可能还真就是造个轮子。

混合并行

如果把上述数据并行、算子拆分和流水并行混合起来,复杂度就更高了。

所以分布式,是第二个难点。

AI学习任重而道远。一起加油

参考:理解深度学习模型复杂度评估_全连接层计算复杂度_coco_12345的博客-CSDN博客

​ 裴健团队44页新作:理解深度学习模型复杂度,看这一篇就够了!_腾讯新闻 (qq.com)

​ 大模型训练的复杂度在哪_远洋之帆的博客-CSDN博客

​ (2 封私信) 为什么说大模型训练很难? - 知乎 (zhihu.com)

qq.com)](https://new.qq.com/rain/a/20210319A05DLG00)

​ 大模型训练的复杂度在哪_远洋之帆的博客-CSDN博客

​ (2 封私信) 为什么说大模型训练很难? - 知乎 (zhihu.com)

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

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

相关文章

C++设计模式_04_Strategy 策略模式

接上篇,本篇将会介绍C设计模式中的Strategy 策略模式,和上篇模板方法Template Method一样,仍属于“组件协作”模式,它与Template Method有着异曲同工之妙。 文章目录 1. 动机( Motivation)2. 代码演示Stra…

2023-9-11 拆分-Nim游戏

题目链接&#xff1a;拆分-Nim游戏 #include <iostream> #include <cstring> #include <algorithm> #include <unordered_set>using namespace std;const int N 110;int f[N];int sg(int x) {if(f[x] ! -1) return f[x];unordered_set<int> S;f…

pip和conda的环境管理,二者到底应该如何使用

关于pip与conda是否能混用的问题&#xff0c;Anaconda官方早就给出了回答 先说结论&#xff0c;如果conda和pip在相同环境下掺杂使用&#xff0c;尤其是频繁使用这两个工具进行包的安装&#xff0c;可能会导致环境状态混乱 就像其他包管理器一样&#xff0c;大部分这些问题均…

Python开发手册 — 有勇气的牛排

前言 一、编程规约 二、异常日志 三、单元测试 四、安全规约 4.1 【强制】用户页面/功能进行权限校验 隶属于用户个人的页面或者功能必须进行权限控制校验。 说明&#xff1a;防止没有做水平校验就可随意访问、修改、删除别人的数据&#xff0c;比如查看那他人的私信内容…

浅析Open vSwitch数据结构:哈希表hmap/smap/shash

文章目录 概述hmaphmap数据结构初始化hmap插入节点扩展hmap空间resize函数 删除节点遍历所有节点辅助函数hmap_first辅助函数hmap_next smapsmap数据结构插入节点删除节点查找节点遍历所有节点 shashshash数据结构插入节点删除节点查找节点遍历所有节点 概述 在OVS软件中&…

卡尔曼滤波公式推导(总结)

假设 小车在t时刻的初始状态可以用Pt&#xff08;当前位置&#xff09;&#xff0c;Vt&#xff08;当前速度&#xff09;&#xff0c;Ut表示加速度&#xff1a; 预测&#xff1a; 利用上一个时刻的旧状态和系统的动量模型&#xff08;如加速度&#xff0c;速度等&#xff09;…

Android逆向——脱壳解析

“壳”是一种对程序进行加密的程序&#xff0c;“壳”形象地表现了这个功能。我们可以把被加壳的程序当成食物&#xff0c;而加壳程序就是在外面加上一层坚硬的外壳&#xff0c;防止别人去窃取其中的程序。加壳后的程序依然可以被直接运行。在程序运行时壳的代码先运行&#xf…

修改hosts文件无权限解决办法

文章目录 一、问题描述二、解决办法 一、问题描述 当我们在hosts文件中添加内容后----->点击文件右上角X按钮---->点击保存 系统会弹出我们没有权限的问题 二、解决办法 在搜索栏中搜索cmd---->右键命令提示符---->点击以管理员身份运行 输入cd C:\Windows\Sy…

文件上传漏洞(CVE-2022-30887)

简介 多语言药房管理系统&#xff08;MPMS&#xff09;是用PHP和MySQL开发的&#xff0c;该软件的主要目的是在药房和客户之间提供一套接口&#xff0c;客户是该软件的主要用户。该软件有助于为药房业务创建一个综合数据库&#xff0c;并根据到期、产品等各种参数提供各种报告…

OpenMMLab MMYOLO目标检测环境搭建(一)

1、环境搭建 conda create -n mmyolo python3.7 -y #创建环境 conda activate mmyolo #激活环境 conda install pytorch torchvision torchaudio cudatoolkit10.2 -c pytorch #安装 PyTorch and torchvision (官方)#如果网不好&#xff0c;可以这样安装 pi…

KNN算法回归问题介绍和实现

上篇博客中&#xff0c;介绍了使用KNN算法实现分类问题&#xff0c;本篇文章介绍使用KNN算法实现回归问题。介绍思路是先使用sklearn包提供的方法实现一个KNN算法的回归问题。再自定义实现一个KNN算法的回归问题工具类。 一、sklearn包使用KNN算法 1. 准备数据 使用sklearn包…

【C++基础】观察者模式(“发布-订阅”模式)

本文参考&#xff1a;观察者模式 - 摩根斯 | 爱编程的大丙 观察者模式允许我们定义一种订阅机制&#xff0c;可在对象事件发生时通知所有的观察者对象&#xff0c;使它们能够自动更新。观察者模式还有另外一个名字叫做“发布-订阅”模式。 发布者&#xff1a; 添加订阅者&…

【数据关联(1)】Tracking-by-detection 多目标跟踪范式与“数据关联”的关系说明

这个领域有一些专有名词需要大家清楚&#xff01; 文章目录 1 Tracking-by-detection multi-object tracking(MOT) 范式跟踪器是什么&#xff1f;1.1 关系图&#xff08;个人理解&#xff0c;如有错误请指正&#xff09;1.2 跟踪器有哪些&#xff1f; 2、核心部分“数据关联”…

Python格式化字符串(格式化输出)

print() 函数的用法&#xff0c;这只是最简单最初级的形式&#xff0c;print() 还有很多高级的玩法&#xff0c;比如格式化输出&#xff0c;这就是本节要讲解的内容。 熟悉C语言 printf() 函数的读者能够轻而易举学会 Python print() 函数&#xff0c;它们是非常类似的。 pri…

SegNetr: 重新思考 U 形网络中的局部-全局交互和跳过连接

SegNetr 会议分析摘要贡献方法整体框架1. SegNetr Block2.Information Retention Skip Connection 实验1.对比实验2.消融实验2.1 Effect of local-global interactions.2.2 Effect of patch size2.3 Effect of IRSC 可借鉴参考 会议分析 论文出处&#xff1a; arXiv预印版 除了…

C++在C语言基础上的优化

目录 一、命名空间 1、命名空间的定义 2、命名空间的使用 二、输入&输出 三、缺省参数 1、缺省参数的概念 2、缺省参数的分类 四、函数重载 五、引用 1.引用的概念 2.引用的特性 3、引用和指针的区别 六、内联函数 七、基于范围的for循环 一、命名空间 命名空…

计算机网络第六章——应用层(下)

等闲变却故人心&#xff0c;却道故人心易变 文章目录 用户代理就是用户和电子邮件系统之间的一个接口&#xff0c;通常都是运行在电脑中的一个程序&#xff0c;用户代理又可以称为电子邮件客户端软件&#xff0c;用户代理可以为用户提供一个比较友好的接口&#xff0c;邮件服务…

详解初阶数据结构之顺序表(SeqList)——单文件实现SeqList的增删查改

目录 一、线性表 二、顺序表 2.1概念及结构 2.2接口实现 2.3动态顺序表的创建 2.3动态顺序表的初始化 2.3.1传值初始化 2.3.2传址初始化 2.4动态顺序表的清空 2.5动态顺序表的扩容 2.6动态顺序表内容的打印 三、动态顺序表的使用 3.1尾插尾删 3.1.1尾插 3.1.2尾删…

集合框架和泛型二

一、Set接口 1. Set接口概述 java.util.Set 不包含重复元素的集合、不能保证存储的顺序、只允许有一个 null。 public interface Set<E> extends Collection<E>抽象方法&#xff0c;都是继承自 java.util.Collection 接口。 Set 集合的实现类有很多&#xff0c;…

分布式AKF拆分原则

目录 1 前言2 什么是AKF3 如何基于 AKF X 轴扩展系统&#xff1f;4 如何基于 AKF Y 轴扩展系统&#xff1f;5 如何基于 AKF Z 轴扩展系统&#xff1f;6 小结 1 前言 当我们需要分布式系统提供更强的性能时&#xff0c;该怎样扩展系统呢&#xff1f;什么时候该加机器&#xff1…