演讲嘉宾 | 张祥雨(旷视研究院主任研究员、基础模型组负责人)

编辑 | Just

出品 | AI科技大本营(ID:rgznai100)

基础模型是现代视觉识别系统中一个至关重要的关注点。基础模型的优劣主要从精度、速度或功耗等角度判定,如何设计模型应对复杂应用场景是非常重要的课题。

近日,由新一代人工智能产业技术创新战略联盟(AITISA)指导,鹏城实验室、北京智源人工智能研究院支持,专业中文 IT 技术社区 CSDN 主办的 2019 中国 AI 开发者大会(AI ProCon 2019)在北京举办。在计算机视觉技术专题,旷视研究院主任研究员、基础模型组负责人张祥雨主要从轻量级架构、模型裁剪、模型搜索三大思路讲述了高效轻量级深度模型的研究和实践。

轻量级架构是模型设计最简单,也是最彻底的做法。而模型裁剪的思路是,先设计一个相对比较重量级的架构,但是通过一些模型裁剪的方法裁下来,得到一个能在端上实时跑的模型。模型搜索则利用模型搜索的方法自动完成模型设计和设备匹配。

其中,张祥雨重点讲述了模型搜索。在他看来,目前模型搜索在轻量级模型设计领域,已逐渐成为最重要的研究方向之一。模型搜索在模型结构的排列组合、结构超参数的调优方面,相对人工设计有明显优势,不过搜索空间设计的好坏很大程度上依靠人工经验。他同时指出,人工设计在网络基本单元挖掘等方面目前仍不可替代,不过,目前已经有相关的NAS工作进行初步尝试。

他还提到模型搜索所面临的的问题和挑战,这包括精度、效率和灵活性的权衡,搜索空间设计,模型搜索的稳定性、可解释性和可重现性以及复杂Pipeline下高效的模型搜索与流程优化。

此外,张祥雨也提到模型设计的其他思路,比如低精度量化,浮点运算通常比较慢,相反用低精度运算可以实现很明显的模型加速。通过知识蒸馏或高效的底层实现也可以进行模型加速,他们会使用以上六种甚至更多的方案综合进行模型的设计。

以下为张祥雨演讲内容实录,A科技大本营(ID:rgznai100)整理:

旷视研究院基础模型组是偏研发类的部门,主要是为其他各个部门提供优质的基础模型,对算法本身的创新性和实用性都有比较高的要求。

视觉理解中,特征表示是最为关键的问题。在深度学习之前的手工设计时代,为了完成了一个视觉理解的任务,通常情况下特征抽取是最重要的模块。进入深度学习时代后这个观点仍然没变,特征仍然是我们物体识别最重要的点。

 模型设计概述

深度学习时代,我们把抽取特征的结构称为基础模型,CNN是目前在视觉上使用最广泛的模型,我们要进行一项物体检测,比较典型的任务是都需要一个非常强力的基础模型作为支撑,这个基础模型是现代视觉识别系统的一个最为关键的点。

基础模型是最为关键的点有两层含义:第一,一个好的基础模型对整个系统的性能提升是决定性的,从精度或者从准确率来说优秀的基础模型起到了本质的作用。第二,从模型的实用性来说,搞深度学习的都知道基础模型通常占据了视觉系统的绝大部分运行时间,也吃了绝大多数运行功耗和存储。不管从精度还是从速度或功耗的角度,基础模型都是视觉系统的核心部分。

