微信号:lls_tech

介绍:Help everyone become a global citizen!

『英语流利说』离线深度神经网络优化

2016-09-03 20:30 Feiteng


『英语流利说』是一款英语口语学习 APP,利用
语音评测技术给口语实时打分、反馈,帮助纠正发音,提高口语能力。流利说语音评测算法将近年人工智能领域取得重大突破的深度神经网络(DNN)模型应用到语音评测系统中,相比传统建模方法,大幅提升各项 benchmark 准确率。 

DNN 模型参数在千万量级,模型训练需要借助 GPU、CPU 集群才能完成,在计算能力远小于 PC 的手机端更是难以利用,业界做法是把数据(语音、图像等)通过网络传送到服务端计算,再将结果传回手机端。

本文介绍在『英语流利说』语音评测算法中深度神经网络在手机端离线实时计算的优化。

深度学习(Deep Learning)

深度学习是机器学习的一个分支,近年,深度学习的复兴引领了一波大众“人工”智能热(泡沫),催生大批人工智能砖家。
主流深度学习模型结构有 Deep Feed Forward Neural Networks (DNN), deep Convolutional Neural Networks (CNN), deep (Long Short-Term Memory) Recurrent Neural Networks ((LSTM)RNN),通常也以 DNN 统称 DNN、CNN、RNN

本文介绍 FeedForward DNN 的 FeedForward 优化,对如何做模型训练不予阐述,优化技巧对 DNN、CNN、RNN 多是通用的。

DNN


From http://cs231n.github.io/neural-networks-1 

给定输入input

FeedForward

Let a_0 = input vector
For i in 1, 2 ... layers: 



通常  是 或函数



分类任务输出层通常为 ,代表 input 属于各个类的概率。

绝大部分的运算在 Wa+b 上,如果一次仅有一个输入,则 x/a 的内容为向量, 若一次输入多个(图像batch处理, 语音多帧音频特征),x/a 的内容为矩阵。

故在给定 DNN 模型参数的情况下,计算的核心是矩阵运算,矩阵*矩阵或 矩阵*向量,本文重点介绍 矩阵*向量 的优化。

BLAS

回想一下,矩阵概念是在线性代数课程引入的,BLAS(Basic Linear Algebra Subprograms) 是基础线性代数程序集的应用程序接口标准,用以规范发布基础线性代数操作的数值库(如向量或矩阵乘法)。在高性能计算领域,BLAS 被广泛使用。著名的开源 BLAS 实现有 OpenBLAS 和 ATLAS。

BLAS 按照功能被分为三个级别:
Level 1:向量-向量运算


Level 2:矩阵-向量运算


Level 3:矩阵-矩阵运算


BLAS 中 gemv 为非特殊结构的 矩阵*向量 标准 API:

void cblas_sgemv(const enum CBLAS_ORDER Order,
                 const enum CBLAS_TRANSPOSE TransA, const int M, const int N,
                 const float alpha, const float *A, const int lda,
                 const float *X, const int incX, const float beta,
                 float *Y, const int incY);

void cblas_dgemv(const enum CBLAS_ORDER Order,
                 const enum CBLAS_TRANSPOSE TransA, const int M, const int N,
                 const double alpha, const double *A, const int lda,
                 const double *X, const int incX, const double beta,
                 double *Y, const int incY);

DNN 计算优化

1.合并、移除 不必要的计算

合并特征归一化

机器学习算法通常需要对输入特征做归一化处理,


其中  为均值,  为标准方差; 将上式移入到第一层的 中,


令 , 则在保证数学运算结果一致的情况下,减少了特征归一化带来的运算。

移除 Softmax 计算

在语音领域并不直接使用 Softmax 输出的概率值,通常使用 Log(Softmax), 则有


实际上


在解码阶段每一帧是否减去  并不会改变竞争条件 :


故模型训练完成后可以移除 Softmax  层,直接使用最后一层 AffineTransform  的 z=Wa+b
图像领域的应用,如果不需要概率值,也可以不计算 Softmax ,是否计算 Softmax 不会改变 z=Wa+b 的大小顺序。

2.gemv 计算优化

以单线程单精度 sgemv 为例,分析多种优化方法,以 OpenBLAS sgemv 为对照。


通常 , 其中

MacBook Pro, 2.5 GHz Intel Core i7, 16 GB 1600 MHz DDR3, clang -O2

注:以下以方阵(M=N)为例, 运行1000次取计算时间平均值,每次运行结果略有不同。

2.0 native实现

baseline

y = β * y
for(int i = 0; i < M; i++) {
    for(int j = 0; j < N; j++) {
        // 这里判断x(j)是否为0 没有大意义
        y(i) += α * A(i, j) * x(j);  // A(i, j) = A[i*LDA + j] LDA = N
    }
}

利用 x 稀疏性

y = β * y
for(int j = 0; j < N; j++) {
   if (x(j) != 0.0) { //如果等于0 则不需要计算
    tmp = α * x(j);
        for(int i = 0; i < M; i++) {
            y(i) += tmp * A(i, j);  // A(i, j) = A[i*LDA + j] LDA = N
        }
    }
}

