本文主要是介绍语音识别--基于MFCC和多层感知机的语音情感识别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
⚠申明: 未经许可,禁止以任何形式转载,若要引用,请标注链接地址。 全文共计3077字,阅读大概需要3分钟
🌈更多学习内容, 欢迎👏关注👀【文末】我的个人微信公众号:不懂开发的程序猿
个人网站:https://jerry-jy.co/❗❗❗知识付费,🈲止白嫖,有需要请后台私信或【文末】个人微信公众号联系我
语音识别--基于MFCC和多层感知机的语音情感识别
- 基于MFCC和多层感知机的语音情感识别
- 一、任务需求
- 二、任务目标
- 1、掌握神经网络的构建
- 2、掌握神经网络的编译
- 3、掌握神经网络的训练
- 4、掌握神经网络的概要输出
- 5、掌握神经网络的模型封装
- 三、任务环境
- 1、jupyter开发环境
- 2、python3.6
- 3、tensorflow2.4
- 四、任务实施过程
- 1、读取数据
- 2、提取声音特征
- 3、处理数据
- 4、训练多层感知机
- 5、预测验证
- 五、任务小结
- 说明
基于MFCC和多层感知机的语音情感识别
一、任务需求
语音情感识别是一个非常有趣的项目。例如呼叫中心可能会很愿意了解话务员和客户之间的聊天气氛。在本节实验中,我们将使用MFCC和多层感知机来做一个简单的语音情感识别模型。
Speech Emotion Recognition,缩写为SER,是试图从语音中识别人类情绪和情感状态的行为。这是利用这样一个事实,即声音通常通过语调和音调反映潜在的情感。这也是像狗和马这样的动物用来理解人类情感的现象。
SER 很难,因为情绪是主观的,注释音频具有挑战性。
要求:利用Sequential模型神经网络使用Tensorflow模型构建与输出SER
二、任务目标
1、掌握神经网络的构建
2、掌握神经网络的编译
3、掌握神经网络的训练
4、掌握神经网络的概要输出
5、掌握神经网络的模型封装
三、任务环境
1、jupyter开发环境
2、python3.6
3、tensorflow2.4
四、任务实施过程
1、读取数据
本实验中,我们将使用 RAVDESS 数据集;这是情绪言语和歌曲数据集的瑞尔森视听数据库,可免费下载。
该数据集包含 7356 个文件,原始数据集是来自 24 个演员的 24.8GB 数据,但本实验并不需要那么大的数据集,因此降低了所有音频的采样率,以降低样本数据的大小。
import librosa
import soundfile
import os, glob, pickle
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import accuracy_score
from IPython.display import clear_output as clear
2、提取声音特征
首先我们定义一个函数extract_feature 来从声音文件中提取mfcc、chroma 和mel 特征。
这个函数有 4 个参数——文件名和三个用于三个特征的布尔参数:
- mfcc: Mel Frequency Cepstral Coefficient,代表声音的短期功率谱
- chroma:属于 12 个不同的音级
- mel:梅尔频谱图频率
在该函数中,我们使用 with-as 方法打开 soundfile声音文件,这样一旦我们完成相关操作就会自动关闭文件。
读取到的数据,被存放在变量 X 中,同时获取该文件的采样率。如果chroma为 True,则先计算 X 的短时傅立叶变换,然后再计算chroma特征。
相应的,如果mfcc或mel为true,则直接计算音频的mfcc或mel。
# 从声音文件中提取特征(mfcc, chroma, mel)
def extract_feature(file_name, mfcc, chroma, mel):with soundfile.SoundFile(file_name) as sound_file:X = sound_file.read(dtype="float32")sample_rate=sound_file.samplerateresult=np.array([])if mfcc:mfccs=np.mean(librosa.feature.mfcc(y=X, sr=sample_rate, n_mfcc=40).T, axis=0)result=np.hstack((result, mfccs))if chroma:stft=np.abs(librosa.stft(X))chroma=np.mean(librosa.feature.chroma_stft(S=stft, sr=sample_rate).T,axis=0)result=np.hstack((result, chroma))if mel:mel=np.mean(librosa.feature.melspectrogram(X, sr=sample_rate).T,axis=0)result=np.hstack((result, mel))return result
3、处理数据
接下来,我们可以定义一个字典来保存 RAVDESS 数据集中的数字和数字代表的情绪,然后创建一个列表来保存实验需要的情绪——冷静、快乐、恐惧、厌恶。
# RAVDESS 数据集中的情绪
emotions={'01':'neutral', # 中性'02':'calm', # 冷静'03':'happy', # 快乐'04':'sad', # 悲伤'05':'angry', # 愤怒'06':'fearful', # 恐惧'07':'disgust', # 厌恶'08':'surprised' # 惊讶
}# 选取待判断的情绪
observed_emotions=['calm', 'happy', 'fearful', 'disgust']
现在,让我们定义一个函数 load_data() 加载数据。该函数参数为测试集的相对大小,例如0.2(20%)。
在该函数中,我们首先定义x 和 y 两个空列表,接下来使用 glob 模块中的 glob() 函数来获取数据集中声音文件的所有路径名。
首先观察文件夹及命名方式:
ls /home/jovyan/datas/speech-emotion-recognition-ravdess-data/
Actor_01/ Actor_05/ Actor_09/ Actor_13/ Actor_17/ Actor_21/
Actor_02/ Actor_06/ Actor_10/ Actor_14/ Actor_18/ Actor_22/
Actor_03/ Actor_07/ Actor_11/ Actor_15/ Actor_19/ Actor_23/
Actor_04/ Actor_08/ Actor_12/ Actor_16/ Actor_20/ Actor_24/
ls /home/jovyan/datas/speech-emotion-recognition-ravdess-data/Actor_01/
03-01-01-01-01-01-01.wav 03-01-04-01-01-01-01.wav 03-01-06-02-01-01-01.wav
03-01-01-01-01-02-01.wav 03-01-04-01-01-02-01.wav 03-01-06-02-01-02-01.wav
03-01-01-01-02-01-01.wav 03-01-04-01-02-01-01.wav 03-01-06-02-02-01-01.wav
03-01-01-01-02-02-01.wav 03-01-04-01-02-02-01.wav 03-01-06-02-02-02-01.wav
03-01-02-01-01-01-01.wav 03-01-04-02-01-01-01.wav 03-01-07-01-01-01-01.wav
03-01-02-01-01-02-01.wav 03-01-04-02-01-02-01.wav 03-01-07-01-01-02-01.wav
03-01-02-01-02-01-01.wav 03-01-04-02-02-01-01.wav 03-01-07-01-02-01-01.wav
03-01-02-01-02-02-01.wav 03-01-04-02-02-02-01.wav 03-01-07-01-02-02-01.wav
03-01-02-02-01-01-01.wav 03-01-05-01-01-01-01.wav 03-01-07-02-01-01-01.wav
03-01-02-02-01-02-01.wav 03-01-05-01-01-02-01.wav 03-01-07-02-01-02-01.wav
03-01-02-02-02-01-01.wav 03-01-05-01-02-01-01.wav 03-01-07-02-02-01-01.wav
03-01-02-02-02-02-01.wav 03-01-05-01-02-02-01.wav 03-01-07-02-02-02-01.wav
03-01-03-01-01-01-01.wav 03-01-05-02-01-01-01.wav 03-01-08-01-01-01-01.wav
03-01-03-01-01-02-01.wav 03-01-05-02-01-02-01.wav 03-01-08-01-01-02-01.wav
03-01-03-01-02-01-01.wav 03-01-05-02-02-01-01.wav 03-01-08-01-02-01-01.wav
03-01-03-01-02-02-01.wav 03-01-05-02-02-02-01.wav 03-01-08-01-02-02-01.wav
03-01-03-02-01-01-01.wav 03-01-06-01-01-01-01.wav 03-01-08-02-01-01-01.wav
03-01-03-02-01-02-01.wav 03-01-06-01-01-02-01.wav 03-01-08-02-01-02-01.wav
03-01-03-02-02-01-01.wav 03-01-06-01-02-01-01.wav 03-01-08-02-02-01-01.wav
03-01-03-02-02-02-01.wav 03-01-06-01-02-02-01.wav 03-01-08-02-02-02-01.wav
文件的名字(例如:02-01-06-01-02-01-12)的解释如下:
- 模态(01 =全音视频,02 =视频,03 =音频)。
- 声道(01 =演讲,02 =歌曲)。
- 情绪(01 =中性,02 =冷静,03 =快乐,04 =悲伤,05 =愤怒,06 =恐惧,07 =厌恶,08 =惊讶)
- 情绪强度(01 =正常,02 =强烈)。注意:中性情绪没有强度。
- 语句(01 =“孩子们在门旁边说话”,02 =“狗坐在门旁边”)。
- 重复(01 =第一次重复,02 =第二次重复)。
- 演员(01 - 24个人的编号)。奇数演员是男性,偶数演员是女性)。文件名的例子:02 - 01 - 06 - 01 - 02 - 01 - 12.mp4 视频(02)演讲(01)恐惧(06)正常(01)狗坐在门旁边(02)第一次重复(01)演员编号(12)女,因为演员的身份证号码是偶数。
音频文件所在文件夹存在一定规律,它们都是Actor_开头,并加上编号组成,因此我们可以使用Actor_*
来表示这些文件夹。
由于文件名都是用.wav做为结尾,因此我们可以使用*.wav
来表示所有wav格式文件。我们为此使用的路径模式是"/home/jovyan/datas/speech-emotion-recognition-ravdess-data/Actor_*/*.wav"
在文件名中的第三个数字,就是该音频所表示的情绪。然后使用我们刚刚制定的情绪字典,将数字转换成对应的情绪。然后检查这个情绪是否在我们的observed_emotions列表中。如果不是,就跳过,继续下一个文件。如果是,就调用extract_feature函数, 并将返回的内容存储在feature
中。然后使用append方式将特征附加到 x 并将情感附加到 y。
# 加载每个声音文件的数据和提取特性
def load_data(test_size=0.2):x,y=[],[]files = glob.glob("/home/jovyan/datas/speech-emotion-recognition-ravdess-data/Actor_*/*.wav")file_nums = len(files)for i,file in enumerate(files):file_name=os.path.basename(file)emotion=emotions[file_name.split("-")[2]]if emotion not in observed_emotions:continuefeature=extract_feature(file, mfcc=True, chroma=True, mel=True)x.append(feature)y.append(emotion)if i+1 < file_nums:print(' '*100,end='')print('\r %s, %.2f%%.'%(file_name,i*100/file_nums),end='')print()return train_test_split(np.array(x), y, test_size=test_size, random_state=9)
将数据集拆分为训练集和测试集,测试集保留 25%。由于涉及到读取文件并提取特征,因此下面这段程序可能执行的比较慢,所以我将这段程序转换为markdown中的代码格式,如果你想执行的话,把它们复制到代码框运行就可以了。
[Input]
%%time
#DataFlair - Split the dataset
x_train,x_test,y_train,y_test=load_data(test_size=0.25)
[Output]
CPU times: user 6min 4s, sys: 26min 43s, total: 32min 47s
Wall time: 16min 36s
如你所见,在我现在使用的平台上(性能不怎么样),一共花费了超过16分钟的时间来处理数据。
如果你不想等待这么长时间,我把x_train,x_test,y_train,y_test
这四个变量保存起来了,保存代码如下:
np.save('06_arr_save.npy',np.array([x_train,x_test,y_train,y_test],dtype=object))
这会把变量保存到当前文件夹的06_arr_save.npy
中,你可以直接加载,就像下边这样做的。
x_train,x_test,y_train,y_test = np.load('06_arr_save.npy',allow_pickle=True)
观察训练和测试数据集的形状
# 获取训练集和测试集的shape
print((x_train.shape[0], x_test.shape[0]))
(576, 192)
得到提取的特征数
# 获取提取到的特征数
print(f'Features extracted: {x_train.shape[1]}')
Features extracted: 180
4、训练多层感知机
接下来我们初始化一个 MLPClassifier。这是一个多层感知器分类器:它使用 LBFGS 或随机梯度下降优化对数损失函数。
与 SVM 或朴素贝叶斯不同,MLPClassifier 具有用于分类目的的内部神经网络。这是一个简单的前馈神经网络模型。
# 初始化多层感知机
model=MLPClassifier(alpha=0.01, batch_size=256, epsilon=1e-08, hidden_layer_sizes=(300,), learning_rate='adaptive', max_iter=500)
设置完模型以后,就可以使用我们划分的训练集对模型进行训练。
%%time
# 训练模型
model.fit(x_train,y_train)
CPU times: user 1min 16s, sys: 6min 20s, total: 7min 37s
Wall time: 3min 50s
MLPClassifier(alpha=0.01, batch_size=256, hidden_layer_sizes=(300,),
learning_rate=‘adaptive’, max_iter=500)
5、预测验证
接下来我们预测测试集的值。并存放在y_pred中(这实际就是测试集的预测情绪)
# 使用测试集进行预测
y_pred=model.predict(x_test)
计算模型的准确性,我们将调用从sklearn导入的accuracy_score() 函数。最后将精度四舍五入到小数点后两位并打印出来。
# 计算模型准确率
accuracy=accuracy_score(y_true=y_test, y_pred=y_pred)# 打印准确率
print("Accuracy: {:.2f}%".format(accuracy*100))
Accuracy: 71.35%
五、任务小结
本实验学习使用库 librosa、soundfile 和 sklearn(以及其他) MLPClassifier 构建模型。通过本实验我们学习到了多层感知机实现语音分类的相关知识,需要掌握以下知识点:
- 使用MFCC提取声音特征
- 使用sklearn创建多层感知机
- 模型的性能评价方法
–end–
说明
本实验(项目)/论文若有需要,请后台私信或【文末】个人微信公众号联系我
这篇关于语音识别--基于MFCC和多层感知机的语音情感识别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!