秋梦无痕

一场秋雨无梦痕,春夜清风冻煞人。冬来冷水寒似铁,夏至京北蟑满城。

Avatar

[转载]简单的音频识别

from: TensorFlow 官方教程

按:因为tensorflow.org被墙了,所以把这篇文章搬过来慢慢看。

本教程将向您展示如何构建可以识别 10 个不同字词的基本语音识别网络。需要注意的是,真正的语音和音频识别系统要复杂得多,但就像用于识别图像的 MNIST,这个基本语音识别网络能够帮助您基本了解所涉及的技术。学完本教程后,您将获得一个模型,该模型会尝试将时长为 1 秒的音频片段归类为无声、未知字词、“yes”、“no”、“up”、“down”、“left”、“right”、“on”、“off”、“stop”或“go”。您还可以在 Android 应用中运行该模型。

准备
==========
您应确保安装了 TensorFlow;此外,由于脚本会下载超过 1GB 的训练数据,因此您需要确保计算机拥有稳定的互联网连接和足够的可用空间。训练过程可能需要几个小时,因此请确保您的计算机可以完成这么长时间的训练操作。

训练
==========
要开始训练过程,请转到 TensorFlow 源代码树,然后运行以下脚本:

python tensorflow/examples/speech_commands/train.py


该脚本会先下载语音指令数据集,其中包含超过 105000 个 WAVE 音频文件,音频内容是有人说出 30 个不同的字词。这些数据由 Google 收集,并依据 CC BY 许可发布,您可以提交 5 分钟自己的录音来帮助改进该数据。归档数据超过 2GB,因此这部分过程可能需要一段时间,但您应该可以看到进度日志;下载完成后,您无需再次执行此步骤。如需详细了解该数据集,请参阅语音指令这篇论文。

下载完成后,您将看到如下日志信息:

I0730 16:53:44.766740   55030 train.py:176] Training from step: 1
I0730 16:53:47.289078   55030 train.py:217] Step #1: rate 0.001000, accuracy 7.0%, cross entropy 2.611571


这表明初始化过程已经完成,训练循环已经开始。您将看到该日志输出每个训练步的信息。下面详细说明了该日志信息的含义:

Step #1 表明正在进行训练循环的第一步。在此示例中总共有 18000 个训练步,您可以查看步编号来了解还有多少步即可完成。
rate 0.001000 是控制网络权重更新速度的学习速率。在训练的早期阶段,它是一个相对较大的数字 (0.001),但在训练周期的后期会减少到原来的十分之一,即 0.0001。
accuracy 7.0% 表示模型在本训练步中预测正确的类别数量。该值通常会有较大的波动,但应该会随着训练的进行总体有所提高。该模型会输出一个数字数组,每个标签对应一个数字,每个数字都表示输入可能归入该类别的预测概率。可通过选择得分最高的条目来挑选预测标签。得分始终介于 0 到 1 之间,值越高表示结果的置信度越高。
cross entropy 2.611571 是用于指导训练过程的损失函数的结果。它是一个得分,通过将当前训练运行的得分向量与正确标签进行比较计算而出,该得分应在训练期间呈下滑趋势。

经过 100 步之后,您应看到如下所示的行:

I0730 16:54:41.813438 55030 train.py:252] Saving to "/tmp/speech_commands_train/conv.ckpt-100"

此行会将当前的训练权重保存到检查点文件中。如果训练脚本中断了,您可以查找上次保存的检查点,然后从该点开始重新启动该脚本:

python tensorflow/examples/speech_commands/train.py --start_checkpoint=/tmp/speech_commands_train/conv.ckpt-100

混淆矩阵
==========
经过 400 步之后,您会看到以下日志信息:

I0730 16:57:38.073667   55030 train.py:243] Confusion Matrix:
 [[258   0   0   0   0   0   0   0   0   0   0   0]
 [  7   6  26  94   7  49   1  15  40   2   0  11]
 [ 10   1 107  80  13  22   0  13  10   1   0   4]
 [  1   3  16 163   6  48   0   5  10   1   0  17]
 [ 15   1  17 114  55  13   0   9  22   5   0   9]
 [  1   1   6  97   3  87   1  12  46   0   0  10]
 [  8   6  86  84  13  24   1   9   9   1   0   6]
 [  9   3  32 112   9  26   1  36  19   0   0   9]
 [  8   2  12  94   9  52   0   6  72   0   0   2]
 [ 16   1  39  74  29  42   0   6  37   9   0   3]
 [ 15   6  17  71  50  37   0   6  32   2   1   9]
 [ 11   1   6 151   5  42   0   8  16   0   0  20]]


第一部分是混淆矩阵。要理解它的具体含义,您首先需要了解所用的标签。在本示例中,所用的标签是“silence”、“unknown”、“yes”、“no”、“up”、“down”、“left”、“right”、“on”、“off”、“stop”和“go”。每列代表一组被模型预测为每个标签的样本,因此第一列代表预测为无声的所有音频片段,第二列代表预测为未知字词的所有音频片段,第三列代表预测为“yes”的所有音频片段,依此类推。

每行表示音频片段实际归入的标签。第一行是归入无声的所有音频片段,第二行是归入未知字词的所有音频片段,第三行是归入“yes”的所有音频片段,依此类推。

此矩阵比单个准确率得分更加有用,因为它可以很好地总结网络出现的错误。在此示例中,您可以发现,除了第一个数值以外,第一行中的所有条目均为 0。因为第一行表示所有实际无声的音频片段,这意味着所有音频片段都未被错误地标记为字词,因此我们未得出任何有关无声的假负例。这表示网络已经可以很好地区分无声和字词。

如果我们往下看,就会发现第一列有大量非零值。该列表示预测为无声的所有音频片段,因此第一个单元格外的正数是错误的预测。这表示一些实际是语音字词的音频片段被预测为无声,因此我们得出了很多假正例。

完美的模型会生成混淆矩阵,除了穿过中心的对角线上的条目以外,所有其他条目都为 0。发现偏离这个模式的地方有助于您了解模型最容易在哪些方面混淆;确定问题所在后,您就可以通过添加更多数据或清理类别来解决这些问题。

验证
==========
在混淆矩阵之后,您应看到如下所示的行:

I0730 16:57:38.073777 55030 train.py:245] Step 400: Validation accuracy = 26.3% (N=3093)


最好将数据集分成三个类别。最大的子集(本示例中为约 80% 的数据)用于训练网络,较小的子集(本示例中为约 10% 的数据,称为“验证”集)预留下来以评估训练期间的准确率,另一个子集(剩下的 10%,称为“测试”集)用来评估训练完成后的准确率。

之所以采用这种拆分方法,是因为始终存在这样一种风险:网络在训练期间开始记忆输入。通过将验证集分离开来,可以确保模型能够处理它之前从未见过的数据。测试集是一种额外的保护措施,可以确保您不仅以适合训练集和验证集的方式调整模型,而且使模型能够泛化到范围更广的输入。

训练脚本会自动将数据集分为这三个类别,上面的日志行会显示在验证集上运行时模型的准确率。理想情况下,该准确率应该相当接近训练准确率。如果训练准确率有所提高但验证准确率没有,则表明存在过拟合,模型只学习了有关训练音频片段的信息,而没有学习能泛化的更广泛模式。

Tensorboard
==========
使用 Tensorboard 可以很好地观察训练进度。默认情况下,脚本会将事件保存到 /tmp/retrain_logs,您可以通过运行以下命令加载这些事件:

tensorboard --logdir /tmp/retrain_logs


然后,在浏览器中转到 http://localhost:6006,您将看到显示模型进度的图表。

