TensorFlow案例学习:简单的音频识别

news2024/11/19 4:16:41

前言

以下内容均来源于官方教程:简单的音频识别:识别关键字

音频识别

下载数据集

下载地址: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,labels

train_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.function
    def __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, labels


train_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 = model

        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.function
    def __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)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1154956.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp使用z-paging插件下拉刷新

z-paging插件地址传送门 z-paging官网说明传送门 一、uniapp使用z-paging插件下拉刷新 1.导入插件 2.粘贴ui结构 <z-paging ref="paging" v-model="dataList"

【嵌入式】【GIT】如何迁移老的GIF到新的仓库时使用LFS功能并保持LOG不变

一、正常迁移流程 假设有仓库 ssh://old/buildroot-201902 需要迁移到新的仓库 ssh://old/buildroot-201902时,我们可以使用以下命令来完成: # 下载老的仓库 git clone ssh://old/buildroot-201902 # 向新的仓库上传所有的tags git push ssh://new/buildroot-201902 --tag…

三款公认简单好用的文字转语音工具

分享3款好用的文字转语音软件&#xff0c;操作简单&#xff0c;主播声音丰富&#xff0c;转换出来的语音能够接近于人声&#xff0c;非常自然&#xff01; 1、TTSMAKER 一款文字转语音在线工具&#xff0c;不需要注册登录&#xff0c;打开就能使用&#xff0c;支持多种语言的语…

【OpenVAS】一个快速、简洁的 OpenVAS 扫描解决方案

一. OpenVAS简介&#xff1a; 官网&#xff1a;http://www.openvas.org/ OpenVas是一个功能齐全的开源的漏洞扫描工具。它具有无身份验证和身份验证测试的功能&#xff0c;支持各种高级和低级互联网和工业协议&#xff0c;能够进行大规模扫描的性能调优&#xff0c;还提供强大…

vue2:路由前置守卫无法获取到this.$store.state.xxx

在获取到vuex的数据时候&#xff0c;想在router目录下的index.js文件去获取到vuex仓库中声明的全局变量&#xff0c;但是通过this.$store.stote.xxx去获取的时候&#xff0c;报错提示&#xff1a;$store未定义 一、store/index.js const store new Vuex.Store({state: {// 属…

VScode clangd 插件浏览 linux 源码

文章目录 VScode clangd 插件浏览 linux 源码clangd 安装与配置VScode 插件安装clangd 安装方法一方法二 clangd 配置 cmake 生成bear 生成 compile_commands.json触发 clangd linux 内核脚本生成 compile_commands.json 文件三种方式对比 VScode clangd 插件浏览 linux 源码 …

外汇天眼:稳定盈利公式揭秘,想明白这个道理少走很多弯路!

所谓资金管理&#xff0c;简单的理解就是如何管好交易账户里的钱&#xff0c;或者说如何用好里面的钱&#xff0c;会更加贴切实际。 实践过程&#xff0c;资金管理最重要的环节应该是&#xff1a;不同行情下仓位的调节和止损的设置。 但据我所知&#xff0c;大多数人在资金管理…

心理测评测试H5小程序开源版开发

心理测评测试h5公众号字节微信小程序app开源版开发 探索心理奥秘&#xff0c;解读内心世界&#xff01; 现在&#xff0c;我们为你带来一款独具特色的心理测评小程序——心理测评测试H5公众号字节微信小程序APP开源版开发&#xff01; 这个强大而灵活的工具&#xff0c;将帮…

【AIFEM案例操作】电器盒谐响应分析

AIFEM是由天洑自主研发的一款通用的智能结构仿真软件&#xff0c;助力用户解决固体结构相关的静力学、动力学、振动、热力学等实际工程问题&#xff0c;软件提供高效的前后处理工具和高精度的有限元求解器&#xff0c;帮助用户快速、深入地评估结构的力学性能&#xff0c;加速产…

Flutter三棵树的创建流程

一、Flutter常见的家族成员 Widget常见的家族成员 Element常见的家族成员 Render常见的家族成员 二、示例代码对应的Flutter Inspector树 示例代码&#xff1a;MyApp->MyHomePage->ErrorWidget&#xff0c;包含了StatelessWidget、StatefulWidget、LeafRenderObjectWid…

