【class18】人工智能初步----语音识别(4)

【class17】

上节课,我们学习了:        语音端点检测的相关概念,并通过代码切分和保存了音频。

本节课,我们将学习这些知识点:
1. 序列到序列模型
2. 循环神经网络
3. 调用短语音识别接口

                      

知其然,知其所以然

在调用语音识别接口前,我们先来学习语音识别系统最核心的部分:强大的黑盒子——语音识别模型
通过学习黑盒子的内部,帮助我们进一步了解语音识别的前因后果。

强大的黑盒子

在一个典型的深度学习语音识别系统中,其模型由两部分组成:
1.编码器                                                       2.解码器

          

编码和译码的目的

1.为了对输入数据进行分析并编写成机器能够处理的信息,就需要编码。
2.为了将编码器编写的信息翻译成人类理解的信息,就需要译码。
          通俗的说,编码器就是让机器读得懂,解码器就是让人读的懂。

编码器解码器模型又叫做seq2seq模型——序列到序列模型。序列到序列也就是说,输入和输出都是序列。

序列到序列模型

定义

序列到序列模型(seq2seq )包括编码器 (Encoder) 和解码器 (Decoder) 两部分。
seq2seq 是自然语言处理中的一种重要模型,可以用于语音识别、机器翻译、对话系统以及自动文摘等。

隐喻

把这个过程想象成谍战片里的情报截获和翻译,编码器为敌方,解码器为我方。我方情报员截获了敌方编码好的情报,为了读懂情报,就需要进行解码。

语音识别的输入和输出都是不定长序列,换句话说,就是每次输入的语音和输出的文字长度不定。比如,时长不一样的语音,采样后所得的数字序列是不一样长的。
像语音识别这种输入输出都是不定长序列时,我们就使用seq2seq模型。

seq2seq模型由编码器解码器组成,而编码器和解码器都是利用了循环神经网络 — RNN来实现的。基本思想就是利用两个RNN,一个RNN作为编码器,另一个RNN作为解码器。

循环神经网络

定义

循环神经网络 (Recurrent Neural Network,RNN) 是一类用于处理序列数据的神经网络。在近些年,人们利用RNN解决了各种各样的问题:语音识别、语言模型、机器翻译和图像描述等。

对于序列数据来说,顺序排列非常重要! 比如,这样一句话「我要给手( )充电」。 我们就可以根据前后文字猜测,( )可能是机、表等单字。

                       

当话变成「电充( )手要我」时,( )里该填什么?是不是满脸问号???显然,针对有关于序列的问题,我们需要一个神经网络来进行专门的处理。于是RNN出来了。

                             

在学习RNN结构之前,我们看其他网络(如CNN)是如何处理数据的:每个网络处理数据是单独进行的。
每个数据通过隐含层(A)处理,都会得到一个对应的结果。

                        

如果待处理的数据之间(x1、x2、x3)有关联顺序,也就是为序列数据时:对于神经网络来说,并没有办法知道数据之间的关联。怎么让网络知道这些数据顺序关联,比如图中的护肤顺序,并能进一步分析呢?

科学家们脑袋一转,不怕不怕,我们把前一个网络的中间状态作为后一个的输入就好啦!这样就能形成一个所有记忆循环分析的网络,处理序列数据刚刚好!

RNN结构

循环神经网络和卷积神经网络一样,它包含三个结构:
1. 输入层                  2. 隐含层                           3. 输出层

为了更好理解,将RNN按照序列顺序将其展开:
RNN 顺序链式结构让它看起来就像是为序列数据而生!(图中的输入x1-xt就可以是我们采样所得的序列数据)

输入层、输出层比较容易理解。
在语音识别中,输入层输入的是语音,输出层输出的是识别结果
那么,隐含层呢?

循环神经网络的隐含层前后顺序相连,前后相互依赖,前一个的输出为后一个的输入。 这与语音的前一个字依赖后一个字或者前一句话依赖后一句话非常契合。

RNN VS  CNN

RNN 与CNN相比,RNN的特别之处在于:
1. 处理序列数据效果好
2. 允许控制输入或输出向量序列的长度
第1点我们已经学习了,接下来,我们通过两个结构模型来理解第2点。

                            

CNN
1->1 结构,固定长的输入和输出 (应用:比如图像分类)
                                     RNN
N->M 结构,不定长的序列输入和序列输出 (应用:比如语音识别)
seq2seq模型输入输出序列的长度是不固定的,对应的就是N->M结构

学习完seq2seq模型RNN的原理和概念之后,该如何实现语音识别呢?接下来,我们完成“调用接口实现语音识别”的第一步——单段音频的语音识别

通过代码调用短语音识别接口实现对单段音频文件的语音识别
让我们一起尝试一下吧~

