Classificazione dei suoni urbani utilizzando il Deep learning

Blog

Classificazione dei suoni urbani utilizzando il Deep learning

Di recente ho completato il progetto Nanodegree Capstone dell'ingegnere di apprendimento automatico di Udacity, intitolato Classificazione dei suoni urbani utilizzando l'apprendimento profondo, in cui dimostro come classificare suoni diversi utilizzando l'intelligenza artificiale.



Quella che segue è una panoramica del progetto, che delinea l'approccio, il set di dati e gli strumenti utilizzati, nonché i risultati. Di seguito verranno pubblicati i collegamenti completi a tutto il codice, i taccuini Jupyter e il rapporto.

Scriverò presto una recensione completa dell'esperienza Udacity per chiunque stia pensando di partecipare al programma... guarda questo spazio.



Sfondo

La classificazione automatica del rumore ambientale è un'area di ricerca in crescita con numerose applicazioni nel mondo reale. Sebbene esista un ampio corpus di ricerche in campi audio correlati come la parola e la musica, il lavoro sulla classificazione dei suoni ambientali è relativamente scarso.

Allo stesso modo, osservando i recenti progressi nel campo della classificazione delle immagini in cui le reti neurali convoluzionali sono utilizzate per classificare le immagini con elevata precisione e su larga scala, si pone la questione dell'applicabilità di queste tecniche in altri domini, come la classificazione del suono.



C'è una pletora di applicazioni del mondo reale per questa ricerca, come ad esempio:

• Indicizzazione e recupero di contenuti multimediali basati su contenuti
• Assistere le persone sorde nelle loro attività quotidiane
• Casi d'uso della casa intelligente come funzionalità di sicurezza e protezione a 360 gradi
• Usi industriali come la manutenzione predittiva

Dichiarazione problema

Di seguito dimostrerà come applicare le tecniche di Deep Learning alla classificazione dei suoni ambientali, concentrandosi in particolare sull'identificazione di particolari suoni urbani.

Quando viene fornito un campione audio in un formato leggibile da computer (come un file .wav) della durata di pochi secondi, vogliamo essere in grado di determinare se contiene uno dei suoni urbani target con un corrispondente Punteggio di accuratezza della classificazione .

set di dati

Per questo utilizzeremo un set di dati chiamato Urbansound8K. Il set di dati contiene 8732 brani sonori (<=4s) of urban sounds from 10 classes, which are:

• Condizionatore
• Clacson
• Bambini che giocano
• Cane che abbaia
• Foratura
• Motore al minimo
• Sparo
• martello pneumatico
• Sirena
• Musica di strada

Un campione di questo set di dati è incluso con il repository git di accompagnamento e il set di dati completo può essere scaricato da qui .

Panoramica dei file audio

