端到端语音识别案例

《DeepSeek大模型高性能核心技术与多模态融合开发(人工智能技术丛书)》(王晓华)【摘要 书评 试读】- 京东图书

语音识别这一技术正如其名,是通过精密地解析说话人的语音来识别并准确转写出其所说的内容。它不仅仅是一个简单的转录过程,更是一项融合了声学、语言学、计算机科学等多个学科领域精华的高科技产物。在现代社会中,随着人工智能技术的飞速发展,语音识别技术正日益显现出其巨大的应用潜力和广阔的市场前景。

无论是在智能手机上的语音助手,还是在家庭中的智能音箱,甚至是在车载系统中,语音识别技术都扮演着举足轻重的角色。它能够将人们的口头语言迅速转化为文字信息,从而极大地提高了交互的便捷性和效率。不仅如此,语音识别还在无障碍沟通、语音搜索、自动化客服等众多领域发挥着不可或缺的作用,为人们的生活和工作带来了前所未有的便利。

11.3.1  全中文音频数据集的准备

我们将使用全中文的音频信号进行转换,这里首选使用aidatatang_200zh数据集作为我们的音频转换目标。aidatatang_200zh是一个用于语音识别的数据集,包含30万条口语化句子,由6408人录制,涵盖不同年龄段和34个省级行政区域。录音环境为安静的室内,采用16kHz 16bit的wav单声道格式,总大小为18G。该数据集适用于语音识别、机器翻译和声纹识别等场景,标注准确率不低于98%。

Aidatatang_200zh是一套开放式中文普通话电话语音库。语料库长达200小时,由Android系统手机(16kHz,16位)和iOS系统手机(16kHz,16位)记录。邀请来自中国不同重点区域的600名演讲者参加录音,录音是在安静的室内环境或环境中进行,其中包含不影响语音识别的背景噪音。参与者的性别和年龄均匀分布。语料库的语言材料是设计为音素均衡的口语句子。每个句子的手动转录准确率大于98%。

读者很容易在互联网上搜索到这个数据集的相关内容,下载解压后的单个文件如图11-8所示。

图11-8  载解压后的单个文件示例

我们说过,对于第一步单文本生成来说,并不需要对语音数据进行批匹配,因此在这一步进行数据读取时仅仅读取txt文本文件中的数据即可。

通过解压后的文件可以看到,Aidatatang_200zh提供了600个文件夹,每个文件夹中存放若干个文本与语音对应的文件,其通过文件名进行一一对应。

首先,第一步是读取所有的文件,代码如下所示。

import os
# 这个是列出所有目录下文件夹的函数
def list_folders(path):"""列出指定路径下的所有文件夹名"""folders = []for root, dirs, files in os.walk(path):for dir in dirs:folders.append(os.path.join(root, dir))return folders
from torch.utils.data import DataLoader, Datasetdef list_files(path):files = []for item in os.listdir(path):file = os.path.join(path, item)if os.path.isfile(file):files.append(file)return files#这里作者使用的是自定义的数据集存放位置,读者可以改成自己所对应的语音数据集位置
dataset_path = "D:/语音识别_数据集/aidatatang_200zh/dataset"folders = list_folders(dataset_path)	#获取了所有文件夹for folder in tqdm(folders):_files = list_files(folder)		for _file in _files:if _file.endswith("txt"):with open(_file,encoding="utf-8") as f:line = f.readline().strip()

其中folders是Aidatatang_200zh目录下所有文件夹,list_folders的作用是对每个文件夹进行重新读取。

接下来,一个非常重要的内容就是建立相应的字库文件,这里我们可以在读取全部文本数据之后使用set结构对每个字符进行存储。

vocab = set()
……
for folder in tqdm(folders):_files = list_files(folder)for _file in _files:if _file.endswith("txt"):with open(_file,encoding="utf-8") as f:line = f.readline().strip()for char in line:vocab.add(char)    
vocab = list(sorted(vocab))

11.3.2  音频特征的提取与融合

梅尔频谱作为音频提取的主要方法,其作用在于对提取的音频信号进行高效的转换与分析。通过模拟人类听觉系统的特性,梅尔频谱能够将复杂的音频数据转化为易于处理和解读的频域表示,从而揭示出音频信号中的关键特征和潜在结构。这种转换不仅有助于简化音频处理流程,还能提高特征提取的准确性和效率,为后续的音频识别、分类和合成等任务奠定坚实基础。因此,梅尔频谱在音频处理领域具有广泛的应用价值,是研究人员和工程师们不可或缺的工具之一。