1. 首先,我们开始打开并读取音频。
使用 with...as 配合open()函数以rb 方式,打开路径为filePath的音频,并赋值给 fp;
使用read()函数读取音频,输出结果为二进制的编码数据

代码示例:

调用短语音识别接口

代码的作用

利用短语音识别接口,对一段音频文件识别,返回值为字典类型。
第20行,
通过asr接口识别输入的音频wavsample,并将结果存储在rejson变量中。

分析代码:

语音识别客户端

使用变量client,即创建好的语音识别客户端,可对其调用。

短语音识别接口

对创建的AipSpeech客户端,使用asr()函数调用短语音识别接口。
注意:该接口只能将60秒以下的音频识别为文字,若音频时长超过限制,可切分为多段音频进行识别。

待识别语音

必选参数wavsample,语音内容的Buffer对象,文件格式支持pcm 或者 wav 或者 amr。

文件格式

必选参数,传入字符串"wav"设置音频文件格式为wav文件。

采样率

必选参数,传入参数16000声明音频文件的采样率为16000Hz。常用的音频采样率有:8000Hz、16000Hz和32000Hz等。

可选参数

asr()函数中传入可选参数{"dev_pid": 参数}设置待识别音频的语音类型。
参数为1537表示可识别的语言:普通话(纯中文识别)。
其余参数和解释如下:

总结:

调用接口----使用asr()函数调用短语音识别接口。将待识别的音频必选参数wavsample,"wav",16000传入到该函数中。输出调用接口返回的结果rejson。

                 

从输出结果可以看到,调用接口返回的是一个字典。 该字典包含多个参数:
corpus_no:语料库码                  err_msg:错误码描述                         err_no:错误码
result:识别结果                        sn:语音数据唯一标识

成功返回

成功返回时rejson字典中的参数err_msg和err_no内容为:
1. err_msg:错误码描述,rejson["err_msg"]为"success."
2. err_no:错误码,rejson["err_no"]为0

成功返回时rejson字典中的参数result为列表结构:rejson["result"]中保存了单段音频语音识别的文字信息。

获取识别结果
查看输出结果,我们从rejson字典中的键result就能得到识别结果。
调用接口返回的是一个复杂的字典结构,我们将它赋值给了变量rejson。
从字典rejson中取出参数"result"的值,可以用rejson["result"]
再从rejson["result"]中取出列表内的元素,可以用rejson["result"][0]

代码示例:

# 获取语音识别结果

# 从返回结果中提取出参数result中的唯一值并赋值给变量msg

msg = rejson["result"][0]

完善代码:

    1. if-else语句判定
      使用if-else语句,若错误码为0,则得到语音识别结果;否则给出"语音识别错误!"提示。
      以防出现语音识别无结果或者出现其他错误情况,而导致代码报错不能正常运行!

代码:

# if—else语句判定

# 若错误码为0,则得到语音识别结果

if rejson["err_no"] == 0:

    # 获取语音识别结果

    # 从返回结果中提取出参数result中的唯一值并赋值给变量msg

    msg = rejson["result"][0]

# 否则给出"语音识别错误!"提示

else:

msg = "语音识别错误!"

    1. 语音识别函数

将调用接口实现语音识别封装为函数,方便后面的调用。
最后通过参数wavsample调用函数,并输出结果。

修改后的代码:

# 定义语音识别函数audio2text()

def audio2text(wav):

    # 调用短语音识别接口把结果赋值给rejson变量

    rejson = client.asr(wav,"wav",16000,{"dev_pid": 1537})

    # if—else语句判定

    # 若错误码为0,则得到语音识别结果

    if rejson["err_no"] == 0:

        # 获取语音识别结果

        # 从返回结果中提取出参数result中的唯一值并赋值给变量msg

        msg = rejson["result"][0]

    # 否则给出"语音识别错误!"提示

    else:

        msg = "语音识别错误!"

    # 返回语音识别结果msg

return msg

调用短语音识别接口实现了单个音频的语音识别。接下来我们对上节课获得的音频片段做批量处理,批量读取音频文件,实现多段音频文件的批量识别
我们先完成第一步——批量读取音频

代码复习
批量处理之前,复习一下前面课程从视频中获取音频文件,并切分和保存为wav文件的完整代码。

"""获取音频文件"""

from moviepy.editor import VideoFileClip

video = VideoFileClip("/Users/yequ/大话西游.mp4")

audio = video.audio

audio.write_audiofile("/Users/yequ/大话西游.wav")

"""音频文件参数设置"""

from pydub import AudioSegment

sound = AudioSegment.from_wav("/Users/yequ/大话西游.wav")

sound = sound.set_frame_rate(16000)

sound = sound.set_channels(1)

"""切分音频"""

from pydub.silence import split_on_silence

min_silence_len = 500

