Toybrick
标题: 人工智能开发系列(6) 语音命令识别 [打印本页]
作者: bobby_jiang 时间: 2019-5-25 23:30
标题: 人工智能开发系列(6) 语音命令识别
本教程视频直播回看:
前言:
本教学主要目的是展示如何在RK3399ProD上构建可以识别 10 个不同字词的基本语音识别网络。模型会尝试将时长为 1 秒的音频片段归类为无声、未知字词、“yes”、“no”、“up”、“down”、“left”、“right”、“on”、“off”、“stop”或“go”。
快速上手:
1.下载附件[attach]640[/attach]
2.安装依赖
- sudo dnf install sox
- sudo pip3 install soundfile
3.转rknn模型
4.测试yes语音
可以看到"inference result:"打印,其中第三个参数值最大,该参数代表yes,说明预测正确
5.用户自己通过麦克风输入预测
- python3 arecord_rknn_quantized.py
rk3399pro上只支持4段式的麦克风,否则无法预测
speech command 模型工作原理:
模型架构基于论文小型关键字检测卷积神经网络《Convolutional Neural Networks for Small-footprint Keyword Spotting》。
本模型所基于的卷积网络类型虽不是最先进的架构,但是相对简单、可快速训练,并且易于理解。
为适应卷积网络,需要对语音数据进行前处理,处理成成类似图像的数据,再输入网络。
资源地址:
语音特征提取:
语音基础:
1、人通过声带产生振动,在声道产生共振,形成语音;
2、语音的物理基础主要有音高、音强、音长、音色,是构成语音的四要素;
3、音素(phone),是根据语音的自然属性划分出来的最小语音单位,依据音节里的发音动作来分析,一个动作构成一个音素;
4、语音信号是一种非平稳的随机信号,所以要对语音进行分片,分片的时间5ms~30ms,在这个分片时间内,认为语音是平稳随机过程,这样就可以套用经典的信号处理方法;
5、声道的形状在语音短时功率谱的包络中显示出来。MFCCs(Mel Frequency Cepstral Coefficents)是一种准确描述这个包络的一种特征。是一种在自动语音和说话人识别中广泛使用的特征;
声谱图:
音频本身是一段时间内的一维连续信号,而不是二维空间问题。但是可以将传入的音频样本分成小段(时长仅为几毫秒)并计算一组频段内频率的强度。一段音频内的每组频率强度被视为数字向量,这些向量按时间顺序排列,形成一个二维数组。然后,该值数组可被视为单通道图像,称为声谱图。
[attach]298[/attach]
Speechcommand模型:
[attach]300[/attach]
speech command的keras模型代码:
- def create_conv_model(model_settings, is_training):
- input_frequency_size = model_settings['fingerprint_width']
- input_time_size = model_settings['spectrogram_length']
-
- model = Sequential()
- model.add(Reshape((input_time_size, input_frequency_size, 1), input_shape=(1, input_time_size, input_frequency_size)))
-
- first_filter_height = 20
- first_filter_width = 8
- first_filter_count = 64
- model.add(Conv2D(first_filter_count, (first_filter_height, first_filter_width),
- strides=(1, 1),
- padding="same",
- activation='relu',
- use_bias=True,
- kernel_initializer=keras.initializers.TruncatedNormal(mean=0.0, stddev=0.01, seed=None),
- bias_initializer=keras.initializers.Zeros()))
-
- if is_training:
- model.add(Dropout(0.5))
-
- model.add(MaxPooling2D(pool_size=(2, 2),strides=(2, 2),padding="same"))
-
- second_filter_height = 10
- second_filter_width = 4
- second_filter_count = 64
- model.add(Conv2D(second_filter_count, (second_filter_height, second_filter_width),
- strides=(1, 1),
- padding="same",
- activation='relu',
- use_bias=True,
- kernel_initializer=keras.initializers.TruncatedNormal(mean=0.0, stddev=0.01, seed=None),
- bias_initializer=keras.initializers.Zeros()))
-
- if is_training:
- model.add(Dropout(0.5))
-
- model.add(Flatten())
-
- label_count = model_settings['label_count']
- model.add(Dense(label_count,
- activation='softmax',
- use_bias=True,
- kernel_initializer=keras.initializers.TruncatedNormal(mean=0.0, stddev=0.01, seed=None),
- bias_initializer=keras.initializers.Zeros()))
-
- return model
数据集:
2、训练前将数据集分为三类:训练数据、验证数据、测试数据;采用训练数据集进行训练,在训练过程中采用验证数据集以评估训练期间的准确率,训练完成后,采用测试数据集用来评估训练完成后的准确率。
3、对数据进行加噪、加静音、时移扭曲,以此加强训练出来模型的鲁棒性。
训练:
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模型转换:
- #!/usr/bin/env python3
- import numpy as np
- import re
- import math
- import random
- import cv2
- from rknn.api import RKNN
- if __name__ == '__main__':
- # Create RKNN object
- rknn = RKNN(verbose=False, verbose_file='./speech_command_build.log')
-
- # Config for Model Input PreProcess
- #rknn.config(quantized_dtype='dynamic_fixed_point-8')
- #rknn.config(quantized_dtype='asymmetric_quantized-u8')
- rknn.config()
- # Load TensorFlow Model
- print('--> Loading model')
- rknn.load_tensorflow(tf_pb='./my_frozen_graph.pb',
- inputs=['Reshape'],
- outputs=['labels_softmax'],
- input_size_list=[[1,3920]])
- print('done')
-
- # Build Model
- print('--> Building model')
- rknn.build(do_quantization=False, dataset='./dataset.txt', pre_compile=False)
- print('done')
-
- # Export RKNN Model
- #rknn.export_rknn('./speech_command_quantized.rknn')
- rknn.export_rknn('./speech_command.rknn')
-
- #import time
- #time.sleep(100)
注意点:
1、从中间抽取部分模型转换,跳过特征提取部分。
2、输入点Reshape,输出点labels_softmax。实际输入点是Reshape的下一层。
3、Input size是根据Reshape的下一层的input size来定义的,为[1,3920]。
4、dataset.txt中为预提取的音频特征存储成[1,3920]的npy格式文件。
RK3399Pro上的推理:麦克风录音:
- #On-board microphone
- #subprocess.call(["arecord", "-D", "MainMicCapture", "-r", "44100", "-c", "2", "-f", "S16_LE", "-d", "1", "record.wav"])
- #subprocess.call(["sox", "record.wav", "-r", "16000","-c", "1", "record_16k.wav","remix","1"])
-
- #external microphone
- subprocess.call(["arecord", "-D", "FreeMicCapture", "-r", "44100", "-c", "2", "-f", "S16_LE", "-d", "1", "record.wav"])
- subprocess.call(["sox", "record.wav", "-r", "16000","-c", "1", "record_16k.wav","remix","2"])
特征提取:
- wav_file = open("record_16k.wav", "rb")
- wav_data = wav_file.read()
- decoded_sample_data = contrib_audio.decode_wav(wav_data, desired_channels=1, desired_samples=16000, name='decoded_sample_data')
- spectrogram = contrib_audio.audio_spectrogram(decoded_sample_data.audio, window_size=480, stride=160, magnitude_squared=True)
- fingerprint_input = contrib_audio.mfcc(spectrogram, 16000, dct_coefficient_count=40)
推理:
- # Create RKNN object
- rknn = RKNN()
- # Load TensorFlow Model
- ret = rknn.load_rknn(path='./speech_command.rknn')
- ret = rknn.init_runtime(perf_debug=False)
- outputs, = rknn.inference(inputs=fingerprint_input_npy,data_type='float32')
- # Release RKNN Context
- rknn.release()
后处理:
- labels = load_labels("./conv_labels.txt")
- predictions = np.array(outputs)
- top_k = predictions[0].argsort()[-3:][::-1]
- for node_id in top_k:
- human_string = labels[node_id]
- score = predictions[0][node_id]
- print('%s (score = %.5f)' % (human_string, score))
结果输出:
[attach]305[/attach]
注意点:
1、数据类型data_type为float32。
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
同样的问题,请问您解决了吗
作者: 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
你好,这个问题解决了嘛
作者: yaya 时间: 2021-3-31 11:00
请问bert-tiny模型是否有rknn转换的案例呀
欢迎光临 Toybrick (https://t.rock-chips.com/) |
Powered by Discuz! X3.3 |