第二个实现在  稀疏的情况下,可以避免不必要的计算; 在矩阵  以行主元存储的时候,y(i) += α * A(i, j) * x(j); 会成为计算的瓶颈:对 A(i,j) 的内存间隔读取导致太多 Cache Misses;第一个实现虽提高了缓存命中率,但在 x  稀疏的情况下,却无法利用这个属性避免不必要的计算(稀疏性下面还会提到)。


Fig0. dense/sparse gemv对比(非以上两种实现的对比,这里gemv_ft0为第二个实现) 


2.1 列主元存储

若矩阵A以列主元存储,便可避免 Cache Misses

y = β * y
for(int j = 0; j < N; j++) {
   if (x(j) != 0.0) { //如果等于0 则不需要计算
     tmp = α * x(j);
        for(int i = 0; i < M; i++) {
            y(i) += tmp * A(j, i);  // A(i, j) = A[i*LDA + j] LDA = M
        }
    }
}



Fig1. 列主元存储(gemv_ft1)


可见,通过列主元存储的方式,无论是  dense/sparse,性能均大幅度提升,矩阵维数越大,提升越明显。

2.2 增加缓存命中率


Fig2. 增加缓存命中率(gemv_ft2) 

通过增加缓存命中率,gemv 性能再次大幅提升。


Fig3. FineTuning 

通过优化,gemv 有1-3倍的性能提升,维数越大,提升越明显。 

2.3 Fixpoint 定点化, ARM NEON 指令集加速

手机设备的处理器绝大多数是 ARM 架构,浮点数运算能力弱;针对 ARM 架构,对 DNN 参数做 Fixpoint 定点化,并使用 NEON 指令集做运算加速。这部分的性能对比,不再列出。

2.4 其他

预先分配内存、内存对齐、指针移位代替索引计算、矩阵转置等;编译器优化选项设置对 ARM 代码的影响很大。

3.DNN 模型设计

gemv 的运算复杂度为 O(M*N),减小神经网络节点数目可以有效降低运算量,如此亦会降低神经网络的准确率。能否在压缩 DNN 模型大小的同时,保证准确率不下降呢? 

  • 模型裁剪、再训练:恢复准确率 裁剪不重要的神经网络节点,通过再训练的方式,恢复模型准确率。

  • teacher-student 训练方法, Dark knowledge(Hinton)
    利用大的神经网络训练更小的神经网络,使之逼近大神经网络准确率

  • SVD 分解矩阵降低运算量、模型压缩等

近年相关文章已经很多了,简要参考 FasterDNN

4.联合优化

在2.0提到, 的计算可以利用  的稀疏性来避免不必要的计算,那么在 DNN 激活函数选择 Wa+b 就可以使得激活向量\(a\)稀疏(约50%),从而大幅减少 Wa+b  的运算量,而且  通常比  有更高的准确率。

5.Skip Frame 跳帧计算

在手机端的测试,只简单做了 Android 平台,测得实时率远低于1,就没再继续优化。在上线 DNN 评测模型时,反馈 iPhone 4/itouch4 比较卡卡卡。时间紧迫,忽然想起已经实现的跳帧计算还没有开启。跳帧计算利用语音信号的特点,运算量减半,准确率几乎无损失。


Fig4. Baseline 为2.0的第一个实现 


语音评测 benchmark 提升

DNN 相比传统建模方法,大幅提升了声学模型的准确率、抗噪能力。语音评测的一个重点就是发音维度评测,与声学模型练习紧密,DNN 声学模型的应用,全面提升了语音评测 benchmark。

Voice Activity Detection(VAD)

自动停止录音功能根据停顿时长判断是否结束录音,使得语音交互更流畅。基于 DNN 模型的 VAD 模型有效提升了该功能的准确性和灵敏度。



总结

通过模型压缩、计算等价性变换、矩阵计算优化等方法完成 DNN 模型在手机端的运行时编码、计算优化,全面提升了语音评测性能。相比网络传输服务端计算的方式,离线计算对用户网络环境要求低,可以给予用户实时反馈。由于单核 CPU 已做到实时计算,“多核 CPU、Mobile GPU 加速”没有继续探索。

据我们了解,我们的产品『英语流利说』是目前市场上为数不多可以离线计算深度神经网络模型的手机应用。不夸张的说,在移动教育产品中,『英语流利说』是全球第一款配备深度神经网络的教育 APP。




 
流利说技术团队 更多文章 浅析 Android 打包流程 在英语流利说,我们这样管理数据采集需求 在认识 Ecto 之前,我从未如此了解 ActiveRecord Never Stop Hacking! 流利说@WWDC 2016
猜您喜欢 内有彩蛋|讲真,我能为你做很多很多 聊聊监控(二):谁为代码负责以及常见的监控痛点 我就不信你看完还不减肥 【公开课】Coreseek_大数据时代的中文搜索技术 及MySQL主从同步技术 深入探索Java 8 Lambda表达式