TensorFlow案例学习:简单的音频识别
前言
以下内容均来源于官方教程:简单的音频识别:识别关键字
音频识别
下载数据集
下载地址:http://storage.googleapis.com/download.tensorflow.org/data/mini_speech_commands.zip
可以直接浏览器访问下载。
下载完成后将其解压到项目里,从文件夹里可以看到有8个子文件夹,文件夹的名称就是8个语音命令。
注意:我们只需要mini_speech_commands
文件夹,其他的不需要
加载数据集
# 加载训练数据集、验证集
train_ds, val_ds = tf.keras.utils.audio_dataset_from_directory(directory='./data/mini_speech_commands', # 数据集路径batch_size=64, # 批次validation_split=0.2, # 验证集占数据集的20%seed=0, # 指定随机生成数据集的种子# 每个样本的输出序列长度。音频剪辑在 1kHz 时为 16 秒或更短。将较短的填充到正好 1 秒(并且会修剪较长的填充),以便可以轻松批量处理output_sequence_length=16000,subset='both' # 训练集和验证集两者同时使用
)
获取类别
# 获取命令的类别
label_names = np.array(train_ds.class_names)
print("命令类别:", label_names)
刚好与子文件的名称和顺序一致。
维度压缩
文档中说,此数据集仅包含单声道音频,因此需要 对输入的音频数据进行维度压缩
-
单声道(mono)音频只有一个声道。这意味着所有的音频信号被混合到一个通道中,不区分左右声道。在单声道音频中,所有的声音通过单个扬声器播放。单声道音频适用于大部分音频应用,如电话通信、语音录音等。
-
多声道(stereo)音频有两个声道,左声道(left channel)和右声道(right channel)。通过左右声道的不同信号,可以在音频空间上创建立体声效果。多声道音频提供了更加丰富的音频体验,可以更好地模拟现实环境中的声音分布。常见的应用包括音乐播放、电影声音、游戏音效等。
def squeeze(audio,labels):audio = tf.squeeze(audio,axis=-1)return audio,labelstrain_ds = train_ds.map(squeeze,tf.data.AUTOTUNE)
val_ds = val_ds.map(squeeze,tf.data.AUTOTUNE)
拆分验证集
这块没太看明白在干嘛
test_ds = val_ds.shard(num_shards=2, index=0)
val_ds = val_ds.shard(num_shards=2, index=1)
for example_audio, example_labels in train_ds.take(1):print(example_audio.shape)print(example_labels.shape)
绘制音频波形
这块只是让我们可视化的观察音频的波形,这块后面可以注释掉
plt.figure(figsize=(8, 5))
rows = 3
cols = 3
n = rows * cols
for i in range(n):plt.subplot(rows, cols, i+1)audio_signal = example_audio[i]plt.plot(audio_signal)plt.title(label_names[example_labels[i]])plt.yticks(np.arange(-1.2, 1.2, 0.2))plt.ylim([-1.1, 1.1])
plt.tight_layout()
plt.show()
将波形转换为频谱图
将波形转换为频谱图的目的是为了更好地分析和理解音频信号。
波形是时域上的表示,它展示了音频信号在时间轴上的变化。然而,频谱图是频域上的表示,它将音频信号分解为不同的频率成分,并显示每个频率成分的能量或振幅。
通过将波形转换为频谱图,我们可以更清晰地看到音频信号中哪些频率成分对于特定的声音或事件是重要的。这对于音频处理任务(如语音识别、音频分类、音频分割等)以及音频信号理解和分析非常有帮助。
def get_spectrogram(waveform):spectrogram = tf.signal.stft(waveform, frame_length=255, frame_step=128)spectrogram = tf.abs(spectrogram)spectrogram = spectrogram[..., tf.newaxis]return spectrogram
浏览数据
打印一个示例的张量化波形和相应频谱图的形状,并播放原始音频:
for i in range(3):label = label_names[example_labels[i]]waveform = example_audio[i]spectrogram = get_spectrogram(waveform)print('Label:', label)print('Waveform shape:', waveform.shape)print('Spectrogram shape:', spectrogram.shape)print('Audio playback')display.display(display.Audio(waveform, rate=16000))
从音频数据集创建频谱图数据集
# 从音频数据集创建频谱图数据集
def make_spec_ds(ds):return ds.map(map_func=lambda audio,label: (get_spectrogram(audio), label),num_parallel_calls=tf.data.AUTOTUNE)train_spectrogram_ds = make_spec_ds(train_ds)
val_spectrogram_ds = make_spec_ds(val_ds)
test_spectrogram_ds = make_spec_ds(test_ds)
减少训练模型时的读取延迟
train_spectrogram_ds = train_spectrogram_ds.cache().shuffle(10000).prefetch(tf.data.AUTOTUNE)
val_spectrogram_ds = val_spectrogram_ds.cache().prefetch(tf.data.AUTOTUNE)
test_spectrogram_ds = test_spectrogram_ds.cache().prefetch(tf.data.AUTOTUNE)
使用卷积神经网络创建并训练模型
# 使用卷积神经网络创建模型
input_shape = example_spectrograms.shape[1:]
print('Input shape:', input_shape)
num_labels = len(label_names)
norm_layer = tf.keras.layers.Normalization() # 创建规范化层,便于更好的进行模型训练和推断
norm_layer.adapt(data=train_spectrogram_ds.map(map_func=lambda spec, label: spec))model = tf.keras.models.Sequential([tf.keras.layers.Input(shape=input_shape),tf.keras.layers.Resizing(32, 32),norm_layer,tf.keras.layers.Conv2D(32, 3, activation='relu'),tf.keras.layers.Conv2D(64, 3, activation='relu'),tf.keras.layers.MaxPool2D(),tf.keras.layers.Dropout(0.25),tf.keras.layers.Flatten(),tf.keras.layers.Dense(128, activation='relu'),tf.keras.layers.Dropout(0.5),tf.keras.layers.Dense(num_labels),
])model.summary()# 编译模型
model.compile(optimizer=tf.keras.optimizers.Adam(), # 优化器loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), # 损失函数metrics=['accuracy'] # 准确率作为评估标准
)# 训练模型,并记录训练的日志
history = model.fit(train_spectrogram_ds,validation_data=val_spectrogram_ds,epochs=10,callbacks=tf.keras.callbacks.EarlyStopping(verbose=1, patience=2),
)
评估性能
model.evaluate(test_spectrogram_ds, return_dict=True)
导出模型
class ExportModel(tf.Module):def __init__(self, model):self.model = model# Accept either a string-filename or a batch of waveforms.# YOu could add additional signatures for a single wave, or a ragged-batch.self.__call__.get_concrete_function(x=tf.TensorSpec(shape=(), dtype=tf.string))self.__call__.get_concrete_function(x=tf.TensorSpec(shape=[None, 16000], dtype=tf.float32))@tf.functiondef __call__(self, x):# If they pass a string, load the file and decode it.if x.dtype == tf.string:x = tf.io.read_file(x)x, _ = tf.audio.decode_wav(x, desired_channels=1, desired_samples=16000,)x = tf.squeeze(x, axis=-1)x = x[tf.newaxis, :]x = get_spectrogram(x)result = self.model(x, training=False)class_ids = tf.argmax(result, axis=-1)class_names = tf.gather(label_names, class_ids)return {'predictions': result,'class_ids': class_ids,'class_names': class_names}export = ExportModel(model)
export(tf.constant('./data/mini_speech_commands/no/012c8314_nohash_0.wav'))tf.saved_model.save(export, "saved")
下面是保存的模型
完整代码
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from IPython import display# 加载训练数据集、验证集
train_ds, val_ds = tf.keras.utils.audio_dataset_from_directory(directory='./data/mini_speech_commands', # 数据集路径batch_size=64, # 批次validation_split=0.2, # 验证集占数据集的20%seed=0, # 指定随机生成数据集的种子# 每个样本的输出序列长度。音频剪辑在 1kHz 时为 16 秒或更短。将较短的填充到正好 1 秒(并且会修剪较长的填充),以便可以轻松批量处理output_sequence_length=16000,subset='both' # 训练集和验证集两者同时使用
)# 获取命令的类别
label_names = np.array(train_ds.class_names)
print("命令类别:", label_names)# 输入数据压缩def squeeze(audio, labels):audio = tf.squeeze(audio, axis=-1)return audio, labelstrain_ds = train_ds.map(squeeze, tf.data.AUTOTUNE)
val_ds = val_ds.map(squeeze, tf.data.AUTOTUNE)# 拆分验证集
test_ds = val_ds.shard(num_shards=2, index=0)
val_ds = val_ds.shard(num_shards=2, index=1)for example_audio, example_labels in train_ds.take(1):print(example_audio.shape)print(example_labels.shape)# 绘制音频波形
# plt.figure(figsize=(8, 5))
# rows = 3
# cols = 3
# n = rows * cols
# for i in range(n):
# plt.subplot(rows, cols, i+1)
# audio_signal = example_audio[i]
# plt.plot(audio_signal)
# plt.title(label_names[example_labels[i]])
# plt.yticks(np.arange(-1.2, 1.2, 0.2))
# plt.ylim([-1.1, 1.1])
# plt.tight_layout()
# plt.show()# 将波形转换为频谱图
def get_spectrogram(waveform):spectrogram = tf.signal.stft(waveform, frame_length=255, frame_step=128)spectrogram = tf.abs(spectrogram)spectrogram = spectrogram[..., tf.newaxis]return spectrogram# 浏览数据
for i in range(3):label = label_names[example_labels[i]]waveform = example_audio[i]spectrogram = get_spectrogram(waveform)print('Label:', label)print('Waveform shape:', waveform.shape)print('Spectrogram shape:', spectrogram.shape)print('Audio playback')display.display(display.Audio(waveform, rate=16000))# 从音频数据集创建频谱图数据集def make_spec_ds(ds):return ds.map(map_func=lambda audio, label: (get_spectrogram(audio), label),num_parallel_calls=tf.data.AUTOTUNE)train_spectrogram_ds = make_spec_ds(train_ds)
val_spectrogram_ds = make_spec_ds(val_ds)
test_spectrogram_ds = make_spec_ds(test_ds)# 检查数据集的不同示例的频谱图
for example_spectrograms, example_spect_labels in train_spectrogram_ds.take(1):break# 减少训练模型时的读取延迟
train_spectrogram_ds = train_spectrogram_ds.cache().shuffle(10000).prefetch(tf.data.AUTOTUNE)
val_spectrogram_ds = val_spectrogram_ds.cache().prefetch(tf.data.AUTOTUNE)
test_spectrogram_ds = test_spectrogram_ds.cache().prefetch(tf.data.AUTOTUNE)# 使用卷积神经网络创建模型
input_shape = example_spectrograms.shape[1:]
print('Input shape:', input_shape)
num_labels = len(label_names)
norm_layer = tf.keras.layers.Normalization() # 创建规范化层,便于更好的进行模型训练和推断
norm_layer.adapt(data=train_spectrogram_ds.map(map_func=lambda spec, label: spec))model = tf.keras.models.Sequential([tf.keras.layers.Input(shape=input_shape),tf.keras.layers.Resizing(32, 32),norm_layer,tf.keras.layers.Conv2D(32, 3, activation='relu'),tf.keras.layers.Conv2D(64, 3, activation='relu'),tf.keras.layers.MaxPool2D(),tf.keras.layers.Dropout(0.25),tf.keras.layers.Flatten(),tf.keras.layers.Dense(128, activation='relu'),tf.keras.layers.Dropout(0.5),tf.keras.layers.Dense(num_labels),
])model.summary()# 编译模型
model.compile(optimizer=tf.keras.optimizers.Adam(), # 优化器loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), # 损失函数metrics=['accuracy'] # 准确率作为评估标准
)# 训练模型,并记录训练的日志
history = model.fit(train_spectrogram_ds,validation_data=val_spectrogram_ds,epochs=10,callbacks=tf.keras.callbacks.EarlyStopping(verbose=1, patience=2),
)# 评估性能
model.evaluate(test_spectrogram_ds, return_dict=True)# 导出模型class ExportModel(tf.Module):def __init__(self, model):self.model = modelself.__call__.get_concrete_function(x=tf.TensorSpec(shape=(), dtype=tf.string))self.__call__.get_concrete_function(x=tf.TensorSpec(shape=[None, 16000], dtype=tf.float32))@tf.functiondef __call__(self, x):if x.dtype == tf.string:x = tf.io.read_file(x)x, _ = tf.audio.decode_wav(x, desired_channels=1, desired_samples=16000,)x = tf.squeeze(x, axis=-1)x = x[tf.newaxis, :]x = get_spectrogram(x)result = self.model(x, training=False)class_ids = tf.argmax(result, axis=-1)class_names = tf.gather(label_names, class_ids)return {'predictions': result,'class_ids': class_ids,'class_names': class_names}export = ExportModel(model)
export(tf.constant('./data/mini_speech_commands/no/012c8314_nohash_0.wav'))tf.saved_model.save(export, "saved")
加载使用导出的模型
使用模型预测down
的音频
import tensorflow as tf# 直接加载模型的目录
new_model = tf.saved_model.load("./saved")
res = new_model('./data/mini_speech_commands/down/004ae714_nohash_0.wav')
print("结果:",res)class_names = ['down', 'go', 'left', 'no', 'right', 'stop', 'up', 'yes']
class_index = res['class_ids'].numpy()[0]
class_name = class_names[class_index]
print("类别名称:", class_name)
相关文章:

TensorFlow案例学习:简单的音频识别
前言 以下内容均来源于官方教程:简单的音频识别:识别关键字 音频识别 下载数据集 下载地址:http://storage.googleapis.com/download.tensorflow.org/data/mini_speech_commands.zip 可以直接浏览器访问下载。 下载完成后将其解压到项目…...

css小程序踩坑记录
写标签设置距离 一直设置不动 写个双层 设置动了 神奇 好玩...
Android sqlite分页上传离线订单后删除
1、判断订单表的的总数是否大于0,如果大于0开始上传订单 public int getOrderCount() {String query "SELECT COUNT(*) FROM " TABLE_NAME;Cursor cursor db.rawQuery(query, null);int count 0;if (cursor.moveToFirst()) {count cursor.getInt(0);…...

Flask基本教程以及Jinjia2模板引擎简介
flask基本使用 直接看代码吧,非常容易上手: # 创建flask应用 app Flask(__name__)# 路由 app.route("/index", methods[GET]) def index():return "FLASK:欢迎访问主页!"if __name__ "__main__"…...

Django实战项目-学习任务系统-兑换物品管理
接着上期代码框架,开发第5个功能,兑换物品管理,再增加一个学习兑换物品表,主要用来维护兑换物品,所需积分,物品状态等信息,还有一个积分流水表,完成任务奖励积分,兑换物品…...

jmeter和postman你选哪个做接口测试?
软件测试行业做功能测试和接口测试的人相对比较多。在测试工作中,有高手,自然也会有小白,但有一点我们无法否认,就是每一个高手都是从小白开始的,所以今天我们就来谈谈一大部分人在做的接口测试,小白变高手…...

mac版本 Adobe总是弹窗提示验证问题如何解决
来自: mac软件下载macsc站 mac电脑使用过程中总是弹出Adobe 的弹窗提示,尤其是打开Adobe的软件,更是频繁的弹出提示: Your Adobe app is not genuine. Adobe reserves the right to disable this software after a 0 grace period…...

钡铼技术ARM工控机在机器人控制领域的应用
ARM工控机是一种基于ARM架构的工业控制计算机,用于在工业自动化领域中进行数据采集、监控、控制和通信等应用。ARM(Advanced RISC Machine)架构是一种低功耗、高性能的处理器架构,广泛应用于移动设备、嵌入式系统和物联网等领域。…...

HTML+CSS+JS实现计算器
🙈作者简介:练习时长两年半的Java up主 🙉个人主页:程序员老茶 🙊 ps:点赞👍是免费的,却可以让写博客的作者开心好久好久😎 📚系列专栏:Java全栈,…...

Git工作原理和常见问题处理方案
博客定位Git工作区域工作区域划分暂存区设计目的 Git基本操作核心操作初始化和配置指令 HEAD指针Git版本回滚指令介绍reset模式reset hard使用场景reset soft使用场景reset mixed使用场景reset使用注意事项checkout使用场景 Git分支管理什么是分支分支应用场景分支相关指令被合…...

C++-实现一个简单的菜单程序
C-实现一个简单的菜单程序 1,if-else语句实现1.1,代码实现1.2,功能检测 2,switch语句实现2.1,代码实现2.2,功能检测 1,if-else语句实现 实现一个简单的菜单程序,运行时显示"Men…...
Git更新 fork 的仓库
文章目录 确保本地仓库是最新的配置上游存储库(remote upstream)获取上游存储库的更改合并上游存储库的更改推送更改到你 fork 的仓库 确保本地仓库是最新的 在命令行中,导航到存储库的本地副本所在的目录,并执行以下命令: # 切换到主分支 …...

chorme安装esay scholar及chrome 无法从该网站添加应用、扩展程序和用户脚本解决方案
问题描述 如题,博主想安装easy scholar用于查询论文的分区,结果安装了半天一直出现chrome 无法从该网站添加应用、扩展程序和用户脚本解决方案的问题。 解决方案 先从这个网址下载:https://www.easyscholar.cc/download 然后对下载好的文…...

数据库-扩展语句,约束方式
扩展语句: 例: 自增长: auto_increment:表示该字段可以自增长,默认从一开始,每条记录会自动递增1 复制: 通过like这个语法直接复制ky32的表结构,只能复制表结构,不能复制表里面的…...

精密数据工匠:探索 Netty ChannelHandler 的奥秘
通过上篇文章(Netty入门 — Channel,把握 Netty 通信的命门),我们知道 Channel 是传输数据的通道,但是有了数据,也有数据通道,没有数据加工也是没有意义的,所以今天学习 Netty 的第四…...
Python四种基本结构的操作
列表 列表的创建有两种方法 SampleList [] SampleList list() 列表中元素的添加 append(obj):在列表末尾添加元素obj extend(seq):在列表末尾添加多个值,使用extend()函数,seq是一个可迭代对象,否则报错。 Inser…...
Eureka:com.netflix.discovery.TimedSupervisorTask - task supervisor timed out
1、原因是spring cloud netflix中,某个服务挂掉了或者是执行某个任务时间过长,而没有发送给Eureka心跳 ,导致调用不到指定的服务,所以检查被调用服务器是否有问题。 2、有可能是某一个微服务自身内部G了,导致没有向eu…...

1.spark standalone环境安装
概述 环境是spark 3.2.4 hadoop版本 3.2.4,所以官网下载的包为 spark-3.2.4-bin-hadoop3.2.tgz 在具体安装部署之前,需要先下载Spark的安装包,进到 spark的官网,点击download按钮 使用Spark的时候一般都是需要和Hadoop交互的&a…...

【问题解决】 avue dicUrl 动态参数加载字典数据(已解决)
事情是这样的,用了avue-crud组件,配置了一个option。 现在有一列source属性要展示为 多选的下拉框 ,当然问题不在这而在于,选项是需要根据同级别属性id去拿的。也就是option.column.source 的配置中 需要该行的option.col…...

学习一下,什么是预包装食品?
预包装食品,指预先定量包装或者制作在包装材料和容器中的食品;包括预先定量包装以及预先定量制作在包装材质和容器中并且在一定量限范围内具有统一的质量或体积标识的食品。简单说, 就是指在包装完成后即具有确定的量值,这一确定的…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...