来自:https://blog.csdn.net/u014365862/article/details/53869701

使用的数据集

THCHS30是Dong Wang, Xuewei Zhang, Zhiyong Zhang这几位大神发布的开放语音数据集,可用于开发中文语音识别系统。

为了感谢这几位大神,我是跪在电脑前写的本帖代码。

下载中文语音数据集(5G+):

[python] view plain copy
  1. #coding: utf-8
  2. import tensorflow as tf
  3. import numpy as np
  4. import os
  5. from collections import Counter
  6. import librosa
  7. from joblib import Parallel, delayed
  8. wav_path = 'data/wav/train'
  9. label_file = 'data/doc/trans/train.word.txt'
  10. def get_wav_files(wav_path = wav_path):
  11. wav_files = []
  12. for (dirpath, dirnames, filenames) in os.walk(wav_path):
  13. for filename in filenames:
  14. if filename.endswith(".wav") or filename.endswith(".WAV"):
  15. filename_path = os.sep.join([dirpath, filename])
  16. if os.stat(filename_path).st_size < 240000:
  17. continue
  18. wav_files.append(filename_path)
  19. return wav_files
  20. wav_files = get_wav_files()
  21. def get_wav_label(wav_files = wav_files, label_file = label_file):
  22. labels_dict = {}
  23. with open(label_file, "r", encoding='utf-8') as f:
  24. for label in f:
  25. label = label.strip("\n")
  26. label_id, label_text = label.split(' ', 1)
  27. labels_dict[label_id] = label_text
  28. labels = []
  29. new_wav_files = []
  30. for wav_file in wav_files:
  31. wav_id = os.path.basename(wav_file).split(".")[0]
  32. if wav_id in labels_dict:
  33. labels.append(labels_dict[wav_id])
  34. new_wav_files.append(wav_file)
  35. return new_wav_files, labels
  36. def get_wav_length(wav):
  37. import numpy as np
  38. import librosa
  39. print(wav)
  40. wav, sr = librosa.load(wav)
  41. mfcc = np.transpose(librosa.feature.mfcc(wav, sr), [1, 0])
  42. return len(mfcc)
  43. pointer = 0
  44. def get_next_batches(batch_size, wav_max_len):
  45. global pointer
  46. batches_wavs = []
  47. batches_labels = []
  48. for i in range(batch_size):
  49. wav, sr = librosa.load(wav_files[pointer])
  50. mfcc = np.transpose(librosa.feature.mfcc(wav, sr), [1,0])
  51. batches_wavs.append(mfcc.tolist())
  52. batches_labels.append(labels_vector[pointer])
  53. pointer += 1
  54. # 取零补齐
  55. # label append 0 , 0 对应的字符
  56. # mfcc 默认的计算长度为20(n_mfcc of mfcc) 作为channel length
  57. for mfcc in batches_wavs:
  58. while len(mfcc) < wav_max_len:
  59. mfcc.append([0]*20)
  60. for label in batches_labels:
  61. while len(label) < label_max_len:
  62. label.append(0)
  63. return batches_wavs, batches_labels
  64. conv1d_index = 0
  65. def conv1d_layer(input_tensor, size, dim, activation, scale, bias):
  66. global conv1d_index
  67. with tf.variable_scope("conv1d_" + str(conv1d_index)):
  68. W = tf.get_variable('W', (size, input_tensor.get_shape().as_list()[-1], dim), dtype=tf.float32, initializer=tf.random_uniform_initializer(minval=-scale, maxval=scale))
  69. if bias:
  70. b = tf.get_variable('b', [dim], dtype = tf.float32, initializer=tf.constant_initializer(0))
  71. out = tf.nn.conv1d(input_tensor, W, stride=1, padding='SAME') + (b if bias else 0)
  72. if not bias:
  73. beta = tf.get_variable('beta', dim, dtype=tf.float32, initializer=tf.constant_initializer(0))
  74. gamma = tf.get_variable('gamma', dim, dtype=tf.float32, initializer=tf.constant_initializer(1))
  75. mean_running = tf.get_variable('mean', dim, dtype=tf.float32, initializer=tf.constant_initializer(0))
  76. variance_running = tf.get_variable('variance', dim, dtype=tf.float32, initializer=tf.constant_initializer(1))
  77. mean, variance = tf.nn.moments(out, axes=list(range(len(out.get_shape()) - 1)))
  78. def update_running_stat():
  79. decay = 0.99
  80. # 定义了均值方差指数衰减 见 http://blog.csdn.net/liyuan123zhouhui/article/details/70698264
  81. update_op = [mean_running.assign(mean_running * decay + mean * (1 - decay)), variance_running.assign(variance_running * decay + variance * (1 - decay))]
  82. # 指定先执行均值方差的更新运算 见 http://blog.csdn.net/u012436149/article/details/72084744
  83. with tf.control_dependencies(update_op):
  84. return tf.identity(mean), tf.identity(variance)
  85. # 条件运算(https://applenob.github.io/tf_9.html) 按照作者这里的指定 是不进行指数衰减的
  86. m, v = tf.cond(tf.Variable(False, trainable=False), update_running_stat,lambda: (mean_running, variance_running))
  87. out = tf.nn.batch_normalization(out, m, v, beta, gamma, 1e-8)
  88. if activation == 'tanh':
  89. out = tf.nn.tanh(out)
  90. elif activation == 'sigmoid':
  91. out = tf.nn.sigmoid(out)
  92. conv1d_index += 1
  93. return out
  94. # 极黑卷积层 https://www.zhihu.com/question/57414498
  95. # 其输入参数中要包含一个大于 1 的rate 输出 channels与输入相同
  96. aconv1d_index = 0
  97. def aconv1d_layer(input_tensor, size, rate, activation, scale, bias):
  98. global aconv1d_index
  99. with tf.variable_scope('aconv1d_' + str(aconv1d_index)):
  100. shape = input_tensor.get_shape().as_list()
  101. # 利用 2 维极黑卷积函数计算相应 1 维卷积,expand_dims squeeze做了相应维度处理
  102. # 实际 上一个 tf.nn.conv1d 在之前的tensorflow版本中是没有的,其的一个实现也是经过维度调整后调用 tf.nn.conv2d
  103. W = tf.get_variable('W', (1, size, shape[-1], shape[-1]), dtype=tf.float32, initializer=tf.random_uniform_initializer(minval=-scale, maxval=scale))
  104. if bias:
  105. b = tf.get_variable('b', [shape[-1]], dtype=tf.float32, initializer=tf.constant_initializer(0))
  106. out = tf.nn.atrous_conv2d(tf.expand_dims(input_tensor, dim=1), W, rate = rate, padding='SAME')
  107. out = tf.squeeze(out, [1])
  108. if not bias:
  109. beta = tf.get_variable('beta', shape[-1], dtype=tf.float32, initializer=tf.constant_initializer(0))
  110. gamma = tf.get_variable('gamma', shape[-1], dtype=tf.float32, initializer=tf.constant_initializer(1))
  111. mean_running = tf.get_variable('mean', shape[-1], dtype=tf.float32, initializer=tf.constant_initializer(0))
  112. variance_running = tf.get_variable('variance', shape[-1], dtype=tf.float32, initializer=tf.constant_initializer(1))
  113. mean, variance = tf.nn.moments(out, axes=list(range(len(out.get_shape()) - 1)))
  114. def update_running_stat():
  115. decay = 0.99
  116. update_op = [mean_running.assign(mean_running * decay + mean * (1 - decay)), variance_running.assign(variance_running * decay + variance * (1 - decay))]
  117. with tf.control_dependencies(update_op):
  118. return tf.identity(mean), tf.identity(variance)
  119. m, v = tf.cond(tf.Variable(False, trainable=False), update_running_stat,lambda: (mean_running, variance_running))
  120. out = tf.nn.batch_normalization(out, m, v, beta, gamma, 1e-8)
  121. if activation == 'tanh':
  122. out = tf.nn.tanh(out)
  123. elif activation == 'sigmoid':
  124. out = tf.nn.sigmoid(out)
  125. aconv1d_index += 1
  126. return out
  127. def speech_to_text_network(n_dim = 128, n_blocks = 3):
  128. out = conv1d_layer(input_tensor=X, size=1, dim = n_dim, activation='tanh', scale=0.14, bias=False)
  129. def residual_block(input_sensor, size, rate):
  130. conv_filter = aconv1d_layer(input_tensor=input_sensor, size=size, rate=rate, activation='tanh', scale=0.03, bias=False)
  131. conv_gate = aconv1d_layer(input_tensor=input_sensor, size=size, rate=rate, activation='sigmoid', scale=0.03, bias=False)
  132. out = conv_filter * conv_gate
  133. out = conv1d_layer(out, size = 1, dim=n_dim, activation='tanh', scale=0.08, bias=False)
  134. return out + input_sensor, out
  135. skip = 0
  136. for _ in range(n_blocks):
  137. for r in [1, 2, 4, 8, 16]:
  138. out, s = residual_block(out, size = 7, rate = r)
  139. skip += s
  140. logit = conv1d_layer(skip, size = 1, dim = skip.get_shape().as_list()[-1], activation='tanh', scale = 0.08, bias=False)
  141. # 最后卷积层输出是词汇表大小
  142. logit = conv1d_layer(logit, size = 1, dim = words_size, activation = None, scale = 0.04, bias = True)
  143. return logit
  144. # 作者自己定义了优化器
  145. class MaxPropOptimizer(tf.train.Optimizer):
  146. def __init__(self, learning_rate=0.001, beta2=0.999, use_locking=False, name="MaxProp"):
  147. super(MaxPropOptimizer, self).__init__(use_locking, name)
  148. self._lr = learning_rate
  149. self._beta2 = beta2
  150. self._lr_t = None
  151. self._beta2_t = None
  152. def _prepare(self):
  153. self._lr_t = tf.convert_to_tensor(self._lr, name="learning_rate")
  154. self._beta2_t = tf.convert_to_tensor(self._beta2, name="beta2")
  155. def _create_slots(self, var_list):
  156. for v in var_list:
  157. self._zeros_slot(v, "m", self._name)
  158. def _apply_dense(self, grad, var):
  159. lr_t = tf.cast(self._lr_t, var.dtype.base_dtype)
  160. beta2_t = tf.cast(self._beta2_t, var.dtype.base_dtype)
  161. if var.dtype.base_dtype == tf.float16:
  162. eps = 1e-7
  163. else:
  164. eps = 1e-8
  165. m = self.get_slot(var, "m")
  166. m_t = m.assign(tf.maximum(beta2_t * m + eps, tf.abs(grad)))
  167. g_t = grad / m_t
  168. var_update = tf.assign_sub(var, lr_t * g_t)
  169. return tf.group(*[var_update, m_t])
  170. def _apply_sparse(self, grad, var):
  171. return self._apply_dense(grad, var)
  172. def train_speech_to_text_network(wav_max_len):
  173. logit = speech_to_text_network()
  174. # CTC loss
  175. indices = tf.where(tf.not_equal(tf.cast(Y, tf.float32), 0.))
  176. target = tf.SparseTensor(indices=indices, values=tf.gather_nd(Y, indices) - 1, dense_shape=tf.cast(tf.shape(Y), tf.int64))
  177. loss = tf.nn.ctc_loss(target, logit, sequence_len, time_major=False)
  178. # optimizer
  179. lr = tf.Variable(0.001, dtype=tf.float32, trainable=False)
  180. optimizer = MaxPropOptimizer(learning_rate=lr, beta2=0.99)
  181. var_list = [t for t in tf.trainable_variables()]
  182. gradient = optimizer.compute_gradients(loss, var_list=var_list)
  183. optimizer_op = optimizer.apply_gradients(gradient)
  184. with tf.Session() as sess:
  185. sess.run(tf.global_variables_initializer())
  186. saver = tf.train.Saver(tf.global_variables())
  187. for epoch in range(16):
  188. sess.run(tf.assign(lr, 0.001 * (0.97 ** epoch)))
  189. global pointer
  190. pointer = 0
  191. for batch in range(n_batch):
  192. batches_wavs, batches_labels = get_next_batches(batch_size, wav_max_len)
  193. train_loss, _ = sess.run([loss, optimizer_op], feed_dict={X: batches_wavs, Y: batches_labels})
  194. print(epoch, batch, train_loss)
  195. if epoch % 1 == 0:   #之前是5
  196. saver.save(sess, r'D:\\tensorflow\\Speech_Recognition\\speech.module', global_step=epoch)
  197. # 训练
  198. #train_speech_to_text_network()
  199. # 语音识别
  200. # 把 batch_size 改为1
  201. def speech_to_text(wav_file):
  202. wav, sr = librosa.load(wav_file, mono=True)
  203. mfcc = np.transpose(np.expand_dims(librosa.feature.mfcc(wav, sr), axis=0), [0,2,1])
  204. logit = speech_to_text_network()
  205. saver = tf.train.Saver()
  206. with tf.Session() as sess:
  207. saver.restore(sess, tf.train.latest_checkpoint('.'))
  208. decoded = tf.transpose(logit, perm=[1, 0, 2])
  209. decoded, _ = tf.nn.ctc_beam_search_decoder(decoded, sequence_len, merge_repeated=False)
  210. decoded = sess.run(decoded, feed_dict={X: mfcc})
  211. # predict = tf.sparse_to_dense(decoded[0].indices, decoded[0].shape, decoded[0].values) + 1
  212. print (decoded)
  213. predict = tf.sparse_to_dense(decoded[0].indices,decoded[0].dense_shape,decoded[0].values) + 1
  214. # predict = decode_sparse_tensor(decoded[0])
  215. predict = sess.run(predict)
  216. print(predict)
  217. if __name__ == "__main__":
  218. wav_files = get_wav_files()
  219. wav_files, labels = get_wav_label()
  220. print(u"样本数 :", len(wav_files))
  221. all_words = []
  222. for label in labels:
  223. # 字符分解
  224. all_words += [word for word in label]
  225. counter = Counter(all_words)
  226. count_pairs = sorted(counter.items(), key=lambda x: -x[1])
  227. words, _ = zip(*count_pairs)
  228. words_size = len(words)
  229. print(u"词汇表大小:", words_size)
  230. word_num_map = dict(zip(words, range(len(words))))
  231. # 当字符不在已经收集的words中时,赋予其应当的num,这是一个动态的结果
  232. to_num = lambda word: word_num_map.get(word, len(words))
  233. # 将单个file的标签映射为num 返回对应list,最终all file组成嵌套list
  234. labels_vector = [list(map(to_num, label)) for label in labels]
  235. label_max_len = np.max([len(label) for label in labels_vector])
  236. print(u"最长句子的字数:" + str(label_max_len))
  237. # 下面仅仅计算了语音特征相应的最长的长度。
  238. # 如果仅仅是计算长度是否需要施加变换后计算长度?
  239. parallel_read = False
  240. if parallel_read:
  241. wav_max_len = np.max(Parallel(n_jobs=7)(delayed(get_wav_length)(wav) for wav in wav_files))
  242. else:
  243. wav_max_len = 673
  244. print("最长的语音", wav_max_len)
  245. batch_size = 8
  246. n_batch = len(wav_files) // batch_size
  247. X = tf.placeholder(dtype=tf.float32, shape=[batch_size, None, 20])
  248. # 实际mfcc中的元素并非同号,不严格的情况下如此得到序列长度也是可行的
  249. sequence_len = tf.reduce_sum(tf.cast(tf.not_equal(tf.reduce_sum(X, reduction_indices=2), 0.), tf.int32), reduction_indices=1)
  250. Y = tf.placeholder(dtype=tf.int32, shape=[batch_size, None])
  251. train_speech_to_text_network(wav_max_len)

