前言
本文是基于Datawhale的2021的四月学习——食物音频分析,此为阿水233的baseline,本文章为代码分析(个人理解,如有错误,请在评论指正,谢谢),本文使用的环境为天池实验室
文章目录
1. 准备工作
1.1 下载数据并解压
1.1.1 使用方法
代码 | 作用 |
---|---|
!wget | 下载数据 |
!unzip | 解压下载的安装包 |
!\rm | 删除一个目录中的一个或多个文件或目录,如果没有使用- r参数,则rm不会删除目录。如果使用 rm 来删除文件,通常仍可以将该文件恢复原状。 |
1.1.2 代码
!wget http://tianchi-competition.oss-cn-hangzhou.aliyuncs.com/531887/train_sample.zip
!unzip -qq train_sample.zip
!\rm train_sample.zip
!wget http://tianchi-competition.oss-cn-hangzhou.aliyuncs.com/531887/test_a.zip
!unzip -qq test_a.zip
!\rm test_a.zip
1.2 导入库函数
1.2.1 注意事项
在本次实验中使用了librosa库进行音频数据分析
1.2.2 代码
# 基本库
import pandas as pd
import numpy as np
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
注:导入此库函数时会出现DeprecationWarning: numpy.core.umath_tests is an internal NumPy module and should not be imported. It will be removed in a future NumPy release.,代表使用了弃用的numpy文件,但对接下来的操作无影响。
#加载音频处理库
import os
import librosa
import librosa.display
import glob
2.特征提取和数据集的建立
2.1 建立字典
2.1.1 分析
如下图所示(左为train,右为train_sample)两图的文件夹名称均一致且为文字类型,所以建立一个字典,并将其用数字作为字典的值,同时创建一个字典:单词为值,数字为索引
2.1.2 代码部分
feature = []
label = []
# 建立类别标签,不同类别对应不同的数字。
label_dict = {'aloe': 0, 'burger': 1, 'cabbage': 2,'candied_fruits':3, 'carrots': 4, 'chips':5,
'chocolate': 6, 'drinks': 7, 'fries': 8, 'grapes': 9, 'gummies': 10, 'ice-cream':11,
'jelly': 12, 'noodles': 13, 'pickles': 14, 'pizza': 15, 'ribs': 16, 'salmon':17,
'soup': 18, 'wings': 19}
label_dict_inv = {v:k for k,v in label_dict.items()}
注:{v:k for k,v in label_dict.items()}参考文献:python代码{v: k for k, v in myArray.items()}是什么意思?
2.2导入音频数据(转换后的)
2.2.1分析
将文件中的音频转换为数据,并保存
参考文献:如何将机器学习和深度学习方法应用到音频分析中
2.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)
2.3 创建训练集和测试集
2.3.1 分析
首先将原来的数据转化为两个向量数据(temp为原来一样的横向向量,data为temp的转置),并将创建X将数据重新构建一个二维数组,同时创建Y读取了标签的值,同时创建了依据标签y,按原数据y中各类比例,分配给train和test,使得train和test中各类数据的比例与原数据集一样的X_train, X_test, Y_train, Y_test
参考文章:
Numpy知识点补充:np.vstack()&np.hstack()
data[:,0] data[1,:]的含义
train_test_split(X, y, stratify=y)
scikit-learn用train_test_split随机划分数据集和训练集
2.3.2 代码
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)
3. 建立模型(CNN)
3.1 搭建CNN网络
3.1.1分析
构建模型
参考文献:
详解keras的model.summary()输出参数Param计算过程
3.1.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'])
# 输出模型的参数状况
model.summary()
# 训练模型
model.fit(X_train, Y_train, epochs = 20, batch_size = 15, validation_data = (X_test, Y_test))
4.预测测试集
4.1.1分析
导入测试集的数据,并输入进模型后储存,导出
4.1.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/')
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)