Toybrick

标题: 人工智能开发系列(6) 语音命令识别 [打印本页]

作者: bobby_jiang    时间: 2019-5-25 23:30
标题: 人工智能开发系列(6) 语音命令识别

[attach]307[/attach]
本教程视频直播回看:
[attach]313[/attach]
前言:
本教学主要目的是展示如何在RK3399ProD上构建可以识别 10 个不同字词的基本语音识别网络。模型会尝试将时长为 1 秒的音频片段归类为无声、未知字词、“yes”、“no”、“up”、“down”、“left”、“right”、“on”、“off”、“stop”或“go”。

快速上手:
1.下载附件[attach]640[/attach]
2.安装依赖
  1. sudo dnf install sox
  2. sudo pip3 install soundfile
复制代码
3.转rknn模型
  1. python3 test_zhuan.py
复制代码
4.测试yes语音
  1. python3 test.py
复制代码
可以看到"inference result:"打印,其中第三个参数值最大,该参数代表yes,说明预测正确

5.用户自己通过麦克风输入预测
  1. python3 arecord_rknn_quantized.py
复制代码
rk3399pro上只支持4段式的麦克风,否则无法预测

speech command 模型工作原理:
模型架构基于论文小型关键字检测卷积神经网络《Convolutional Neural Networks for Small-footprint Keyword Spotting》。
本模型所基于的卷积网络类型虽不是最先进的架构,但是相对简单、可快速训练,并且易于理解。
为适应卷积网络,需要对语音数据进行前处理,处理成成类似图像的数据,再输入网络。

资源地址:
Speech command 源码: https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/speech_commands
Speech command 教程:https://tensorflow.google.cn/tutorials/sequences/audio_recognition

语音特征提取:
语音基础:
1、人通过声带产生振动,在声道产生共振,形成语音;
2、语音的物理基础主要有音高、音强、音长、音色,是构成语音的四要素;
3、音素(phone),是根据语音的自然属性划分出来的最小语音单位,依据音节里的发音动作来分析,一个动作构成一个音素;
4、语音信号是一种非平稳的随机信号,所以要对语音进行分片,分片的时间5ms~30ms,在这个分片时间内,认为语音是平稳随机过程,这样就可以套用经典的信号处理方法;
5、声道的形状在语音短时功率谱的包络中显示出来。MFCCs(Mel Frequency Cepstral Coefficents)是一种准确描述这个包络的一种特征。是一种在自动语音和说话人识别中广泛使用的特征;

声谱图:
音频本身是一段时间内的一维连续信号,而不是二维空间问题。但是可以将传入的音频样本分成小段(时长仅为几毫秒)并计算一组频段内频率的强度。一段音频内的每组频率强度被视为数字向量,这些向量按时间顺序排列,形成一个二维数组。然后,该值数组可被视为单通道图像,称为声谱图。
[attach]298[/attach]

Speechcommand模型:
[attach]300[/attach]
speech command的keras模型代码:
  1. def create_conv_model(model_settings, is_training):
  2.   input_frequency_size = model_settings['fingerprint_width']
  3.   input_time_size = model_settings['spectrogram_length']
  4.   
  5.   model = Sequential()
  6.   model.add(Reshape((input_time_size, input_frequency_size, 1), input_shape=(1, input_time_size, input_frequency_size)))
  7.   
  8.   first_filter_height = 20
  9.   first_filter_width = 8
  10.   first_filter_count = 64
  11.   model.add(Conv2D(first_filter_count, (first_filter_height, first_filter_width),
  12.                 strides=(1, 1),
  13.                 padding="same",
  14.                 activation='relu',
  15.                 use_bias=True,
  16.                 kernel_initializer=keras.initializers.TruncatedNormal(mean=0.0, stddev=0.01, seed=None),
  17.                 bias_initializer=keras.initializers.Zeros()))
  18.   
  19.   if is_training:
  20.     model.add(Dropout(0.5))
  21.   
  22.   model.add(MaxPooling2D(pool_size=(2, 2),strides=(2, 2),padding="same"))
  23.   
  24.   second_filter_height = 10
  25.   second_filter_width = 4
  26.   second_filter_count = 64
  27.   model.add(Conv2D(second_filter_count, (second_filter_height, second_filter_width),
  28.                 strides=(1, 1),
  29.                 padding="same",
  30.                 activation='relu',
  31.                 use_bias=True,
  32.                 kernel_initializer=keras.initializers.TruncatedNormal(mean=0.0, stddev=0.01, seed=None),
  33.                 bias_initializer=keras.initializers.Zeros()))
  34.   
  35.   if is_training:
  36.     model.add(Dropout(0.5))
  37.   
  38.   model.add(Flatten())
  39.   
  40.   label_count = model_settings['label_count']
  41.   model.add(Dense(label_count,
  42.                 activation='softmax',
  43.                 use_bias=True,
  44.                 kernel_initializer=keras.initializers.TruncatedNormal(mean=0.0, stddev=0.01, seed=None),
  45.                 bias_initializer=keras.initializers.Zeros()))
  46.   
  47.   return model