后续:从麦克风获得语音输入,使用上面的模型进行识别。

然后预测可以用下边这个:

[python] view plain copy
  1. if __name__ == "__main__":
  2. wav_files = get_wav_files()
  3. wav_files, labels = get_wav_label()
  4. print(u"样本数 :", len(wav_files))
  5. all_words = []
  6. for label in labels:
  7. # 字符分解
  8. all_words += [word for word in label]
  9. counter = Counter(all_words)
  10. count_pairs = sorted(counter.items(), key=lambda x: -x[1])
  11. words, _ = zip(*count_pairs)
  12. words_size = len(words)
  13. print(u"词汇表大小:", words_size)
  14. word_num_map = dict(zip(words, range(len(words))))
  15. # 当字符不在已经收集的words中时,赋予其应当的num,这是一个动态的结果
  16. to_num = lambda word: word_num_map.get(word, len(words))
  17. # 将单个file的标签映射为num 返回对应list,最终all file组成嵌套list
  18. labels_vector = [list(map(to_num, label)) for label in labels]
  19. label_max_len = np.max([len(label) for label in labels_vector])
  20. print(u"最长句子的字数:" + str(label_max_len))
  21. # 下面仅仅计算了语音特征相应的最长的长度。
  22. # 如果仅仅是计算长度是否需要施加变换后计算长度?
  23. parallel_read = False
  24. if parallel_read:
  25. wav_max_len = np.max(Parallel(n_jobs=7)(delayed(get_wav_length)(wav) for wav in wav_files))
  26. else:
  27. wav_max_len = 673
  28. print("最长的语音", wav_max_len)
  29. batch_size = 1
  30. n_batch = len(wav_files) // batch_size
  31. X = tf.placeholder(dtype=tf.float32, shape=[batch_size, None, 20])
  32. # 实际mfcc中的元素并非同号,不严格的情况下如此得到序列长度也是可行的
  33. sequence_len = tf.reduce_sum(tf.cast(tf.not_equal(tf.reduce_sum(X, reduction_indices=2), 0.), tf.int32), reduction_indices=1)
  34. Y = tf.placeholder(dtype=tf.int32, shape=[batch_size, None])
  35. #train_speech_to_text_network(wav_max_len)  #训练
  36. wav_file = "./D4_750.wav"
  37. print (wav_file)
  38. speech_to_text(wav_file)

