使用Keras将音乐分类为不同类型
在本文中,我们将使用机器学习把音乐片段分类为不同类型。
我们将使用GTZAN genre collection数据集。此机器学习数据集可以从此处获取(http://opihi.cs.uvic.ca/sound/genres.tar.gz)。该机器学习数据集由10种类型组成,每种类型由100个音乐片段组成,每个音乐片段长30秒。
我们将使用Keras,采用tensorflow作为后端。
导入Python库
import librosa import pandas as pd import numpy as np import matplotlib.pyplot as plt %matplotlib inline import os import csv # Preprocessing from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder, StandardScaler #Keras import keras
重要的提示:
检查tensorflow的版本应该大于1.1否则各种keras功能将失败。
Pip可能无法获得最新的tensorflow版本,因此请使用以下命令安装tensorflow:
pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-1.6.0-py3-none-any.whl
创建数据集
我们将根据我们的要求处理机器学习数据集。我们将创建一个包含我们所需数据的CSV文件。
header = 'filename chroma_stft rmse spectral_centroid spectral_bandwidth rolloff zero_crossing_rate' for i in range(1, 21): header += f' mfcc{i}' header += ' label' header = header.split()
这里我们为CSV文件生成标题。
我们将获得20 mfcc的给定采样率,因为它是针对每个帧计算的,因此mfcc有20列。
现在,我们将计算所有特征。
file = open('data.csv', 'w', newline='') with file: writer = csv.writer(file) writer.writerow(header) genres = 'blues classical country disco hiphop jazz metal pop reggae rock'.split() for g in genres: for filename in os.listdir(f'./genres/{g}'): songname = f'./genres/{g}/{filename}' y, sr = librosa.load(songname, mono=True, duration=30) chroma_stft = librosa.feature.chroma_stft(y=y, sr=sr) rmse = librosa.feature.rmse(y=y) spec_cent = librosa.feature.spectral_centroid(y=y, sr=sr) spec_bw = librosa.feature.spectral_bandwidth(y=y, sr=sr) rolloff = librosa.feature.spectral_rolloff(y=y, sr=sr) zcr = librosa.feature.zero_crossing_rate(y) mfcc = librosa.feature.mfcc(y=y, sr=sr) to_append = f'{filename} {np.mean(chroma_stft)} {np.mean(rmse)} {np.mean(spec_cent)} {np.mean(spec_bw)} {np.mean(rolloff)} {np.mean(zcr)}' for e in mfcc: to_append += f' {np.mean(e)}' to_append += f' {g}' file = open('data.csv', 'a', newline='') with file: writer = csv.writer(file) writer.writerow(to_append.split())
我们使用librosa包计算了所有功能,并创建了一个带有data.csv文件名的数据集,并在给定的标题中插入了给定音乐的所有特征值。
预处理机器学习数据集
读取数据集
data = pd.read_csv('data.csv') data.head()
删除不必要的列
# Dropping unneccesary columns data = data.drop(['filename'],axis=1) data.head()
“文件名”列不是必需的。
现在,我们将把类型编码为整数
genre_list = data.iloc[:, -1] encoder = LabelEncoder() y = encoder.fit_transform(genre_list) print(y)
在这里,我们创建了一个流派和整数之间的映射。每个整数代表特定的类型。
归一化数据集
scaler = StandardScaler() X = scaler.fit_transform(np.array(data.iloc[:, :-1], dtype = float))
x的计算方法是取均值除以方差。
将机器学习数据集拆分为训练和测试数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
我们将数据集分成80:20比例的训练和测试数据集。
机器学习模型创建,训练和测试
创建模型
from keras import models from keras import layers model = models.Sequential() model.add(layers.Dense(256, activation='relu', input_shape=(X_train.shape[1],))) model.add(layers.Dense(128, activation='relu')) model.add(layers.Dense(64, activation='relu')) model.add(layers.Dense(10, activation='softmax'))
我们使用keras序列模型。
我们的网络有4层。首先是输入层,因此必须给出输入大小。然后有2个隐藏层,最后一层是输出层。dense内的值表示输出空间的维度。所以第一层有256个神经元,因此它的输出空间的维数是256。输出层有10个神经元,因为我们分为10个类型。
编译模型
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
在开始训练之前,我们需要先进行配置。Optimizer代表了一种优化算法,我们将使用adam算法,它在深度学习中被广泛使用。loss是评价网络效率的一个函数。模型的目标是减少这个损失函数。Metric是要评估的度量,我们将评估准确性。损失函数sparse_categorical_crossentropy与categorical_crossentropy类似,后者仅在有多个分类字段时使用。
训练模型
history = model.fit(X_train, y_train, epochs=20, batch_size=128)
利用fit函数对给定训练输入和输出的模型进行训练。
评估模型
test_loss, test_acc = model.evaluate(X_test,y_test) print('test_acc: ',test_acc)
我们将获得模型的准确性,可以根据提取的特征预测给定音乐的类型。
预测
predictions = model.predict(X_test) np.argmax(predictions[0])
predict函数给出了每种音乐类型匹配程度的百分比。给定类型的最高百分比是由argmax计算的最终结果。