训练完成
==========
经过几个小时(具体取决于计算机的速度)的训练后,脚本应该已经完成了全部 18000 个训练步。它会输出在测试集上运行时的最终混淆矩阵以及准确率得分。使用默认设置时,您应该会看到准确率介于 85% 到 90% 之间。

由于音频识别在移动设备上特别有用,因此接下来我们会将其导出为易于在这些平台上使用的紧凑格式。为此,请运行以下命令行:

python tensorflow/examples/speech_commands/freeze.py \
--start_checkpoint=/tmp/speech_commands_train/conv.ckpt-18000 \
--output_file=/tmp/my_frozen_graph.pb


创建冻结模型后,您可以使用 label_wav.py 脚本对其进行测试,如下所示:

python tensorflow/examples/speech_commands/label_wav.py \
--graph=/tmp/my_frozen_graph.pb \
--labels=/tmp/speech_commands_train/conv_labels.txt \
--wav=/tmp/speech_dataset/left/a5d485dc_nohash_0.wav


上述命令应该会输出 3 个标签:

left (score = 0.81477)
right (score = 0.14139)
_unknown_ (score = 0.03808)


希望“left”的得分最高,因为它是正确的标签,但由于训练是随机的,因此尝试的第一个文件可能并非如此。尝试一下同一文件夹中的其他一些 .wav 文件,看看效果如何。

得分介于 0 到 1 之间,值越高表示模型对其预测越有信心。

在 Android 应用中运行模型
==========
要查看该模型在实际应用中的工作原理,最简单的方法是下载预构建的 Android 演示应用,并将其安装在手机上。您会在应用列表中看到“TF Speech”,打开它就会看到我们刚刚训练模型时使用的动词列表(以“Yes”和“No”开始)。授权该应用使用麦克风以后,您应该可以试着说出这些字词,在该模型识别出其中一个字词时,您会在界面中看到相应字词突出显示出来。

您还可以自行构建该应用,因为它是开源的,可在GitHub 上的 TensorFlow 代码库中找到。默认情况下,它会从 tensorflow.org 下载预训练的模型,但您可以轻松地将其替换为自己训练的模型。如果这样做,您需要确保主要 SpeechActivity Java 源文件中的常量(例如 SAMPLE_RATE 和 SAMPLE_DURATION)与您在训练期间对默认设置所做的任何更改相匹配。您还会看到一个Java 版本的 RecognizeCommands 模块,它与本教程中的 C++ 版本非常相似。如果您已经调整了参数,也可以在 SpeechActivity 中进行更新,以获得与服务器测试中的结果相同的结果。

演示应用会根据您复制到资源(位于冻结图旁边)中的标签文本文件自动更新其结果界面列表,这意味着您可以轻松尝试不同的模型,而无需更改任何代码。如果更改路径,则需要更新 LABEL_FILENAME 和 MODEL_FILENAME 以指向所添加的文件。

此模型的工作原理
==========
本教程中使用的架构基于小型关键字检测卷积神经网络这篇论文中介绍的一些架构。之所以选择它,是因为它虽然不是最先进的架构,但是相对简单、可快速训练,并且易于理解。可以通过多种方法构建用于处理音频的神经网络模型,其中包括递归网络扩张(带洞)卷积。对于本教程所基于的卷积网络类型,接触过图像识别的人可能都很熟悉。不过,初次接触时也可能会觉得不可思议,因为音频本身是一段时间内的一维连续信号,而不是二维空间问题。

为了解决这一问题,我们会定义一个我们认为我们的语音字词应该符合的时间范围,并将这段时间内的音频信号转换成图像。为此,可以将传入的音频样本分成小段(时长仅为几毫秒)并计算一组频段内频率的强度。一段音频内的每组频率强度被视为数字向量,这些向量按时间顺序排列,形成一个二维数组。然后,该值数组可被视为单通道图像,称为声谱图。如果要查看音频样本生成的图像类型,可以运行 wav_to_spectrogram 工具:

bazel run tensorflow/examples/wav_to_spectrogram:wav_to_spectrogram -- \
--input_wav=/tmp/speech_dataset/happy/ab00c4b2_nohash_0.wav \
--output_image=/tmp/spectrogram.png


如果您打开 /tmp/spectrogram.png,应该会看到如下内容:

由于 TensorFlow 的内存排序原因,该图像中的时间从上往下逐渐增加,而频率从左到右排列,这与时间从左到右排列的声谱图惯例不同。您应该能够看到几个不同的部分,第一个音节“Ha”与“ppy”不同。

由于人耳对某些频率更加敏感,因此语音识别领域传统的做法是进一步处理该表示法,将其转换成一组梅尔倒频谱系数(简称 MFCC)。MFCC 也是一种二维单通道表示法,因此也可将其视为图像。如果您的目标是一般声音而不是语音,您可以跳过此步骤并直接在声谱图上进行操作。

然后,这些处理步骤生成的图像会馈送到多层卷积神经网络中,最后是全连接层,后跟 softmax。您可以在以下位置了解该部分的定义:tensorflow/examples/speech_commands/models.py

流式处理准确率
==========
大部分音频识别应用需要在连续的音频流上运行,而不是在单个音频片段上运行。在此环境中使用模型的典型方法是在不同的时间偏移量处重复应用该模型,并计算一小段时间内结果的平均值,以生成平滑预测。如果您将输入视为图像,则它将沿时间轴持续滚动。我们想要识别的字词可能在任意时间点出现,因此,我们需要拍摄一系列快照,以便有机会生成一种对齐方式,用于捕获在我们馈送到模型的时间段内出现的大部分语音内容。如果我们以足够快的速度采样,那么我们就很有可能在多个时间段内捕获相关字词,因此计算结果的平均值可以提高预测的整体置信度。

有关如何对流式数据使用模型的示例,请查看test_streaming_accuracy.cc。该示例使用RecognizeCommands类处理一个较长的输入音频、尝试检测字词,并将这些预测结果与标签和时间的真实列表进行对比。该示例可清楚说明如何将模型应用于一段时间内的音频信号流。

要测试模型,您需要使用一个时长较长的音频文件,以及标注每个语音字词出现位置的标签文件。如果您不想自己录制音频,可以使用 generate_streaming_test_wav 实用程序生成一些合成测试数据。默认情况下,该实用程序会生成一个时长为 10 分钟的 .wav 文件(其中大约每隔 3 秒出现一个语音字词),以及一个包含字词语音实际出现时间的文本文件。这些字词来自当前数据集的测试部分,与背景噪声混在一起。要运行该文件,请使用:

bazel run tensorflow/examples/speech_commands:generate_streaming_test_wav


该命令会将 .wav 文件保存到 /tmp/speech_commands_train/streaming_test.wav,并将列出标签的文本文件保存到 /tmp/speech_commands_train/streaming_test_labels.txt。然后,您可以通过以下命令运行准确率测试:

bazel run tensorflow/examples/speech_commands:test_streaming_accuracy -- \
--graph=/tmp/my_frozen_graph.pb \
--labels=/tmp/speech_commands_train/conv_labels.txt \
--wav=/tmp/speech_commands_train/streaming_test.wav \
--ground_truth=/tmp/speech_commands_train/streaming_test_labels.txt \
--verbose


该命令会输出以下信息:字词与标签匹配正确的字词数量、预测为错误标签的字词数量,以及没有实际语音内容时触发模型的次数。有多种参数可以控制平均信号操作的行为,其中包括 --average_window_ms(设置计算结果平均值的时长)、--clip_stride_ms(表示应用模型的间隔时间)、--suppression_ms(在发现第一个字词后的一段时间内阻止触发后续字词检测),以及 --detection_threshold(控制平均得分必须达到多少才可被视为稳定结果)。