为了研究一个非常好的深度基础模型,我们总是会从精度和实用性两个维度进行探索,这两个维度通常来讲有一定的互斥。我们都知道从2015年的AlexNet开始,在准确率这个角度得到了非常大的发展,到了打败人类的精度。然而准确度的提升并没有同步带来实用性的提升,大家从右边图可以明显看出来,准确度蓝色这条线在不断提升,Error在不断下降,但计算复杂度也在持续上升。典型的比赛模型计算复杂度可能要到4GFLOPs以上,典型的手机端实时模型是小于100MFLOPs,中间有好几个数量级。
另外,学术界习惯用理论计算量来衡量复杂度。但理论复杂度低的模型并不总是伴随着实际复杂度低。模型的实用性很多时候和具体的业务需求和目标的平台都有关。举个例子,最适合分类的模型并不适合于做检测和做分割,我们要把GPU的产品落地到一个ARM或者手机芯片端,模型结构有非常大的不同,面对非常复杂的需求我们如何针对特定的任务和平台设计最好的模型?
模型设计应用案例,这是我们的手机解锁业务。手机解锁这个应用非常简单,拿出手机,我们现在提供人脸解锁,50毫秒内发生的内容要经过哪些步骤呢?第一步我们要做人脸检测,判断画面里有没有脸以及脸的位置,看起来是非常简单的,但是考虑到手机大部分时候都在口袋里,大家都知道检测算法对计算的资源消耗通常也最大,如果你反复运行检测任务手机很快就会发热。虽然第一步检测看起来是非常简单的任务,但是具体到手机解锁业务也有很多具体需求。紧接着我们需要对人脸属性进行判断,最典型的是视线有没有盯着手机。
第三步要进行活体检测,判断是不是靠一个相片或屏幕进行的攻击。最后一步进行比对识别,最后出一个验证结果。
所有这些步骤都涉及一个识别问题,不同步骤使用的模型特点和任务也是不同的。检测需要处理很大分辨率的(图像),需要跑到一个非常高的速度;而对于人脸识别和活体检测任务,实时性要求相对低一些(因为用户不可能总是盯着这个手机),但是要求精准度非常高。所以如何设计模型应对不同的应用场景也是非常重要的课题。
高效模型设计的基本思路
我简单介绍一下我们团队在高效模型设计的基本思路,主要有六点。
第一点最简单,我们直接设计一个轻量级架构,这是最简单也是最彻底的做法。第二种思路,我们可以设计一个相对比较重量级的架构,但是通过一些模型裁剪的方法把它裁下来,得到一个能在端上实时跑的。第三种可以建立一种模型搜索,利用模型搜索的方法自动完成模型设计和设备匹配。还有一些其他的思路,比如低精度量化,浮点运算通常比较慢,相比之下,使用低精度可以实现很明显的加速。我们还可以用知识蒸馏或高效的底层实现进行模型加速,旷视会使用这六种甚至更多的方案综合进行模型的设计。
轻量级架构
我主要分享前三种思路。首先是轻量级架构,轻量级架构是什么意思?大家会关注很多论文,这些论文为了达到很高的精度或处于学术界的考虑,会设计一个比较复杂的模型。而在具体实践中,通常我们会综合考虑设备的运行时间和任务特性进行统筹,综合使用多种设计思想。这里我们总结出了两个轻量级模型设计的总体原则:
第一个原则是我们要在有限的计算复杂度实现尽可能高的模型表示能力。学术界提出了很多解决方案。比如采用高效的卷积计算方式如Xception、MobileNet v1等提出了深度可分离卷积;还有一些工作着眼于增加有效的通道数量,例如Bottleneck结构(ResNeXt等);以及引入特征复用(如DenseNet,Res2Net)等思路。
我们前年提出的ShuffleNet v1网络模型就遵循了这样的设计思路。它采用深度可分离卷积+多层分组卷积的结构单元,在较小的复杂度下实现较高的模型能力,同时尽可能提高通道数量。但是这种结构会带来一些副作用,比如通道之间缺少信息交流,因此我们引入了通道重排的操作来解决这一问题。
这个结构在移动端可以非常高效的执行。但我们现在已经不使用了,这个模型虽然理论复杂度较低,但是在高并行的设备(如GPU)实际效率并不好。主要原因是里面使用了大量的分组卷积,这在GPU上执行非常低效。
由此我们引入了第二个设计原则。我们认为要想设计一个高效的模型不能只考虑理论复杂度,还需要尽可能在设备上有更高的实际执行速度。例如对于很多模型,虽然理论上卷积运算占据了大部分复杂度,但是实际执行时其他操作也会占用大量时间。影响实际执行速度的因素不仅有理论计算量,还有计算/访存比、模块并行度、设备特性/实现效率等。
那么,考虑了实际执行速度以后我们能不能设计一些更好的模型?这里我们提出了一些设计准则。第一,我们在设计卷积的时候可以让它的输入输出通道数量尽可能接近,在相同的计算量下可以做到访存量最小。第二,需要谨慎使用分组卷积,因为分组卷积大幅提升了内存访问量,还增加了高效实现的难度。第三,要设法减少网络碎片。碎片化操作一大特点是计算量少访存量大,不太容易实现非常高的并行,所以这种操作也要尽可能减少。第四,逐元素运算不可忽视。虽然算理论复杂度的时候不会计算在内,但是运行的时候也会带来很多开销。
基于这些原则大家再重新审视一下学术界的模型,我们可以看到很多模型并不适合落地使用。它们普遍违反了高效执行的准则,并不适合在目前大部分设备上使用。那么什么样的结构在设备上更为高效呢?
这是我们去年提出的ShuffleNet v2的结构,它在设计的时候综合考虑了前面说的四点原则,所以它在设备上可以得到非常高的速度。它用了特征复用的特性,保证高速度的同时还有非常高的精度。从这个图表可以看出,相对谷歌的MobileNet系列,v2这个结构无论在ARM还是GPU端都达到了最优精度和速度的权衡。最近我们对v2进行了进一步增强,比如引入一些AutoML的技术和Swish以后,v2达到了更高的精度。这个模型在我们公司的绝大多数产品得到了广泛使用。
刚刚是说在小模型方面,v2在大模型方面也有非常好的发挥。把ShuffleNet v2的大小扩展到比较大尺寸以后,和目前学术界最好的模型相比,我们发现达到相同精度的时候理论计算量减了将近一半。另外这个模型不只适用于分类,它在检测上帮助我们拿到了去年COCO的四个项目冠军。例如,COCO物体检测单模型性能达到mmAP 56%+。
大家可能会质疑我们在公司里刷大模型有什么用,其实是非常有用的。虽然不能直接部署在业务端,但是这种大模型的精度非常高,它可以代替人工完成很大一部分数据清洗的任务。此外借助模型蒸馏技术,大模型还可以可以带动小模型达到非常高的性能。
前面回顾了模型设计的几个指导原则。模型设计是不是只有这几个原则呢?当然不是了,模型设计是非常细碎的,在实际业务中针对不同平台和不同业务场景都需要设计。对于不同平台来说,我们公司的很多产品横跨云端芯三大平台。在云上我们会选择结构规则、并行度很高的大模型,比如最原始的ResNet,虽然已经是比较老的模型,但是它在GPU上运行效率非常高,主要在云上使用。在端上靠ShuffleNet系列,可以平衡精度和速度。而在芯片上我们自己有相关的芯片研发,会选择量化后的模型进行部署。
前面说的是平台。而对于任务来说,我们需要针对不同的任务设计不同的模型。举个例子,前不久我们提出了ThunderNet模型,达到了detection最大的速度和精度的平衡。它的设计要点是专门考虑了detection模型的具体要求:首先在骨干网络上继续使用ShuffleNet v2,这是一个修改版,针对detection的具体要求进行了专门的优化。detection head部分则使用了一个LightHead R-CNN。相比于业界广泛使用的SSD系列,ThunderNet实现了数量级的提升,无论是速度还是精度都超过了目前最好的水平。
对于语义分割任务,我们也提出了高性能模型DFANet,它是我们在手机拍摄这条产品线的模型经过整理归纳之后发表的。它的设计要点包括:首先,在骨干网络上使用了Xception,因为语义分割需要非常大的感受野,Xception的结构更适合做语义分割的任务。其次,我们通过多尺度特征融合和特征复用实现高性能。
这里给大家展示一些结果。相对于业界广泛使用的模型,DFANet实现了精度和速度的全面提升。这个网络已经落地到我们的手机算法产品中,用于手机端的单摄虚化。它的技术原理非常简单,就是一个语义分割,分割出前景和背景,只要你分割得足够准确,我们就可以模拟出一种长焦摄像头的背景虚化效果来突出前景。听起来很简单,但是实现难度很大,主要原因是需要在手机这样一个低功耗的设备上实现非常高速度的实时分割,而且分割得必须非常精准。当然这里还配合了一些其他的技术。
前面我说的大部分模型已经开源,这里给出一些资源。
ShuffleNet v1
https://github.com/megvii-model/ShuffleNet-Series/tree/master/ShuffleNetV1
ShuffleNet v2
https://github.com/megvii-model/ShuffleNet-Series/tree/master/ShuffleNetV2
ShuffleNet v2+
https://github.com/megvii-model/ShuffleNet-Series/tree/master/ShuffleNetV2
ShuffleNet v2 Large
https://github.com/megvii-model/ShuffleNet-Series/tree/master/ShuffleNetV2.Large
模型搜索
前面说了轻量级架构的设计思路。那么在高效轻量级模型设计领域还有哪些思路?目前最火的是使用模型搜索,利用机器来代替人工自动完成模型设计。过去,轻量级模型设计是一个非常依靠经验的劳动,我前面提到的所有项目背后都有一大批非常优秀的工程师,他们凭借对模型、算法和业务的理解,对每个模型分别进行非常细致的调优,才形成了一个性能非常高的模型和算法。
我们不禁要问,既然轻量级模型设计如此复杂,有没有更简单、通用的方法,使用统一的自动化算法代替人工来完成如此高要求的模型设计任务?近年发展出来的AutoML技术被寄予厚望。AutoML旨在使用一个机器学习算法设计另一个机器学习系统。传统机器学习里面有很多超参数,进入神经网络时代以后超参数就更多了,比如对于网络结构要怎么连才最好,这是搜索空间非常大的超参。针对它我们应用AutoML,这个叫神经网络架构搜索(NAS)。此外架构超参数如通道数等也是搜索的关键点。其他的像数据增广方法、激活函数等也都是可以搜的。
这里列出了NAS和人工架构的一些性能对比,可见自动化模型在性能上有明显优势。2017年谷歌的NASNet算法首次打败人工,从此AutoML和NAS一发而不可收。从文献上大家也可以看出,2017年AutoML爆发之后,如今有超过200篇文章讨论了AutoML和架构搜索。
我简单说一下AutoML和NAS在业务上的应用。模型搜索的文章在学术界文章很多,但是在目前应用上尚有很多问题,其中主要问题可以抽象为这三个关键词,一个是效率,一个是性能,一个是灵活性。在性能方面,我们在业务中通常不能只对其中的某一块进行优化,要对整个算法流程进行总的优化;怎么实现复杂环境下的搜索是非常难的问题。灵活性方面,现在基于梯度的搜索算法在灵活性方面非常差,例如,很多任务要求算法在某个型号的设备上的执行时间不能太长,功耗不能太高,加入这些限制后,我们发现大部分搜索算法的使用还是非常不方便的。
我们总结和对比了学术界的主要算法在工业落地上的主要优缺点。大家会发现目前没有一种算法适合实际使用的需求。
鉴于此,我们提出了一种更适合应用落地的算法叫Single Path One-Shot NAS,对效率、准确度、灵活性进行了很大程度上的改良,使得搜索流程大幅简化,很多时候只需要付出比正常训练一个模型2倍左右的时间,就可以得到精度好很多,并且可以在具体设备上高效执行的模型。
大家会发现这个算法还是非常通用的,既可以进行一个网络结构单元的搜索,也可以进行通道数的搜索,还可以进行混合精度量化的搜索。该算法在我们云端芯全系列的模型上都可以实现非常高效率的搜索。并且和之前SOTA相比,不管是搜索速度还是最终得到的模型精度都有比较明显的提升。
我给出一个应用的具体案例:用它做一个物体检测模型的搜索。物体检测模型包含很多关键的结构单元,比如图像预处理、FPN特征融合等。
这里给出一个对骨干网络搜索的例子。Detection模型的骨干网络搜索是一个非常困难的任务,因为每次我们改了基础模型,后面的特征就都变了,需要重新训练一遍,反复迭代需要非常长的时间。我们大致测算了一下,采样类似谷歌NASNet这种搜索方法,把算法运行完成需要将近一年时间,无法实现有效的搜索。但是使用了前面介绍的Single-Path One-Shot搜索算法之后,模型搜索只需要走一遍就可以高效完成,只需要进行一次完整运行就可以实现显著的效果提升。
这是搜索过程中的图示,随着迭代的进行大模块会退到后面,小模块会移到前面,这符合我们对检测系统的认知。这张图展示了系统性能,大家会发现相对于业界普遍使用的基础模型如ResNet等,我们搜出的DetNAS模型在相同的计算量下实现了性能极大程度的提升。
总结一下,目前在轻量级模型设计这个领域,基于模型搜索的方法已经成为了目前的主流,也是最重要的研究方向之一。在实践中我们发现模型搜索对设备适配问题,尤其是寻找对于具体设备上运行时间最快、功耗最少的模型,相对于人工有非常大的优势。但是模型搜索也有很多问题,搜索空间现在还是依靠人工设计,搜索空间的设计非常依赖经验,并且没有好的指导原则,这是未来的研究方向和难点。
前面说的两个模型也已经开源了:
One-Shot Single Path NAS
https://github.com/megvii-model/ShuffleNet-Series/tree/master/OneShot
DetNAS
https://github.com/megvii-model/ShuffleNet-Series/tree/master/DetNAS
模型裁剪
模型裁剪也是设计轻量级模型的非常重要的思想。一句话概括就是先设计一个大的再砍下来。在模型裁剪中有很多种方法,比如可以使用稀疏连接、低秩分解、通道裁剪等。其中通道裁剪是最有效的方法,算法相对简单,容易得到规整的结构,方便硬件的实现。
我们2017年提出了一个通道裁剪的方法,可以实现对通道的自动化选择和参数重建。训练完一个模型以后,不需要进行重新训练,我们的通道裁剪算法只需要很短时间就可以自动生成比之前快2到4倍左右的模型。
不过,我们在实用中发现这个算法有很多缺陷,其中最大的问题就是它对模型结构的依赖相对来讲比较大。比如对于ResNet等对通道数量有很强约束的模型来说,这个通道裁剪方法很难取得比较高的裁剪效果。这是所有类似模型裁剪框架的本质问题。正是因为有这些问题,这两年基于AutoML和NAS的通道裁剪方法开始兴起。
这是我们最新提出的MetaPruning算法。它和之前的算法不一样,之前的算法通常是为了找最具代表性的特征,以及选择哪些通道进行化简。而MetaPruning的主要目标和NAS比较像,更多的预测化简后的结构,以及不同层的通道数。基本的思想是构建一个大的网络,通过PruningNet对内部不同的子网络进行随机采样,只需要经过一次训练就得到不同的模型。具体算法流程大家可以参考上图。
从效果来看,对比之前最好的模型裁剪算法,我们的方法可以用更少的优化时间得到更强的模型性能,和进行手工裁剪相比可以达到明显好的性能和速度。
关于MetaPruning和Channel Pruning我们已经开源,在安防等关键任务上得到了落地应用。从我们团队的使用经验来说,它们更多的还是在设备适配上面能够得到非常好的效果,而在模型结构上的改进带来的性能提升就比较有限。
资源:
MetaPruning
https://github.com/megvii-model/MetaPruning
Channel Pruning
https://github.com/yihui-he/channel-pruning
提问:做模型加速的时候模型的精度肯定会往下降,但是模型的计算精度还是挺重要的,怎么平衡精度下降多少是业务允许的?
张祥雨:所有业务做的时候都会先定一个基准线,我们当然希望精度越高越好,但是随着业务应用的不同,并不是所有业务都要精度优先,更多还是需要综合考虑多种因素。比如对于手机解锁的应用,一般对活体检测要求比较高,而对人脸识别的要求不是特别高。每次产品开始立项的时候我们会先定一条线,精度方面只需要达到这个线就可以了,剩下的工作则是在多个维度对算法进行优化。具体到模型化简的业务流程来说,通常我们会先训练一个比较大的模型,先保证精度超过预设的这条线,再逐渐往下砍,砍到能够过线为止。我们去优化算法,需要综合考虑精度、速度等多个维度,而不是始终要把其中一个push到极致。
提问:您说把骨干网络应用到不同的场景中,比如目标检测等,有什么一般的原则去微调这些网络架构?
张祥雨:有些通用的规则,不过很多时候对于每个具体的业务都是不太一样的。比如某些任务的模型访存量特别高,这个时候我们通常需要设计一些快速降采样的模块,把分辨率快速降下来,同时利用特征复用的技术在快速降分辨率的同时保证细节不被损失。又比如某些物体检测任务的问题特点是尺度变化特别剧烈,产品中会涉及非常小的物体也会有非常大的物体,我们一般会用自动化搜索帮你确定神经网络设计的关键要点。
演讲嘉宾简介:
张祥雨,现任旷视研究院主任研究员、基础模型组负责人。2017年博士毕业于西安交通大学。期间参加西交大-微软亚洲研究院联合培养博士生项目,师从孙剑博士和何恺明博士。目前团队研究方向包括高性能卷积网络设计、AutoML与自动化神经网络架构搜索、深度模型的裁剪与加速等。已在CVPR/ICCV/ECCV/NIPS/TPAMI等顶级会议/期刊上发表论文二十余篇,获CVPR 2016最佳论文奖,Google Scholar引用数38000+。多次获得顶级视觉竞赛如ImageNet 2015、COCO 2015/2017/2018冠军。代表作包括ResNet、ShuffleNet v1/v2等,均在业界得到广泛应用。
(*本文为AI科技大本营整理文章,转载请微信联系1092722531)

