【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客户端实现了语音转文字功能。
下节课,我们将学习视频文件字幕格式,并通过代码生成标准格式字幕文件

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

香橙派 AIpro 昇腾 Ascend C++ 分类模型适配

香橙派 AIpro 昇腾 Ascend C 分类模型适配 flyfish 文章目录 香橙派 AIpro 昇腾 Ascend C 分类模型适配前言一、PyTorch官网resnet模型处理方式1、PyTorch模型 导出 onnx格式2、完整测试 输出top1结果3、完整测试 输出top5结果 二、YOLOv8官网resnet模型Python处理方式三、昇腾…

NSSCTF-Web题目3

目录 [BJDCTF 2020]easy_md5 1、知识点 2、题目 3、思路 [ZJCTF 2019]NiZhuanSiWei 1、知识点 2、题目 3、思路 第一层 第二层 第三层 [BJDCTF 2020]easy_md5 1、知识点 弱比较,强比较、数组绕过、MD5加密 2、题目 3、思路 1、首先我们跟着题目输入&a…

微信好友,如此的陌生,渐渐都成了只是人名!也许没有利益关系导致!

微信里一直聊天聊的挺好的朋友,不知怎么到后来却联系少了,最后渐渐的变成躺在微信备注里的一个陌生朋友! 以前通过工作认识了一个朋友,初次见面的印象不是很深刻了,只记得当时给我的印象是对方很有礼貌,特别…

快团团帮卖团长如何修改供货大团长复制帮卖团的信息?

一、功能说明 在复制帮卖团中,帮卖团长可以选择:①修改团购内容 ②同步大团长的团购内容 二、具体操作步骤 点击“编辑后帮卖”,在团购设置中设置开启/关闭“同步大团长内容” 开启“同步大团长内容”后,大团长修改图文后&#xf…

分享个自用的 Nginx 加强 WordPress 防护的规则

Nginx WordPress 的组合是目前非常普及的组合了,我们完全可以借助 Nginx 规则来加强 WordPress 的防护,提高 WordPress 的安全性,今天明月就给大家分享个自用的 Nginx 针对 WordPress 的防护规则,部分规则大家只需要根据自己的需要…

计算机图形学入门02:线性代数基础

