Аудиоклассификация с предварительно обученным VGG-19 (Keras)

В этом посте я остановлюсь на проблеме классификации аудио. Я обучу классификатор SVM на функциях, извлеченных предварительно обученным VGG-19 из сигналов аудио. Основная идея этого поста - показать мощь предварительно обученных моделей и простоту их применения.

Я хотел оценить этот подход на реальных данных. Так что я подумал о классификации аудио суперкаров и тяжелых мотоциклов. Ниже приведены шаги, которые я выполнил для создания этого классификатора:

Скачать аудиофайлы с Youtube

Сначала я выбрал видео на YouTube, для которых мне нужен звук, а затем использовал следующий фрагмент кода для загрузки аудиофайлов в формате .mp3.

from __future__ import unicode_literals
import youtube_dl


ydl_opts = {
    'format': 'bestaudio/best',
    'postprocessors': [{
        'key': 'FFmpegExtractAudio',
        'preferredcodec': 'mp3',
        'preferredquality': '192',
    }],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    ydl.download([<youtube video link>])
# for bike sounds : https://www.youtube.com/watch?v=sRdRwHPjJPk
# for car sounds : https://www.youtube.com/watch?v=PPdNb-XQXR8

Преобразование аудиофайлов из .mp3 в .wav

После загрузки файлов .mp3 я преобразовал их в файлы .wav, используя следующий фрагмент кода.

from pydub import AudioSegment
sound = AudioSegment.from_mp3("car.mp3")
sound.export("car.wav", format="wav")

Извлечение фрагментов аудио

На следующем этапе я извлек фрагменты 15-секундного аудио из файлов .wav.

from pydub import AudioSegment
import os
if not os.path.exists("bike"):
    os.makedirs("bike")

count=1
for i in range(1,1000,15):
    t1 = i * 1000 #Works in milliseconds
    t2 = (i+15) * 1000
    newAudio = AudioSegment.from_wav("bikes.wav")
    newAudio = newAudio[t1:t2]
    newAudio.export('bike/'+str(count)+'.wav', format="wav") #Exports to a wav file in the current path.
    print(count)
    count+=1

Построение кривых амплитуды

Следующим шагом было построение сигналов этих аудиофайлов. Это было сделано с помощью следующего кода.

from scipy.io.wavfile import read
import matplotlib.pyplot as plt
from os import walk
import os
if not os.path.exists("carPlots"):
    os.makedirs("carPlots")
car_wavs = []
for (_,_,filenames) in walk('car'):
    car_wavs.extend(filenames)
    break
for car_wav in car_wavs:
    # read audio samples
    input_data = read("car/" + car_wav)
    audio = input_data[1]
    # plot the first 1024 samples
    plt.plot(audio)
    # label the axes
    plt.ylabel("Amplitude")
    plt.xlabel("Time")
    # set the title
    # plt.title("Sample Wav")
    # display the plot
    plt.savefig("carPlots/" + car_wav.split('.')[0] + '.png')
    # plt.show()
    plt.close('all')

Извлечение функций и обучение LinearSVM

После того, как у меня были эти формы сигналов для автомобилей и мотоциклов, я извлек элементы из этих изображений, чтобы передать их в LinearSVM для классификации. Чтобы извлечь элементы, я использовал предварительно обученную модель VGG-19 и извлек абстрактные элементы изображения из плоского слоя. После извлечения этих функций я создал тестовую группу из 70–30 поездов и обучил LinearSVM. Ниже приведен код для этого.

import os
from keras.applications.vgg19 import VGG19
from keras.preprocessing import image
from keras.applications.vgg19 import preprocess_input
from keras.models import Model
import numpy as np

base_model = VGG19(weights='imagenet')
model = Model(inputs=base_model.input, outputs=base_model.get_layer('flatten').output)

def get_features(img_path):
    img = image.load_img(img_path, target_size=(224, 224))
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = preprocess_input(x)
    flatten = model.predict(x)
    return list(flatten[0])

X = []
y = []

car_plots = []
for (_,_,filenames) in os.walk('carPlots'):
    car_plots.extend(filenames)
    break

for cplot in car_plots:
    X.append(get_features('carPlots/' + cplot))
    y.append(0)

bike_plots = []
for (_,_,filenames) in os.walk('bikePlots'):
    bike_plots.extend(filenames)
    break

for cplot in bike_plots:
    X.append(get_features('bikePlots/' + cplot))
    y.append(1)

from sklearn.model_selection import train_test_split
from sklearn.svm import LinearSVC
from sklearn.metrics import accuracy_score

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=42, stratify=y)

clf = LinearSVC(random_state=0, tol=1e-5)
clf.fit(X_train, y_train)

predicted = clf.predict(X_test)

# get the accuracy
print (accuracy_score(y_test, predicted))

Эта простая модель показала точность 97% на тестовой выборке . Это показывает, насколько мощны эти предварительно обученные модели и как каждый может использовать их для создания инструмента.

Одно из применений этого, которое я могу придумать, - это создать расширение chrome, которое сообщает, содержит ли звук видео, присутствующего на веб-странице, явные шумы или нет. Я призываю новичков, читающих этот пост, подумать о новой проблеме и решить ее, используя метод, представленный здесь.