复制代码
数据集:
1、先下载语音指令数据集,其中包含超过 105000 个 WAVE 音频文件,音频内容是有人说出 30 个不同的字词。这些数据由 Google 收集,并依据 CC BY 许可发布,用户也可以提交 5 分钟自己的录音来帮助改进该数据。数据集地址:https://storage.cloud.google.com/download.tensorflow.org/data/speech_commands_v0.02.tar.gz
2、训练前将数据集分为三类:训练数据、验证数据、测试数据;采用训练数据集进行训练,在训练过程中采用验证数据集以评估训练期间的准确率,训练完成后,采用测试数据集用来评估训练完成后的准确率。
3、对数据进行加噪、加静音、时移扭曲,以此加强训练出来模型的鲁棒性。

训练:
1、tensorflow/tensorflow/tree/master/tensorflow/examples/speech_commands/目录下,执行python3 train.py,开始训练。
2、训练完成后,执行python3 tensorflow/examples/speech_commands/freeze.py--start_checkpoint=/tmp/speech_commands_train/conv.ckpt-18000 --output_file=/tmp/my_frozen_graph.pb来生成pb模型。
3、要想在pc上验证模型,可以录制一段1秒钟的16K采样率的xxx.wav音频,然后执行python3 label_wav.py --wav xxx.wav--graph /tmp/my_frozen_graph.pb --labels/tmp/speech_commands_train/conv_labels.txt,结果就可以输出该段音频语音识别的结果。

rknn模型转换:
  1. #!/usr/bin/env python3

  2. import numpy as np

  3. import re
  4. import math
  5. import random
  6. import cv2

  7. from rknn.api import RKNN

  8. if __name__ == '__main__':
  9.     # Create RKNN object
  10.     rknn = RKNN(verbose=False, verbose_file='./speech_command_build.log')
  11.    
  12.     # Config for Model Input PreProcess
  13.     #rknn.config(quantized_dtype='dynamic_fixed_point-8')
  14.     #rknn.config(quantized_dtype='asymmetric_quantized-u8')
  15.     rknn.config()
  16.     # Load TensorFlow Model
  17.     print('--> Loading model')
  18.     rknn.load_tensorflow(tf_pb='./my_frozen_graph.pb',
  19.                          inputs=['Reshape'],
  20.                          outputs=['labels_softmax'],
  21.                          input_size_list=[[1,3920]])
  22.     print('done')
  23.    
  24.     # Build Model
  25.     print('--> Building model')
  26.     rknn.build(do_quantization=False, dataset='./dataset.txt', pre_compile=False)
  27.     print('done')
  28.    
  29.     # Export RKNN Model
  30.     #rknn.export_rknn('./speech_command_quantized.rknn')
  31.     rknn.export_rknn('./speech_command.rknn')
  32.    
  33.     #import time
  34.     #time.sleep(100)
复制代码

注意点:
1、从中间抽取部分模型转换,跳过特征提取部分。
2、输入点Reshape,输出点labels_softmax。实际输入点是Reshape的下一层。
3、Input size是根据Reshape的下一层的input size来定义的,为[1,3920]。
4、dataset.txt中为预提取的音频特征存储成[1,3920]的npy格式文件。

RK3399Pro上的推理:
麦克风录音:
  1. #On-board microphone
  2. #subprocess.call(["arecord", "-D", "MainMicCapture", "-r", "44100", "-c", "2", "-f", "S16_LE", "-d", "1", "record.wav"])
  3. #subprocess.call(["sox", "record.wav", "-r", "16000","-c", "1", "record_16k.wav","remix","1"])
  4.             
  5. #external microphone
  6. subprocess.call(["arecord", "-D", "FreeMicCapture", "-r", "44100", "-c", "2", "-f", "S16_LE", "-d", "1", "record.wav"])
  7. subprocess.call(["sox", "record.wav", "-r", "16000","-c", "1", "record_16k.wav","remix","2"])
