在实时音视频中应用深度学习,你须要了解这些

在场景需求的推进下,以及背后算法、算力、数据的支撑下,AI 已经慢慢走出实验室,开始拥抱产业,这其中也包括 RTC 行业。在实时的视频、实时音频、实时传输、视频内容检索与推荐、实时交互等层面,都已经出现了与 AI 结合的落地应用。算法

从实时的视频来说,超分辨率就是最典型的应用之一。在深度学习的帮助下,咱们能够在视频接收端提升原有图像的分辨率,获得高分辨率的图像,这个过程就是超分辨率重建。咱们之前也分享过一些知名的算法模型。 实时音频方面,咱们能够看到不少 AI 的应用。例如带宽扩展,在咱们通话的过程当中,对方的声音听起来有些闷,这是由于语音信号中的高频区域被移除掉了。而基于DNN的频带扩展则可将高频区域恢复出来,就像下图这样。通过频带扩展后的信号增长了不少高频信息,实际的听感也会更加明亮、清晰。网络

除此以外,AI 在实时语音上的应用还包括语音加强、基于 RNN 的丢包恢复、语音音乐分类器等。AI的发展使得音频领域有了更多的可能性去解决以前难以处理的问题。对于实时音频而言,AI是一把全面提高质量的利刃,但实时音频所必须的低复杂度、低延时特性注定全面AI化引擎还有很长的路要走。 另外,除了实时音视频,AI架构

还能够用于改善实时传输质量,也能够用于视频内容的检索与推荐,或进行音视频内容审核。以上这些相关话题,你均可以在今年的 RTC 实时互联网大会上听到。 10 月 24 日、25 日即将举行的 RTC 2019 实时互联网大会(2019.rtcexpo.org/) 邀请了来自声网Agora、Hulu、依图科技、南京大学等公司与高校的演讲人,他们将从分享 AI 在移动端实时视频超分辨率、音频优化、传输优化、视频内容推荐、音频内容审核等角度分享实践经验。细数下来,今年几十个演讲中,有近 1/3 的演讲都与深度学习、神经网络相关。函数

同时,在大会第一天上午的主会中,声网Agora 首席科学家钟声、搜狗公司AI交互事业部高级总监、语音技术部负责人陈伟,也将围绕 AI 与 RTC 深刻分享更多技术实践与趋势。性能

不过,对于刚刚入门神经网络的开发者而言,可能须要要过许多弯路,咱们下面来总结一下训练神经网络的入门级知识点,从循环神经元的选择、激活函数、过拟合,到优化器的选择。学习

1.循环神经单元的选择测试

若是神经网络中须要用到循环神经单元,首先须要从多个现有模板里选择一个。单向循环神经单元如今主流的有RNN/LSTM/GRU,这几个循环神经单元综合来讲性价比是RNN<LSTM<GRU。大数据

RNN是一个设计比较早的结构,缺点是每一个时间步的输入的比重是同样的,若是输入的时间步过多,RNN会遗忘较早的信息。优化

LSTM是为了解决上述RNN缺点而设计出来的,相比RNN,LSTM主要增长了4个门和1个细胞状态,用来控制哪些信息须要遗忘,哪些信息须要记住,但LSTM的缺点是模型比较复杂,权重不少,比较难训练且模型比较大。翻译

GRU至关因而一个简化版的LSTM,GRU只有三个门,而且融合了细胞状态C和输出状态h,这样GRU的计算复杂度和模型体积大概只有LSTM的3/4,而且更容易训练。

除此以外,还有一个非主流的模型SRU,SRU使用大量哈达玛乘积代替了传统的矩阵点乘,而且当前时刻的输出已经不依赖以前时间步的输出,只依赖前一时刻的细胞状态。该模型的一大优势是能够对其进行并行化优化,提高其在GPU上的计算性能。相同hidden layer数量的SRU的模型体积和计算复杂度大概是GRU的1/2,但偏差有所上升。SRU的详细介绍能够参考另一篇征文。

2.激活函数的选择

主流激活函数有sigmoid/tanh/relu/leakyrelu/prelu等。

值得一提的是,循环神经单元门内的激活函数通常是sigmoid,输出的激活函数通常是tanh,这两个通常来讲不建议修改,错误的修改容易引发梯度爆炸。

