本教程视频直播回看: 前言: 本教学主要目的是展示如何在RK3399ProD上构建可以识别 10 个不同字词的基本语音识别网络。模型会尝试将时长为 1 秒的音频片段归类为无声、未知字词、“yes”、“no”、“up”、“down”、“left”、“right”、“on”、“off”、“stop”或“go”。
快速上手:
1.下载附件
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》。 本模型所基于的卷积网络类型虽不是最先进的架构,但是相对简单、可快速训练,并且易于理解。 为适应卷积网络,需要对语音数据进行前处理,处理成成类似图像的数据,再输入网络。
资源地址: Speech command 源码: [url=https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/speech_commands]https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/speech_commands
语音特征提取: 语音基础: 1、人通过声带产生振动,在声道产生共振,形成语音; 2、语音的物理基础主要有音高、音强、音长、音色,是构成语音的四要素; 3、音素(phone),是根据语音的自然属性划分出来的最小语音单位,依据音节里的发音动作来分析,一个动作构成一个音素; 4、语音信号是一种非平稳的随机信号,所以要对语音进行分片,分片的时间5ms~30ms,在这个分片时间内,认为语音是平稳随机过程,这样就可以套用经典的信号处理方法; 5、声道的形状在语音短时功率谱的包络中显示出来。MFCCs(Mel Frequency Cepstral Coefficents)是一种准确描述这个包络的一种特征。是一种在自动语音和说话人识别中广泛使用的特征;
声谱图: 音频本身是一段时间内的一维连续信号,而不是二维空间问题。但是可以将传入的音频样本分成小段(时长仅为几毫秒)并计算一组频段内频率的强度。一段音频内的每组频率强度被视为数字向量,这些向量按时间顺序排列,形成一个二维数组。然后,该值数组可被视为单通道图像,称为声谱图。
Speechcommand模型:
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))
结果输出:
注意点:
1、数据类型data_type为float32。 2、数据的size是根据Reshape的下一层的input size来定义的,需要转为[1,3920]。
|