精彩推荐


推荐阅读

你点的每个“在看”,我都认真当成了喜欢“

旷视张祥雨:高效轻量级深度模型的研究和实践 | AI ProCon 2019相关推荐

  1. 【资源下载】旷视研究院张祥雨valse2019报告PPT——高效轻量级深度模型的研究与实践

    报告题目 高效轻量级深度模型的研究与实践 报告摘要 深度基础模型在现代深度视觉系统中居于核心地位.在实际应用中,受应用场景.目标任务.硬件平台等的不同,经常会对模型的执行速度.存储大小.运算功耗等进行 ...

  2. R Talk | 旷视研究院张祥雨:高效轻量级深度模型的研究与实践

    「R Talk 」是一个深度学习专栏,将通过不定期的推送展示旷视的学术分享及阶段性技术成果.「R」是 Research 的缩写,也是旷视研究院的内部代号:而所有「Talk」都是来自旷视 Researc ...

  3. 旷视张祥雨和孙剑入选中美10年AI影响力学者榜 位列榜眼

    近10年人工智能领域最有影响力的学者有哪些? 近日,上海交通大学 Acemap 团队开发了一个基于度量的全球顶级研究机构排名系统--AceRankings,这是一份人工智能研究机构.学者大排名!根据在 ...

  4. 高效轻量级深度模型的研究与实践

    原文: https://mp.weixin.qq.com/s/pWaU4Q2fAL6LcY8nC2eWDw 一.背景 众所周知,CNN 模型已是现代深度视觉系统的一个核心部分,作为基础模型,它起到了特 ...

  5. 旷视张祥雨:神经网络架构设计新思路

    智源导读:深度学习模型在很多任务上都取得了不错的效果,但调参却是一项非常痛苦的事情,大量的超参数和网络结构参数会产生爆炸性的组合.因此最近几年神经网络的架构搜索和超参数优化成为一个研究热点.此外,对于 ...

  6. VALSE学习(八):矿视-轻量级深度模型的研究与实践

    VALSE2019 张祥雨 旷视 一.轻量化模型设计思想 深度基础模型在现代深度视觉系统中居于核心地位.在实际应用中,受应用场景.目标任务.硬件平 台等的不同,经常会对模型的执行速度.存储大小.运算功 ...

  7. 旷视研究院张祥雨:3年看1800篇论文,28岁掌舵旷视基础模型研究

    第1000篇原 摘自:http://mp.weixin.qq.com/s?__biz=MzA3NjIzMTk0NA==&mid=2651649744&idx=2&sn=9f48 ...

  8. 智源青年科学家候选人 | 张祥雨:挑战自动化深度学习系统

    4月16日,北京智源人工智能研究院发布"智源学者计划",宣布重点支持四类人才:智源科学家首席(CS).智源研究项目经理(PM).智源研究员(PI),以及智源青年科学家. 其中,智源 ...

  9. LGD:涨点神器!旷视孙剑、张祥雨团队提出标签引导的自蒸馏技术,助力目标检测!...

    关注公众号,发现CV技术之美 本文介绍论文『LGD: Label-guided Self-distillation for Object Detection』,由旷视孙剑.张祥雨团队等提出标签引导的自 ...

