hello,吴恩达老师深度学习的
最后一课来啦,参考博客为何宽大佬的https://blog.csdn.net/u013733326/article/details/97619187
把自己复现代码遇到的问题记录一下
问题一:在代码
出现错误TypeError: Calling ‘.seed()’ on instances is deprecated. Use the class method ‘Faker.seed()’ instead.
解决办法:将faker版本降低到2.0.0,并重启jupyter notebook。附上pip镜像代码:
pip3 install -i https://pypi.doubanio.com/simple/ faker==2.0.0
2.触发词检测
import numpy as np
from pydub import AudioSegment
import random
import sys
import io
import os
import glob
import IPython
import sys
sys.path.append('E:/360MoveData/Users/Administrator/Desktop/Course 5 - 3/Trigger word detection')
from td_utils import *
%matplotlib inline
IPython.display.Audio("E:/360MoveData/Users/Administrator/Desktop/Course 5 - 3/Trigger word detection/raw_data/activates/1.wav")
IPython.display.Audio("E:/360MoveData/Users/Administrator/Desktop/Course 5 - 3/Trigger word detection/audio_examples/example_train.wav")
x = graph_spectrogram("E:/360MoveData/Users/Administrator/Desktop/Course 5 - 3/Trigger word detection/audio_examples/example_train.wav")
结果:
_, data = wavfile.read("E:/360MoveData/Users/Administrator/Desktop/Course 5 - 3/Trigger word detection/audio_examples/example_train.wav")
print("Time steps in audio recording before spectrogram", data[:,0].shape)
print("Time steps in input after spectrogram", x.shape)
结果:
现在,您可以定义:
Tx = 5511 # 从频谱图输入到模型的时间步数
n_freq = 101 # 在频谱图的每个时间步输入模型的频率数
请注意,即使我们的默认训练示例长度为10秒,也可以将10秒的时间离散化为不同的值。你已经知道 441000(原始音频)和 5511(频谱图)。在前一种情况下,每一步代表 10 / 441000 ≈ 0.000023 10/441000 \approx 0.00002310/441000≈0.000023 秒。在第二种情况下,每个步骤代表 10 / 5511 ≈ 0.0018 10/5511 \approx 0.001810/5511≈0.0018 秒。
对于10秒的音频,您将在此作业中看到的键值为:
- 441000 441000441000 (原始音频)
- 5511 = T x 5511 = T_x5511=Tx (频谱图输出和神经网络输入的维数).
- 10000 1000010000 (由
pydub
模块用来合成音频) - 1375 = T y 1375 = T_y1375=Ty (您将构建的GRU输出中的步骤数).
请注意,这些表示中的每一个都恰好对应于10秒的时间。只是他们在不同程度上将它们离散化。所有这些都是超参数,可以更改(除了 441000,这是麦克风的性能)。我们选择了语音系统标准范围内的值。
考虑上面 T y = 1375 T_y = 1375Ty=1375 的值,这意味着对于模型的输出,我们将10秒离散化为 1375 个时间间隔(每一个长度 10 / 1375 ≈ 0.0072 10/1375 \approx 0.007210/1375≈0.0072s) 并且尝试预测每个区间是否有人最近说完 “activate” 。
还要考虑上面的 10000 的值。这相当于将10秒剪辑离散为 10/10000 = 0.001秒间隔。0.001秒也称为1毫秒,或者1ms。因此,当我们说我们按照1ms间隔进行离散化时,这意味着我们使用了10,000步。
Ty = 1375 # 我们模型输出中的时间步数
2.1.3 - 生成单个训练样例
由于语音数据难以获取和标记,您将使用正例,负例和背景的音频剪辑合成您的训练数据。录制大量10秒音频片段并且里面随机的有 “activates” 是很慢的。相反,很容易录制很多正例和负例单词,背景噪音(或者从网上免费的下载背景噪音)
要合成单个训练示例,您将:
- 选择一个随机的10秒背景音频剪辑。
- 随机将 0-4 段正例(“activate”)的音频剪辑插入到这个10秒音频剪辑中。
- 随机将 0-2 段负例(不是 “activate”)的音频剪辑插入到这个10秒音频剪辑中。
因为您已将 “activate” 一词合成到背景剪辑中,所以您确切地知道在10秒剪辑中 “activate” 出现的时间。稍后您会看到,这样也可以更容易地生成标签y 〈 t 〉 y^{\langle t \rangle}y〈t〉。
您将使用pydub包来操纵音频。Pydub将原始音频文件转换为Pydub数据结构列表(这里不需要了解详细信息过程)。Pydub使用1ms作为离散化间隔(1ms是1毫秒= 1/1000秒),这就是为什么10秒剪辑总是用10,000步表示的原因。
# 使用pydub加载音频片段
activates, negatives, backgrounds = load_raw_audio()
print("background len: " + str(len(backgrounds[0]))) # 应该是10,000,因为它是一个10秒的剪辑
print("activate[0] len: " + str(len(activates[0]))) # 也许大约1000,因为 "activate" 音频剪辑通常大约1秒(但变化很大)
print("activate[1] len: " + str(len(activates[1]))) # 不同的 "activate" 剪辑可以具有不同的长度
这里注意一下,如果路径没放在默认地址的话,请到![](https://i-blog.csdnimg.cn/blog_migrate/b54444254a6331f7c69c214913138be3.png)
修改下路径即可。
执行结果:
background len: 10000
activate[0] len: 721
activate[1] len: 731</code></span>
def get_random_time_segment(segment_ms):
"""
获取 10,000 ms音频剪辑中时间长为 segment_ms 的随机时间段。
参数:
segment_ms -- 音频片段的持续时间,以毫秒为单位("ms" 代表 "毫秒")
返回:
segment_time -- 以ms为单位的元组(segment_start,segment_end)
"""
segment_start = np.random.randint(low=0, high=10000-segment_ms) # 确保段不会超过10秒背景
segment_end = segment_start + segment_ms - 1
return (segment_start, segment_end)
我跳过了一部分代码
2.1.4 - 完整的训练集
您现在已经实现了生成单个训练示例所需的代码。我们使用此过程生成一个大型训练集。为了节省时间,我们已经生成了一组训练样例。
# 加载预处理的训练样例
X = np.load("E:/360MoveData/Users/Administrator/Desktop/Course 5 - 3/Trigger word detection/XY_train/X.npy")
Y = np.load("E:/360MoveData/Users/Administrator/Desktop/Course 5 - 3/Trigger word detection/XY_train/Y.npy")
- 2.1.5 - 开发集
为了测试我们的模型,我们记录了一个包含25个示例的开发集。虽然我们的训练数据是合成的,但我们希望使用与实际输入相同的分布来创建开发集。因此,我们录制了25个10秒钟的人们说 “activate” 和其他随机单词的音频剪辑,并用手标记。这遵循课程3中描述的原则,即我们创建的开发集应该尽可能与测试集分布相似;这就是我们的开发集使用真实音频而非合成音频的原因。
# 加载预处理开发集示例
X_dev = np.load("E:/360MoveData/Users/Administrator/Desktop/Course 5 - 3/Trigger word detection/XY_dev/X_dev.npy")
Y_dev = np.load("E:/360MoveData/Users/Administrator/Desktop/Course 5 - 3/Trigger word detection/XY_dev/Y_dev.npy")
这里何宽大佬给的文件有一部分是压缩的,解压后即可
2.2 - 模型
现在您已经构建了一个数据集,让我们编写并训练一个触发词检测模型!
该模型将使用1-D卷积层,GRU层和全连接层。让我们加载允许您在Keras中使用这些图层的包。
这可能需要一分钟才能加载。
from keras.callbacks import ModelCheckpoint
from keras.models import Model, load_model, Sequential
from keras.layers import Dense, Activation, Dropout, Input, Masking, TimeDistributed, LSTM, Conv1D
from keras.layers import GRU, Bidirectional, BatchNormalization, Reshape
from keras.optimizers import Adam
2.2.1 - 建立模型
这是我们将使用的架构。
花一些时间来查看模型,看看它是否有意义。
# GRADED FUNCTION: model
def model(input_shape):
"""
用 Keras 创建模型的图 Function creating the model's graph in Keras.
参数:
input_shape -- 模型输入数据的维度(使用Keras约定)
返回:
model -- Keras 模型实例
"""
X_input = Input(shape = input_shape)
# 第一步:卷积层 (≈4 lines)
X = Conv1D(196, 15, strides=4)(X_input) # CONV1D
X = BatchNormalization()(X) # Batch normalization 批量标准化
X = Activation('relu')(X) # ReLu activation ReLu 激活
X = Dropout(0.8)(X) # dropout (use 0.8)
# 第二步:第一个 GRU 层 (≈4 lines)
X = GRU(units = 128, return_sequences=True)(X) # GRU (使用128个单元并返回序列)
X = Dropout(0.8)(X) # dropout (use 0.8)
X = BatchNormalization()(X) # Batch normalization 批量标准化
# 第三步: 第二个 GRU 层 (≈4 lines)
X = GRU(units = 128, return_sequences=True)(X) # GRU (使用128个单元并返回序列)
X = Dropout(0.8)(X) # dropout (use 0.8)
X = BatchNormalization()(X) # Batch normalization 批量标准化
X = Dropout(0.8)(X) # dropout (use 0.8)
# 第四步: 时间分布全连接层 (≈1 line)
X = TimeDistributed(Dense(1, activation = "sigmoid"))(X) # time distributed (sigmoid)
model = Model(inputs = X_input, outputs = X)
return model
model = model(input_shape = (Tx, n_freq))
model.summary()
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) (None, 5511, 101) 0
_________________________________________________________________
conv1d_1 (Conv1D) (None, 1375, 196) 297136
_________________________________________________________________
batch_normalization_1 (Batch (None, 1375, 196) 784
_________________________________________________________________
activation_1 (Activation) (None, 1375, 196) 0
_________________________________________________________________
dropout_1 (Dropout) (None, 1375, 196) 0
_________________________________________________________________
gru_1 (GRU) (None, 1375, 128) 124800
_________________________________________________________________
dropout_2 (Dropout) (None, 1375, 128) 0
_________________________________________________________________
batch_normalization_2 (Batch (None, 1375, 128) 512
_________________________________________________________________
gru_2 (GRU) (None, 1375, 128) 98688
_________________________________________________________________
dropout_3 (Dropout) (None, 1375, 128) 0
_________________________________________________________________
batch_normalization_3 (Batch (None, 1375, 128) 512
_________________________________________________________________
dropout_4 (Dropout) (None, 1375, 128) 0
_________________________________________________________________
time_distributed_1 (TimeDist (None, 1375, 1) 129
=================================================================
Total params: 522,561
Trainable params: 521,657
Non-trainable params: 904
____________________________
网络的输出维度是 (None, 1375, 1) 而输入是 (None, 5511, 101)。Conv1D 将步数从 5511 减少到了 1375。
2.2.2 - 训练模型
触发字检测训练需要花费很长时间。为了节省时间,我们已经使用您在上面构建的架构在GPU上训练了大约3个小时的模型,以及大约4000个示例的大型训练集。
让我们加载模型。
model = load_model('E:/360MoveData/Users/Administrator/Desktop/Course 5 - 3/Trigger word detection/models/tr_model.h5')
您可以使用Adam优化器和二进制交叉熵损失进一步训练模型,如下所示。这将很快运行,因为我们仅训练迭代一次,并且是一个包含26个示例的小训练集。
opt = Adam(lr=0.0001, beta_1=0.9, beta_2=0.999, decay=0.01)
model.compile(loss='binary_crossentropy', optimizer=opt, metrics=["accuracy"])
model.fit(X, Y, batch_size = 5, epochs=1)
Epoch 1/1
26/26 [==============================] - ETA: 19s - loss: 0.0811 - accuracy: 0.973 - ETA: 10s - loss: 0.0503 - accuracy: 0.985 - ETA: 6s - loss: 0.0495 - accuracy: 0.985 - ETA: 3s - loss: 0.0508 - accuracy: 0.98 - ETA: 0s - loss: 0.0460 - accuracy: 0.98 - 14s 542ms/step - loss: 0.0481 - accuracy: 0.9844
<keras.callbacks.callbacks.History at 0x16b7b492b70>
2.2.3 - 测试模型
最后,让我们看看您的模型在开发集上的表现。
loss, acc = model.evaluate(X_dev, Y_dev)
print("Dev set accuracy = ", acc)