相关资源:

  • 深度学习大牛Andrew Ng:Speech Recognition and Beyond
  • https://github.com/kaldi-asr/kaldi
  • http://cmusphinx.sourceforge.net
  • https://pypi.python.org/pypi/SpeechRecognition

Share the post "TensorFlow练习15: 中文语音识别"

tf15: 中文语音识别【转】相关推荐

  1. tf15: 中文语音识别

    使用的数据集 THCHS30是Dong Wang, Xuewei Zhang, Zhiyong Zhang这几位大神发布的开放语音数据集,可用于开发中文语音识别系统. 为了感谢这几位大神,我是跪在电脑 ...

  2. 实战:基于tensorflow 的中文语音识别模型 | CSDN博文精选

    作者 | Pelhans 来源 | CSDN博客 目前网上关于tensorflow 的中文语音识别实现较少,而且结构功能较为简单.而百度在PaddlePaddle上的 Deepspeech2 实现功能 ...

  3. kaldi上第一个免费的中文语音识别例子

    今天在清华大学cslt实验室王东老师的分享下,kaldi终于有了免费的中文语音识别的例子,网址为:https://github.com/kaldi-asr/kaldi/tree/master/egs/ ...

  4. springboot中文语音识别_【记录】语音识别软件包、代码示例、数据集汇集

    语音识别工具 (1)librosa:python,视频与音乐分析 链接:https://github.com/librosa/librosa (2)ASRT_SpeechRecognition:pyt ...

  5. 基于深度学习的中文语音识别系统框架(pluse)

    目录 声学模型 GRU-CTC DFCNN DFSMN 语言模型 n-gram CBHG 数据集 本文搭建一个完整的中文语音识别系统,包括声学模型和语言模型,能够将输入的音频信号识别为汉字. 声学模型 ...

  6. 中文语音识别系统搭建流程笔记

    标签:ASR, Python, Keras, CTC 最近在自己动手搭建一个中文语音识别系统,因为也是入门阶段,所以比较吃力,直到在GitHub上找到了一个已经在做的开源工程,找到了做下去的动力,附上 ...

  7. 分享 | 开源的中文语音识别系统

    原标题:分享 | 开源的中文语音识别系统 语音识别目前已经广泛应用于各种领域,那么你会想做一个自己的语音识别系统吗?这篇文章介绍了一种开源的中文语音识别系统,读者可以借助它快速训练属于自己的中文语音识 ...

  8. 绝佳的ASR学习方案:这是一套开源的中文语音识别系统

    ASRT 是一套基于深度学习实现的语音识别系统,全称为 Auto Speech Recognition Tool,由 AI 柠檬博主开发并在 GitHub 上开源(GPL 3.0 协议).本项目声学模 ...

  9. 来自DFRobot的中文语音识别模块

    如果哪一天你要做机器人了,是否也想让它拥有一个类似于Siri的语音识别系统呢?如果你要求不高的话,语音识别模块Voice Recognition可以帮助你打造简单的中文语音识别系统. 由国内开源硬件厂 ...

  10. 依图做语音了!识别精度创中文语音识别新高点

    新智元报道 编辑:闻菲 [新智元导读]依图强势进军智能语音,联合微软发布语音开放云平台,携手华为发布软硬件一体化的智能语音联合解决方案.依图语音识别算法在全球最大开源中文数据库AISHELL-2上词错 ...

