1. 语音识别介绍

语音识别的最主要过程是:

  1. 特征提取:从声音波形中提取声学特征;
  2. 声学模型(语音模型):将声学特征转换成发音的音素;
  3. 语言模型使用语言模型等解码技术转变成我们能读懂的文本。

语音识别系统的典型结构如图1所示:

图1 语音识别结构

1.1 声学特征提取

声音实际上一种波,原始的音频文件叫WAV文件,WAV文件中存储的除了一个文件头以外,就是声音波形的一个个点。如图2所示:

图2 声音波形示意图

要对声音进行分析,首先对声音进行分帧,把声音切分成很多小的片段,帧与帧之间有一定的交叠,如图3,每一帧长度是25ms,帧移是10ms,两帧之间有25-10=15ms的交叠。

图3 帧切割图

分帧后,音频数据就变成了很多小的片段,然后针对小片段进行特征提取,常见的提取特征的方法有:线性预测编码(Linear Predictive Coding,LPC),梅尔频率倒谱系数(Mel-frequency Cepstrum),把一帧波形变成一个多维向量的过程就是声学特征提取。

1.2. 声学特征转换成音素(声学模型)

音素是人发音的基本单位。对于英文,常用的音素是一套39个音素组成的集合。对于汉语,基本就是汉语拼音的生母和韵母组成的音素集合,大概200多个。本文例子中LSTM+CTC神经网络就是声学特征转换成音素这个阶段,该阶段的模型被称为声学模型。

1.3. 音素转文本(语言模型+解码)

得到声音的音素序列后,就可以使用语言模型等解码技术将音素序列转换成我们可以读懂的文本。解码过程对给定的音素序列和若干假设词序列计算声学模型和语言模型分数,将总体输出分数最高的序列作为识别的结果。

2. 语音识别简单实现

本文通过一个简单的例子演示如何用tensorflow的LSTM+CTC完成一个端到端的语音识别,为了简化操作,本例子中的语音识别只训练一句话,这句话中的音素分类也简化成对应的字母(与真实因素的训练过程原理一致)。计算过程如下图所示:

2.1 提取WAV文件中特征

首先读者肯定会有疑问?什么是WAV文件?笔者在此简单的介绍一下,WAV格式是微软公司开发的一种声音文件格式,也叫波形声音文件,是最早的数字音频格式,被Windows平台及其应用程序广泛支持,是一种无损的音频数据存放格式。

本文在读取WAV的特征数据后,采用python_speech_features包中的方法来读取文件的MFCC特征,详细代码如下:

def get_audio_feature():'''获取wav文件提取mfcc特征之后的数据'''audio_filename = "audio.wav"#读取wav文件内容,fs为采样率, audio为数据fs, audio = wav.read(audio_filename)#提取mfcc特征inputs = mfcc(audio, samplerate=fs)# 对特征数据进行归一化,减去均值除以方差feature_inputs = np.asarray(inputs[np.newaxis, :])feature_inputs = (feature_inputs - np.mean(feature_inputs))/np.std(feature_inputs)  #特征数据的序列长度feature_seq_len = [feature_inputs.shape[1]]return feature_inputs, feature_seq_len

函数的返回值feature_seq_len表示这段语音被分割成了多少帧,一帧数据计算出一个13维长度的特征值。返回值feature_inputs是一个二维矩阵,矩阵行数是feature_seq_len长度,列数是13。

2.2 将WAV文件对应的文本文件转换成音素分类

本文音素的数量是28,分别对应26个英文字母、空白符和没有分到类情况。WAV文件对应的文本文件的内容是she had your dark suit in greasy wash water all year。现在把这句话转换成整数表示的序列,空白用0表示,a-z分别用数字1-26表示,则转换的结果为:[19 8 5 0 8 1 4 0 25 15 21 18 0 4 1 18 110 19 21 9 20 0 9 14 0 7 18 5 1 19 25 0 231 19 8 0 23 1 20 5 18 0 1 12 12 0 25 5 118],最后将整个序列转换成稀疏三元组结构,这样就可以直接用在tensorflow的tf.sparse_placeholder上。转换代码如下:

