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).