AI实战:用 TensorFlow 识别数字 0-9

摘要

本项目的目标是使用深度学习来检测数字 0-9 的语音。

我们将利用深度学习技术,把语音文件转译为文本数据,例如把英语 three 的发音转译为文本 “three”。

我们将使用 TensorFlow/Keras 来创建模型、训练模型,再使用测试数据评估它的性能。

运行环境

因为 AI 需要在 GPU 上运算,而一般的 PC 是没有 GPU 的,所以我们要借用云端的算力。

我选择的云端算力平台是 OpenBayes,你使用下面的链接进行注册,将可以获得免费 4 小时 RTX-4090 显卡的使用时长。

注册链接如下:
https://openbayes.com/console/signup?r=comehope_JrJj

点击它,会出现下面的登录界面,填写用户名、邮箱、密码、手机号和短信验证码,就可以完成注册,如下图所示。

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?在这里插入图片描述

克隆教程

注册成功之后,进入到个人控制台,在左侧菜单中选择“公共资源/公共教程”,搜索“0-9”,找到“语音识别入门教程:用 TensorFlow 识别数字 0-9”这篇教程,如下图所示。

在这里插入图片描述

打开这篇教程,点击右上角的“克隆”按钮,如下图所示。

在这里插入图片描述

在接下来“从模板创建:基本信息”的界面中点击“下一步:选择算力”按钮,如下图所示。

在这里插入图片描述

所谓算力,就是显卡类型,请选择“RTX 4090”,这里会显示您获赠的时长。再选择镜像类型中,选择“TensorFlow”,然后,显示右下角的“下一步:审核”按钮,如下图所示。

在这里插入图片描述

接下来列出了刚才选择过的算力和镜像,点击右下角的“继续执行”按钮,如下图所示。

在这里插入图片描述

接下来,系统会自动分配资源,稍待片刻,等到页面中显示“打开工作空间”按钮,点击它,就可以进入运行中的教程了,如下图所示。

在这里插入图片描述

工作空间的界面如下图所示。

在这里插入图片描述

接下来,运行“教程.jpynb”文件即可。以下内容与 “教程.jpynb” 的内容完全相同,建议您在 Jupyter 中运行,可以实时看到运行结果。

教程正文

先安装库文件,所有依赖都保存在 requirements.txt 中,其中主要是 librosa 库,是一个提取语音特征的库。

!pip install -r /openbayes/home/requirements.txt -q

数据集包含 1700 个语音文件,录制了多个人的英语数字发音,每个录音大约 1 秒到 2 秒时长。

数据集已经下载到 data 文件夹中。

接下来我们开始正式编码。

首先,定义数据集的文件夹路径,每个数字的语音都保存在以它的英语单词命名的文件夹中。

file_paths = {
    '0': 'zero',
    '1': 'one',
    '2': 'two',
    '3': 'three',
    '4': 'four',
    '5': 'five',
    '6': 'six',
    '7': 'seven',
    '8': 'eight',
    '9': 'nine'
}

初始化 2 个列表 audio_data 和 labels,用于保存音频数据和音频对应的标签。

audio_data = []
labels = []

使用 librosa 库提取语音特征,即所有音频文件的 MFCC 特征,并且使帧长固定为 40。MFCC(梅尔频率倒谱系数)适合描绘人类的语音特征。

使用 librosa 库提取语音特征,即所有音频文件的 MFCC 特征,并且使帧长固定为 40。MFCC(梅尔频率倒谱系数)适合描绘人类的语音特征。

import os
import numpy as np

n_frames = 40
for label, file_path in file_paths.items():
    print("processing: ", label, file_path)
    for file_name in os.listdir('data/' + file_path):
        file_path_full = os.path.join('data/' + file_path, file_name)
        audio, sr = librosa.load(file_path_full, sr=16000)
        mfccs = librosa.feature.mfcc(y=audio, sr=sr, n_mfcc=n_frames)
        if mfccs.shape[1] < n_frames:
            mfccs = np.pad(mfccs, ((0, 0), (0, n_frames - mfccs.shape[1])), mode='constant')
        else:
            mfccs = mfccs[:, :n_frames]
        mfccs_normalized = (mfccs - np.mean(mfccs)) / np.std(mfccs)
        mfccs_reshaped = mfccs_normalized.reshape((mfccs_normalized.shape[0], mfccs_normalized.shape[1], 1))
        audio_data.append(mfccs_reshaped)
        labels.append(label)

将之前定义的列表 audio_data 和 labels 转换成 numpy 数组,便于后续进行机器学习。

并且提高数据的精度,把数据类型转为 float64。

audio_data = np.array(audio_data, dtype=object)
labels = np.array(labels)

audio_data = audio_data.astype('float64')
labels = labels.astype('float64')

将 labels 列表转换成独热编码(one-hot encoding)。独热编码用于在分类任务中对数据进行预处理,本项目要处理的问题可以看作是一个对语音进行分类的问题,数字 0-9 一共是 10 个分类。

