|
简单的音频识别
. M; u4 A) [) M. m1 d. T8 M7 i4 o0 ^1 z$ l
, L1 G& C' U% Y' f/ O
今天的文章将向您展示如何构建可以识别 10 个不同字词的基本语音识别网络。需要注意的是,真正的语音和音频识别系统要复杂得多,但就像用于识别图像的 MNIST,这个基本语音识别网络能够帮助您基本了解所涉及的技术。学完本教程后,您将获得一个模型,该模型会尝试将时长为 1 秒的音频片段归类为无声、未知字词、“yes”、“no”、“up”、“down”、“left”、“right”、“on”、“off”、“stop” 或 “go”。您还可以在 Android 应用中运行该模型。
# ?* ~* | U8 ]# M) l9 u2 a4 I. `, h. p! U2 z: U" \" @' d" y3 i
% S& ^& C1 {9 E! u2 i) i
准备
2 ?0 v& ?4 @% S+ ~- i3 H您应确保安装了 TensorFlow;此外,由于脚本会下载超过 1GB 的训练数据,因此您需要确保计算机拥有稳定的互联网连接和足够的可用空间。训练过程可能需要几个小时,因此请确保您的计算机可以完成这么长时间的训练操作。: P/ |7 U; u8 c: | X
8 C5 n+ ]% O* j
+ ]" y7 o- [% e2 t6 j) I0 M训练 d' P1 ?- _, B% V
要开始训练过程,请转到 TensorFlow 源代码树,然后运行以下脚本:
$ {8 N" @3 Y) [) K* e. ipython tensorflow/examples/speech_commands/train.py8 Q" _ A- n7 X* P) d" O/ d
' C, Z: @. O! Z) v+ H3 K该脚本会先下载语音指令数据集,其中包含超过 105000 个 WAVE 音频文件,音频内容是有人说出 30 个不同的字词。这些数据由 Google 收集,并依据 CC BY 许可发布,您可以提交 5 分钟自己的录音来帮助改进该数据。归档数据超过 2GB,因此这部分过程可能需要一段时间,但您应该可以看到进度日志;下载完成后,您无需再次执行此步骤。如需详细了解该数据集,请参阅 https://arxiv.org/abs/1804.03209: }/ I( y5 L8 X9 O. m
; D& H2 ~# g9 {3 x/ g下载完成后,您将看到如下日志信息: d# U: x" f, G2 d" f; n1 h' }1 e4 n
I0730 16:53:44.766740 55030 train.py:176] Training from step: 18 u, g+ Q- J6 K$ g6 Y
I0730 16:53:47.289078 55030 train.py:217] Step #1: rate 0.001000, accuracy 7.0%, cross entropy 2.611571
$ l, O6 U+ \% Z% I3 {/ r ^; n2 f9 D9 Y" }( {
这表明初始化过程已经完成,训练循环已经开始。您将看到该日志输出每个训练步的信息。下面详细说明了该日志信息的含义:$ U2 ?0 ?) _( ?7 X6 I
# _9 X' G( D8 m; B5 N3 r
Step #1 表明正在进行训练循环的第一步。在此示例中总共有 18000 个训练步,您可以查看步编号来了解还有多少步即可完成。, M$ Z) }! x; a4 k) J- O
) ^: w# O) r( L; v9 I- B/ m/ y6 Y
rate 0.001000 是控制网络权重更新速度的学习速率。在训练的早期阶段,它是一个相对较大的数字 (0.001),但在训练周期的后期会减少到原来的十分之一,即 0.0001。
" c; q+ {* b; i
6 @% [, o# d$ W- i* b% L0 iaccuracy 7.0% 表示模型在本训练步中预测正确的类别数量。该值通常会有较大的波动,但应该会随着训练的进行总体有所提高。该模型会输出一个数字数组,每个标签对应一个数字,每个数字都表示输入可能归入该类别的预测概率。可通过选择得分最高的条目来挑选预测标签。得分始终介于 0 到 1 之间,值越高表示结果的置信度越高。
: o! n7 W$ N/ _0 u9 V. Y
( g6 }2 Q& O) o; B( b! ocross entropy 2.611571 是用于指导训练过程的损失函数的结果。它是一个得分,通过将当前训练运行的得分向量与正确标签进行比较计算而出,该得分应在训练期间呈下滑趋势。
! Y9 z5 m( L) \8 H" r, w6 O) P
经过 100 步之后,您应看到如下所示的行:
3 Y4 w; P$ f) A9 S7 uI0730 16:54:41.813438 55030 train.py:252] Saving to "/tmp/speech_commands_train/conv.ckpt-100"
4 _- G; _1 U& e* v! i, F7 \ _" k: ?9 q% ~4 {
此行会将当前的训练权重保存到检查点文件中。如果训练脚本中断了,您可以查找上次保存的检查点,然后将 --start_checkpoint=/tmp/speech_commands_train/conv.ckpt-100 用作命令行参数重启该脚本,以便从该点开始。
4 w0 M+ y' ^; X w
) Y9 a' I+ J% z+ _4 b+ i" ]/ |5 W% d2 o, s( C. A
混淆矩阵" x5 @" A; P) M& B$ P
经过 400 步之后,您会看到以下日志信息:# U$ ?- n9 X/ E6 J9 I- \% m
I0730 16:57:38.073667 55030 train.py:243] Confusion Matrix:
@' L ^, `: \, u7 A: r1 @3 p' s [[258 0 0 0 0 0 0 0 0 0 0 0]& B+ V1 d2 B& D: [
[ 7 6 26 94 7 49 1 15 40 2 0 11]4 a% |: O1 v5 p
[ 10 1 107 80 13 22 0 13 10 1 0 4]; ~4 h2 p* Q! u+ D9 g
[ 1 3 16 163 6 48 0 5 10 1 0 17]
2 N* y0 _) c+ C9 S" ^3 |: F3 D, s$ a2 e4 T [ 15 1 17 114 55 13 0 9 22 5 0 9]
e/ X/ P# W( ^2 R0 L. ` [ 1 1 6 97 3 87 1 12 46 0 0 10]
* B# v1 f; g Z' L( d! r) j# n0 V [ 8 6 86 84 13 24 1 9 9 1 0 6], Z! I/ V: M8 ^1 Y$ i+ K
[ 9 3 32 112 9 26 1 36 19 0 0 9]
7 V4 a. |5 J6 |% ~ [ 8 2 12 94 9 52 0 6 72 0 0 2]" i% k6 W; {6 e: O9 B
[ 16 1 39 74 29 42 0 6 37 9 0 3]/ M1 G0 f& N" h N1 S
[ 15 6 17 71 50 37 0 6 32 2 1 9]2 T4 }" Q& E, `' J& Q
[ 11 1 6 151 5 42 0 8 16 0 0 20]]
- X1 y k0 K5 J# D
+ ~/ c6 O6 S( L' q6 K第一部分是混淆矩阵。要理解它的具体含义,您首先需要了解所用的标签。在本示例中,所用的标签是 “silence”、“unknown”、“yes”、“no”、“up”、“down”、“left”、“right”、“on”、“off”、“stop” 和 “go”。每列代表一组被模型预测为每个标签的样本,因此第一列代表预测为无声的所有音频片段,第二列代表预测为未知字词的所有音频片段,第三列代表预测为 “yes” 的所有音频片段,依此类推。' b S( M/ I( B! [/ B3 J0 w3 y
" \0 R9 T3 A6 v P8 c每行表示音频片段实际归入的标签。第一行是归入无声的所有音频片段,第二行是归入未知字词的所有音频片段,第三行是归入 “yes” 的所有音频片段,依此类推。7 t: ?+ Y$ G! Z7 s
0 Q: \& G0 b5 j: h此矩阵比单个准确率得分更加有用,因为它可以很好地总结网络出现的错误。在此示例中,您可以发现,除了第一个数值以外,第一行中的所有条目均为 0。因为第一行表示所有实际无声的音频片段,这意味着所有音频片段都未被错误地标记为字词,因此我们未得出任何有关无声的假负例。这表示网络已经可以很好地区分无声和字词。
! y) U$ F9 a% E8 R% d
, _" ]2 c1 n" Q! E. [& ?6 ^0 C如果我们往下看,就会发现第一列有大量非零值。该列表示预测为无声的所有音频片段,因此第一个单元格外的正数是错误的预测。这表示一些实际是语音字词的音频片段被预测为无声,因此我们得出了很多假正例。
3 D" l# R/ H! K3 d# J* o7 Y( }3 e/ |5 P6 S" ]& j5 \1 C
完美的模型会生成混淆矩阵,除了穿过中心的对角线上的条目以外,所有其他条目都为 0。发现偏离这个模式的地方有助于您了解模型最容易在哪些方面混淆;确定问题所在后,您就可以通过添加更多数据或清理类别来解决这些问题。, @) ]: X3 U i! \5 {9 E
' B o6 S: ~1 h2 s3 \" s9 B0 B; P- @/ D) _7 X0 ?' b2 D
验证7 p) A3 C" P* C, f
在混淆矩阵之后,您应看到如下所示的行:
2 ?6 R0 m, U: {& F6 bI0730 16:57:38.073777 55030 train.py:245] Step 400: Validation accuracy = 26.3% (N=3093)" {$ T g& ]1 X; p
( h0 `. p! q8 \$ [1 g: k6 X. C最好将数据集分成三个类别。最大的子集(本示例中为约 80% 的数据)用于训练网络,较小的子集(本示例中为约 10% 的数据,称为 “验证” 集)预留下来以评估训练期间的准确率,另一个子集(剩下的 10%,称为 “测试” 集)用来评估训练完成后的准确率。# R/ ^5 J) `" O1 |
- X. b; R3 O. F; p
之所以采用这种拆分方法,是因为始终存在这样一种风险:网络在训练期间开始记忆输入。通过将验证集分离开来,可以确保模型能够处理它之前从未见过的数据。测试集是一种额外的保护措施,可以确保您不仅以适合训练集和验证集的方式调整模型,而且使模型能够泛化到范围更广的输入。/ y+ [* g7 R( e& t0 X
; Y$ ?' d3 A$ N+ T" a# B; Y6 n
训练脚本会自动将数据集分为这三个类别,上面的日志行会显示在验证集上运行时模型的准确率。理想情况下,该准确率应该相当接近训练准确率。如果训练准确率有所提高但验证准确率没有,则表明存在过拟合,模型只学习了有关训练音频片段的信息,而没有学习能泛化的更广泛模式。7 R5 O8 M& i6 W, P
: R- ]0 v4 |3 J! z
# v* V! D) X" ~7 j9 n8 }$ }Tensorboard8 _5 b& @ B# F+ ?8 V- P9 g, ]- ^0 ~
使用 Tensorboard 可以很好地观察训练进度。默认情况下,脚本会将事件保存到 /tmp/retrain_logs,您可以通过运行以下命令加载这些事件:
& `4 A5 {3 ^, d* H$ w9 }8 i! E7 R7 Rtensorboard --logdir /tmp/retrain_logs, [1 N0 s+ }* h0 D) ~+ N7 s& m& J
7 ]+ b, g3 |) |& h然后,在浏览器中转到 http://localhost:6006,您将看到显示模型进度的图表。
) ?! C m) T# l3 i" T L% u4 X( G4 @0 I j8 Q2 T9 }
|
|