您将看到流式准确率输出 3 个数字,而不仅仅是训练中使用的一个指标。这是因为不同的应用具有不同的要求,其中一些应用可以容忍频繁的错误结果,只要找到了实际字词(较高的召回率)就行;还有一些应用非常注重确保预测出的标签很有可能正确,即便未检测到一些字词(较高的精确率)。您可以根据该工具提供的数字了解模型在应用中的效果,还可以尝试调整信号平均参数来调整模型,以获得所需的效果。要了解适用于您应用的参数,您可以查看生成的ROC 曲线来权衡利弊。

RecognizeCommands
==========
流式准确率工具使用一个简单的解码器,该解码器包含在名为RecognizeCommands的小型 C++ 类中。该类会获得在一段时间内运行 TensorFlow 模型的输出,然后计算信号的平均值,并在有充分证据表明已发现可识别的字词时返回有关标签的信息。这个实现的规模很小,只需跟踪最后几条预测并计算平均值即可,因此可根据需要轻松移植到其他平台和语言。例如,在 Android 上可以通过 Java 很方便地执行相似的操作,或者在树莓派上使用 Python 执行相似的操作。只要这些实现采用相同的逻辑,您就可以使用流式测试工具调整控制计算平均值的参数,然后将这些参数转到应用中以获取类似的结果。

高级训练
==========
训练脚本的默认设置旨在在一个相对较小的文件中生成良好的端到端结果,但您可以根据自己的要求更改多个选项以自定义结果。

自定义训练数据
----------
默认情况下,脚本将下载Speech Commands 数据集,但您也可提供自己的训练数据。要使用您自己的数据进行训练,您应确保您要识别的每个声音至少有几百条录音,并按照类别将它们整理到文件夹中。例如,如果您尝试让模型区分狗吠声和猫叫声,则需要创建一个名为 animal_sounds 的根文件夹,然后在该文件夹下创建两个分别名为 bark 和 miaow 的子文件夹。然后,将音频文件整理到相应文件夹中。

要将脚本指向新的音频文件,您需要设置 --data_url= 以阻止 Speech Commands 数据集的下载,并设置 --data_dir=/your/data/folder/ 以查找您刚刚创建的文件。

这些文件本身应是 16 位有小端字节序且采用 PCM 编码的 WAVE 格式。采样率默认为 16000,但是可以使用 --sample_rate 参数更改采样率,只要所有音频始终保持相同的采用率(脚本不支持重新采样)即可。音频片段也应保持大致相同的时长。默认预期时长为 1 秒,但您可以使用 --clip_duration_ms 标记设置时长。如果音频片段在开头的无声时长不同,则可以考虑使用字词对齐工具标准化这些音频片段(也可以使用此处提供的临时应急方法)。

需要注意一个问题,数据集中可能存在相同声音的非常类似的重复,如果这些重复分布在训练集、验证集和测试集中,可能会产生误导性指标。例如,Speech Commands 集合让人们多次重复相同的字词。这些重复的语音之间可能会非常相似,如果训练出现过拟合并记住其中一个,则模型在测试集中发现非常类似的副本时会给出过好的预测。为了避免这种风险,Speech Commands 努力确保将同一人发出的相同字词的多个音频片段放入同一数据集中。音频片段根据其文件名的哈希值分配到训练集、测试集或验证集中,这样一来,即使添加新的音频片段,也能确保分配是稳定的,并避免训练样本转移到其他集合。为了确保同一位指定发声人的所有字词语音都位于同一数据集中,哈希函数在计算分配时会忽略文件名中“nohash”之后的所有内容。这意味着如果您有 pete_nohash_0.wav 和 pete_nohash_1.wav 这样的文件名,则它们肯定位于同一集合中。

未知类别
----------
应用可能会听到训练集之外的声音,并且您希望模型表明它无法识别这些情况下的噪声。为了帮助网络学习要忽略哪些声音,您需要提供一些不属于任何类别的音频片段。为此,您需要创建 quack、oink 和 moo 子文件夹,并使用用户可能会听到的其他动物的噪声填充这些子文件夹。在训练期间,脚本的 --wanted_words 参数定义您关注的类别,子文件夹名称中提到的所有其他类别用于填充 _unknown_ 类别。Speech Commands 数据集中的未知类别下有 20 个字词,包括 0 到 9 之间的数字和随机姓名(如“Sheila”)。

