|
简单的音频识别' M. q4 ~& v9 R: W6 b! S& h
* k2 ^5 P, A2 W; v& A3 f
. x* L1 a W" L. E$ @" R
今天的文章将向您展示如何构建可以识别 10 个不同字词的基本语音识别网络。需要注意的是,真正的语音和音频识别系统要复杂得多,但就像用于识别图像的 MNIST,这个基本语音识别网络能够帮助您基本了解所涉及的技术。学完本教程后,您将获得一个模型,该模型会尝试将时长为 1 秒的音频片段归类为无声、未知字词、“yes”、“no”、“up”、“down”、“left”、“right”、“on”、“off”、“stop” 或 “go”。您还可以在 Android 应用中运行该模型。1 s+ Z* y2 [$ h% l! Y( G
2 n" |6 R9 @& g: Y
# K. r8 ~; U4 [: Q. t, _! c准备! G5 {/ z Q- | R4 _% I( ~7 v
您应确保安装了 TensorFlow;此外,由于脚本会下载超过 1GB 的训练数据,因此您需要确保计算机拥有稳定的互联网连接和足够的可用空间。训练过程可能需要几个小时,因此请确保您的计算机可以完成这么长时间的训练操作。7 i: }* s: Q3 P# w) x6 _- S
$ H `1 {, l: S Y0 {* b
3 q' `+ ^- p9 x, B, X: I
训练
! u$ b s/ v* S% B% ~2 O要开始训练过程,请转到 TensorFlow 源代码树,然后运行以下脚本:
( F* Q8 |0 B1 q hpython tensorflow/examples/speech_commands/train.py4 J8 [9 ~# @( O' V! R
% F: y" i7 |7 l% a" h1 M
该脚本会先下载语音指令数据集,其中包含超过 105000 个 WAVE 音频文件,音频内容是有人说出 30 个不同的字词。这些数据由 Google 收集,并依据 CC BY 许可发布,您可以提交 5 分钟自己的录音来帮助改进该数据。归档数据超过 2GB,因此这部分过程可能需要一段时间,但您应该可以看到进度日志;下载完成后,您无需再次执行此步骤。如需详细了解该数据集,请参阅 https://arxiv.org/abs/1804.032093 C" y* s K! `% ]! a
& s7 o$ R3 D6 y! F; v z) M下载完成后,您将看到如下日志信息:4 I* |7 _1 n2 \ |3 t( w2 s+ m
I0730 16:53:44.766740 55030 train.py:176] Training from step: 1) C1 L( g* D' \8 e
I0730 16:53:47.289078 55030 train.py:217] Step #1: rate 0.001000, accuracy 7.0%, cross entropy 2.611571/ d9 m6 c2 T6 Q, ?& o& Z( R
7 x4 n; w" z" y; {- R. { k这表明初始化过程已经完成,训练循环已经开始。您将看到该日志输出每个训练步的信息。下面详细说明了该日志信息的含义:0 h7 e+ j' Z# e T7 {, O
2 L, l/ B! |5 @- @1 @Step #1 表明正在进行训练循环的第一步。在此示例中总共有 18000 个训练步,您可以查看步编号来了解还有多少步即可完成。6 w& M1 t" B# s$ L( ~' E( W! _
6 I8 B1 X' {1 }rate 0.001000 是控制网络权重更新速度的学习速率。在训练的早期阶段,它是一个相对较大的数字 (0.001),但在训练周期的后期会减少到原来的十分之一,即 0.0001。
$ ]2 `+ f0 d. ^9 t
3 h# n' s' p4 h! s" x9 Saccuracy 7.0% 表示模型在本训练步中预测正确的类别数量。该值通常会有较大的波动,但应该会随着训练的进行总体有所提高。该模型会输出一个数字数组,每个标签对应一个数字,每个数字都表示输入可能归入该类别的预测概率。可通过选择得分最高的条目来挑选预测标签。得分始终介于 0 到 1 之间,值越高表示结果的置信度越高。; w) P$ M# ^& ?8 b
$ _! |, m7 z7 Y2 M
cross entropy 2.611571 是用于指导训练过程的损失函数的结果。它是一个得分,通过将当前训练运行的得分向量与正确标签进行比较计算而出,该得分应在训练期间呈下滑趋势。) J+ ~+ j' \( p$ W$ P: U
8 ]+ ?/ p& w- ?. q0 @4 S
经过 100 步之后,您应看到如下所示的行:& [, P! }! G1 B, U4 L( J2 X E
I0730 16:54:41.813438 55030 train.py:252] Saving to "/tmp/speech_commands_train/conv.ckpt-100"
' r! B5 E5 f. N+ p- X" O# V6 e% O2 ^7 R( j1 F' m+ s
此行会将当前的训练权重保存到检查点文件中。如果训练脚本中断了,您可以查找上次保存的检查点,然后将 --start_checkpoint=/tmp/speech_commands_train/conv.ckpt-100 用作命令行参数重启该脚本,以便从该点开始。
3 y; Q; H- W. T8 E# ~8 }" ~4 `2 Z- Z' G+ s( n; u
3 g% I7 o5 e: e, G# z混淆矩阵
4 p6 h' E2 m: Y3 i4 y经过 400 步之后,您会看到以下日志信息:% U) i8 I! W- K% V/ U
I0730 16:57:38.073667 55030 train.py:243] Confusion Matrix:1 R: c3 r3 B6 e
[[258 0 0 0 0 0 0 0 0 0 0 0]7 ^* }- x" s, C0 w( M
[ 7 6 26 94 7 49 1 15 40 2 0 11]8 M4 D; n X, t: a
[ 10 1 107 80 13 22 0 13 10 1 0 4]' U* I9 ~- @6 y6 r. t% ^
[ 1 3 16 163 6 48 0 5 10 1 0 17]) [5 w5 A) Y8 g! V+ G3 P
[ 15 1 17 114 55 13 0 9 22 5 0 9]
7 l l0 s) E X# S7 L [ 1 1 6 97 3 87 1 12 46 0 0 10], l' |' V, \: {! P
[ 8 6 86 84 13 24 1 9 9 1 0 6]1 Y0 y/ z' w8 a# ]2 ^. d
[ 9 3 32 112 9 26 1 36 19 0 0 9]
# h5 V5 f# e/ G \ m/ ^! a4 g [ 8 2 12 94 9 52 0 6 72 0 0 2]8 {4 b: Y- i% n* K5 k
[ 16 1 39 74 29 42 0 6 37 9 0 3]% X9 \: e: a5 b. S4 u) s+ \
[ 15 6 17 71 50 37 0 6 32 2 1 9]! c3 J* |, F- k
[ 11 1 6 151 5 42 0 8 16 0 0 20]]
: R( ?8 U( r _" P& Y% _
9 B8 U* x+ A$ G0 w' N$ r第一部分是混淆矩阵。要理解它的具体含义,您首先需要了解所用的标签。在本示例中,所用的标签是 “silence”、“unknown”、“yes”、“no”、“up”、“down”、“left”、“right”、“on”、“off”、“stop” 和 “go”。每列代表一组被模型预测为每个标签的样本,因此第一列代表预测为无声的所有音频片段,第二列代表预测为未知字词的所有音频片段,第三列代表预测为 “yes” 的所有音频片段,依此类推。
: B1 j9 e$ [2 D- Q/ Y$ Y, H9 C8 e' s9 H: |5 z7 [# x K# K" N8 I
每行表示音频片段实际归入的标签。第一行是归入无声的所有音频片段,第二行是归入未知字词的所有音频片段,第三行是归入 “yes” 的所有音频片段,依此类推。$ D e! w" m5 Z4 p0 Y& w) A7 S3 }
4 K2 h: h) t2 j+ @
此矩阵比单个准确率得分更加有用,因为它可以很好地总结网络出现的错误。在此示例中,您可以发现,除了第一个数值以外,第一行中的所有条目均为 0。因为第一行表示所有实际无声的音频片段,这意味着所有音频片段都未被错误地标记为字词,因此我们未得出任何有关无声的假负例。这表示网络已经可以很好地区分无声和字词。
B" K8 f% j+ s/ g7 `! J9 u& _# H+ w- ^
如果我们往下看,就会发现第一列有大量非零值。该列表示预测为无声的所有音频片段,因此第一个单元格外的正数是错误的预测。这表示一些实际是语音字词的音频片段被预测为无声,因此我们得出了很多假正例。; Q+ ~2 K6 G. x! _. M! Q ^
1 {* Q2 ?+ b( R- C1 D0 V
完美的模型会生成混淆矩阵,除了穿过中心的对角线上的条目以外,所有其他条目都为 0。发现偏离这个模式的地方有助于您了解模型最容易在哪些方面混淆;确定问题所在后,您就可以通过添加更多数据或清理类别来解决这些问题。- ]0 l0 z1 \, ]( T6 n V
& p2 H# Z4 T( w5 f2 P( g* ~8 D6 H- q$ b" p2 a) x
验证
) t6 _$ I, B" x3 _/ c/ p1 x5 K3 `在混淆矩阵之后,您应看到如下所示的行:8 r8 M; r5 X1 {1 l
I0730 16:57:38.073777 55030 train.py:245] Step 400: Validation accuracy = 26.3% (N=3093)
) T- H# g+ j8 Y
: u8 [* ]" p2 H5 i; Q) t最好将数据集分成三个类别。最大的子集(本示例中为约 80% 的数据)用于训练网络,较小的子集(本示例中为约 10% 的数据,称为 “验证” 集)预留下来以评估训练期间的准确率,另一个子集(剩下的 10%,称为 “测试” 集)用来评估训练完成后的准确率。
+ P; E* H4 V7 J. L% o/ P5 h5 N6 v
5 G0 K( R# D* `之所以采用这种拆分方法,是因为始终存在这样一种风险:网络在训练期间开始记忆输入。通过将验证集分离开来,可以确保模型能够处理它之前从未见过的数据。测试集是一种额外的保护措施,可以确保您不仅以适合训练集和验证集的方式调整模型,而且使模型能够泛化到范围更广的输入。7 f' ?) A1 R! H1 L4 f
. y9 S+ p# p3 t% x1 A9 z
训练脚本会自动将数据集分为这三个类别,上面的日志行会显示在验证集上运行时模型的准确率。理想情况下,该准确率应该相当接近训练准确率。如果训练准确率有所提高但验证准确率没有,则表明存在过拟合,模型只学习了有关训练音频片段的信息,而没有学习能泛化的更广泛模式。. K! n+ h3 {5 [ K
) {- G) Q1 t4 P& A, O7 t, `% ^) D$ {6 l$ L" ]- k
Tensorboard
: W% C. _# j* e+ Y7 I5 I$ o0 |# n9 i使用 Tensorboard 可以很好地观察训练进度。默认情况下,脚本会将事件保存到 /tmp/retrain_logs,您可以通过运行以下命令加载这些事件:
* I/ ?2 P- O! Ttensorboard --logdir /tmp/retrain_logs
+ @' x: y) i5 [: o' U! o5 [5 B) k' r
然后,在浏览器中转到 http://localhost:6006,您将看到显示模型进度的图表。
, h% C3 ^7 x7 @) H6 ]2 h% |* B$ r: |6 B/ y( B1 Q+ U( V4 p* q
|
|