silence_thresh = -50

pieces = split_on_silence(sound,min_silence_len,silence_thresh)

"""导出音频片段"""

count = 0

for i in pieces:

    path = "/Users/yequ/音频片段"+str(count)+".wav"

    i.export(path,format = "wav")

count += 1

step1.批量读取音频
将文件读取部分代码封装为函数:定义文件读取函数read_file(),传入参数文件地址filePath,返回音频对象wavsample。
再通过for循环批量读取切分完的音频文件,共12个音频文件,循环范围为0-11,即range(count)

代码:

# 定义文件读取函数read_file(),传入参数文件地址filePath

def read_file(filePath):

    # 使用 with...as 配合open函数以rb 方式,打开路径为filePath的音频

    with open(filePath,"rb") as fp:

        # 使用read()函数读取音频赋值给wavsample

        wavsample = fp.read()

        # 返回音频对象

        return wavsample

# 通过for循环批量读取切分完的音频文件

for i in range(count):##

    wavsample = read_file("/Users/yequ/音频片段"+str(i)+".wav")

    # 输出查看wavsample结果

print(wavsample)

step2批量读取完音频之后:
我们将实现“多段音频文件的批量识别”的第二步——批量调用接口识别音频

批量调用接口识别音频:在for循环结果的循环体内,调用语音识别函数audio2text(),获取语音识别结果,并输出识别结果,实现批量调用接口识别音频。

代码:

# 通过for循环调用批量读取切分完的音频文件

for i in range(count):

    # 调用文件读取函数read_file(),读取所有音频片段文件

    wavsample = read_file("/Users/yequ/音频片段"+str(i)+".wav")

    # 调用语音识别函数audio2text(),获取语音识别结果

    text = audio2text(wavsample)

    # 输出查看text

print(text)

代码整理

将今日学习的代码分为三个部分:
part1. 读取文件函数
part2. 语音识别函数
part3. 调用函数批量识别音频

本节课,我们学习了语音识别模型的结构和原理,同时调用创建好的AipSpeech客户端实现了语音转文字功能。
下节课,我们将学习视频文件字幕格式,并通过代码生成标准格式字幕文件

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

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

相关文章

数组单调栈-901. 股票价格跨度、leetcode

单调栈作为一种数据结构在求解类递增、递减方面的题目中有较为广泛的应用,在以往的leetcode中所见到的相关单调栈的题目均为单一元素,今天刷到901题目时,想到了将数组元素作为单调栈中元素的方法进行求解。 题目链接及描述 901. 股票价格跨…

【c++leetcode】69. Sqrt(x)

问题入口 二分搜索 最困难的是能否意识到用二分搜索法解题。 算术平方根的区间在[1, x] 。代码如下&#xff1a; class Solution { public:int mySqrt(int x) {if (x 1 || x 0){return x;}int64_t start 1;int64_t end x;while (start < x){int64_t mid start (en…

以果决其行,只为文化的传承

从他们每一个人的身上&#xff0c;我们看到传神的东西&#xff0c;就是他们都能用结果&#xff0c;去指引自己前进的方向&#xff0c;这正是我要解读倪海厦老师的原因&#xff0c;看倪海厦2012年已经去世&#xff0c;到现在已经十几年时间了&#xff0c;但是我们看现在自学中医…

【Pandas】深入解析`pd.to_sql()`函数

【Pandas】深入解析pd.to_sql()函数 &#x1f308; 欢迎莅临我的个人主页&#x1f448;这里是我深耕Python编程、机器学习和自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;并乐于分享知识与经验的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1…

2024年第六届中青杯数学建模竞赛浅析

获取比赛资料&#xff0c;请关注gzh“小何数模”&#xff01; 本次中青杯数学建模的赛题已正式出炉&#xff0c;无论是赛题难度还是认可度&#xff0c;该比赛都是仅次于数模国赛的独一档&#xff0c;可以用于国赛前的练手训练。考虑到大家解题实属不易&#xff0c;为了帮助大家…

JavaSE:StringBuilder和StringBuffer类

1、引言 在上一篇文章中&#xff0c;我们理解了字符串的常用方法&#xff0c;细心的同学大概已经发现&#xff0c;不管是将字符串中的字符转变为大写或小写&#xff0c;或是完成字符串的替换&#xff0c;又或是去除空白字符等等&#xff0c;只要涉及到字符串的修改&#xff0c…

【PB案例学习笔记】-10 进度条使用

写在前面 这是PB案例学习笔记系列文章的第10篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

Java用反射reflect来实例化对象: class.getDeclaredConstructor().newInstance()

Java用反射reflect来实例化对象: class.getDeclaredConstructor().newInstance() 从java9开始, class.newInstance()已过时, 被加上Deprecated强烈反对注解 SuppressWarnings("removal")CallerSensitiveDeprecated(since"9")public T newInstance()throws …