默认情况下,从未知类别中挑选 10% 的训练样本,但您可以使用 --unknown_percentage 标记控制该比例。如果提高该比例,模型将未知字词误识别为所需字词的可能性就会降低,但如果该比例过高,则可能会适得其反,因为模型可能认为将所有字词都归类为未知字词是最安全的做法!

背景噪声
----------
即使环境中出现其他不相关的声音,实际应用也必须识别音频。为了构建一个可以稳健应对此类干扰的模型,我们需要使用具有类似特性的已录制音频进行训练。Speech Commands 数据集中的文件是由用户使用各种设备在多种不同的环境(而不是在录音室)中录制的,因此有助于提高训练的真实性。为了更加真实,您可以将环境音频的随机片段混合到训练输入中。Speech Commands 集合中有一个名为 _background_noise_ 的特殊文件夹,其中包含时长 1 分钟的 WAVE 文件,内容为白噪音以及机械和日常家庭活动的录音。

这些文件的小片段是随机选择的,并在训练期间以较低的音量混合到音频片段中。音量也是随机选择的,并由 --background_volume 参数按比例进行控制,其中 0 表示无声,1 表示最大音量。并非所有音频片段中都加入背景噪声,因此 --background_frequency 标记控制混入噪声的比例。

您自己的应用在其自身环境中运行所用的背景噪声模式可能与默认模式不同,因此您可以在 _background_noise_ 文件夹中提供自己的音频片段。这些音频片段的采样率应与主数据集相同,但时长应该长很多,以便可以从中选择一组效果良好的随机片段。

无声
----------
在大多数情况下,您关注的声音都是断断续续的,因此务必要清楚何时没有匹配的音频。为此,可以使用一个特殊的 _silence_ 标签,表明模型何时未检测到任何值得关注的内容。由于真实环境中并不存在绝对的无声情况,因此我们实际上必须提供安静且不相关的音频样本。为此,我们重复使用也混入到实际音频片段中的 _background_noise_ 文件夹,提取音频数据的简短片段,并馈送这些片段(包含实际类别标签 _silence_)。默认情况下,10% 的训练数据是按照这种方法提供的,但可以使用 --silence_percentage 控制该比例。与未知字词一样,如果提高该比例,则模型给出的结果可能倾向于无声的真正例,代价是字词出现假负例;但如果该比例过高,则可能导致模型陷入始终猜测无声的陷阱。

时移
----------
为了符合实际地扭曲训练数据以有效增加数据集的大小,进而提高整体准确率,一种方式是添加背景噪声,而另一种方式是时移。这涉及到训练样本数据在时间方面的随机偏移,以便截去开头或结尾的一小部分,而另一部分则用零填充。这模拟了训练数据开始时间的自然变化,并由 --time_shift_ms 标记控制,默认为 100 毫秒。提高该值将提供更多变化,但可能会截去音频的重要部分。一种通过真实扭曲来增强数据的相关方法是使用时间伸缩和音调缩放,但这不在本教程的讨论范围之内。

自定义模型
==========
用于该脚本的默认模型非常大,每次推理需要使用超过 8 亿 FLOP,并需要使用 940000 个权重参数。该模型在台式机或新型手机上可以快速运行,但要在资源更有限的设备上快速运行,则涉及到太多计算。为了支持这些用例,可以采用几个替代方法:

low_latency_conv 基于Neural Networks for Small-footprint Keyword Spotting(小型关键字检测卷积神经网络)这篇论文中介绍的“cnn-one-fstride4”拓扑。准确率略低于卷积神经网络,但权重参数的数量大致相同,但运行一次预测只需要 1100 万 FLOP,提高了模型的运行速度。