Questi brani sonori sono file audio digitali in formato .wav. Le onde sonore vengono digitalizzate campionandole a intervalli discreti noti come frequenza di campionamento (in genere 44,1 kHz per l'audio di qualità CD, il che significa che i campioni vengono prelevati 44.100 volte al secondo).

Ogni campione è l'ampiezza dell'onda in un particolare intervallo di tempo, dove la profondità di bit determina quanto dettagliato il campione sarà anche noto come intervallo dinamico del segnale (in genere 16 bit, il che significa che un campione può variare da 65.536 valori di ampiezza).

Questo è il titolo dell'immagine

Un'onda sonora, in rosso, rappresentata digitalmente, in blu (dopo il campionamento e la quantizzazione a 4 bit), con l'array risultante mostrato a destra. Originale © Aquegg | Wikimedia Commons

dove posso comprare un cucciolo di lupo?

L'immagine sopra mostra come un brano sonoro viene preso da una forma d'onda e trasformato in una matrice unidimensionale o in un vettore di valori di ampiezza.

Quello che segue è un ottimo video di Youtube per spiegare i concetti fondamentali del campionamento audio digitale.

Esplorazione dei dati

Da un'ispezione visiva possiamo vedere che è difficile visualizzare la differenza tra alcune delle classi. In particolare, le forme d'onda per i suoni ripetitivi per il condizionatore d'aria, la perforazione, il minimo del motore e il martello pneumatico sono di forma simile.

Questo è il titolo dell'immagine

Successivamente, approfondiremo l'estrazione delle proprietà dei file audio, il numero di canali audio, la frequenza di campionamento e la profondità di bit utilizzando il codice seguente.
2%20Dati%20Preelaborazione%20e%20Dati% 20Splitting.py

# Load various imports import pandas as pd import os import librosa import librosa.display from helpers.wavfilehelper import WavFileHelper wavfilehelper = WavFileHelper() audiodata = [] for index, row in metadata.iterrows(): file_name = os.path.join(os.path.abspath('/UrbanSound8K/audio/'),'fold'+str(row['fold'])+'/',str(row['slice_file_name'])) data = wavfilehelper.read_file_properties(file_name) audiodata.append(data) # Convert into a Panda dataframe audiodf = pd.DataFrame(audiodata, columns=['num_channels','sample_rate','bit_depth'])

wavfilehelper.py

import struct class WavFileHelper(): def read_file_properties(self, filename): wave_file = open(filename,'rb') riff = wave_file.read(12) fmt = wave_file.read(36) num_channels_string = fmt[10:12] num_channels = struct.unpack('

Qui possiamo vedere che il set di dati ha una gamma di proprietà audio variabili che dovranno essere standardizzate prima di poterlo utilizzare per addestrare il nostro modello.

Canali audio la maggior parte dei campioni ha due canali audio (che significa stereo) con alcuni con un solo canale (mono).

Questo è il titolo dell'immagine

Frequenza di campionamento c'è una vasta gamma di frequenze di campionamento che sono state utilizzate in tutti i campioni che è un problema (che vanno da 96kHz a 8kHz).

Questo è il titolo dell'immagine

Bit-profondità c'è anche una gamma di profondità di bit (che vanno da 4 bit a 32 bit).

Questo è il titolo dell'immagine

Pre-trattamento dei dati

Nella sezione precedente abbiamo identificato le seguenti proprietà audio che necessitano di pre-elaborazione per garantire la coerenza nell'intero set di dati:

• Canali audio
• Frequenza di campionamento
• Profondità in bit

Librosa è un pacchetto Python per l'elaborazione di musica e audio di Brian McFee e ci consentirà di caricare l'audio nel nostro notebook come un array numpy per l'analisi e la manipolazione.

Per gran parte della pre-elaborazione saremo in grado di utilizzare Il carico di Librosa () funzione, che per impostazione predefinita converte la frequenza di campionamento a 22,05 KHz, normalizza i dati in modo che i valori di profondità di bit siano compresi tra -1 e 1 e appiattisce i canali audio in mono.

Estrai caratteristiche

Il prossimo passo è estrarre le funzionalità di cui avremo bisogno per addestrare il nostro modello. Per fare ciò, creeremo una rappresentazione visiva di ciascuno dei campioni audio che ci consentirà di identificare le caratteristiche per la classificazione, utilizzando le stesse tecniche utilizzate per classificare le immagini con elevata precisione.

Gli spettrogrammi sono una tecnica utile per visualizzare lo spettro delle frequenze di un suono e come variano durante un periodo di tempo molto breve. Useremo una tecnica simile nota come Coefficienti Cepstrale Mel-Frequency (MFCC) .

La differenza principale è che uno spettrogramma utilizza una scala di frequenza distanziata lineare (quindi ogni bin di frequenza è distanziato di un uguale numero di Hertz), mentre un MFCC utilizza una scala di frequenza distanziata quasi logaritmica, che è più simile a come elabora il sistema uditivo umano suoni.

L'immagine seguente confronta tre diverse rappresentazioni visive di un'onda sonora, la prima è la rappresentazione nel dominio del tempo, confrontando l'ampiezza nel tempo. Il prossimo è uno spettrogramma che mostra l'energia in diverse bande di frequenza che cambia nel tempo, quindi finalmente un MFCC che possiamo vedere è molto simile a uno spettrogramma ma con dettagli più distinguibili.

Questo è il titolo dell'immagine

Per ogni file audio nel set di dati, estrarremo un MFCC (il che significa che abbiamo una rappresentazione dell'immagine per ogni campione audio) e lo memorizzeremo in un Panda Dataframe insieme alla sua etichetta di classificazione. Per questo useremo La funzione mfcc() di Librosa che genera un MFCC da dati audio di serie temporali.

feature_extraction.py

def extract_features(file_name): try: audio, sample_rate = librosa.load(file_name, res_type='kaiser_fast') mfccs = librosa.feature.mfcc(y=audio, sr=sample_rate, n_mfcc=40) mfccsscaled = np.mean(mfccs.T,axis=0) except Exception as e: print('Error encountered while parsing file: ', file) return None return mfccsscaled # Load various imports import pandas as pd import os import librosa # Set the path to the full UrbanSound dataset fulldatasetpath = '/Urban Sound/UrbanSound8K/audio/' metadata = pd.read_csv(fulldatasetpath + '../metadata/UrbanSound8K.csv') features = [] # Iterate through each sound file and extract the features for index, row in metadata.iterrows(): file_name = os.path.join(os.path.abspath(fulldatasetpath),'fold'+str(row['fold'])+'/',str(row['slice_file_name'])) class_label = row['class_name'] data = extract_features(file_name) features.append([data, class_label]) # Convert into a Panda dataframe featuresdf = pd.DataFrame(features, columns=['feature','class_label']) print('Finished feature extraction from ', len(featuresdf), ' files')

Conversione dei dati e delle etichette, quindi suddivisione del set di dati

Useremo |_+_| per codificare i dati di testo categorico in dati numerici comprensibili dal modello.

Quindi useremo |_+_| per dividere il set di dati in set di addestramento e test. La dimensione del set di test sarà del 20% e imposteremo uno stato casuale.

convert_data.py

sklearn.preprocessing.LabelEncoder

Costruire il nostro modello

Il prossimo passo sarà costruire e addestrare una rete neurale profonda con questi set di dati e fare previsioni.

Qui useremo una rete neurale convoluzionale (CNN). Le CNN in genere fanno buoni classificatori e si comportano particolarmente bene con le attività di classificazione delle immagini grazie alle loro parti di estrazione e classificazione delle funzionalità. Credo che questo sarà molto efficace nel trovare schemi all'interno degli MFCC, proprio come sono efficaci nel trovare schemi all'interno delle immagini.

Utilizzeremo un modello sequenziale, partendo da un'architettura del modello semplice, costituita da quattro strati di convoluzione Conv2D, con il nostro strato di output finale che sarà uno strato denso. Il nostro livello di output avrà 10 nodi (num_labels) che corrispondono al numero di possibili classificazioni.

Vedi il rapporto completo per una ripartizione approfondita dei livelli scelti, confrontiamo anche le prestazioni della CNN con un MLP più tradizionale.

cnn.py

sklearn.model_selection.train_test_split

Per compilare il nostro modello, utilizzeremo i seguenti tre parametri:

cnn_compiling.py

from sklearn.preprocessing import LabelEncoder from keras.utils import to_categorical # Convert features and corresponding classification labels into numpy arrays X = np.array(featuresdf.feature.tolist()) y = np.array(featuresdf.class_label.tolist()) # Encode the classification labels le = LabelEncoder() yy = to_categorical(le.fit_transform(y)) # split the dataset from sklearn.model_selection import train_test_split x_train, x_test, y_train, y_test = train_test_split(X, yy, test_size=0.2, random_state = 42)

Qui addestreremo il modello. Poiché l'addestramento di una CNN può richiedere una quantità significativa di tempo, inizieremo con un numero basso di epoche e una dimensione di batch ridotta. Se possiamo vedere dall'output che il modello sta convergendo, aumenteremo entrambi i numeri.

cnn_training.py

import numpy as np from keras.models import Sequential from keras.layers import Dense, Dropout, Activation, Flatten from keras.layers import Convolution2D, Conv2D, MaxPooling2D, GlobalAveragePooling2D from keras.optimizers import Adam from keras.utils import np_utils from sklearn import metrics num_rows = 40 num_columns = 174 num_channels = 1 x_train = x_train.reshape(x_train.shape[0], num_rows, num_columns, num_channels) x_test = x_test.reshape(x_test.shape[0], num_rows, num_columns, num_channels) num_labels = yy.shape[1] filter_size = 2 # Construct model model = Sequential() model.add(Conv2D(filters=16, kernel_size=2, input_shape=(num_rows, num_columns, num_channels), activation='relu')) model.add(MaxPooling2D(pool_size=2)) model.add(Dropout(0.2)) model.add(Conv2D(filters=32, kernel_size=2, activation='relu')) model.add(MaxPooling2D(pool_size=2)) model.add(Dropout(0.2)) model.add(Conv2D(filters=64, kernel_size=2, activation='relu')) model.add(MaxPooling2D(pool_size=2)) model.add(Dropout(0.2)) model.add(Conv2D(filters=128, kernel_size=2, activation='relu')) model.add(MaxPooling2D(pool_size=2)) model.add(Dropout(0.2)) model.add(GlobalAveragePooling2D()) model.add(Dense(num_labels, activation='softmax'))

Quanto segue esaminerà l'accuratezza del modello sia sui set di dati di addestramento che di test.

cnn_testing.py

# Compile the model model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam') # Display model architecture summary model.summary() # Calculate pre-training accuracy score = model.evaluate(x_test, y_test, verbose=1) accuracy = 100*score[1] print('Pre-training accuracy: %.4f%%' % accuracy)

Risultati

Il nostro modello addestrato ha ottenuto un'accuratezza dell'addestramento del 98,19% e un'accuratezza del test del 91,92%.

Le prestazioni sono molto buone e il modello si è generalizzato bene, sembrando prevedere bene quando testato rispetto a nuovi dati audio.

osservazioni

È stato precedentemente notato nella nostra esplorazione dei dati che è difficile visualizzare la differenza tra alcune delle classi. In particolare, i seguenti sottogruppi sono di forma simile:

• Suoni ripetitivi per condizionatore d'aria, perforazione, motore al minimo e martello pneumatico.
• Cime affilate per abbaiare di cani e colpi di pistola.
• Schema simile per i bambini che giocano e la musica di strada.

Utilizzando una matrice di confusione esamineremo se anche il modello finale ha faticato a differenziare tra queste classi.

Questo è il titolo dell'immagine

The Confusion Matrix racconta una storia diversa. Qui possiamo vedere che il nostro modello lotta maggiormente con i seguenti sottogruppi:

come ottenere input in c++

• aria condizionata, martello pneumatico e musica di strada.
• clacson, perforazione e musica di strada.
• condizionatore, bambini che giocano e motore al minimo.
• martello pneumatico e perforazione.
• aria condizionata, clacson, giochi per bambini e musica di strada.

Questo ci mostra che il problema è più sfumato rispetto alla nostra valutazione iniziale e fornisce alcune informazioni sulle caratteristiche che la CNN sta estraendo per fare le sue classificazioni. Ad esempio, la musica di strada è una delle classi comunemente classificate erroneamente e potrebbe corrispondere a un'ampia varietà di campioni diversi all'interno della classe.

Prossimi passi

Il prossimo passo logico è vedere come quanto sopra può essere applicato sia all'audio in streaming in tempo reale che all'utilizzo di suoni del mondo reale.

L'audio nel mondo reale è molto più di una sfida 'disordinata', poiché dovremo adattarsi a diversi suoni di sottofondo, diversi livelli di volume del suono target e la probabilità di echi.

Farlo in tempo reale pone anche le sue sfide in quanto il modello dovrà funzionare bene con una bassa latenza, così come il calcolo MFCC, il tutto durante la sincronizzazione con il thread del buffer audio senza ritardi.

#apprendimento profondo #ai