智能语音之远场关键词识别实践(一)
off999 2024-12-10 19:12 16 浏览 0 评论
语音识别主要分两大类:大词汇量连续语音识别技术(Large Vocabulary Continuous Speech Recognition,LVCSR)和关键词识别(keyword Spotting,KWS)。LVCSR由于对算力要求较高,一般在云端(服务器侧)做,而KWS对算力的要求相对较小,可以在终端上做。我们公司是芯片设计公司,主要设计终端上的芯片,想要在语音识别上做点事情,最可能的是做KWS,于是我们就选择KWS来实践语音识别。按距离远近,语音识别可分为近场识别和远场识别,远场的应用场景更丰富些,如智能音箱、智能家居等,如是远场的话需要用到麦克风阵列。讨论下来我们决定做远场下的关键词识别。图1是其框图:(麦克风阵列为圆阵且有四个麦克风,即有四个语音通道)
图 1
从上图可以看出,系统可以分为前端和后端两部分。前端主要包括去混响、声源定位和波速形成(beamforming)、单通道降噪四大模块。混响是指声音信号遇到墙壁、天花板、地面等障碍物形成反射声,并和直达声相叠加的现象。去混响就是去除那些叠加的声音。声源定位是利用多通道语音信号来计算目标说话人的角度和距离从而实现对目标说话人的跟踪,严格的声源定位是指同时确定说话人的角度(包括方位角、俯仰角)和距离。在消费级的麦克风阵列中,通常关心的是声源到达的方向,也就是波达方向(Direction of Arrival,DOA)。波束形成是对信号进行空域滤波,将多个通道的语音数据变成一个波束(即一个通道)的目标声源,目标声源的信干噪比(SINR)得到提升。单通道降噪是抑制单个通道上的噪声。后端主要包括特征提取和神经网络模型推理两大模块,特征提取是得到作为神经网络模型输入的语音的特征向量,神经网络模型推理是根据输入的特征向量计算出一个输出。不管是前端还是后端,对我们都是陌生的,讨论下来由于我们team人数较少就先从后端入手,有一个识别率较高的模型后再去做前端相关的。本篇先讲在后端上的一些实践,下篇讲在前端上的一些实践以及将前端和后端连起来形成一个完整的方案。
后端主要是语音识别相关的。语音识别分为训练和识别两个阶段。在训练阶段,用海量的相关的语料训练出一个识别率较高的神经网络模型。在识别阶段,采集到的语音经过前端处理后提取出特征向量再经过神经网络模型推理得到相应的输出。后端的主要工作如下:训练语料获取、语料数据增强、模型训练、模型量化、模型推理实现等。
1, 训练语料获取
训练语料一般有三种办法获得。一是用公开的语料库,中文比较出名的语料库有thchs30等,但这些公开的一般适用于LVCSR,不太适用于KWS,因为KWS是一些特定词。二是花钱买,三是自己录。花钱买的语料库一般较贵,当前我们处于起步阶段,所以我们决定自己录语料。自己录要先选定应用场景和关键词,讨论后我们选定了智能家居场景,关键词包括“打开空调”、“关闭空调”、“打开窗帘”、“拉上窗帘”等。定好关键词后就开始录音了,我们先后录过两次音。第一次录音是在做后端神经网络模型时,录的是单声道数据。找来5台安卓手机,装上录音软件easyrecord,放在一个安静的会议室里,距离说话人50CM左右处,示意如图2:
图 2
说话人先以正常语速说一遍关键词,然后以较快语速说一遍,最后以较慢语速说一遍。当时请了部门里几乎所有同学近100人参与录音,得到了一个我们自己定义的单声道关键词的语料库。由于人数较少,是一个小语料库。第二次录音是在做前端麦克风阵列中去混响、波束形成等算法时,录的是多声道数据。买来一块多声道采集的评估板放在一个大会议室里,同时评估板边上放风扇、菜场等噪声,说话人在相对远处不同的位置上说关键词,示意如图3:
图 3
依旧是先以正常语速说一遍关键词,然后以较快语速说一遍,最后以较慢语速说一遍。这是一个带不同种类噪声的关键词多声道语料库。
2,对语料做数据增强
刚开始我们采集到语料后就开始训练模型了。由于录到的语料都是干净语音,模型训练好后干净语音识别率还可以,但是带噪语音就不行了。遇到问题就要找解决方法。调查后发现通常的做法是对语料做数据增强(augmentation)。所谓数据增强就是用一些音频处理的算法(比如加噪声)对已有的训练集里的语音(通常训练集里的语音是在安静的环境下录制的,比如录音棚里)进行一定的处理,让其变得更接近真实场景中的语音,来增加训练样本的多样性。基于神经网络的深度学习技术,通常都需要使用大量的数据来训练,语音识别也不例外。对一个语音识别系统而言,决定其识别准确率的关键因素,大致可以分为两个方面:一是模型本身的好坏;二是训练所使用的训练数据。对于训练数据而言,其与真实使用场景中的数据的匹配度越高,则语音识别的性能越好。实际应用中,语音识别的使用场景很复杂,环境噪声、人的说话方式,如音量、语速等,都会一定程度上影响语音识别系统的准确率。训练数据对这些复杂的情况覆盖得越全面,则语音识别系统的效果越好。为了构建一个强大的语音识别系统,应该广泛地搜集各种复杂的真实场景下的语音数据,来构建训练集。然而在现实条件下,想要做到这一点却很不容易,尤其对于中小厂商。因为不是每个厂商都有获取真实场景语音数据的渠道和能力,即使成功获得了真实场景的语音数据,数据标注也是一项极为费时费力费钱的工作。在训练集数据有限的情况下,可以通过数据增强的方法来扩充训练集数据,使训练集数据更多样性,来提高语音识别的准确率。我们用python开源库(nlpaug.augmenter.audio)做了数据增强,用的数据增强方法主要有如下几种:
1)Loudness:调整音频的音量(增大或减小)
2)Speed:调整音频的播放速度(加速或减速)
3)Pitch:调整音频的音高
4)Noise:加入噪声,主要有白噪声、粉红噪声、环境噪声等。
做好数据增强后语料库就增大了好多倍。用增大后的语料库去训练得到新的模型,再用带噪语音去测试模型识别率提高了好多。
3,模型训练
模型训练是个大话题,这里就简述了,主要分几块:语料库的数据预处理、模型选择和迭代训练及评估。这些都在python下实践。找一个开源的语音识别开源框架,并根据自己的需求改造。我们是在框架中基于keras来训练模型的。
1) 数据预处理
数据预处理主要包括语音的特征(feature)选取和提取以及标签(label)处理。语音识别里常用的特征是MFCC和Fbank。我们刚开始用的特征是MFCC,后来随着用的深入,发现Fbank的效果比MFCC好,就改成用Fbank了。特征提取就是把wav中的每帧PCM数据变成特征向量,作为神经网络模型的输入。标签(label)就是标注wav文件对应的内容。语音识别神经网络模型通常都是分类模型,且有不同的分类方法。可以以音素分类,分出来的音素类型有几十或者上百个,标注时就是以音素为标签(label),代码中每个音素都有一个数字ID。如果用作唤醒词识别(唤醒词识别是关键词识别的一个特例,只有一个关键词),就是一个典型的二分类问题,是唤醒词的标注为1,不是的标注为0。把这些label作为target也作为模型的输入。训练前要把语料分成训练集/验证集/测试集,通常比例是8:1:1。训练集和验证集用于训练,测试集用于评估。
2)模型训练和评估
模型训练的第一步是选择网络架构。对于语音识别,目前主流的网络架构有卷积神经网络(CNN)和循环神经网络(RNN/LSTM)等。我们根据项目的需求选择CNN作为网络架构(主要是因为CNN相对简单且有很多KWS论文里的网络模型可以参考)。网络架构确定后训练模型时最好先找一个相关论文里的成熟模型来借鉴,然后对其进行改进,最终通过训练确定CNN层数、每层的Kernel个数、Kernel Size、Stride等。训练过程就是用训练集的数据作为输入,经过网络前向传播计算出输出,再同事先设定的标签(label)进行loss计算(根据设定的损失函数计算),然后通过反向传播来更新权重后,再迭代进行前向传播、loss计算和反向传播更新权重,直至loss值达到预期效果的过程。根据应用场景我们先后训练出两个网络模型,多关键词网络模型和单关键词(即唤醒词)网络模型。多关键词网络模型是音素分类模型,以CTC为损失函数,网络模型输出是每个音素的概率值,概率最大的那个音素作为输出,后接CTC解码,得到结果。唤醒词网络模型是二分类模型,以交叉熵为损失函数,网络模型输出是唤醒词和非唤醒词的概率值,再设定一个是唤醒词概率的阈值,如果输出的唤醒词概率大于阈值,就认为是唤醒词了,反之不是。
模型训练好后要对其进行评估,看是否满足要求。KWS模型一般都是分类模型,对于分类模型,曾写过文章介绍过评价指标,具体见《深度学习分类问题中accuracy等评价指标的理解》。只有这些评价指标都符合要求了,模型训练工作才算结束。否则要分析不达标的原因,找解决方法,再重新训练,直到所有指标都达标。模型训练就是一个不断重复迭代的过程。
4,模型量化
训练好的模型中的参数都是浮点数,在识别过程中模型推理(inference)时为了降低CPU load和节省memory,需要对模型做量化处理。至于具体怎么做,请参见曾写过的文章《深度学习中神经网络模型的量化》。
5,模型推理实现
KWS模型训练是在python下完成的,但识别推理是在嵌入式系统上完成,因此要用其他语言把模型推理实现了。嵌入式系统上最常用的语言是C,我们就用C实现了模型推理。实现过程中参考了CMSIS的代码。为了节省memory,我们对实现过程做了优化,具体见曾写过的文章《嵌入式设备上卷积神经网络推理时memory的优化》。
以上就是后端的主要工作。写起来简单,其实都是需要花不少时间的,尤其在模型训练上。如果是第一次做,则需要花更多的时间,有一个摸索的过程。
相关推荐
- wifi连接上却不能访问互联网
-
原因一:路由器问题,可能路由器过热或者损坏;重启一下路由器试试,或者将路由器恢复一下出厂设置,然后重新拨号上网,并根据设置向导重新设置WiFi,或者更换新路由器再进行拨号连接上网。 原因二:可能宽带...
-
- 显卡驱动在哪里打开(显卡驱动设置在哪里)
-
1.以华硕x16、windows11、amd22.8.1为例。先进入电脑桌面,然后点击电脑开始菜单。2.找到“AMDRadeonsettings”点击展开。3.可以看到“AMDRadeonsettings”的主程序,点击打开。4.这...
-
2025-12-26 16:51 off999
- bios启动项里找不到固态硬盘
-
这个是BIOS设置问题,操作步骤不正确。需要在【启动】菜单中【硬盘BBS属性】中设置。下面提供一下完整的操作步骤,请参考:1、将装有固态硬盘的电脑重启,同时按键盘F2键。2、进入BIOS界面,在标题栏...
-
- 用手机解除路由器限速(用手机解除路由器限速教程)
-
1、设置wifi限速等功能时,需要打开路由器管理页面,所以先打开一个浏览器,在里面输入192.168.1.1,然后点击确定,再把路由器的密码输进去点击确定,原始账密在路由器的背面会有。2、打开wifi路由器的管理页面后,找到设备管理项点击它...
-
2025-12-26 15:51 off999
- 系统集成项目管理工程师报考
-
中级系统集成项目报考条件及费用如下:1、凡遵守中华人民共和国宪法和各项法律,恪守职业道德,具有一定计算机技术应用能力的人员,均可根据本人情况,报名参加相应专业类别、级别的考试。2、获准在中华人民共和国...
- 电脑显示内存不能为read(电脑显示内存不能为read怎样修改虚拟内存)
-
1内存不能为read可能是因为程序在读取数据时没有分配足够的内存空间。2解决方法可以是增加程序的内存分配,或者优化内存使用方式,例如使用缓存等技术。3此外,还可以通过检查代码逻辑是否有误,或者是...
- 网易用户中心官网(网易用户中心官网注册账号)
-
要登录网易个人中心的话,首先你网易要有自己的账户。你可以搜索一下网易的官方链接,打开以后先注册,注册成功了以后你就可以进到个人中心了,上面也可以做一些设置或修改你的密码之类的。然后你就可以多看一下,看...
- windows defender怎么关闭win11
-
1.启用或禁用WindowsDefender的实时保护可以通过设置打开或者关闭某些模块(例如实时保护)的选项。第一步,右键点击开始菜单--设置或者按住WIN+I(大写的i)快捷键...
- 无法识别硬盘(无法识别硬盘怎么解决)
-
1.有可能可以修复2.因为硬盘无法识别可能是由于硬盘本身的故障或者连接线松动等原因导致的,可以尝试更换连接线或者使用一些数据恢复软件进行修复。但是如果硬盘本身的故障比较严重,可能需要专业的数据恢复...
- win10固态硬盘如何分区(win10固态硬盘分区多大合适)
-
可以按照以下步骤进行分区。1.打开“此电脑”或“文件资源管理器”,右击“此电脑”,选择“管理”。2.在计算机管理窗口中,选择“磁盘管理”,找到你的固态硬盘。3.右击固态硬盘,选择“新建简单卷”。...
- 博图v19(博图v19安装过程中出错)
-
西门子博途(TIAPortal)是用于工程设计和编程的软件平台,博途V19和V18是该平台的不同版本。它们在功能、性能和用户体验上有一定的区别。以下是一些主要区别:1.新功能和性能提升...
- 小米怎么关闭自动更新(如何关闭小米自动更新系统)
-
方法/步骤分享: 1、首先找到自己手机上的设置选项。 2、找到设置之后我们看到下面有一个我的设备选项。 3、在我的设备下面有一个miui版本,点击这个版本号后面的箭头。 4、进入到系统更新...
- 隐藏的文件夹怎么才能显示出来
-
你可以打开我的电脑,随便找一个盘符点进去,然后点击左上角的组织选项,找到文件和文件夹选项,然后会弹出一个列表,找到选项显示所有文件和文件夹,把前面的勾打上就可以了。1.在资源管理器中,打开文件夹属性...
- 恢复出厂设置有什么影响吗(恢复出厂设置对有影响吗)
-
基本上没什么危害。恢复出厂设置是一次大容量的数据读写,清除,存储过程,相对一般日常使用来说,只是会对电脑的整个硬件硬盘形成一次重大磨损过程,大容量的数据读写,清除,存储,会加快硬盘的老化,但对电脑本身...
欢迎 你 发表评论:
- 一周热门
-
-
抖音上好看的小姐姐,Python给你都下载了
-
全网最简单易懂!495页Python漫画教程,高清PDF版免费下载
-
Python 3.14 的 UUIDv6/v7/v8 上新,别再用 uuid4 () 啦!
-
飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx
-
python入门到脱坑 输入与输出—str()函数
-
宝塔面板如何添加免费waf防火墙?(宝塔面板开启https)
-
Python三目运算基础与进阶_python三目运算符判断三个变量
-
(新版)Python 分布式爬虫与 JS 逆向进阶实战吾爱分享
-
失业程序员复习python笔记——条件与循环
-
系统u盘安装(win11系统u盘安装)
-
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
