系列文章目录
Datawhale的2021的四月学习——食物音频分析 baseline
Datawhale的2021的四月学习——食物音频 特征分析
Datawhale的2021的四月学习——食物音频音频 数据特征分析
文章目录
前言
本文是基于Datawhale的2021的四月学习——食物音频分析,此为里奥呐多艾斯的Task4 食物声音识别-深度学习模型搭建与训练,本文章为代码分析(个人理解,如有错误,请在评论指正,谢谢),本文使用的环境为天池实验室
1. 基础操作(数据处理)
1.1 导包
1.1.1 分析
略,基本使用已经在之前的baseline中已经写过,此处略过,有需要时请点击链接
1.1.2 代码
#基本库
import pandas as pd
import numpy as np
pd.plotting.register_matplotlib_converters()
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.model_selection import GridSearchCV
from sklearn.preprocessing import MinMaxScaler
#深度学习框架
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, Flatten, Dense, MaxPool2D, Dropout
from tensorflow.keras.utils import to_categorical
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
import tensorflow as tf
import tensorflow.keras
#音频处理库
import os
import librosa
import librosa.display
import glob
1.2 特征提取及数据集的建立
1.2.1 分析
略,基本使用已经在之前的baseline中已经写过,此处略过,有需要时请点击链接
1.2.2 代码
from tqdm import tqdm
def extract_features(parent_dir, sub_dirs, max_file=10, file_ext="*.wav"):
c = 0
label, feature = [], []
for sub_dir in sub_dirs:
for fn in tqdm(glob.glob(os.path.join(parent_dir, sub_dir, file_ext))[:max_file]): # 遍历数据集的所有文件
# segment_log_specgrams, segment_labels = [], []
#sound_clip,sr = librosa.load(fn)
#print(fn)
label_name = fn.split('/')[-2]
label.extend([label_dict[label_name]])
X, sample_rate = librosa.load(fn,res_type='kaiser_fast')
mels = np.mean(librosa.feature.melspectrogram(y=X,sr=sample_rate).T,axis=0) # 计算梅尔频谱(mel spectrogram),并把它作为特征
feature.extend([mels])
return [feature, label]
# 自己更改目录
parent_dir = './train_sample/'
save_dir = "./"
folds = sub_dirs = np.array(['aloe','burger','cabbage','candied_fruits',
'carrots','chips','chocolate','drinks','fries',
'grapes','gummies','ice-cream','jelly','noodles','pickles',
'pizza','ribs','salmon','soup','wings'])
# 获取特征feature以及类别的label
temp = extract_features(parent_dir,sub_dirs,max_file=100)
temp = np.array(temp)
data = temp.transpose()
# 获取特征
X = np.vstack(data[:, 0])
# 获取标签
Y = np.array(data[:, 1])
print('X的特征尺寸是:',X.shape)
print('Y的特征尺寸是:',Y.shape)
# 在Keras库中:to_categorical就是将类别向量转换为二进制(只有0和1)的矩阵类型表示
Y = to_categorical(Y)
'''最终数据'''
print(X.shape)
print(Y.shape)
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, random_state = 1, stratify=Y)
print('训练集的大小',len(X_train))
print('测试集的大小',len(X_test))
X_train = X_train.reshape(-1, 16, 8, 1)
X_test = X_test.reshape(-1, 16, 8, 1)
2. 建立模型(本次重点,之前的详细分析有需要的可以看之前的几篇文章)
2.1 深度学习框架
Keras 是一个用 Python 编写的高级神经网络 API,它能够以 TensorFlow, CNTK, 或者 Theano 作为后端运行。Keras 的开发重点是支持快速的实验。能够以最小的时延把你的想法转换为实验结果,是做好研究的关键。
如果你在以下情况下需要深度学习库,请使用 Keras:
-
允许简单而快速的原型设计(由于用户友好,高度模块化,可扩展性)。
-
同时支持卷积神经网络和循环神经网络,以及两者的组合。
-
在 CPU 和 GPU 上无缝运行。
官方文档:Keras 中文文档
使用Keras搭建一个神经网络:
2.1.1 网络模型搭建(本处是CNN网络)
Keras 模型
Keras提供的模型,其中分为两类:
Sequential 顺序模型
Model 类模型
我们可以通过 from keras.models import Sequential
或者 from keras.models import Model
来导入对应的模型。
本次使用的是 Sequential 顺序模型
(官方文档)
2.1.2 CNN网络
卷积神经网络CNN的结构一般包含这几个层:
1)输入层:用于数据的输入
2)卷积层:使用卷积核进行特征提取和特征映射------>可以多次重复使用
3)激励层:由于卷积也是一种线性运算,因此需要增加非线性映射(也就是激活函数)
4)池化层:进行下采样,对特征图稀疏处理,减少数据运算量----->可以多次重复使用
5)Flatten操作:将二维的向量,拉直为一维的向量,从而可以放入下一层的神经网络中
6)全连接层:通常在CNN的尾部进行重新拟合,减少特征信息的损失----->DNN
网络
对于Keras操作中,可以简单地使用 .add()
,将需要搭建的神经网络的layer堆砌起来,像搭积木一样:
如果需要,你还可以进一步地配置你的优化器.complies()
。Keras 的核心原则是使事情变得相当简单,同时又允许用户在需要的时候能够进行完全的控制(终极的控制是源代码的易扩展性)。
一些代码图例(转载自:参考文献)
1.keras网络结构
2.keras网络配置
其中回调函数callbacks应该是keras的精髓~
3.keras预处理功能
所以本次代码为添加了两层卷积层,两层池化层,一层Dropout层防止过拟合。
2.2 代码
model = Sequential()
# 输入的大小
input_dim = (16, 8, 1)
model.add(Conv2D(64, (3, 3), padding = "same", activation = "tanh", input_shape = input_dim))# 卷积层
model.add(MaxPool2D(pool_size=(2, 2)))# 最大池化
model.add(Conv2D(128, (3, 3), padding = "same", activation = "tanh")) #卷积层
model.add(MaxPool2D(pool_size=(2, 2))) # 最大池化层
model.add(Dropout(0.1))
model.add(Flatten()) # 展开
model.add(Dense(1024, activation = "tanh"))
model.add(Dense(20, activation = "softmax")) # 输出层:20个units输出20个类的概率
# 编译模型,设置损失函数,优化方法以及评价标准
model.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])
3. CNN模型训练和测试
3.1 模型训练
Keras model.fit()参数
参数 | 作用 |
---|---|
batch_size | 整数 ,每次梯度更新的样本数。未指定,默认为32 |
epochs | 整数,训练模型迭代次数 |
3.2 代码
# 训练模型
model.fit(X_train, Y_train, epochs = 90, batch_size = 50, validation_data = (X_test, Y_test))
#查看网络的统计信息
model.summary()
4.生成预测测试集(提交结果)
4.1 分析
略,基本使用已经在之前的baseline中已经写过,此处略过,有需要时请点击链接
4.2 代码
def extract_features(test_dir, file_ext="*.wav"):
feature = []
for fn in tqdm(glob.glob(os.path.join(test_dir, file_ext))[:]): # 遍历数据集的所有文件
X, sample_rate = librosa.load(fn,res_type='kaiser_fast')
mels = np.mean(librosa.feature.melspectrogram(y=X,sr=sample_rate).T,axis=0) # 计算梅尔频谱(mel spectrogram),并把它作为特征
feature.extend([mels])
return feature
X_test = extract_features('./test_a/')
5. 问题
1.为什么要将形状转为(-1, 16, 8, 1)而不是直接使用?
2.最后几步的目的是什么?(下为最后几步代码)
X_test = np.vstack(X_test)
predictions = model.predict(X_test.reshape(-1, 16, 8, 1))
preds = np.argmax(predictions, axis = 1)
preds = [label_dict_inv[x] for x in preds]
path = glob.glob('./test_a/*.wav')
result = pd.DataFrame({'name':path, 'label': preds})
result['name'] = result['name'].apply(lambda x: x.split('/')[-1])
result.to_csv('submit.csv',index=None)
!ls ./test_a/*.wav | wc -l
!wc -l submit.csv