Authors: Blake Bullwinkel, Mark Penrod
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
import librosa
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import confusion_matrix, plot_confusion_matrix, accuracy_score
from tensorflow.keras.layers import Input, LSTM, Bidirectional, Dense, Dropout
from tensorflow.keras.models import Model, Sequential
from tensorflow.data import Dataset
!gsutil cp gs://cs181_practical_data/Xtrain_amp.npy ./
!gsutil cp gs://cs181_practical_data/ytrain_amp.npy ./
!gsutil cp gs://cs181_practical_data/Xtest_amp.npy ./
!gsutil cp gs://cs181_practical_data/ytest_amp.npy ./
!gsutil cp gs://cs181_practical_data/Xtrain_mel.npy ./
!gsutil cp gs://cs181_practical_data/ytrain_mel.npy ./
!gsutil cp gs://cs181_practical_data/Xtest_mel.npy ./
!gsutil cp gs://cs181_practical_data/ytest_mel.npy ./
# Load train data
X_amp_train = np.load("Xtrain_amp.npy")
y_amp_train = np.load("ytrain_amp.npy")
X_amp_train.shape
# Load test data
X_amp_test = np.load("Xtest_amp.npy")
y_amp_test = np.load("ytest_amp.npy")
X_amp_test.shape
# Load train data
X_mel_train = np.load("Xtrain_mel.npy")
y_mel_train = np.load("ytrain_mel.npy")
X_mel_train.shape
# Load test data
X_mel_test = np.load("Xtest_mel.npy")
y_mel_test = np.load("ytest_mel.npy")
X_mel_test.shape
def make_spec(amp_i):
mel_i = librosa.feature.melspectrogram(y=amp_i, sr=22050)
assert mel_i.shape == (128,87)
mel_i = mel_i.reshape(1,mel_i.shape[0],mel_i.shape[1])
return mel_i
def amps_to_specs(fold='train'):
amps = np.load('X{}_amp.npy'.format(fold))
ys = np.load('y{}_amp.npy'.format(fold))
mels = [make_spec(amp) for amp in amps]
del amps # save memory
mels = np.concatenate(mels,axis=0)
np.save('X{}_mel.npy'.format(fold),mels)
np.save('y{}_mel.npy'.format(fold),ys)
del mels # save memory
# Flatten Mel spectrogram and normalize data
X_mel_train_flatten = X_mel_train.reshape((X_mel_train.shape[0], -1))
X_mel_test_flatten = X_mel_test.reshape((X_mel_test.shape[0], -1))
# normalize the data
amp_scaler = MinMaxScaler().fit(X_amp_train)
mel_scaler = MinMaxScaler().fit(X_mel_train_flatten)
# amplitude
X_amp_train_scaled = amp_scaler.transform(X_amp_train)
X_amp_test_scaled= amp_scaler.transform(X_amp_test)
# mel spectrogram
X_mel_train_scaled = mel_scaler.transform(X_mel_train_flatten)
X_mel_test_scaled= mel_scaler.transform(X_mel_test_flatten)
# Get PCA components
# amplitude
amp_PCA = PCA(n_components=500).fit(X_amp_train_scaled)
PCA_amp_train = amp_PCA.transform(X_amp_train_scaled)
PCA_amp_test = amp_PCA.transform(X_amp_test_scaled)
# mel spectrogram
mel_PCA = PCA(n_components=500).fit(X_mel_train_scaled)
PCA_mel_train = mel_PCA.transform(X_mel_train_scaled)
PCA_mel_test = mel_PCA.transform(X_mel_test_scaled)
# variance explained
print(f'The first 500 PCs account for {np.sum(amp_PCA.explained_variance_ratio_)*100:0.3}% of the variation in the Amplitude data')
print()
print(f'The first 500 PCs account for {np.sum(mel_PCA.explained_variance_ratio_)*100:0.3}% of the variation in training Mel spectrogram data')
# function to print accuracy
def display_accuracies(data_type, y_train, y_test, train_preds, test_preds):
# confusion matrix
train_conf_mtx = confusion_matrix(y_train, train_preds)
test_conf_mtx = confusion_matrix(y_test, test_preds)
# compute accuracies from confusion matrix
accs_train = [train_conf_mtx[i][i]/np.sum(train_conf_mtx[i,:]) for i in range(10)]
accs_test = [test_conf_mtx[i][i]/np.sum(test_conf_mtx[i,:]) for i in range(10)]
# display
print(f'Class Accuracies {data_type}')
print('----------------------------')
print('Train')
for i in range(10):
print(f'Class {i} accuracy: {accs_train[i] * 100:0.3}%')
print(f'Overall accuracy: {accuracy_score(y_train, train_preds)*100:0.3}%')
print('\nTest:')
for i in range(10):
print(f'Class {i} accuracy: {accs_test[i] * 100:0.3}%')
print(f'Overall accuracy: {accuracy_score(y_test, test_preds)*100:0.3}%')
# return accuracies for plotting
return accs_train, accs_test
# save accuracies for plotting
amp_train_accs_by_model = []
amp_test_accs_by_model = []
mel_train_accs_by_model = []
mel_test_accs_by_model = []
# naive model: predict class based on frequency in data set
classes = range(10)
probs = np.array([12.6, 3.54, 12.53, 9.42, 10.93, 12.98, 1.49, 11.85, 12.03, 12.61])
probs = probs/sum(probs)
naive_train_preds = np.random.choice(classes, size=len(y_amp_train), p=probs)
naive_test_preds = np.random.choice(classes, size=len(y_amp_test), p=probs)
# Report accuracy
amp_train_accs_m0, amp_test_accs_m0 = display_accuracies('Amplitude', y_amp_train, y_amp_test, naive_train_preds, naive_test_preds)
print()
mel_train_accs_m0, mel_test_accs_m0 = display_accuracies('Mel spectrogram', y_mel_train, y_mel_test, naive_train_preds, naive_test_preds)
# save
amp_train_accs_by_model.append(amp_train_accs_m0)
amp_test_accs_by_model.append(amp_test_accs_m0)
mel_train_accs_by_model.append(mel_train_accs_m0)
mel_test_accs_by_model.append(mel_test_accs_m0)
# train logistic regression using PCA
# Amplitude
log_model_amp_m1 = LogisticRegression(multi_class='multinomial', penalty='none', max_iter=2000).fit(PCA_amp_train, y_amp_train)
amp_train_preds_m1 = log_model_amp_m1.predict(PCA_amp_train)
amp_test_preds_m1 = log_model_amp_m1.predict(PCA_amp_test)
# Mel spectrogram
log_model_mel_m1 = LogisticRegression(multi_class='multinomial', penalty='none', max_iter=2000).fit(PCA_mel_train, y_mel_train)
mel_train_preds_m1 = log_model_mel_m1.predict(PCA_mel_train)
mel_test_preds_m1 = log_model_mel_m1.predict(PCA_mel_test)
# Report accuracy
amp_train_accs_m1, amp_test_accs_m1 = display_accuracies('Amplitude', y_amp_train, y_amp_test, amp_train_preds_m1, amp_test_preds_m1)
print()
mel_train_accs_m1, mel_test_accs_m1 = display_accuracies('Mel spectrogram', y_mel_train, y_mel_test, mel_train_preds_m1, mel_test_preds_m1)
# save
amp_train_accs_by_model.append(amp_train_accs_m1)
amp_test_accs_by_model.append(amp_test_accs_m1)
mel_train_accs_by_model.append(mel_train_accs_m1)
mel_test_accs_by_model.append(mel_test_accs_m1)
# train logistic regression using PCA
# Amplitude
log_model_amp_m2 = LogisticRegression(multi_class='multinomial', max_iter=2000).fit(PCA_amp_train, y_amp_train)
amp_train_preds_m2 = log_model_amp_m2.predict(PCA_amp_train)
amp_test_preds_m2 = log_model_amp_m2.predict(PCA_amp_test)
# Mel spectrogram
log_model_mel_m2 = LogisticRegression(multi_class='multinomial', max_iter=2000).fit(PCA_mel_train, y_mel_train)
mel_train_preds_m2 = log_model_mel_m2.predict(PCA_mel_train)
mel_test_preds_m2 = log_model_mel_m2.predict(PCA_mel_test)
# Report accuracy
amp_train_accs_m2, amp_test_accs_m2 = display_accuracies('Amplitude', y_amp_train, y_amp_test, amp_train_preds_m2, amp_test_preds_m2)
print()
mel_train_accs_m2, mel_test_accs_m2 = display_accuracies('Mel spectrogram', y_mel_train, y_mel_test, mel_train_preds_m2, mel_test_preds_m2)
# save
amp_train_accs_by_model.append(amp_train_accs_m2)
amp_test_accs_by_model.append(amp_test_accs_m2)
mel_train_accs_by_model.append(mel_train_accs_m2)
mel_test_accs_by_model.append(mel_test_accs_m2)
# train logistic regression using PCA
# Amplitude
log_model_amp_m3 = LogisticRegression(multi_class='multinomial', class_weight='balanced', max_iter=2000).fit(PCA_amp_train, y_amp_train)
amp_train_preds_m3 = log_model_amp_m3.predict(PCA_amp_train)
amp_test_preds_m3 = log_model_amp_m3.predict(PCA_amp_test)
# Mel spectrogram
log_model_mel_m3 = LogisticRegression(multi_class='multinomial', class_weight='balanced', max_iter=2000).fit(PCA_mel_train, y_mel_train)
mel_train_preds_m3 = log_model_mel_m3.predict(PCA_mel_train)
mel_test_preds_m3 = log_model_mel_m3.predict(PCA_mel_test)
# Report accuracy
amp_train_accs_m3, amp_test_accs_m3 = display_accuracies('Amplitude', y_amp_train, y_amp_test, amp_train_preds_m3, amp_test_preds_m3)
print()
mel_train_accs_m3, mel_test_accs_m3 = display_accuracies('Mel spectrogram', y_mel_train, y_mel_test, mel_train_preds_m3, mel_test_preds_m3)
# save
amp_train_accs_by_model.append(amp_train_accs_m3)
amp_test_accs_by_model.append(amp_test_accs_m3)
mel_train_accs_by_model.append(mel_train_accs_m3)
mel_test_accs_by_model.append(mel_test_accs_m3)
# plot via transforming to dataframe
# Amplitude Train
amp_train_data = pd.DataFrame(np.transpose(amp_train_accs_by_model), columns=['Naïve Model', 'Model 1', 'Model 2', 'Model 3'])
amp_train_plot = amp_train_data.plot.bar()
amp_train_plot.set_xticklabels(range(10), rotation=0)
amp_train_plot.set_ylim(0,1)
amp_train_plot.set_xlabel('Class')
amp_train_plot.set_ylabel('Accuracy')
amp_train_plot.legend(bbox_to_anchor=(1.4, 1))
amp_train_plot.set_title('Class Accuracies by Model – Amplitude (train)');
# Amplitude Test
amp_test_data = pd.DataFrame(np.transpose(amp_test_accs_by_model), columns=['Naïve Model', 'Model 1', 'Model 2', 'Model 3'])
amp_test_plot = amp_test_data.plot.bar()
amp_test_plot.set_xticklabels(range(10), rotation=0)
amp_test_plot.set_ylim(0,1)
amp_test_plot.set_xlabel('Class')
amp_test_plot.set_ylabel('Accuracy')
amp_test_plot.legend(bbox_to_anchor=(1.4, 1))
amp_test_plot.set_title('Class Accuracies by Model – Amplitude (test)');
# Mel spectrogram Train
mel_train_data = pd.DataFrame(np.transpose(mel_train_accs_by_model), columns=['Naïve Model', 'Model 1', 'Model 2', 'Model 3'])
mel_train_plot = mel_train_data.plot.bar()
mel_train_plot.set_xticklabels(range(10), rotation=0)
mel_train_plot.set_ylim(0,1)
mel_train_plot.set_xlabel('Class')
mel_train_plot.set_ylabel('Accuracy')
mel_train_plot.legend(bbox_to_anchor=(1.05, 1))
mel_train_plot.set_title('Class Accuracies by Model – Mel spectrogram (train)');
# Mel spectrogram Test
mel_test_data = pd.DataFrame(np.transpose(mel_test_accs_by_model), columns=['Naïve Model', 'Model 1', 'Model 2', 'Model 3'])
mel_test_plot = mel_test_data.plot.bar()
mel_test_plot.set_xticklabels(range(10), rotation=0)
mel_test_plot.set_ylim(0,1)
mel_test_plot.set_xlabel('Class')
mel_test_plot.set_ylabel('Accuracy')
mel_test_plot.legend(bbox_to_anchor=(1.4, 1))
mel_test_plot.set_title('Class Accuracies by Model – Mel spectrogram (test)');
from imblearn.over_sampling import SMOTE
# Balance the amplitude training data
sm = SMOTE()
X_amp_train_balanced, y_amp_train_balanced = sm.fit_resample(X_amp_train, y_amp_train)
# normalize the data
amp_scaler = MinMaxScaler().fit(X_amp_train_balanced)
# amplitude
X_amp_train_balanced_scaled = amp_scaler.transform(X_amp_train_balanced)
X_amp_test_scaled = amp_scaler.transform(X_amp_test)
# Get PCA components
# amplitude
amp_PCA_balanced = PCA(n_components=500).fit(X_amp_train_balanced_scaled)
PCA_amp_train_balanced = amp_PCA_balanced.transform(X_amp_train_balanced_scaled)
PCA_amp_test = amp_PCA_balanced.transform(X_amp_test_scaled)
# Train kNN classifiers on the balanced amplitude PCA data
# Amplitude data
amp_knn = KNeighborsClassifier(n_neighbors=3)
amp_knn.fit(PCA_amp_train_balanced, y_amp_train_balanced)
amp_knn_train_pred = amp_knn.predict(PCA_amp_train_balanced)
amp_knn_test_pred = amp_knn.predict(PCA_amp_test)
knn_amp_train_accs, knn_amp_test_accs = display_accuracies('Amplitude', y_amp_train_balanced, y_amp_test, amp_knn_train_pred, amp_knn_test_pred)
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
# Train kNN classifiers on the PCA data
# Amplitude data
amp_knn = KNeighborsClassifier(n_neighbors=3)
amp_knn.fit(PCA_amp_train, y_amp_train)
amp_knn_train_pred = amp_knn.predict(PCA_amp_train)
amp_knn_test_pred = amp_knn.predict(PCA_amp_test)
# Spectrogram data
mel_knn = KNeighborsClassifier(n_neighbors=5)
mel_knn.fit(PCA_mel_train, y_mel_train)
mel_knn_train_pred = mel_knn.predict(PCA_mel_train)
mel_knn_test_pred = mel_knn.predict(PCA_mel_test)
# Report accuracy
knn_amp_train_accs, knn_amp_test_accs = display_accuracies('Amplitude', y_amp_train, y_amp_test, amp_knn_train_pred, amp_knn_test_pred)
print()
knn_mel_train_accs, knn_mel_test_accs = display_accuracies('Mel spectrogram', y_mel_train, y_mel_test, mel_knn_train_pred, mel_knn_test_pred)
# Train random forest classifiers on the PCA data
# Amplitude data
amp_rfc = RandomForestClassifier(n_estimators=100, max_depth=20, min_samples_leaf=1)
amp_rfc.fit(PCA_amp_train, y_amp_train)
amp_rfc_train_pred = amp_knn.predict(PCA_amp_train)
amp_rfc_test_pred = amp_knn.predict(PCA_amp_test)
# Spectrogram data
mel_rfc = RandomForestClassifier(n_estimators=100, max_depth=20, min_samples_leaf=1)
mel_rfc.fit(PCA_mel_train, y_mel_train)
mel_rfc_train_pred = mel_knn.predict(PCA_mel_train)
mel_rfc_test_pred = mel_knn.predict(PCA_mel_test)
# Report accuracy
rfc_amp_train_accs, rfc_amp_test_accs = display_accuracies('Amplitude', y_amp_train, y_amp_test, amp_rfc_train_pred, amp_rfc_test_pred)
print()
rfc_mel_train_accs, rfc_mel_test_accs = display_accuracies('Mel spectrogram', y_mel_train, y_mel_test, mel_rfc_train_pred, mel_rfc_test_pred)
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.utils import to_categorical
# Train FFNN on the amplitude data
# One-hot encode the class labels
y_amp_train_categorical = to_categorical(y_amp_train)
y_amp_test_categorical = to_categorical(y_amp_test)
y_mel_train_categorical = to_categorical(y_mel_train)
y_mel_test_categorical = to_categorical(y_mel_test)
# Define the FFNN
def ffnn():
ffnn = Sequential()
ffnn.add(Dense(500, input_dim=500, activation='relu'))
ffnn.add(Dropout(0.5))
ffnn.add(Dense(300, activation='relu'))
ffnn.add(Dropout(0.5))
ffnn.add(Dense(100, activation='relu'))
ffnn.add(Dense(10, activation='softmax'))
ffnn.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return ffnn
# Amplitude data
amp_ffnn = ffnn()
amp_ffnn.fit(PCA_amp_train, y_amp_train_categorical, verbose=0, epochs=100)
amp_ffnn_train_pred = amp_ffnn.predict(PCA_amp_train)
amp_ffnn_test_pred = amp_ffnn.predict(PCA_amp_test)
amp_ffnn_train_pred = [np.argmax(pred) for pred in amp_ffnn_train_pred]
amp_ffnn_test_pred = [np.argmax(pred) for pred in amp_ffnn_test_pred]
# Spectrogram data
mel_ffnn = ffnn()
mel_ffnn.fit(PCA_mel_train, y_mel_train_categorical, verbose=0, epochs=100)
mel_ffnn_train_pred = mel_ffnn.predict(PCA_mel_train)
mel_ffnn_test_pred = mel_ffnn.predict(PCA_mel_test)
mel_ffnn_train_pred = [np.argmax(pred) for pred in mel_ffnn_train_pred]
mel_ffnn_test_pred = [np.argmax(pred) for pred in mel_ffnn_test_pred]
# Report accuracy
ffnn_amp_train_accs, ffnn_amp_test_accs = display_accuracies('Amplitude', y_amp_train, y_amp_test, amp_ffnn_train_pred, amp_ffnn_test_pred)
print()
ffnn_mel_train_accs, ffnn_mel_test_accs = display_accuracies('Mel spectrogram', y_mel_train, y_mel_test, mel_ffnn_train_pred, mel_ffnn_test_pred)
def plot_class_accuracies(accuracies, model_names, data_label, train_or_test, anchor):
data = pd.DataFrame(np.transpose(accuracies), columns=model_names)
accs_plot = data.plot.bar()
accs_plot.set_xticklabels(range(len(accuracies[0])), rotation=0)
accs_plot.set_ylim(0,1.1)
accs_plot.set_xlabel('Class')
accs_plot.set_ylabel('Accuracy')
accs_plot.legend(bbox_to_anchor=anchor)
accs_plot.set_title(f'Class Accuracy by Model – {data_label} ({train_or_test})')
plt.show()
# Amplitude train
plot_class_accuracies([knn_amp_train_accs, rfc_amp_train_accs, ffnn_amp_train_accs],
['KNN', 'Random Forest', 'FFNN'],
'Amplitude',
'train',
anchor=(1.05,1))
# Amplitude test
plot_class_accuracies([knn_amp_test_accs, rfc_amp_test_accs, ffnn_amp_test_accs],
['KNN', 'Random Forest', 'FFNN'],
'Amplitude',
'test',
anchor=(1.4,1))
# Mel spectrogram train
plot_class_accuracies([knn_mel_train_accs, rfc_mel_train_accs, ffnn_mel_train_accs],
['KNN', 'Random Forest', 'FFNN'],
'Mel spectrogram',
'train',
anchor=(1.4,1))
# Mel spectrogram test
plot_class_accuracies([knn_mel_test_accs, rfc_mel_test_accs, ffnn_mel_test_accs],
['KNN', 'Random Forest', 'FFNN'],
'Mel spectrogram',
'test',
anchor=(1.4,1))
from sklearn.model_selection import ParameterGrid
# Define a function to do hyper-parameter optimization via grid search
def grid_search(inputTrain, targetTrain, inputTest,
targetTest, max_depth, min_samples_leaf):
'''
INPUTS
======
inputTrain: list or np.ndarray of training input
targetTrain: list or np.ndarray of training target
inputTest: list or np.ndarray of test input
targestTest: list or np.ndarray of test target
max_depth: list of np.ndarray of max_depth values to search
min_samples_leaf: list of np.ndarray of min_samples_leaf values to search
RETURNS
=======
accuracy_vals: 2d np.ndarray of test (overall) accuracy values
'''
# Set the parameter grid
param_grid = {'max_depth': max_depth, 'min_samples_leaf': min_samples_leaf}
# Set the grid to be searched
grid = ParameterGrid(param_grid)
# Initialize a 2d numpy array to hold accuracy values
accuracy_vals = np.zeros((len(min_samples_leaf), len(max_depth)))
# Loop through the grid parameters
for params in grid:
# Get spectral radius value and index
max_depth_val = params['max_depth']
max_depth_idx = np.where(max_depth==max_depth_val)[0][0]
# Get sparsity value and index
min_samples_leaf_val = params['min_samples_leaf']
min_samples_leaf_idx = np.where(min_samples_leaf==min_samples_leaf_val)[0][0]
# Initialize a random forest classifier
rfc = RandomForestClassifier(
n_estimators=100,
max_depth=max_depth_val,
min_samples_leaf=min_samples_leaf_val)
# Fit to the training data
rfc.fit(inputTrain, targetTrain)
# Predict on the test data
test_pred = rfc.predict(inputTest)
# Calculate the accuracy of the predictions
test_accuracy = accuracy_score(targetTest, test_pred)
# Insert the accuracy in accuracy_vals
accuracy_vals[min_samples_leaf_idx][max_depth_idx] = test_accuracy
# Return the 2d array of accuracy values
return accuracy_vals
# Set values of max_depth and min_samples_leaf to search
max_depth_vals = np.array([20, 30, 40, 50, 60])
min_samples_leaf_vals = np.array([1, 2, 3, 4, 5])
# Perform grid search for amplitude data
amp_accuracy_vals = grid_search(inputTrain=PCA_amp_train, targetTrain=y_amp_train, inputTest=PCA_amp_test,
targetTest=y_amp_test, max_depth=max_depth_vals, min_samples_leaf=min_samples_leaf_vals)
# Plot a heatmap to visualize the hyper-parameter search
plt.figure(figsize=(8,5))
plt.imshow(amp_accuracy_vals, cmap=plt.cm.hot)
plt.xlabel('max_depth', fontsize=15)
plt.ylabel('min_samples_leaf', fontsize=15)
plt.xticks([0,1,2,3,4], max_depth_vals)
plt.yticks([0,1,2,3,4], min_samples_leaf_vals)
plt.title('Amplitude heatmap for hyper-parameter search', fontsize=15)
cbar = plt.colorbar()
cbar.ax.set_ylabel('Test Accuracy', rotation=270, fontsize=12, labelpad=16)
plt.tight_layout()
# Print out the optimal test accuracy
print(f'The best test accuracy found optimizing hyper-parameters for the amplitude data is {np.max(amp_accuracy_vals):.4f}')
# Extract the optimal hyper-parameters
best_min_samples_idx, best_max_depth_idx = np.where(amp_accuracy_vals == np.max(amp_accuracy_vals))
best_min_samples = min_samples_leaf_vals[best_min_samples_idx][0]
best_max_depth = max_depth_vals[best_max_depth_idx][0]
print(f"The optimal max_depth value is: {best_max_depth}")
print(f"The optimal min_samples_leaf value is: {best_min_samples}")
# Perform grid search for mel spectrogram data
mel_accuracy_vals = grid_search(inputTrain=PCA_mel_train, targetTrain=y_mel_train, inputTest=PCA_mel_test,
targetTest=y_mel_test, max_depth=max_depth_vals, min_samples_leaf=min_samples_leaf_vals)
# Plot a heatmap to visualize the hyper-parameter search
plt.figure(figsize=(8,5))
plt.imshow(mel_accuracy_vals, cmap=plt.cm.hot)
plt.xlabel('max_depth', fontsize=15)
plt.ylabel('min_samples_leaf', fontsize=15)
plt.xticks([0,1,2,3,4], max_depth_vals)
plt.yticks([0,1,2,3,4], min_samples_leaf_vals)
plt.title('Mel spectrogram heatmap for hyper-parameter search', fontsize=15)
cbar = plt.colorbar()
cbar.ax.set_ylabel('Test Accuracy', rotation=270, fontsize=12, labelpad=16)
plt.tight_layout()
# Print out the optimal test accuracy
print(f'The best test accuracy found optimizing hyper-parameters for the Mel spectrogram data is {np.max(mel_accuracy_vals):.4f}')
# Extract the optimal hyper-parameters
best_min_samples_idx, best_max_depth_idx = np.where(mel_accuracy_vals == np.max(mel_accuracy_vals))
best_min_samples = min_samples_leaf_vals[best_min_samples_idx][0]
best_max_depth = max_depth_vals[best_max_depth_idx][0]
print(f"The optimal max_depth value is: {best_max_depth}")
print(f"The optimal min_samples_leaf value is: {best_min_samples}")
# Perform hyperparameter tuning for kNN
n_neighbors_list = [1,2,3,4,5,6]
# Initialize empty arrays to hold test accuracies
knn_amp_test_accuracies = []
knn_mel_test_accuracies = []
# Loop throug the values of k
for k in n_neighbors_list:
amp_knn = KNeighborsClassifier(n_neighbors=k)
amp_knn.fit(PCA_amp_train, y_amp_train)
amp_knn_test_pred = amp_knn.predict(PCA_amp_test)
mel_knn = KNeighborsClassifier(n_neighbors=k)
mel_knn.fit(PCA_mel_train, y_mel_train)
mel_knn_test_pred = mel_knn.predict(PCA_mel_test)
amp_test_accuracy = accuracy_score(y_amp_test, amp_knn_test_pred)
mel_test_accuracy = accuracy_score(y_mel_test, mel_knn_test_pred)
knn_amp_test_accuracies.append(amp_test_accuracy)
knn_mel_test_accuracies.append(mel_test_accuracy)
# Print out the results
print(f"The best accuracy achieved for amplitude was: {max(knn_amp_test_accuracies):.4f} with k={np.argmax(knn_amp_test_accuracies)+1}")
print(f"The best accuracy achieved for Mel spectrogram was: {max(knn_mel_test_accuracies):.4f} with k={np.argmax(knn_mel_test_accuracies)+1}")
Mel spectrogram
# convert flattened and scaled mel data back to 3d
X_mel_train_input = X_mel_train_scaled.reshape(X_mel_train.shape)
X_mel_test_input = X_mel_test_scaled.reshape(X_mel_test.shape)
# split data into train and val
X_mel_train_input, X_mel_val_input, y_mel_train, y_mel_val = train_test_split(X_mel_train_input, y_mel_train, train_size=0.8)
# save into dataframe
mel_train_data = Dataset.from_tensor_slices((X_mel_train_input, tf.keras.utils.to_categorical(y_mel_train))).batch(32)
mel_val_data = Dataset.from_tensor_slices((X_mel_val_input, tf.keras.utils.to_categorical(y_mel_val))).batch(32)
mel_test_data = Dataset.from_tensor_slices((X_mel_test_input, tf.keras.utils.to_categorical(y_mel_test))).batch(32)
# Create LSTM
lstm = Sequential(name='Mel')
lstm.add(Bidirectional(LSTM(128), input_shape=X_mel_train_input.shape[1:]))
# lstm.add(Bidirectional(LSTM(64)))
lstm.add(Dense(500, activation='relu'))
lstm.add(Dropout(0.05))
lstm.add(Dense(256, activation='relu'))
lstm.add(Dropout(0.05))
lstm.add(Dense(128, activation='relu'))
lstm.add(Dense(10, activation='softmax'))
lstm.summary()
lstm.compile(
optimizer=tf.optimizers.Adam(1e-4),
loss='categorical_crossentropy',
metrics='accuracy'
)
es = EarlyStopping(monitor='val_loss', patience=30)
mel_history = lstm.fit(mel_train_data,
validation_data=mel_val_data,
epochs=175,
verbose=2)
fig, axs = plt.subplots(1, 2, figsize=(12,5))
num_epochs = len(mel_history.history['accuracy'])
axs[0].plot(range(num_epochs), mel_history.history['accuracy'], label='train accuracy')
axs[0].plot(range(num_epochs), mel_history.history['val_accuracy'], label='validation accuracy')
axs[0].set_xlabel('Epochs')
axs[0].set_ylabel('Accuracy')
axs[0].set_title('LSTM – Train and Val Accuracy')
axs[0].legend()
axs[1].plot(range(num_epochs), mel_history.history['loss'], label='train loss')
axs[1].plot(range(num_epochs), mel_history.history['val_loss'], label='validation loss')
axs[1].set_xlabel('Epochs')
axs[1].set_ylabel('Loss')
axs[1].set_title('LSTM – Train and Val Loss')
axs[1].legend();
test_accuracy = lstm.evaluate(mel_test_data)[1]
final_val_acc = mel_history.history['val_accuracy'][-1]
final_train_acc = mel_history.history['accuracy'][-1]
print(f'The LSTM\'s accuracy for the test set is {test_accuracy*100:0.4}%')
print(f'The final training and test accuracies are {final_train_acc*100:0.4}% and {final_val_acc*100:0.4}%, respectively')