with open(target_filename, 'r') as f:#原始文本为“she had your dark suit in greasy wash water all year”line = f.readlines()[0].strip()targets = line.replace(' ', '  ')targets = targets.split(' ')targets = np.hstack([SPACE_TOKEN if x == '' else list(x) for x in targets])targets = np.asarray([SPACE_INDEX if x == SPACE_TOKEN else ord(x) - FIRST_INDEXfor x in targets])# 将列表转换成稀疏三元组train_targets = sparse_tuple_from([targets])print(train_targets)return train_targets

2.3 定义双向LSTM

定义双向LSTM及LSTM之后的特征映射的代码如下:

def inference(inputs, seq_len):#定义一个向前计算的LSTM单元,40个隐藏单元cell_fw = tf.contrib.rnn.LSTMCell(num_hidden, initializer=tf.random_normal_initializer(mean=0.0, stddev=0.1),state_is_tuple=True)# 组成一个有2个cell的listcells_fw = [cell_fw] * num_layers# 定义一个向后计算的LSTM单元,40个隐藏单元cell_bw = tf.contrib.rnn.LSTMCell(num_hidden, initializer=tf.random_normal_initializer(mean=0.0, stddev=0.1),state_is_tuple=True)# 组成一个有2个cell的listcells_bw = [cell_bw] * num_layersoutputs, _, _ = tf.contrib.rnn.stack_bidirectional_dynamic_rnn(cells_fw, cells_bw, inputs,dtype=tf.float32,sequence_length=seq_len)shape = tf.shape(inputs)batch_s, max_timesteps = shape[0], shape[1]outputs = tf.reshape(outputs, [-1, num_hidden])W = tf.Variable(tf.truncated_normal([num_hidden,num_classes],stddev=0.1))b = tf.Variable(tf.constant(0., shape=[num_classes]))# 进行全连接线性计算logits = tf.matmul(outputs, W) + b# 将全连接计算的结果,由宽度40变成宽度80,# 即最后的输入给CTC的数据宽度必须是26+2的宽度logits = tf.reshape(logits, [batch_s, -1, num_classes])# 转置,将第一维和第二维交换。# 变成序列的长度放第一维,batch_size放第二维。# 也是为了适应Tensorflow的CTC的输入格式logits = tf.transpose(logits, (1, 0, 2))return logits

2.4 模型训练和测试

最后将读取数据、构建LSTM+CTC网络及训练过程结合起来,在完成500次迭代训练后,进行测试,并将结果输出,部分代码如下:

def main():# 输入特征数据,形状为:[batch_size, 序列长度,一帧特征数]inputs = tf.placeholder(tf.float32, [None, None, num_features])# 输入数据的label,定义成稀疏sparse_placeholder会生成稀疏的tensor:SparseTensor# 这个结构可以直接输入给ctc求losstargets = tf.sparse_placeholder(tf.int32)# 序列的长度,大小是[batch_size]大小# 表示的是batch中每个样本的有效序列长度是多少seq_len = tf.placeholder(tf.int32, [None])# 向前计算网络,定义网络结构,输入是特征数据,输出提供给ctc计算损失值。logits = inference(inputs, seq_len)# ctc计算损失# 参数targets必须是一个值为int32的稀疏tensor的结构:tf.SparseTensor# 参数logits是前面lstm网络的输出# 参数seq_len是这个batch的样本中,每个样本的序列长度。loss = tf.nn.ctc_loss(targets, logits, seq_len)# 计算损失的平均值cost = tf.reduce_mean(loss)

训练过程及结果如下图:

从上图训练结果可以清洗的看出经过500次的迭代训练,语音文件基本已经可以完全识别,本例只演示了一个简单的LSTM+CTC的端到端的训练,实际的语音识别系统还需要大量训练样本以及将音素转换成文本的解码过程。后续文章中,笔者会继续深入语音识别。

