Final Model#
The next step is to save the best model and let it ready for predicting the Parkinson disease level of new patients.
Requirements#
import numpy as np
import polars as pl
import sys
import pickle
from sklearn.neural_network import MLPClassifier
import seaborn as sns
sns.set_style('whitegrid')
from itertools import combinations
import joblib
sys.path.insert(0, r'C:\Users\fscielzo\Documents\Packages\PyAudio_Package_Private')
from PyAudio import get_X_audio_features
with open(r'C:\Users\fscielzo\Documents\DataScience-GitHub\Audio Analysis\Parkinson_Severity_Classification\results\final_best_method', 'rb') as file:
final_best_method = pickle.load(file)
with open(r'C:\Users\fscielzo\Documents\DataScience-GitHub\Audio Analysis\Parkinson_Severity_Classification\results\final_best_stats', 'rb') as file:
final_best_stats = pickle.load(file)
with open(r'C:\Users\fscielzo\Documents\DataScience-GitHub\Audio Analysis\Parkinson_Severity_Classification\results\final_best_model', 'rb') as file:
final_best_model = pickle.load(file)
with open(r'C:\Users\fscielzo\Documents\DataScience-GitHub\Audio Analysis\Parkinson_Severity_Classification\results\best_params_3', 'rb') as file:
best_params = pickle.load(file)
Data definition#
files_list_name = r'C:\Users\fscielzo\Documents\DataScience-GitHub\Audio Analysis\Parkinson_Severity_Classification\Data\Files_List.txt'
files_df = pl.read_csv(files_list_name, separator='\t', has_header=False, new_columns=['path', 'level'])
fs = 16000 # Sampling frequency
wst = 0.032 # Window size (seconds)
fpt = 0.008 # Frame period (seconds)
nfft = int(np.ceil(wst*fs)) # Window size (samples)
fp = int(np.ceil(fpt*fs)) # Frame period (samples)
nbands = 40 # Number of filters in the filterbank
ncomp = 20 # Number of MFCC components
Y = files_df['level'].to_numpy()
simple_methods = ['MFCC', 'spectral_centroid', 'chroma', 'spectral_bandwidth',
'spectral_contrast', 'spectral_rolloff', 'zero_crossing_rate', 'tempogram']
combined_methods = []
stats = ['mean-std', 'median-std', 'mean-median-std', 'mean-Q25-median-Q75-std']
sizes = range(2, len(simple_methods) + 1)
combined_methods = ['-'.join(sorted(combi)) for size in sizes for combi in combinations(simple_methods, size)]
X_stats, X_stats_train, X_stats_test = {method: {} for method in simple_methods + combined_methods}, {method: {} for method in simple_methods + combined_methods}, {method: {} for method in simple_methods + combined_methods}
for method in simple_methods:
for stat in stats:
X_stats[method][stat] = get_X_audio_features(paths=files_df['path'], method=method, stats=stat, sr=fs, n_fft=nfft, hop_length=fp, n_mels=nbands, n_mfcc=ncomp)
for method in combined_methods:
for stat in stats:
X_stats[method][stat] = np.column_stack([X_stats[method.split('-')[i]][stat] for i in range(0, len(method.split('-')))])
Saving the final model#
# Initializing th ebest model with its best params
final_model = MLPClassifier(random_state=123).set_params(**best_params[final_best_method][final_best_stats][final_best_model])
# Training the model with all the available data, using the predictors matrix obtained with the best method for feature extraction
final_model.fit(X=X_stats[final_best_method][final_best_stats], y=Y)
# Saving the model already initialized and trained
joblib.dump(final_model, r"C:\Users\fscielzo\Documents\DataScience-GitHub\Audio Analysis\Parkinson_Severity_Classification\results\final_model.joblib")
Predicting new data#
Loading the saved model
final_model = joblib.load(r"C:\Users\fscielzo\Documents\DataScience-GitHub\Audio Analysis\Parkinson_Severity_Classification\results\final_model.joblib")
final_best_method
'MFCC-chroma-spectral_bandwidth-spectral_contrast-zero_crossing_rate'
final_best_stats
'mean-Q25-median-Q75-std'
Loading a new audio and extracting its features to be used for predicting its class.
# Image that this audio would be the audio of a new patient
new_audio_file = 'PDSpeechData/loc17/loc17_s01.wav'
individual_methods = final_best_method.split('-')
X_stats_new = {}
for method in individual_methods:
X_stats_new[method] = get_X_audio_features(paths=[new_audio_file], method=method, stats=final_best_stats, sr=fs, n_fft=nfft, hop_length=fp, n_mels=nbands, n_mfcc=ncomp)
X_stats_new[final_best_method] = np.column_stack([X_stats_new[method] for method in individual_methods])
X_stats_new[final_best_method]
array([[-1.85570816e+02, 9.09455872e+01, -2.44680901e+01,
-7.04029322e+00, -1.81235161e+01, 1.39041967e+01,
-2.44391179e+00, -5.16143751e+00, 2.11006179e-01,
-7.74400330e+00, 2.35691810e+00, -2.67633553e+01,
5.93925667e+00, -1.15721340e+01, -4.94519901e+00,
5.14253676e-01, -5.60667944e+00, -6.44442844e+00,
-1.17365682e+00, -7.13852310e+00, -1.89633648e+02,
8.78949642e+01, -2.86219001e+01, -8.75667405e+00,
-2.10318441e+01, 1.22900267e+01, -4.22333467e+00,
-7.48853457e+00, -2.43984455e+00, -9.48855925e+00,
1.24283183e+00, -2.94770994e+01, 4.33485985e+00,
-1.30440550e+01, -6.32022858e+00, -8.08254302e-01,
-6.70881236e+00, -8.22138071e+00, -2.99997491e+00,
-8.18231726e+00, -1.78737259e+02, 9.08615875e+01,
-2.59062710e+01, -7.23408175e+00, -1.86913033e+01,
1.43382187e+01, -1.84077740e+00, -5.62563133e+00,
9.03636396e-01, -7.57154369e+00, 2.89028454e+00,
-2.75321198e+01, 5.99315166e+00, -1.17777500e+01,
-4.63353157e+00, 6.95228815e-01, -5.28252792e+00,
-6.28008127e+00, -1.39672756e-01, -7.07232285e+00,
-1.72016666e+02, 9.48241558e+01, -2.17102180e+01,
-5.72324336e+00, -1.59190898e+01, 1.62780442e+01,
-5.05787343e-01, -3.74578071e+00, 2.97263265e+00,
-6.07587433e+00, 4.47198141e+00, -2.49392586e+01,
7.43928492e+00, -1.05807405e+01, -3.53231090e+00,
2.11837941e+00, -4.14229715e+00, -4.89462614e+00,
1.01112199e+00, -6.14946342e+00, 3.44640160e+01,
8.54371929e+00, 6.75597477e+00, 3.24377370e+00,
4.74247742e+00, 3.56070065e+00, 3.60298586e+00,
4.35234976e+00, 3.89350390e+00, 3.08828521e+00,
3.20561314e+00, 4.40958166e+00, 2.33475471e+00,
2.49087715e+00, 2.19335175e+00, 2.81028867e+00,
2.50210786e+00, 2.40119553e+00, 3.29892015e+00,
1.92691517e+00, 2.68232167e-01, 9.74107757e-02,
7.84232393e-02, 1.81179240e-01, 1.34862140e-01,
1.35297760e-01, 2.20617712e-01, 4.52856570e-01,
8.93089771e-01, 6.17546499e-01, 2.48015136e-01,
2.03347132e-01, 1.82855524e-01, 3.42847975e-02,
3.22547620e-02, 1.58063572e-01, 6.69326093e-02,
8.18430148e-02, 1.53404191e-01, 2.72765324e-01,
8.62154603e-01, 3.47047240e-01, 1.29612152e-01,
1.12793140e-01, 2.53752053e-01, 5.90377823e-02,
5.17480709e-02, 1.83818281e-01, 1.06828719e-01,
1.07313737e-01, 1.99755162e-01, 3.83032024e-01,
1.00000000e+00, 5.70766330e-01, 1.79053977e-01,
1.67406633e-01, 2.96096116e-01, 1.27084665e-01,
9.71525591e-02, 1.98757619e-01, 1.87182598e-01,
1.38937242e-01, 2.51306139e-01, 5.84615633e-01,
1.00000000e+00, 9.77550074e-01, 3.08580481e-01,
2.44446613e-01, 1.44635484e-01, 1.06388748e-01,
9.08590853e-02, 7.64739513e-02, 9.36693773e-02,
1.01360939e-01, 1.32439837e-01, 2.51666516e-01,
1.92621216e-01, 2.88530469e-01, 1.68179289e-01,
1.37687087e-01, 1.10841622e+03, 1.03688598e+03,
1.10835233e+03, 1.16289666e+03, 1.35345014e+02,
1.59233145e+01, 1.97263040e+01, 1.97874896e+01,
2.19017376e+01, 2.17854443e+01, 2.71397313e+01,
2.06653908e+01, 1.29470125e+01, 1.80485732e+01,
1.77418782e+01, 1.95303016e+01, 1.93713544e+01,
2.53756767e+01, 1.80994219e+01, 1.55093246e+01,
1.94724328e+01, 1.98857833e+01, 2.19474409e+01,
2.15898569e+01, 2.73392028e+01, 2.00202393e+01,
1.83502822e+01, 2.14509713e+01, 2.20797367e+01,
2.45153179e+01, 2.40613377e+01, 2.90980859e+01,
2.25949269e+01, 4.90878185e+00, 3.72218075e+00,
3.96292597e+00, 4.04428607e+00, 3.77969961e+00,
3.19132955e+00, 3.90431497e+00, 7.52911218e-02,
7.51953125e-02, 7.61718750e-02, 7.76367188e-02,
6.54263855e-03]])
X_stats_new[final_best_method].shape
(1, 205)
We predict the new audio with the pre-trained model.
final_model.predict(X=X_stats_new[final_best_method])
array([0], dtype=int64)
The new patient is predicted as class 0 (normal).