防止自动化攻击的最佳实践

防止自动化攻击的最佳实践 在当今的网络安全环境中&#xff0c;保护用户账户免受自动化攻击已成为每个网站和应用程序的重要任务。攻击者可以利用多种不同类型的自动化攻击来尝试破坏用户账户。本文将详细介绍常见的攻击类型及其防御机制&#xff0c;帮助您更好地保护用户账户…

adb 连接机顶盒命令

抓机顶盒日志的方法&#xff0c;使用此命令进行抓日志&#xff0c;个别无法抓日志的盒子可以使用此方法 1、安卓9.0版本查询命令 ps -ef |grep com.cm.webos.iptv 2、安卓4.4版本查询命令 ps |grep com.cm.webos.iptv 3、查询顺序&#xff1a;首先进入shell下进行操作 adb she…

C++青少年简明教程:for循环语句

C青少年简明教程&#xff1a;for循环语句 C的for循环语句是一种迭代控制语句&#xff0c;用于重复执行一段代码。 语法格式&#xff1a; for(表达式1&#xff1b;表达式2&#xff1b;表达式3) 循环体 for循环语句执行流程图&#xff1a; 不太好理解&#xff0c;请看下图&am…

VSCode配置Lua5.4安装

参考&#xff1a;VSCode 配置 Lua 开发环境(清晰明了)_lua vscode-CSDN博客 1.下载 Lua Binaries Download (sourceforge.net) 2.配置环境变量 解压放到某文件夹&#xff1a; 环境变量&#xff1a; 3.VSCode安装插件 4.配置 5.测试

Python | Leetcode Python题解之第116题填充每个节点的下一个右侧节点指针

题目&#xff1a; 题解&#xff1a; class Solution:def connect(self, root: Node) -> Node:if not root:return root# 从根节点开始leftmost rootwhile leftmost.left:# 遍历这一层节点组织成的链表&#xff0c;为下一层的节点更新 next 指针head leftmostwhile head:#…

快解析动态域名解析,实现外网访问内网数据库

今天跟大家分享一下如何借助快解析动态域名解析&#xff0c;在两种特定网络环境下&#xff0c;实现外网访问内网mysql数据库。 第1种网络环境&#xff1a;路由器分配的是动态公网IP&#xff0c;且有路由器登录管理权限。如何实现外网访问内网mysql数据库&#xff1f; 针对这种…

继承与Object

一.继承 Java语言的继承&#xff1a;单继承 1.类和类之间的关系 (1)组合关系 公司和员工&#xff0c;学校和学生 (2)继承关系 学生和人 二.Object类 public class Object {private static native void registerNatives();static {registerNatives();} 1.finalize() 对象…

FPGA时钟:驱动数字逻辑的核心

一、引言 在FPGA&#xff08;现场可编程门阵列&#xff09;设计中&#xff0c;时钟信号是不可或缺的关键要素。时钟信号作为时序逻辑的心跳&#xff0c;推动着FPGA内部各个存储单元的数据流转。无论是实现复杂的逻辑运算还是处理高速数据流&#xff0c;都需要精确的时钟信号来保…

Vanna使用ollama分析本地MySQL数据库

上一章节中已经实现了vanna的本地运行&#xff0c;但是大模型和数据库都还是远程的&#xff0c;因为也就没办法去训练&#xff0c;这节一起来实现vanna分析本地mysql数据库&#xff0c;因为要使用本地大模型&#xff0c;所以开始之前需要给本地安装好大模型&#xff0c;我这里用…

WPF/C#:理解与实现WPF中的MVVM模式

MVVM模式的介绍 MVVM&#xff08;Model-View-ViewModel&#xff09;是一种设计模式&#xff0c;特别适用于WPF&#xff08;Windows Presentation Foundation&#xff09;等XAML-based的应用程序开发。MVVM模式主要包含三个部分&#xff1a;Model&#xff08;模型&#xff09;、…

期权具体怎么交易详细的操作流程?

期权就是股票&#xff0c;唯一区别标的物上证指数&#xff0c;会看大盘吧&#xff0c;交易两个方向认购做多&#xff0c;认沽做空&#xff0c;双向t0交易&#xff0c;期权具体交易流程可以理解选择方向多和空&#xff0c;选开仓的合约&#xff0c;买入开仓和平仓没了&#xff0…

【Spring Cloud】API网关

目录 什么是API网关为什么需要API网关前言问题列表 API网关解决了什么问题常见的网关解决方案NginxLuaSpring Cloud Netflix ZuulSpringCloud Zuul的IO模型弊端 Spring Cloud Gateway 第二代网关——GatewayGateway的特征Spring Cloud Gateway的处理流程Spring Cloud Gateway的…