最新文章

  1. OC基础 代理和协议
  2. android.app.activityview,ViewModel 概览
  3. pdb 调试python
  4. [Java] 蓝桥杯BASIC-19 基础练习 完美的代价
  5. shell学习之-sed用法解析_Shell脚本之sed的使用
  6. 计算机子网掩码作用,子网掩码计算器有什么用,有哪些优势
  7. 锐文网络安全网闸卡各种应用场景
  8. ArcGIS 图像合并至新栅格图层
  9. 精英问题,大家没事可以做一做
  10. Gris 游戏开发-day04
  11. MySQL索引的数据结构及算法原理
  12. Python爬虫入门之2022软科中国大学排名爬取保存到csv文件
  13. 数据库 物化视图详解
  14. [ 工具篇 ] 谷歌安装 hackbar (超级详细)
  15. jenkins占据内存过大
  16. 番茄花园移花接木和微软的36计
  17. php模板引擎 例子,PHP实现简单的模板引擎功能示例
  18. Fabric 1.0源代码分析(6)configtx(配置交易) #ChannelConfig(通道配置)
  19. 使用python获得N个区分度较高的RGB颜色值
  20. 小学生数学测试软件编写分析,小学生数学测试软件C语言课程设计

热门文章

  1. Linux 小记录!
  2. 递归思想解决输出目录下的全部文件
  3. linux中使用CST时间
  4. shell shocked什么意思_Shell 启动类型探究 ── login interactive
  5. cv_bridge使用笔记
  6. java webpack web项目_官方出品,微信小程序和 Web 端同构解决方案——kbone
  7. IOS 编程中引用第三方的方类库的方法及常见问题
  8. Python 查看本机WiFi密码
  9. 一个球从100米高度自由落下,每次落地后反弹回原高度的一半; * 再落下,求在第几次之后反弹高度小于0.1米, * 并计算在这一次落地时共经过多少米?...
  10. CSS3边框背景-边框背景(-border-image)