from tensorflow import keras

labels_one_hot = keras.utils.to_categorical(labels)

把数据分为训练集和测试集,测试集占比 20%。其中,X_train 和 y_train 是训练集的特征数据和标签数据,X_test 和 y_test 是测试集的特征数据和标签数据。

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(audio_data, labels_one_hot, test_size=0.2, random_state=42)

构建卷积神经网络模型,模型一共 9 层,第一层的输出会成为下一层的输入。

先是一个二维卷积层,接着是一个二维最大池化层。接下来的几层重复了卷积和池化的过程,卷积核的数量从 32 增加到 64,再到 128,这有助于模型学习更复杂的特征。

再接下来将二维的输入一维化,交给下一个全连接层处理,使用 relu 激活函数。

最后一层也是全连接层,它有10个神经元,对应于10个分类类别,使用 softmax 激活函数,将输出转换为概率分布。

model = keras.models.Sequential([
    keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=X_train.shape[1:]),
    keras.layers.MaxPooling2D((2,2)),
    keras.layers.Conv2D(64, (3,3), activation='relu'),
    keras.layers.MaxPooling2D((2,2)),
    keras.layers.Conv2D(128, (3,3), activation='relu'),
    keras.layers.MaxPooling2D((2,2)),
    keras.layers.Flatten(),
    keras.layers.Dense(64, activation='relu'),
    keras.layers.Dense(10, activation='softmax')
])

编译模型。优化器为 adam,这是一种流行的梯度下降优化算法;损失函数为与独热编码匹配的 categorical_crossentropy;评估指标只使用准确率 accuracy。

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

定义 2 个回调函数,用于在模型训练过程中应用特定的策略,ReduceLROnPlateau 用于调整学习率,EarlyStopping 用于防止过拟合。

from tensorflow.keras.callbacks import ReduceLROnPlateau
from tensorflow.keras.callbacks import EarlyStopping

reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=3, verbose=1, min_lr=0.0001)
early_stop = EarlyStopping(monitor='val_loss', patience=5, verbose=1)

定义数据生成器。尽管我们处理的是音频而不是图像,但此前已经将音频特征转换为二维图像数据,所以使用图像数据增强工具来提高模型的泛化能力。

from keras.preprocessing.image import ImageDataGenerator

datagen = ImageDataGenerator(
    width_shift_range=0.1,
    height_shift_range=0.1,
    zoom_range=0.1,
    shear_range=0.1,
    rotation_range=10
)

接下来开始训练模型。

训练中使用了数据增强和回调函数来优化训练过程,一共训练 30 轮。

训练过程中的所有信息记录在 history 变量中,后面我们可以用它来查看训练过程中的性能变化。

在 RTX 4090 显卡上,训练大约需要 3 分钟。

history = model.fit(
    datagen.flow(X_train, y_train, batch_size=32),
    epochs=30,
    validation_data=(X_test, y_test),
    steps_per_epoch=len(X_train) // 32,
    callbacks=[reduce_lr, early_stop]
)

在测试集上进行性能评估,并查看准确率。

_, test_accuracy = model.evaluate(X_test, y_test)
print('Test accuracy:', test_accuracy)

准确率大约 95%。

再把训练过程中关键指标的变化数据绘制成图看一看。

import matplotlib.pyplot as plt

plt.plot(history.history['accuracy'], label='Training Accuracy')
plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.show()

plt.plot(history.history['loss'], label='Training Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.show()

可以看到准确率一直在提升,而损失值一直在下降,这说明我们的训练是有效的。

现在,我们可以用自己录制的音频来实测一下效果了。

定义一个函数 predict() 实现语音到文字的转译,它先提取出音频文件的特征,然后调用模型进行预测,返回概率最高的分类。

def predict(audio, sr):
    mfccs = librosa.feature.mfcc(y=audio, sr=sr, n_mfcc=n_frames)
    if mfccs.shape[1] < n_frames:
        mfccs = np.pad(mfccs, ((0, 0), (0, n_frames - mfccs.shape[1])), mode='constant')
    else:
        mfccs = mfccs[:, :n_frames]
    mfccs_normalized = (mfccs - np.mean(mfccs)) / np.std(mfccs)
    mfccs_reshaped = mfccs_normalized.reshape((1, mfccs_normalized.shape[0], mfccs_normalized.shape[1], 1))

    predictions = model.predict(mfccs_reshaped)
    predicted_class = np.argmax(predictions)
    return 'Predicted class: ' + str(predicted_class)

我一共录制了 3 小段音频,下面是测试其中 1 段音频的代码。

audio, sr = librosa.load('audio1.wav', sr=16000)

predict(audio, sr)

可以看到,打印出的结果和读音是一致的。

是不是很有意思?

你也来试试吧!

记得使用我的注册链接哦,可以获得免费 4 小时 4090 时长呢~

https://openbayes.com/console/signup?r=comehope_JrJj

  • 17
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值