relu系列主要是为了解决深度神经网络中梯度消失的问题,实际上,在relu设计出来以前,深度神经网络仍是很依赖pretraining+finetuning这种方法的,relu的做用是和droupout/L1 regularization的功能相似,即便得部分权重失活,达到稀疏网络的目的。

leakyrelu和prelu是relu的变种,这两个激活函数在输入为负的时候仍有输出,但负值输入会被乘上一个权重,leakyrelu须要手动设置这个权重,prelu则会经过训练获得整个权重。性能上relu<leakyrelu<prelu,但prelu在训练的时候须要额外的计算量,由于它多一个反向传播。

推荐首选relu系列激活函数,由于它在大多数场景下都有较明显的优点。

3.过拟合及防止过拟合的手段

过拟合近乎是训练网络时没法避免的问题,严重的过拟合会在训练集上跑出完美的结果,却彻底没法在测试集上工做。总的来讲,目前防止过拟合的手段都围绕着一个思想:稀疏网络。

经常使用的防止过拟合的方法主要有:dropout、regularization,上述的relu系列激活函数也算是一种方法。整体来讲,防止过拟合的思路是使网络变得稀疏,稀疏能够简单理解为把一个大网络里全部权重共同协做的方式改成大网络里多个小网络并行计算,这种描述不太准确,但能够大概这么理解。dropout实现稀疏的方法比较直接,就是在训练的时候随机让一些权重失活,在使用网络时时恢复这些权重,并将输出除以(1-α),其中α是dropout的比例。regularization的中文翻译为“正则化”,这个不太好理解,可能把它理解为“限制”更好一些,它实际上是针对权重加了一个限制。regularization分为L1 regularization和L2 regularization,L1 regularization是在反向传播偏差时加上权重自己的一个一阶范数,它的做用是,使得最终训练出网络的权重有更多的0值,实现了稀疏网络的目的;L2 regularization是在权重上加了权重自己的二阶范数,这使得最终训练出网络的权重都变小并趋近于0,但不等于0,也实现了稀疏网络的目的。

关于为何稀疏的网络能够防止过拟合,个人理解是,一个大网络里其实有好多权重是没什么用的,但这些权重计算出的信息会去很好的拟合训练集,但会在验证集和测试集上引入噪声,所以,经过稀疏网络,使得这些“无用权重”扮演的角色变小,网络就能更好的拟合历来没见过的测试集。

4.优化器的选择

优化器是训练网络时的梯度降低的方法,目前主流优化器有SGD、Adagrad、Adadelta、RMSprop、Adam、NAdam这几种。

其中,SGD的全称是stochastic gradient descent,它的思想是每次只训练少许样本进行梯度降低,优势是相比以前的BGD(Batch gradient descent)占用内存少一些,可以进行大数据量的训练,缺点是由于每次只用少许样本,可能loss是震荡降低的,所以SGD很依赖于部分超参的设置,如学习率在何时衰减对SGD来讲是很是重要的,能够暂时这么说,若是SGD的超参设置的很是完美,那它就能训练出最佳的模型,但通常来讲这个是很难的。

Adagrad的最大特色在于它经过累计计算过去的梯度(就是导数),给不一样参数不一样的学习率,但这个优化器的一个最大的问题是,累计的梯度越大,学习率越小,很容易出如今训练未结束时学习率就降低到很是低的问题。

Adadelta则修正了Adagrad的学习率降低过早的问题,它经过指数加权平均方法计算过去N个梯度值,再也不是从第一次训练一直开始累积梯度,这样就从必定程度上避免了上述问题。此外,Adadelta还能够本身计算学习率,所以不须要预设。

RMSprop能够看作Adadelta的一个超参特殊版,值得一提的是,RMSprop在训练循环神经网络时的表现不错。

Adam是目前最容易被选择的一个优化器,它能够看作是RMSprop+Momentum,Momentum能够计算过去训练的累计梯度,若是历史梯度降低方向和当前降低方向一致,学习率就会被增强,若是历史梯度降低方向和当前方向不一致,学习率就会被减弱。须要注意的是,Momentum累计梯度时累计的是梯度自己的值,而上面几个优化器自己累计梯度时累计的是梯度的平方,因此Momentum和优化器自己至关因而两个并行的控制函数,这两个函数的超参也是分别设置的。

NAdam至关于Adam+Nesterov,Nesterov至关于对Momentum又加了一个校订,理论上能够达到更好的效果,但问题是,施加这个校订须要从新计算一遍梯度降低,因此NAdam的计算量差很少是Adam的两倍,所以要慎用NAdam,除非不在乎训练时间。