梅尔频谱的独特之处在于其基于梅尔刻度的频率划分方式。与传统的线性频率刻度相比,梅尔刻度更符合人类听觉系统对频率的感知特性。在梅尔频谱中,低频段的分辨率较高,能够捕捉到更多的细节信息,而高频段的分辨率则相对较低,以适应人类对高频声音的不敏感性。这种特性使得梅尔频谱在处理具有丰富低频成分的音频信号时表现出色,如语音和音乐等。

此外,梅尔频谱还具有良好的抗噪性能和稳定性。在音频信号受到噪声干扰或质量下降时,梅尔频谱仍能有效地提取出有用的特征信息,保持较高的识别准确率。这使得梅尔频谱在实际应用中具有更强的鲁棒性和可靠性,能够满足各种复杂场景下的音频处理需求。

基于librosa库完成的特征信号提取,其代码如下所示。

# 计算梅尔频率图
def compute_melspec(y, sr, n_mels, fmin, fmax):""":param y:传入的音频序列,每帧的采样:param sr: 采样率:param n_mels: 梅尔滤波器的频率倒谱系数:param fmin: 短时傅里叶变换(STFT)的分析范围 min:param fmax: 短时傅里叶变换(STFT)的分析范围 max:return:"""# 计算Mel频谱图的函数melspec = lb.feature.melspectrogram(y=y, sr=sr, n_mels=n_mels, fmin=fmin, fmax=fmax)  # (128, 1024) 这个是输出一个声音的频谱矩阵# 是Python中用于将音频信号的功率值转换为分贝(dB)值的函数melspec = lb.power_to_db(melspec).astype(np.float32)# 计算MFCCmfccs = lb.feature.mfcc(S=melspec)return melspec,mfccs

从上面代码可以看到,我们通过梅尔频谱获取到了梅尔特征以及梅尔频率倒谱系数,这是从不同的角度对语音特征进行提取。

接下来就是我们希望将提取到的特征进行融合,具体融合的方式可以在数据特征输入到模型之前完成,即在特征提取后,经过一个正则化处理使用在特定维度拼接的方式完成,代码如下所示。

# 对输入的频谱矩阵进行正则化处理
def mono_to_color(X, eps=1e-6, mean=None, std=None):mean = mean or X.mean()std = std or X.std()X = (X - mean) / (std + eps)_min, _max = X.min(), X.max()if (_max - _min) > eps:V = np.clip(X, _min, _max)V = 255. * (V - _min) / (_max - _min)V = V.astype(np.uint8)else:V = np.zeros_like(X, dtype=np.uint8)return V
……
def audio_to_image(audio, sr, n_mels, fmin, fmax):melspec,mfccs = compute_melspec(audio, sr, n_mels, fmin, fmax)    #(128, 688)melspec = mono_to_color(melspec)mfccs = mono_to_color(mfccs)spec = np.concatenate((melspec, mfccs), axis=0)return spec

这里需要注意,我们获取到的音频特征,由于其采样的方式不同,其数值大小也千差万别。因此,在进行concatenate拼接之前,需要进行正则化处理。

获取数据的完整代码如下:

from tqdm import tqdm
import os# 这个是列出所有目录下文件夹的函数
def list_folders(path):"""列出指定路径下的所有文件夹名"""folders = []for root, dirs, files in os.walk(path):for dir in dirs:folders.append(os.path.join(root, dir))return folders
from torch.utils.data import DataLoader, Datasetdef list_files(path):files = []for item in os.listdir(path):file = os.path.join(path, item)if os.path.isfile(file):files.append(file)return filesdataset_path = "D:/语音数据库/aidatatang_200zh"
#dataset_path = "../dataset/aidatatang_200zh/"
folders = list_folders(dataset_path)
folders = folders[:5]max_length = 18
sampling_rate = 16000
wav_max_length = 22#这里的计数单位是秒
context_list = []
token_list = []
wav_image_list = []for folder in tqdm(folders):_files = list_files(folder)for _file in _files:if _file.endswith("txt"):#_file = "D:/aidatatang_200zh/G0084/T0055G0084S0496.txt"with open(_file,encoding="utf-8") as f:line = f.readline().strip()if len(line) <= max_length:wav_name = _file.replace("txt", "wav")audio, orig_sr = sf.read(wav_name, dtype="float32")  # 这里均值是 1308338,   0.8中位数是1730351,所以我采用了中位数的部分audio = sound_untils.crop_or_pad(audio, length=sampling_rate * wav_max_length)  # 我的想法是把audio做一个整体输入,在这里就所有的都做了输入wav_image = sound_untils.audio_to_image(audio, sampling_rate, 128, 0, sampling_rate//2) #输出的是(128, 688)wav_image_list.append(wav_image)#token_list.append(token)np.save("./saver/wav_image_list.npy",wav_image_list)