语音识别(一):介绍和简单实现相关推荐

  1. android开发-百度语音识别Android SDK的简单使用

    目录 1.引言 2.开发环境 3.准备开发环境 3.1安装Android studio 3.2创建百度智能云平台应用 3.1下载百度语音识别SDK 4.实现语音识别的简单案例 4.1创建Android ...

  2. Matplotlib的介绍及简单操作

    Matplotlib的介绍及简单操作 1 什么是Matplotlib 是专门用于开发2D图表(包括3D图表) 以渐进.交互式方式实现数据可视化 2 为什么要学习Matplotlib 可视化是在整个数据 ...

  3. (三)AJAX基本介绍和简单实例03

    (三)AJAX基本介绍和简单实例03-----Ajax与数据库的动态应用 前台显示界面: 选择所有客户之后: 选择其中一个客户---杜森: Demo03.html代码 <html> < ...

  4. rabbitMQ消息队列 – 面板介绍及简单demo

    首先rabbit安装好之后,运维会给一个控制面板. 默认账号密码为guest 登入以后可以看到具体界面. 在此鸣谢百度翻译给予的大力支持.. ###写一个简单的demo 编写之前..虽然说可以直接用底 ...

  5. Protobuf介绍及简单使用(上)

    目录 Protobuf 介绍 优势 protobuf语法 Specifying Field Rules Data type Data name Number Protobuf注释 保留字段与标识符 s ...

  6. SQL Server中追踪器Trace的介绍和简单使用

    原文:SQL Server中追踪器Trace的介绍和简单使用 一.What is Trace? 对于SQL Profiler这个工具相信大家都不是很陌生,没用过的朋友可以在SQL Server Man ...

  7. S3C2440移植linux3.4.2内核之内核框架介绍及简单修改

    文章目录 uboot启动内核分析 简单配置内核 编译内核 设置机器ID 修改晶振 移植Linux3.4.2内核其他文章链接: S3C2440移植linux3.4.2内核之内核框架介绍及简单修改 S3C ...

  8. 新颖的自我介绍_简单新颖的自我介绍范文

    简单新颖的自我介绍范文 简单新颖的自我介绍范文1 各位考官好,今天能够站在这里参加面试,有机会向各位考官请教和学习,我感到非常的荣幸.希望通过这次面试能够把自己展示给大家,希望大家记住我.我叫.... ...

  9. Quartz框架实现定时任务介绍及简单使用

    https://blog.csdn.net/bicheng4769/article/details/81097305 Quartz框架介绍及简单使用 https://www.cnblogs.com/d ...

  10. Hive第一天——Hive介绍以及简单使用

    Hive第二天--Hive介绍以及简单使用 自己的话:黑发不知勤学早,白首方悔读书迟 每天都要保持前进! 一.什么是Hive 数据库: mysql.oracle.sqlserver.DB2.sqlit ...

最新文章

  1. 英特尔在移动市场另辟蹊径
  2. 德国人工智能研究中心波尔特:人工智能与工业4.0并驾齐驱
  3. 泛海精灵的用户分析:补充【Song Xie】
  4. JavaScript学习笔记之 数组方法一 堆栈 和队列
  5. 使用anaconda安装pytorch的清华镜像地址
  6. HTG Explains: Why Linux Doesn’t Need Defragmenting
  7. 单词计数WordCountApp.class
  8. 【小夕精选】如何优雅而时髦的解决不均衡分类问题
  9. [开源]430驱动的12864图形点阵LCD
  10. 《Hack与HHVM权威指南》——1.1 为什么使用类型检查器
  11. 不显示负频率的部分,坐标轴转换为频率,幅值量纲还原改善频谱图以及功率谱和对数功率谱
  12. 瑞萨RH850F1L用户手册(UM)LIN master接口章节 中文翻译(Section 6 Exceptions/Interrupts(异常/中断))
  13. 分享psd格式怎么预览的方法和psd文件缩略图插件
  14. 如何在matlab中产生瞬态信号,基于小波分析的微弱信号检测及其在Matlab中的仿真...
  15. Windows下制作苹果电脑U盘启动
  16. 国产_系统_加油 by tmddebaba
  17. Linux怎么给命令创建别名,linux设置命令别名
  18. About Garbage Collector and finilize()
  19. 2017南宁(重温经典)
  20. 用matlab绘制抛物线y的x平方,利用matlab绘制多重x/y曲线

热门文章

  1. Nreal MR眼镜开发入门教程
  2. AIX7.1 安装配置 EMC CLARiiON 存储驱动软件
  3. 图像彩色化方法(深度学习)
  4. 彻底关闭烦人的---FF新推荐
  5. c语言对孩子的作用,爸爸用C语言给孩子早教,孩子逐渐崩溃,网友:你别害孩子秃顶...
  6. XILINX DSP Slice功能特点
  7. 对字符串进行一个顺序排列
  8. Android 6.0 新特性和功能,系统和 API 行为更新
  9. 关闭Hyper-v虚拟服务
  10. 传统行业的互联网创业机会在哪里?