综上,Adam是万能公式,能够在训练循环神经网络时尝试RMSprop,尽可能避免使用SGD,除非对本身的调参能力很是自信。此外,Adam这种带Momentum的优化器很容易在训练末期陷入抖动,没法降低到最优势,一种比较麻烦的处理方法是,先使用Adam训练,再换成SGD进行最后的收尾工做。

5.学习率的设置

学习率最重要的是初始值设定和衰减方法,初始值设定根据不一样种类的目标有所不一样,建议对于一个新的模型,开始不要尝试太大的学习率,能够用小一点的学习率,如0.001试一下,训练完毕后,把偏差降低曲线打印出来,观察loss曲线,理想的loss曲线应该是相似于y=1/x,若是曲线过于平滑,说明学习率过小,若是偏差曲线降低的很快并伴随着上下波动,说明学习率过大。

衰减方法主要有按轮次衰减和根据loss衰减,以keras为例,若是按照10轮训练衰减一次,每次衰减一半,须要调用LearningRateSchedule():

若是想根据监控验证集的loss调整学习率,须要调用ReduceLROnPlateau(),当连续n轮loss不降低,进行学习率的衰减。

  1. 其他细节

如下总结仅供参考,不必定对每一个task都起做用

(1)权重初始化:推荐orthogonal初始化,能够有效避免梯度消失或爆炸,缘由可见这篇博文。

(2)Attention层:Attention层多用于语音识别或转化,Attention经过对每一个timestep分配权重,设定了一个特定注意力区域,而不是把注意力都集中在最新时刻的输入。如今讲Attention的文章有不少,这里就再也不赘述了。

(3)当多循环单元串联时,建议不要修改循环单元内部激活函数,避免梯度爆炸。这就带来一个问题,以GRU为例,输出状态h通过的是一个tanh。若是只单纯串联多个循环单元,整个网络没有relu来稀疏网络,致使网络性能降低。

建议多层串联循环网络架构以下:GRU-PRelu-TimeDistributed-tanh-GRU…,或者是GRU-PRelu-LayerNormalization-GRU…。这样作的缘由是:加入Prelu用来稀疏网络,加强网络鲁棒性;加入TimeDistributed用来实现更复杂的类Attention的功能;最后的激活函数选择tanh是由于但愿数据在输入下一个循环单元前范围限制在-1~1之间。LayerNormalization能够重置数据的分布,目的是和上述作法差很少的。

(4)Batch Normalization:该层能够将输入的批数据强行变成均值为0,方差为1的高斯分布。理论上Batch Normalization层带来的白化数据能够加速训练,但我实验下来在RNN系列上偏差有所上升,且Batch Normalization性能依赖于batch size,对训练机器的性能有考验。推荐在RNN类的网络上仍是使用LayerNormalization好一些。

(5)若是网络没有明显的过拟合,或者只过拟合了一丢丢,在回归问题上建议不要使用Regularization,Regularization能够较明显的泛化网络输出结果,使得模型在测试集上的表现也出现必定降低。

(6)结合CNN的循环单元,若是须要使用,建议把CNN搁到循环单元后面。这么作一是避免破坏原始输入数据的时域相关特性,二是参考了这篇文章里的实验结果。

(7)关于数据预处理:数据归一化在无特殊状况下都是建议作的。关于变化域的数据预处理,以前尝试过对信号进行PCA后输入到神经网络,但出现了部分白化后数据梯度爆炸的现象,并且PCA没有带来很明显的正向增益,却会引入必定复杂度,在数据预处理时,须要谨慎选用PCA,但PCA能够有效实现降维,当数据维数过大致使网络难以拟合时,PCA是一个不错的选择。

(8)Loss function的肯定:对于回归问题来讲,若是数据是归一化的,建议使用MAE或其近似变种就好,MSE可能会使其性能降低。分类问题暂时没有作过相关项目,就不写了。

(9)网络架构的优化:循环神经网络主要的模型体积和计算复杂度来源于那几个门控单元,其随着门控单元隐层数量平方级增长,除了剪枝等方法,一种简单的优化方法是,把大的循环单元拆分红多个小的循环单元,尽可能减小大矩阵相乘的次数。但这样须要更多巧妙的小设计去弥补带来的偏差,能够参考已有相似网络的设计,如Wavenet等。

相关文章
相关标签/搜索