这里为了加速模型的训练,我们首先读取了音频,并创建了融合后的音频特征,将其进行存储。为了将数据输入到模型中,还需要实现torch.utils.data.Dataset数据类。代码如下:

class TextSamplerDataset(torch.utils.data.Dataset):def __init__(self, token_list = token_list,wav_image_list = wav_image_list):super().__init__()self.token_list = token_listself.wav_image_list = wav_image_listdef __getitem__(self, index):token = self.token_list[index]token = torch.tensor(token).long()token_inp, token_tgt = token[:-1], token[1:]wav_image = self.wav_image_list[index]#sound_untils.audio_to_image(audio, sampling_rate, 128, 0, sampling_rate//2) #输出的是(128, 688)wav_image = torch.tensor(wav_image,dtype=torch.float).float()return token_inp,wav_image,token_tgtdef __len__(self):return len(self.token_list)

11.3.3  基于生成模型的端到端语音识别任务

我们需要完成的是基于端到端的语音识别任务,特别是使用生成模型将输入的语音特征转化为文本内容,遇到的第一个问题将会是如何将可变的生成文本与语音特征信号进行融合。

首先,我们采用将语音特征压缩特性的方式进行融合,即将多维的语音特征压缩成一维后与输入的可变长度的文本信息相加后进行处理,代码如下:

class ReshapeImageLayer(torch.nn.Module):def __init__(self):super().__init__()self.reshape_layer = torch.nn.Linear(688,model_cfg.dim * 2)self.norm = layers.LayerNorm(model_cfg.dim * 2)self.act = layers.SwiGLU()def forward(self,image):image = self.reshape_layer(image)image = self.norm(image)image = self.act(image)image = torch.permute(image,[0,2,1])image = torch.nn.AdaptiveAvgPool1d(1)(image)image = torch.permute(image,[0,2,1])return image

上面代码创建了一个简单的卷积层对信号进行提取,之后通过了AvgPool对特征进行压缩,在调整维度后进行返回。

对于生成模型来说,其核心就是采用注意力机制建立跨区域关注。因此,我们可以在创建因果掩码后完成生成模型的设计。代码如下:

class GLMSimple(torch.nn.Module):def __init__(self,dim = model_cfg.dim,num_tokens = model_cfg.num_tokens,device = all_config.device):super().__init__()self.num_tokens = num_tokensself.causal = model_cfg.causalself.device = deviceself.token_emb = torch.nn.Embedding(num_tokens,dim)self.layers = torch.nn.ModuleList([])for _ in range(model_cfg.depth):block = GLMBlock()self.layers.append(block)self.to_logits = torch.nn.Linear(dim, num_tokens, bias=False)self.reshape_layer = ReshapeImageLayer()self.merge_norm = layers.LayerNorm(dim)def forward(self,x,image = None):if not self.causal:mask = x > 0x = x.masked_fill(~mask, 0)else:mask = Nonex = self.token_emb(x)image = self.reshape_layer(image)for layer in self.layers:x += imagex = self.merge_norm(x)x = x + layer(x, mask = mask)x = torch.nn.Dropout(0.1)(x)logits = self.to_logits(x)return logits

在上面代码中,GLMBlock是我们实现的经典的因果注意力模型,目的是将向量化处理后的可变文本特征与一维的语音特征相加后,输入到因果注意力模型进行计算。

为了配合因果注意力机制的输入,对于文本的最终输入,我们也可以采用比较巧妙的设计,代码如下:

@torch.no_grad()
def generate(self, seq_len, image=None, temperature=1., filter_logits_fn=top_k,filter_thres=0.99, pad_value=0., eos_token=2,                       return_seq_without_prompt=True, #这个的作用是在下面随机输出的时候,把全部的字符输出):# 这里是我后加上去的,输入进来可以是listimage = torch.tensor(image,dtype=torch.float).float()image = torch.unsqueeze(image,dim=0)image = image.to(self.device)prompt = torch.tensor([1])prompt = prompt.to(self.device)prompt, leading_dims = pack([prompt], '* n')n, out = prompt.shape[-1], prompt.clone()#wrapper_fn = identity if not use_tqdm else tqdmsample_num_times = max(1, seq_len - prompt.shape[-1])for _ in (range(sample_num_times)):logits = self.forward(out,image)logits = logits[:, -1]sample = gumbel_sample_once(logits, temperature=temperature, dim=-1)out, _ = pack([out, sample], 'b *')if exists(eos_token):is_eos_tokens = (out == eos_token)if is_eos_tokens.any(dim=-1).all():breakout, = unpack(out, leading_dims, '* n')if not return_seq_without_prompt:return outreturn out[..., n:]

上面代码中,我们采用generate 函数来产生输入的文本内容,随后通过逐个添加字符的方式逐步扩充所给信息,进而利用下一个字符的预测来完成最终结果的构建。

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

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

相关文章

QT——信号和槽

QT是图形化界面&#xff0c;自然是需要与用户进行交互的&#xff0c;但是该如何实现用户与界面或者程序的交互呢。答案是通过信号和槽。 一&#xff0c;什么是信号和槽&#xff1f; 在Linux操作系统里面&#xff0c;我们知道信号是由硬件或者软件产生&#xff0c;但是在QT里面…

Q:如何保证备份的有效性以及备份频率设置的优化方案?

1、如何保障备份数据的一致性 a) 快照 快照通过捕获数据在某一时刻的完整状态来保障备份一致性。在应用层&#xff0c;快照会暂停业务写入或生成事务一致性检查点&#xff08;如数据库的全局读视图&#xff09;&#xff0c;确保备份数据不包含未提交的事务&#xff1b;在存…

Linux实用操作及命令

一、各类小技巧&#xff08;快捷键&#xff09; 1、强制停止&#xff08;ctrlc&#xff09; Linux某些程序的运行&#xff0c;如果想要强制停止它&#xff0c;可以使用快捷键ctrl c 命令输入错误&#xff0c;也可以通过快捷键ctrl c&#xff0c;退出当前输入&#xff0c;重…

压测工具开发(一)——使用Qt Designer构建简单界面

你好&#xff0c;我是安然无虞。 文章目录 项目功能概述构建菜单栏、工具栏1. 菜单栏注意事项2. 工具栏注意事项3. 日志停靠窗口 项目功能概述 开发一款 Qt版本的压测工具, 可以用来做 基于HTTP API接口的 性能测试. 要求做一个 MDI 多功能子窗口的 图形界面程序, 方便公司内…

Ubuntu 22 Linux上部署DeepSeek R1保姆式操作详解(ollama方式)

操作系统&#xff1a;Ubuntu Linux 22.04 一、安装模型运行环境 打开链接https://ollama.com/download/linux 1.安装ollama &#xff08;1&#xff09;一条指令即可实现的简易版安装方法&#xff08;也可称为在线安装&#xff09; curl -fsSL https://ollama.com/install.s…

MySQL 和 Redis 数据一致性解决方案

MySQL 和 Redis 数据一致性解决方案 MySQL 和 Redis 作为两种不同类型的数据库(关系型 vs 内存型)&#xff0c;在配合使用时需要特别注意数据一致性问题。以下是几种常见的解决方案&#xff1a; 1. 缓存更新策略 1.1 Cache Aside Pattern (旁路缓存模式) 读操作&#xff1a…

Java高频面试之集合-20

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本baby今天来报道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面试官&#xff1a;讲讲 HashSet 的底层实现&#xff1f; HashSet 是 Java 集合框架中用于存储唯一元素的高效数据结构&#xff0c;其底层实…

【MySQL】从零开始:掌握MySQL数据库的核心概念(四)

人们之所以不愿改变&#xff0c;是因为害怕未知。但历史唯一不变的事实&#xff0c;就是一切都会改变。 前言 这是我自己学习mysql数据库的第四篇博客总结。后期我会继续把mysql数据库学习笔记开源至博客上。 上一期笔记是关于mysql数据库的表格约束&#xff0c;没看的同学可以…

Manus:通用智能体的架构革命与产业破局

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…

HTTP协议手写服务器

目录 一、请求的是Web根目录 二、GET方法通过URL传参 三、根据资源类型对应出Content-Type值 四、Http代码 项目完整源代码&#xff1a;Http 周不才/cpp_linux study - 码云 - 开源中国 一、请求的是Web根目录 如果URL中请求的资源是Web根目录&#xff0c;则自动跳转到主…