最新文章

  1. 职称计算机和职称英语期限,专业技术职称考试,职称英语和职称计算机有效期多长时间,每年什么时候报名啊?上海的...
  2. Taylor Swift - Red
  3. How Kyma plugin register hook to Activate and deactivate event
  4. 8 -- 深入使用Spring -- 5... Spring 3.1 新增的缓存机制
  5. VisualBox 安装 CentOS 7.6 操作记录
  6. Android属性动画初探之ObjectAnimator
  7. 20190912每日一句
  8. kaggle泰坦尼克
  9. 原生列表table固定表头
  10. linux脚本:每天晚上 12 点,打包站点目录/var/www/html 备份到/data 目录下
  11. 鼠标放在可以点击的文字上,变成小手样式
  12. 1-系统C盘迁移到新买的固态硬盘SSD中有影响但不主要,但有必要将系统盘C盘迁移到新安装的 固态硬盘SSD中吗?
  13. 零基础程序员自学编程有这 6 种方法,你的自学方法是合理的么?
  14. Element 中图片预览后如何快速关闭
  15. HX8110A功放IC大功率功放芯片
  16. 写了一个计算利息和还款计划的html小工具
  17. String类型转换成LocalDate 和 LocalDateTime
  18. 你知道CAD看图软件浩辰CAD看图王中的批注如何删除/保存吗?
  19. obs nginx-rtmp-module搭建流媒体服务器实现直播 ding
  20. 黑苹果能安装mysql吗_黑苹果安装 篇一:小白的黑苹果之路:系统安装思路

热门文章

  1. git gui 中文乱码解决方法
  2. 关于Tungsten Fabic版本问题,这一篇文章说清了
  3. 将一个数组划分成总和相等的两部分(分割数组)
  4. WinRAR密码破解(精)
  5. Si5395/94/92时钟芯片配置步骤
  6. 石乙己——孔乙己程序员版
  7. WS小世界网络模型构造算法
  8. 鸿蒙系统微信双开,支持微信双开 老旗舰一加3/3T喜迎系统更新
  9. VR全景图拍摄制作之无人机航拍
  10. IOTOS物联中台从0到1开发Thales800驱动 实例详解