|
简单的音频识别8 p1 M9 [* ^2 A
+ V( L; j) ]( I. v
' Y8 Z+ J5 A: W今天的文章将向您展示如何构建可以识别 10 个不同字词的基本语音识别网络。需要注意的是,真正的语音和音频识别系统要复杂得多,但就像用于识别图像的 MNIST,这个基本语音识别网络能够帮助您基本了解所涉及的技术。学完本教程后,您将获得一个模型,该模型会尝试将时长为 1 秒的音频片段归类为无声、未知字词、“yes”、“no”、“up”、“down”、“left”、“right”、“on”、“off”、“stop” 或 “go”。您还可以在 Android 应用中运行该模型。
! j! \ Y2 p, Q) m+ ?3 k
" p" @8 [2 G) o2 P9 T) q' W4 G2 Y
准备3 U( g) I1 H/ w! t: R% [
您应确保安装了 TensorFlow;此外,由于脚本会下载超过 1GB 的训练数据,因此您需要确保计算机拥有稳定的互联网连接和足够的可用空间。训练过程可能需要几个小时,因此请确保您的计算机可以完成这么长时间的训练操作。
% ]; Q8 ]/ n( D+ e4 a! L/ F, w* [ V5 k k$ b8 A! u4 @6 {
7 I; T$ J+ {/ y& D; p训练2 W9 `9 Z5 [7 h/ U
要开始训练过程,请转到 TensorFlow 源代码树,然后运行以下脚本:
1 t' B9 p% t) [! S4 vpython tensorflow/examples/speech_commands/train.py
# q/ s V$ [1 G! h, f& S
' k3 e& P" C+ Y3 K" K5 [该脚本会先下载语音指令数据集,其中包含超过 105000 个 WAVE 音频文件,音频内容是有人说出 30 个不同的字词。这些数据由 Google 收集,并依据 CC BY 许可发布,您可以提交 5 分钟自己的录音来帮助改进该数据。归档数据超过 2GB,因此这部分过程可能需要一段时间,但您应该可以看到进度日志;下载完成后,您无需再次执行此步骤。如需详细了解该数据集,请参阅 https://arxiv.org/abs/1804.03209
6 Z/ U2 k, l. H; B/ r
$ B* T# S# H# m d+ L4 G, N下载完成后,您将看到如下日志信息:! Z8 l2 o* X, x* Q: v- z$ ?
I0730 16:53:44.766740 55030 train.py:176] Training from step: 17 d( a5 Q! u- u7 G( j2 `
I0730 16:53:47.289078 55030 train.py:217] Step #1: rate 0.001000, accuracy 7.0%, cross entropy 2.611571
8 A8 R3 E- b' N e- T, h& q! |" a
, B$ G; T' N9 z3 X' x) t这表明初始化过程已经完成,训练循环已经开始。您将看到该日志输出每个训练步的信息。下面详细说明了该日志信息的含义:
Z8 h8 |+ B8 I. S# f/ ]
9 D/ j( U/ _8 T: s2 N7 R3 u" yStep #1 表明正在进行训练循环的第一步。在此示例中总共有 18000 个训练步,您可以查看步编号来了解还有多少步即可完成。8 U3 Q( o1 H7 J& U
, n' `. |5 o. w2 y2 a% v7 U
rate 0.001000 是控制网络权重更新速度的学习速率。在训练的早期阶段,它是一个相对较大的数字 (0.001),但在训练周期的后期会减少到原来的十分之一,即 0.0001。. P- W2 h9 U$ M) `; `. E& R& @
6 p! X; Q! F G0 y% R: X
accuracy 7.0% 表示模型在本训练步中预测正确的类别数量。该值通常会有较大的波动,但应该会随着训练的进行总体有所提高。该模型会输出一个数字数组,每个标签对应一个数字,每个数字都表示输入可能归入该类别的预测概率。可通过选择得分最高的条目来挑选预测标签。得分始终介于 0 到 1 之间,值越高表示结果的置信度越高。$ ]' v$ r7 a" H) I! {* w* T! C) s1 Z
3 Z2 V. ?/ g2 e! r. pcross entropy 2.611571 是用于指导训练过程的损失函数的结果。它是一个得分,通过将当前训练运行的得分向量与正确标签进行比较计算而出,该得分应在训练期间呈下滑趋势。
) Z9 A5 u6 `1 c: E* |9 | l1 X- c' v) ^" \& i# k# w
经过 100 步之后,您应看到如下所示的行:
! ]* {; S) n" b% k9 J$ VI0730 16:54:41.813438 55030 train.py:252] Saving to "/tmp/speech_commands_train/conv.ckpt-100"
1 x. Z8 h2 Z( F9 P8 O3 S% l9 l& S/ G- C& o3 q" w" `( w
此行会将当前的训练权重保存到检查点文件中。如果训练脚本中断了,您可以查找上次保存的检查点,然后将 --start_checkpoint=/tmp/speech_commands_train/conv.ckpt-100 用作命令行参数重启该脚本,以便从该点开始。
$ f! _* T. C! e& Z7 e! Y8 `
$ d; T! c; E: O3 b2 Z' W1 H% Q4 H h& e* P( p( |8 o9 \, s
混淆矩阵
6 }3 S+ v& a1 p8 k% ?% n9 e# Q经过 400 步之后,您会看到以下日志信息: `, ~9 d9 T8 {: A+ T! Y
I0730 16:57:38.073667 55030 train.py:243] Confusion Matrix:6 w) d* Y* j& C. J
[[258 0 0 0 0 0 0 0 0 0 0 0]
+ p& d2 g: y w& J; Y: S6 L, S [ 7 6 26 94 7 49 1 15 40 2 0 11]
$ f; }+ U0 D5 S" L [ 10 1 107 80 13 22 0 13 10 1 0 4]8 B+ f5 o6 |: P" t z
[ 1 3 16 163 6 48 0 5 10 1 0 17]% k5 | g, P1 x5 _/ N
[ 15 1 17 114 55 13 0 9 22 5 0 9]6 V) _6 J8 W/ [, L2 N
[ 1 1 6 97 3 87 1 12 46 0 0 10]0 K5 h+ ]9 p T
[ 8 6 86 84 13 24 1 9 9 1 0 6]; E8 s# b4 _: h) W3 o% z
[ 9 3 32 112 9 26 1 36 19 0 0 9]
1 l6 ~1 ?1 ^. B( E [ 8 2 12 94 9 52 0 6 72 0 0 2]; Y! {. b' R. T3 Z& Z. I( q O
[ 16 1 39 74 29 42 0 6 37 9 0 3]
5 b: ?& Z: M; w3 Q' _ [ 15 6 17 71 50 37 0 6 32 2 1 9]
5 {; x# u" f8 t% M- ^% z1 Q [ 11 1 6 151 5 42 0 8 16 0 0 20]]
% w \. V; u2 ~4 {1 Y1 ?7 o4 _" V$ @
0 a" s3 D6 E' A: q7 r0 U第一部分是混淆矩阵。要理解它的具体含义,您首先需要了解所用的标签。在本示例中,所用的标签是 “silence”、“unknown”、“yes”、“no”、“up”、“down”、“left”、“right”、“on”、“off”、“stop” 和 “go”。每列代表一组被模型预测为每个标签的样本,因此第一列代表预测为无声的所有音频片段,第二列代表预测为未知字词的所有音频片段,第三列代表预测为 “yes” 的所有音频片段,依此类推。4 J! M6 h4 T# o" x9 x( i2 K8 h* \) |. m
" z7 }3 t0 k, C每行表示音频片段实际归入的标签。第一行是归入无声的所有音频片段,第二行是归入未知字词的所有音频片段,第三行是归入 “yes” 的所有音频片段,依此类推。
0 T$ e% P, b/ H( [
2 v" x: o3 W7 G/ s# l此矩阵比单个准确率得分更加有用,因为它可以很好地总结网络出现的错误。在此示例中,您可以发现,除了第一个数值以外,第一行中的所有条目均为 0。因为第一行表示所有实际无声的音频片段,这意味着所有音频片段都未被错误地标记为字词,因此我们未得出任何有关无声的假负例。这表示网络已经可以很好地区分无声和字词。1 z; u; D. s6 N( W7 ?8 d6 n
6 f2 b+ F* m3 v8 T: s! F& m/ r
如果我们往下看,就会发现第一列有大量非零值。该列表示预测为无声的所有音频片段,因此第一个单元格外的正数是错误的预测。这表示一些实际是语音字词的音频片段被预测为无声,因此我们得出了很多假正例。1 B* f# v' W: y/ @& C6 Z: P: G5 y4 S
7 Z/ T" ?4 D, i) u" {6 t6 A
完美的模型会生成混淆矩阵,除了穿过中心的对角线上的条目以外,所有其他条目都为 0。发现偏离这个模式的地方有助于您了解模型最容易在哪些方面混淆;确定问题所在后,您就可以通过添加更多数据或清理类别来解决这些问题。
! } }; v! b4 _7 }( o4 G5 m2 T* {4 u8 w$ @/ Z4 N
1 Z, w, @7 M2 [7 W验证- F# O/ Z/ c# R, r8 Y0 G
在混淆矩阵之后,您应看到如下所示的行:
" E* b8 \. A$ e! a! II0730 16:57:38.073777 55030 train.py:245] Step 400: Validation accuracy = 26.3% (N=3093); b( e! ?. c: {
6 ?6 k0 Q$ A, {/ s3 _) Z最好将数据集分成三个类别。最大的子集(本示例中为约 80% 的数据)用于训练网络,较小的子集(本示例中为约 10% 的数据,称为 “验证” 集)预留下来以评估训练期间的准确率,另一个子集(剩下的 10%,称为 “测试” 集)用来评估训练完成后的准确率。
/ `0 k6 }! w7 l7 k+ ~2 Q
# B/ w, F$ B9 f3 `# r2 ?, V之所以采用这种拆分方法,是因为始终存在这样一种风险:网络在训练期间开始记忆输入。通过将验证集分离开来,可以确保模型能够处理它之前从未见过的数据。测试集是一种额外的保护措施,可以确保您不仅以适合训练集和验证集的方式调整模型,而且使模型能够泛化到范围更广的输入。
! t/ R$ Y: B. B/ B1 O1 A# p' d
l5 w3 `% i, s+ Q! T8 v' e训练脚本会自动将数据集分为这三个类别,上面的日志行会显示在验证集上运行时模型的准确率。理想情况下,该准确率应该相当接近训练准确率。如果训练准确率有所提高但验证准确率没有,则表明存在过拟合,模型只学习了有关训练音频片段的信息,而没有学习能泛化的更广泛模式。4 u$ t5 F1 \$ _9 K
7 A% e6 L6 @' N* r
) @/ t. f& ]: U+ A, n
Tensorboard9 w$ a0 }- }0 ~$ c4 s
使用 Tensorboard 可以很好地观察训练进度。默认情况下,脚本会将事件保存到 /tmp/retrain_logs,您可以通过运行以下命令加载这些事件:
4 m: h* p! t7 `1 o( P8 K6 rtensorboard --logdir /tmp/retrain_logs+ K8 w) g- D* J# b$ S
/ ]; Q( ]% w; P然后,在浏览器中转到 http://localhost:6006,您将看到显示模型进度的图表。
# O5 N: a% ^$ P/ w3 J; [0 \3 a) F( z, t1 s& ]
|
|