小蓝和钥匙

错位排序组合数 从28个人里面选14个人分到原来房间的钥匙 C 28 14 另外14个人错位排序 模板 请在此处填写你的解题思路 D14 都是模板记住就好了 无需理解 做题可以看出来是错位排序 或者组合数 然后会写代码就行了 import java.util.Scanner;/*** author zb* date2025/3…

使用飞书API自动化更新共享表格数据

飞书API开发之自动更新共享表格 天马行空需求需求拆解1、网站数据爬取2、飞书API调用2.1 开发流程2.2 创建应用2.3 配置应用2.4 发布应用2.5 修改表格权限2.6 获取tenant_access_token2.7 调用API插入数据 总结 天马行空 之前一直都是更新的爬虫逆向内容&#xff0c;工作中基本…

Python-Django入手

18.1 建立项目 18.1.1 制定规范 - 定义项目目标&#xff1a;明确应用的核心功能 - 创建项目文档&#xff1a;用README.md记录技术栈和开发流程 - 规划目录结构&#xff1a;建议遵循Django官方推荐的项目布局 18.1.2 建立虚拟环境 在命令行执行&#xff1a; python -m ven…

LangChain4j 入门(二)

LangChain 整合 SpringBoot 下述代码均使用 阿里云百炼平台 提供的模型。 创建项目&#xff0c;引入依赖 通过 IDEA 创建 SpringBoot 项目&#xff0c;并引入 Spring Web 依赖&#xff0c;SpringBoot 推荐使用 3.x 版本。 引入 LangChain4j 和 WebFlux 依赖 <!--阿里云 D…

3.30学习总结 Java包装类+高精度算法+查找算法

包装类&#xff1a; 基本数据类型对应的引用数据类型。 基本数据类型&#xff1a;在内存中记录的是真实的值。 八种包装类的父类都是Object类。 对象之间不能直接进行计算。 JDK5之后可以把int和integer看成一个东西&#xff0c;因为会进行内部优化。自动装箱和自动拆箱。 …

centos 7 LVM管理命令

物理卷&#xff08;PV&#xff09;管理命令 pvcreate&#xff1a;用于将物理磁盘分区或整个磁盘创建为物理卷。 示例&#xff1a;sudo pvcreate /dev/sdb1 解释&#xff1a;将 /dev/sdb1 分区创建为物理卷。 pvdisplay&#xff1a;显示物理卷的详细信息&#xff0c;如大小、所属…

借助FastAdmin和uniapp,高效搭建AI智能平台

在数字化办公时代&#xff0c;效率与协作是企业发展的核心竞争力。传统的办公工具虽然功能丰富&#xff0c;但在面对复杂多变的团队协作需求时&#xff0c;往往显得力不从心。为了解决这一痛点&#xff0c;我们推出了一款全新的办公AI平台&#xff0c;它不仅能够满足文字和语音…

项目上传github——SSH连接配置文档

1. 检查是否已有 SSH 密钥 打开终端&#xff0c;检查是否已经存在 SSH 密钥对&#xff1a; ls ~/.ssh如果你看到类似 id_rsa 和 id_rsa.pub 的文件&#xff0c;说明你已经有 SSH 密钥。否则&#xff0c;继续下一步。 2. 生成 SSH 密钥 如果你没有 SSH 密钥&#xff0c;使用…

传奇类网游页游2.5D游戏场景地图素材Eagle库 沙漠沙海隔壁

传奇类网游页游2.5D游戏场景地图素材Eagle库 沙漠沙海隔壁 链接: https://pan.baidu.com/s/1GY8N-KEkHBGEbS7uxrE4Dg 提取码: yrs8 备用下载地址&#xff1a;http://pan.1234f.com:5212/s/rLzIp 电子资料文档&#xff1a;https://www.1234f.com/sj/GitHub/sucai/20250327/1323…

通过TIM+DMA Burst 实现STM32输出变频且不同脉冲数量的PWM波形

Burst介绍&#xff1a; DMA控制器可以生成单次传输或增量突发传输&#xff0c;传输的节拍数为4、8或16。 为了确保数据一致性&#xff0c;构成突发传输的每组传输都是不可分割的&#xff1a;AHB传输被锁定&#xff0c;AHB总线矩阵的仲裁器在突发传输序列期间不会撤销DMA主设备…