要使用该模型,请在命令行上指定 --model_architecture=low_latency_conv。您还需要更新训练速率和训练步数,因此完整命令如下所示:

python tensorflow/examples/speech_commands/train \
--model_architecture=low_latency_conv \
--how_many_training_steps=20000,6000 \
--learning_rate=0.01,0.001


该命令要求脚本以 0.01 的学习速率训练 20000 个训练步,然后进行微调,以原来速率的十分之一完成 6000 个训练步。

low_latency_svdf 基于Compressing Deep Neural Networks using a Rank-Constrained Topology paper(利用秩受限的拓扑压缩深度神经网络)这篇论文中介绍的拓扑。准确率也低于卷积神经网络,但只使用大约 750000 个参数,最重要的是,它允许在测试时(即您在应用中实际用到时)优化执行,并且需要 750000 个 FLOP。

要使用该模型,请在命令行上指定 --model_architecture=low_latency_svdf,并更新训练速率和训练步数,因此完整命令如下所示:

python tensorflow/examples/speech_commands/train \
--model_architecture=low_latency_svdf \
--how_many_training_steps=100000,35000 \
--learning_rate=0.01,0.005

请注意,尽管所需的训练步数多于前两个拓扑,但计算数量减少意味着训练花费的时间应大致相同,并且最终得出的准确率大约为 85%。此外,您还可以通过在 SVDF 层中更改以下参数轻松地进一步调整拓扑,以便实现所需的计算量和准确率。
•rank - 近似秩(通常越高越好,但会导致更多计算)。
•num_units - 类似于其他层类型,指定层中的节点数(节点越多,效果越好,计算量也会更多)。

对于运行时,由于层允许通过缓存某些内部神经网络激活进行优化,因此您需要确保在冻结图和在流式模式(例如 test_streaming_accuracy.cc)下执行模型时使用一致的步长(例如 clip_stride_ms 标记)。

自定义其他参数如果您想尝试自定义模型,最好先从调整声谱图创建参数开始。这可能会更改模型的输入图像的大小,并且models.py中的创建代码会自动调整计算和权重的数量,以适应不同维度。如果您缩小输入图像的大小,则模型将需要更少的计算来处理输入,这样做可以很好地改善延迟情况,但会降低准确率。--window_stride_ms 控制每个频率分析样本与前一个之间相隔的时间。如果增加该值,则指定时长内的样本就会变少,输入的时间轴也会变短。--dct_coefficient_count 标记控制用于频率计算的分桶数量,因此降低该值会减少其他维度中的输入。--window_size_ms 参数不会影响大小,但会控制每个样本用于计算频率的区域宽度。如果您要寻找的声音时长很短,则缩短训练样本的时长(由 --clip_duration_ms 控制)也会有所帮助,因为这样也会缩短输入的时间维度。不过,您需要确保所有训练数据都在音频片段的初始部分包含正确的音频。

如果您想到了一个可以解决问题的完全不同模型,您可以将其插入models.py中,并让脚本的剩余部分处理所有预处理和训练工作。您可以向 create_model 添加一个新子句,查找该模型架构的名称,然后调用模型创建函数。该函数获得声谱图输入的大小以及其他模型信息,并且会创建 TensorFlow 操作来读取这些信息,同时生成输出预测向量和控制丢弃率的占位符。脚本的剩余部分负责将该模型集成到更大的图中,该图会执行输入计算,并应用 softmax 和损失函数来训练模型。

在调整模型和训练超参数时会遇到的一个常见问题是,可能会引入非数字值,这是由数值精确问题所致。通常,解决此问题的方式是减小学习速率等数值的大小并减少权重初始化函数,但如果问题仍然存在,则可以启用 --check_nans 标记来跟踪错误的来源。启用该标记后,系统会在 TensorFlow 中的大部分常规操作之间插入检查操作,而且会在遇到这些错误时中止训练过程并显示实用的错误消息。