复制代码

特征提取:
  1. wav_file = open("record_16k.wav", "rb")
  2. wav_data = wav_file.read()
  3. decoded_sample_data = contrib_audio.decode_wav(wav_data, desired_channels=1, desired_samples=16000, name='decoded_sample_data')
  4. spectrogram = contrib_audio.audio_spectrogram(decoded_sample_data.audio, window_size=480, stride=160, magnitude_squared=True)
  5. fingerprint_input = contrib_audio.mfcc(spectrogram, 16000,  dct_coefficient_count=40)
复制代码

推理:
  1. # Create RKNN object
  2. rknn = RKNN()
  3. # Load TensorFlow Model
  4. ret = rknn.load_rknn(path='./speech_command.rknn')
  5. ret = rknn.init_runtime(perf_debug=False)
  6. outputs, = rknn.inference(inputs=fingerprint_input_npy,data_type='float32')
  7. # Release RKNN Context
  8. rknn.release()
复制代码

后处理:
  1. labels = load_labels("./conv_labels.txt")
  2. predictions = np.array(outputs)
  3. top_k = predictions[0].argsort()[-3:][::-1]
  4. for node_id in top_k:
  5.     human_string = labels[node_id]
  6.     score = predictions[0][node_id]
  7.     print('%s (score = %.5f)' % (human_string, score))
复制代码

结果输出:
[attach]305[/attach]
注意点:
1、数据类型data_typefloat32
2、数据的size是根据Reshape的下一层的input size来定义的,需要转为[1,3920]







作者: zsf    时间: 2019-6-11 11:31
本帖最后由 zsf 于 2019-6-11 12:03 编辑

可以直接用tensorflow中的解码脚本进行解码不??
作者: zsf    时间: 2019-6-11 12:07
>>> ret = rknn.init_runtime(perf_debug=False)
E RKNNAPI: rknn_init,  input_reorder == INPUT_REORDER_NA when n_dims==3!
E Catch exception when init runtime!
T Traceback (most recent call last):
T   File "rknn/api/rknn_base.py", line 617, in rknn.api.rknn_base.RKNNBase.init_runtime
T   File "rknn/api/rknn_runtime.py", line 378, in rknn.api.rknn_runtime.RKNNRuntime.build_graph
T Exception: RKNN init failed. error code: RKNN_ERR_MODEL_INVALID

作者: vkaoke    时间: 2019-10-5 14:53
npy格式的文件到底怎么生成,文档也没说,没法弄呀,或者你给一个可以运行的程序,传到github上
作者: JSnobody    时间: 2020-5-22 15:20
我想请问麦克风用的是什么?另外,我想构建多一点的语音命令,如何操作,谢谢!
作者: NIELSONGOD    时间: 2020-6-5 09:36
JSnobody 发表于 2020-5-22 15:20
我想请问麦克风用的是什么?另外,我想构建多一点的语音命令,如何操作,谢谢! ...

同样的问题,请问您解决了吗
作者: Wells    时间: 2020-11-18 14:53
本帖最后由 Wells 于 2020-11-18 17:54 编辑

您好 我想请问一下运行python3 test.py之后运行结果第三个参数值不是最大的要怎么办啊
作者: sunterry    时间: 2020-11-24 15:45
标题: 有遇到这个问题吗
(TF1.13) terry:/rknn_test$ python test.py
--> Loading model
load_rknn done
--> Init runtime environment
init_runtime done
W Inputs should be placed in a list, like [img1, img2], both the img1 and img2 are ndarray.
ASSERT in gcMathConvert.cpp.SE6M15_From_SE5M10D(1374): !FL16_IsInfinity(In, false)
terminate called after throwing an instance of 'bool'
Aborted (core dumped)
作者: Ryan_zdst    时间: 2021-3-16 10:10
sunterry 发表于 2020-11-24 15:45
(TF1.13) terry:/rknn_test$ python test.py
--> Loading model
load_rknn done

你好,这个问题解决了嘛
作者: yaya    时间: 2021-3-31 11:00
请问bert-tiny模型是否有rknn转换的案例呀





欢迎光临 Toybrick (https://t.rock-chips.com/) Powered by Discuz! X3.3