1.向量(Vetors) 向量表示一个方向,还能表示长度(向量的摸)。一般使用单位向量表示方向。 向量加减:平行四边形法则、三角形法则。比卡尔坐标系描述向量,坐标直接相加。 1.1向量点乘(…

腾讯云联络中心ivr调用自定义接口

1&#xff0c;java代码&#xff1a;http接口 RequestMapping(value "/getMsg5", method RequestMethod.POST) public Map<String, String> index(RequestBody Map<String, String> params) {String id params.get("id");HashMap<String…

Java-Stream流-概述、创建、使用:遍历/匹配、筛选、聚合、映射、归约、排序、提取/组合

Java8-Stream&#xff1a; 一、Stream流概述1.Stream流的特点&#xff1a;2.使用步骤&#xff1a;3.常用方法示例&#xff1a; 二、Stream流创建1.常见的创建Stream的方法2. stream()或parallelStream()方法的使用和选择 三、Stream流使用Optional案例中使用的实体类1.遍历/匹配…

【哈希】闭散列的线性探测和开散列的哈希桶解决哈希冲突(C++两种方法模拟实现哈希表)(1)

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; C进阶 &#x1f389;其它专栏&#xff1a; C初阶 | Linux | 初阶数据结构 小伙伴们大家好&#xff0c;本片文章将会讲解 哈希函数与哈希 之 闭散列的线性探测解决哈希冲突 的相关内容。 如…

CAS原理技术

CAS原理技术 背景介绍结构体系术语接口原理基础模式1. 首次访问集成CAS Client的应用2. 再次访问集成CAS Client的同一应用3. 访问集成CAS Client的其他应用 代理模式1. 用户在代理服务器上执行身份认证2. 通过代理应用访问其他应用上授权性资源 背景 本文内容大多基于网上其他…

快速版-JS基础01书写位置

1.书写位置 2.标识符 3.变量 var&#xff1a;声明变量。 &#xff08;1&#xff09;.变量的重新赋值 &#xff08;2&#xff09;.变量的提升 打印结果&#xff1a;console.log(变量名) 第一个是你写在里面的。 第二个是实际运行的先后之分&#xff0c;变量名字在最前面。变量…

牛客NC392 参加会议的最大数目【中等 贪心+小顶堆 Java/Go/PHP 力扣1353】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/4d3151698e33454f98bce1284e553651 https://leetcode.cn/problems/maximum-number-of-events-that-can-be-attended/description/ 思路 贪心优先级队列Java代码 import java.util.*;public class Solution {/**…

《MySQL怎样运行的》—InnoDB数据页结构

在上一篇文章中我们讲了&#xff0c;InnoDB的数据页是InnoDB管理存储空间的基本单位&#xff0c;一个页的大小基本为16kb 那你有没有疑问&#xff0c;就是说这个InnoDB的数据页的结构是什么样的&#xff0c;还有他这些结构分别有那些功能~接下来我们一一讲解 数据页的总览结构…

GPT-4o和GPT-4有什么区别?我们还需要付费开通GPT-4?

GPT-4o 是 OpenAI 最新推出的大模型&#xff0c;有它的独特之处。那么GPT-4o 与 GPT-4 之间的主要区别具体有哪些呢&#xff1f;今天我们就来聊聊这个问题。 目前来看&#xff0c;主要是下面几个差异。 响应速度 GPT-4o 的一个显著优势是其处理速度。它能够更快地回应用户的查…

java中的Collections类+可变参数

一、概述 Collections类是集合类的工具类&#xff0c;与数组的工具类Arrays类似 二、可变参数(变&#xff1a;数量) 格式&#xff1a;参数类型名...参数&#xff0c;可变参数就是一个数组 注意&#xff1a;可变参数必须放在参数列表的最后并且一个参数列表只能有一个可变参…

Golang | Leetcode Golang题解之第101题对称二叉树

题目&#xff1a; 题解&#xff1a; func isSymmetric(root *TreeNode) bool {u, v : root, rootq : []*TreeNode{}q append(q, u)q append(q, v)for len(q) > 0 {u, v q[0], q[1]q q[2:]if u nil && v nil {continue}if u nil || v nil {return false}if …

conda 环境找不到 libnsl.so.1

安装prokka后运行报错 perl: error while loading shared libraries: libnsl.so.1: cannot open shared object file: No such file or directory 通过conda list 可以看到 有libsnl 2.00版本&#xff0c;通过修改软链接方式进行欺骗

Vue3项目练习详细步骤(第一部分:项目构建,登录注册页面)

项目环境准备 工程创建 安装依赖 项目调整 注册功能 页面结构 接口文档 数据绑定和校验 数据接口调用 解决跨域问题 登录功能 接口文档 数据绑定和校验 数据接口调用 优化登录/注册成功提示框 项目演示 项目的后端接口参考&#xff1a;https://blog.csdn.net/daf…

selenium 学习笔记(一)

pip的安装 新建一个txt curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py 把上面的代码复制进去后&#xff0c;把后缀名改为.bat然后双击运行 当前目录会出现一个这个文件 然后在命令行pyhon get-pip.py等它下好就可以了selenium安装 需要安装到工程目…

第15章-超声波避障功能 HC-SR04超声波测距模块详解STM32超声波测距

这个是全网最详细的STM32项目教学视频。 第一篇在这里: 视频在这里 STM32智能小车V3-STM32入门教程-openmv与STM32循迹小车-stm32f103c8t6-电赛 嵌入式学习 PID控制算法 编码器电机 跟随 15.1-超声波测距 完成超声波测距功能、测量数据显示在OLED屏幕上 硬件介绍 使用&#…