hdlbits系列verilog解答(加减法器)-28

文章目录 一、问题描述二、verilog源码三、仿真结果一、问题描述 可以通过将其中一个输入变为负来从加法器构建加法器-减法器,这相当于将其输入反相然后加 1。最终结果是一个可以执行两个操作的电路:(a + b + 0) 和 (a + ~b + 1)。如果您想更详细地解释该电路的工作原理…

【小白专用】Mysql的安装配置教程(详细)

首先简单概述分为几个步骤&#xff1a; 一、下载Mysql 二、安装Mysql 三、验证Mysql安装是否成功 四、 配置环境变量 五、验证配置环境变量是否成功 一、下载Mysql 要在Windows或Mac上安装MySQL&#xff0c;首先从MySQL官方网站下载最新的MySQL Community Server版本&…

图形库篇 | EasyX | 图形绘制

图形库篇 | EasyX | 图形绘制 设置颜色 函数功能函数设置画线颜色void setlinecolor(COLORREF color)设置填充颜色void setfillcolor(COLORREF color) 设置画线颜色&#xff1a;void setlinecolor(COLORREF color) 具体功能&#xff1a;设置当前设备画线颜色返回值&#xff…

带IV的分组加密下密文分散存储且存在混淆密文片段的多项式时间解密方案

在使用带IV的分组加密模式下&#xff0c;考虑这样一个场景&#xff1a;分组加密后&#xff0c;每组密文都被分散保存&#xff0c;且在恢复的时候&#xff0c;每组密文会和n个混淆的密文一起提供&#xff0c;此时&#xff0c;若想完整的恢复明文&#xff0c;需要一个多项式时间的…

新手尝试硬件买单片机还是树莓派?

今日话题&#xff0c;新手尝试硬件买单片机还是树莓派&#xff1f;对于硬件初学者&#xff0c;建议首先学习单片机&#xff0c;如51单片机或STM32等。这些平台有丰富的学习资源和示例项目&#xff0c;程序相对简单&#xff0c;更贴近硬件&#xff0c;使初学者能够轻松入门&…

RecyclerView在点击事件的处理上也优于ListView

主要是细节的支持&#xff0c;ListView直接提供setOnItemClickListener,而RecyclerView没有&#xff0c;是因为RV考虑的更细节&#xff0c;比如我要点击条目上的某个图标生效&#xff0c;使用ListView会很难实现&#xff0c;但是RV实现会很容易&#xff0c;直接在适配器中由Vie…

财务管理系统 财务管理软件

财务管理系统 财务管理软件 系统功能介绍&#xff1a; 1、预算管理系统 预算管理是一个承上启下的业务衔接系统&#xff0c;主要用于记录本单位的年度预算指标数据&#xff0c;可以通过接口从财政年度预算数据中导入&#xff0c;也可以根据自身管理控制需要录入…

前端移动web详细解析四

移动 Web 第四天 01-vw适配方案 vw和vh基本使用 vw和vh是相对单位&#xff0c;相对视口尺寸计算结果 vw&#xff1a;viewport width&#xff08;1vw 1/100视口宽度 &#xff09; vh&#xff1a;lviewport height ( 1vh 1/100视口高度 ) vw布局 vw单位的尺寸 px 单位数…

神经网络的解释方法之CAM、Grad-CAM、Grad-CAM++、LayerCAM

原理优点缺点GAP将多维特征映射降维为一个固定长度的特征向量①减少了模型的参数量&#xff1b;②保留更多的空间位置信息&#xff1b;③可并行计算&#xff0c;计算效率高&#xff1b;④具有一定程度的不变性①可能导致信息的损失&#xff1b;②忽略不同尺度的空间信息CAM利用…

Allegro如何恢复器件的丝印,位号

在用Allegro Layout的过程中,有时候会无意间删除掉器件的丝印,位号等,那怎么恢复呢? 被无意删除的电容丝印框,如下图。 首先点击菜单Place 点击Update Symbols...(更新器件) 跳出下面的对话框,找到对应的封装类型打勾。 然后下面四项打勾,然后点击恢复按钮即可。 恢复…