小波神经网络算法原理python(使用Python中的线性回归通过语音诊断帕金森氏病)(1)

本文,我们将创建一个简单的Python机器学习算法,以便能够通过声音来诊断该人是否为患者。

我们将使用一组(健康者和帕金森病患者)音频文件库,通过对音频进行一些测量来构建我们的机器学习数据集。建立机器学习数据集后,我们将使用SciKit Learn库训练线性回归模型。最后,我们将构建一个python库,这个库可以轻松集成到其他应用程序中。

数据集

首先,我们需要将音频文件转换成包含音频测量值以及患者是否健康标识的表格。

我们将要使用的音频文件(https://zenodo.org/record/2867216#.Xp4kVsgzaUl )。

让我们从导入必要的Python库开始。

import glob import numpy as np import pandas as pd import parselmouth from parselmouth.praat import call

接下来,我们将创建一个函数,该函数允许您对输入音频文件进行各种复杂的测量。这些测量是通过parselmouth库实现的,它允许在python代码中使用praat。(https://parselmouth.readthedocs.io/en/stable/)

def measurePitch(voiceID, f0min, f0max, unit): Sound = parselmouth.Sound(voiceID) # read the sound pitch = call(sound, "To Pitch", 0.0, f0min, f0max) pointProcess = call(sound, "To PointProcess (periodic, cc)", f0min, f0max)#create a praat pitch object localJitter = call(pointProcess, "Get jitter (local)", 0, 0, 0.0001, 0.02, 1.3) localabsoluteJitter = call(pointProcess, "Get jitter (local, absolute)", 0, 0, 0.0001, 0.02, 1.3) rapJitter = call(pointProcess, "Get jitter (rap)", 0, 0, 0.0001, 0.02, 1.3) ppq5Jitter = call(pointProcess, "Get jitter (ppq5)", 0, 0, 0.0001, 0.02, 1.3) localShimmer = call([sound, pointProcess], "Get shimmer (local)", 0, 0, 0.0001, 0.02, 1.3, 1.6) localdbShimmer = call([sound, pointProcess], "Get shimmer (local_dB)", 0, 0, 0.0001, 0.02, 1.3, 1.6) apq3Shimmer = call([sound, pointProcess], "Get shimmer (apq3)", 0, 0, 0.0001, 0.02, 1.3, 1.6) aqpq5Shimmer = call([sound, pointProcess], "Get shimmer (apq5)", 0, 0, 0.0001, 0.02, 1.3, 1.6) apq11Shimmer = call([sound, pointProcess], "Get shimmer (apq11)", 0, 0, 0.0001, 0.02, 1.3, 1.6) harmonicity05 = call(sound, "To Harmonicity (cc)", 0.01, 500, 0.1, 1.0) hnr05 = call(harmonicity05, "Get mean", 0, 0) harmonicity15 = call(sound, "To Harmonicity (cc)", 0.01, 1500, 0.1, 1.0) hnr15 = call(harmonicity15, "Get mean", 0, 0) harmonicity25 = call(sound, "To Harmonicity (cc)", 0.01, 2500, 0.1, 1.0) hnr25 = call(harmonicity25, "Get mean", 0, 0) harmonicity35 = call(sound, "To Harmonicity (cc)", 0.01, 3500, 0.1, 1.0) hnr35 = call(harmonicity35, "Get mean", 0, 0) harmonicity38 = call(sound, "To Harmonicity (cc)", 0.01, 3800, 0.1, 1.0) hnr38 = call(harmonicity38, "Get mean", 0, 0) return localJitter, localabsoluteJitter, rapJitter, ppq5Jitter, localShimmer, localdbShimmer, apq3Shimmer, aqpq5Shimmer, apq11Shimmer, hnr05, hnr15 ,hnr25 ,hnr35 ,hnr38

然后,我们为每种类型的测量创建一个列表,再创建一个列表用来表示病人是否健康。在列表被填入后用来构建机器学习数据集。

localJitter_list = [] #measure localabsoluteJitter_list = [] #measure rapJitter_list = [] #measure ppq5Jitter_list = [] #measure localShimmer_list = [] #measure localdbShimmer_list = [] #measure apq3Shimmer_list = [] #measure aqpq5Shimmer_list = [] #measure apq11Shimmer_list = [] #measure hnr05_list = [] #measure hnr15_list = [] #measure hnr25_list = [] #measure parkinson_list = [] #Parkinson(1) or healthy(0)

现在,我们可以使用前面创建的函数通过对音频文件进行测量来填充列表。我们需要使用4个for循环来填充列表。

for wave_file in glob.glob("audio/SpontaneousDialogue/PD/*.wav"): sound = parselmouth.Sound(wave_file) (localJitter, localabsoluteJitter, rapJitter, ppq5Jitter, localShimmer, localdbShimmer, apq3Shimmer, aqpq5Shimmer, apq11Shimmer, hnr05, hnr15 ,hnr25 ,hnr35 ,hnr38) = measurePitch(sound, 75, 1000, "Hertz") file_list.append(wave_file) # make an ID list localJitter_list.append(localJitter) # make a mean F0 list localabsoluteJitter_list.append(localabsoluteJitter) # make a sd F0 list rapJitter_list.append(rapJitter) ppq5Jitter_list.append(ppq5Jitter) localShimmer_list.append(localShimmer) localdbShimmer_list.append(localdbShimmer) apq3Shimmer_list.append(apq3Shimmer) aqpq5Shimmer_list.append(aqpq5Shimmer) apq11Shimmer_list.append(apq11Shimmer) hnr05_list.append(hnr05) hnr15_list.append(hnr15) hnr25_list.append(hnr25) parkinson_list.append(1) #1 because parkinson file for wave_file in glob.glob("audio/ReadText/PD/*.wav"): sound = parselmouth.Sound(wave_file) (localJitter, localabsoluteJitter, rapJitter, ppq5Jitter, localShimmer, localdbShimmer, apq3Shimmer, aqpq5Shimmer, apq11Shimmer, hnr05, hnr15 ,hnr25 ,hnr35 ,hnr38) = measurePitch(sound, 75, 1000, "Hertz") file_list.append(wave_file) # make an ID list localJitter_list.append(localJitter) # make a mean F0 list localabsoluteJitter_list.append(localabsoluteJitter) # make a sd F0 list rapJitter_list.append(rapJitter) ppq5Jitter_list.append(ppq5Jitter) localShimmer_list.append(localShimmer) localdbShimmer_list.append(localdbShimmer) apq3Shimmer_list.append(apq3Shimmer) aqpq5Shimmer_list.append(aqpq5Shimmer) apq11Shimmer_list.append(apq11Shimmer) hnr05_list.append(hnr05) hnr15_list.append(hnr15) hnr25_list.append(hnr25) parkinson_list.append(1) #1 because parkinson file for wave_file in glob.glob("audio/SpontaneousDialogue/HC/*.wav"): sound = parselmouth.Sound(wave_file) (localJitter, localabsoluteJitter, rapJitter, ppq5Jitter, localShimmer, localdbShimmer, apq3Shimmer, aqpq5Shimmer, apq11Shimmer, hnr05, hnr15 ,hnr25 ,hnr35 ,hnr38) = measurePitch(sound, 75, 1000, "Hertz") file_list.append(wave_file) # make an ID list localJitter_list.append(localJitter) # make a mean F0 list localabsoluteJitter_list.append(localabsoluteJitter) # make a sd F0 list rapJitter_list.append(rapJitter) ppq5Jitter_list.append(ppq5Jitter) localShimmer_list.append(localShimmer) localdbShimmer_list.append(localdbShimmer) apq3Shimmer_list.append(apq3Shimmer) aqpq5Shimmer_list.append(aqpq5Shimmer) apq11Shimmer_list.append(apq11Shimmer) hnr05_list.append(hnr05) hnr15_list.append(hnr15) hnr25_list.append(hnr25) parkinson_list.append(0) #0 because healthy file for wave_file in glob.glob("audio/ReadText/HC/*.wav"): sound = parselmouth.Sound(wave_file) (localJitter, localabsoluteJitter, rapJitter, ppq5Jitter, localShimmer, localdbShimmer, apq3Shimmer, aqpq5Shimmer, apq11Shimmer, hnr05, hnr15 ,hnr25 ,hnr35 ,hnr38) = measurePitch(sound, 75, 1000, "Hertz") file_list.append(wave_file) # make an ID list localJitter_list.append(localJitter) # make a mean F0 list localabsoluteJitter_list.append(localabsoluteJitter) # make a sd F0 list rapJitter_list.append(rapJitter) ppq5Jitter_list.append(ppq5Jitter) localShimmer_list.append(localShimmer) localdbShimmer_list.append(localdbShimmer) apq3Shimmer_list.append(apq3Shimmer) aqpq5Shimmer_list.append(aqpq5Shimmer) apq11Shimmer_list.append(apq11Shimmer) hnr05_list.append(hnr05) hnr15_list.append(hnr15) hnr25_list.append(hnr25) parkinson_list.append(0) #0 because healthy file

最后,借助于panda和numpy库,我们必须将这些列表分组到一个表中,从而将它们转换为机器学习数据集。

pred = pd.DataFrame(np.column_stack([parkinson_list,localJitter_list, localabsoluteJitter_list, rapJitter_list, ppq5Jitter_list, localShimmer_list, localdbShimmer_list, apq3Shimmer_list, aqpq5Shimmer_list, apq11Shimmer_list, hnr05_list, hnr15_list, hnr25_list]), columns=["Parkinson","Jitter_rel","Jitter_abs","Jitter_RAP","Jitter_PPQ","Shim_loc","Shim_dB","Shim_APQ3","Shim_APQ5","Shi_APQ11", "hnr05", "hnr15", "hnr25"]) #add these lists to pandas in the right order pred['hnr25'].fillna((parkinson['hnr25'].mean()), inplace=True) #Data cleaning because they may be NaN values pred['hnr15'].fillna((parkinson['hnr15'].mean()), inplace=True) #Data cleaning because they may be NaN values pred.to_csv("processed_results.csv", index=False) # Write out the updated dataset

制作机器学习模型

我们将使用前面提到的SciKit learn库的线性回归算法,该算法允许我们根据几个参数(measures)对标签(0或1)进行分类。

首先,我们将通过指定参数(measurements)和标签(0或1)来训练我们的机器学习模型。

parkinson = pd.read_csv("processed_results.csv") #Loading CSV dataset predictors=["Jitter_rel","Jitter_abs","Jitter_RAP","Jitter_PPQ","Shim_loc","Shim_dB","Shim_APQ3","Shim_APQ5","Shi_APQ11","hnr05","hnr15", "hnr25"] #Listing predictors for col in predictors: # Loop through all columns in predictors if parkinson[col].dtype == 'object': # check if column's type is object (text) parkinson[col] = pd.Categorical(parkinson[col]).codes # convert text to numerical from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(parkinson[predictors], parkinson['Parkinson'], test_size=0.25, random_state=1) from sklearn.linear_model import LogisticRegression clf = LogisticRegression() clf.fit(X_train, y_train) train_score = clf.score(X_train, y_train) test_score = clf.score(X_test, y_test) print ('train accuracy =', train_score) print ('test accuracy =', test_score) #train accuracy = 0.6666666666666666 #test accuracy = 0.631578947368421

我们获得0.63的精度,考虑数据集的数据如此有限,这个结果还是令人满意的。

导出机器学习模型的Python代码如下:

import joblib clf.fit(X_train, y_train) joblib.dump(clf, "trainedModel.sav")

制作库

请记住,我们的目标是获得一个可以被另一个程序使用的库。Python实现代码如下:

import joblib import parselmouth from parselmouth.praat import call import pandas as pd import numpy as np import sklearn def loadModel(PATH): clf = joblib.load(PATH) return clf def measurePitch(voiceID, f0min, f0max, unit): sound = parselmouth.Sound(voiceID) # read the sound pitch = call(sound, "To Pitch", 0.0, f0min, f0max) pointProcess = call(sound, "To PointProcess (periodic, cc)", f0min, f0max)#create a praat pitch object localJitter = call(pointProcess, "Get jitter (local)", 0, 0, 0.0001, 0.02, 1.3) localabsoluteJitter = call(pointProcess, "Get jitter (local, absolute)", 0, 0, 0.0001, 0.02, 1.3) rapJitter = call(pointProcess, "Get jitter (rap)", 0, 0, 0.0001, 0.02, 1.3) ppq5Jitter = call(pointProcess, "Get jitter (ppq5)", 0, 0, 0.0001, 0.02, 1.3) localShimmer = call([sound, pointProcess], "Get shimmer (local)", 0, 0, 0.0001, 0.02, 1.3, 1.6) localdbShimmer = call([sound, pointProcess], "Get shimmer (local_dB)", 0, 0, 0.0001, 0.02, 1.3, 1.6) apq3Shimmer = call([sound, pointProcess], "Get shimmer (apq3)", 0, 0, 0.0001, 0.02, 1.3, 1.6) aqpq5Shimmer = call([sound, pointProcess], "Get shimmer (apq5)", 0, 0, 0.0001, 0.02, 1.3, 1.6) apq11Shimmer = call([sound, pointProcess], "Get shimmer (apq11)", 0, 0, 0.0001, 0.02, 1.3, 1.6) harmonicity05 = call(sound, "To Harmonicity (cc)", 0.01, 500, 0.1, 1.0) hnr05 = call(harmonicity05, "Get mean", 0, 0) harmonicity15 = call(sound, "To Harmonicity (cc)", 0.01, 1500, 0.1, 1.0) hnr15 = call(harmonicity15, "Get mean", 0, 0) harmonicity25 = call(sound, "To Harmonicity (cc)", 0.01, 2500, 0.1, 1.0) hnr25 = call(harmonicity25, "Get mean", 0, 0) harmonicity35 = call(sound, "To Harmonicity (cc)", 0.01, 3500, 0.1, 1.0) hnr35 = call(harmonicity35, "Get mean", 0, 0) harmonicity38 = call(sound, "To Harmonicity (cc)", 0.01, 3800, 0.1, 1.0) hnr38 = call(harmonicity38, "Get mean", 0, 0) return localJitter, localabsoluteJitter, rapJitter, ppq5Jitter, localShimmer, localdbShimmer, apq3Shimmer, aqpq5Shimmer, apq11Shimmer, hnr05, hnr15 ,hnr25 ,hnr35 ,hnr38 def predict(clf, wavPath): file_list = [] localJitter_list = [] localabsoluteJitter_list = [] rapJitter_list = [] ppq5Jitter_list = [] localShimmer_list = [] localdbShimmer_list = [] apq3Shimmer_list = [] aqpq5Shimmer_list = [] apq11Shimmer_list = [] hnr05_list = [] hnr15_list = [] hnr25_list = [] hnr35_list = [] hnr38_list = [] sound = parselmouth.Sound(wavPath) (localJitter, localabsoluteJitter, rapJitter, ppq5Jitter, localShimmer, localdbShimmer, apq3Shimmer, aqpq5Shimmer, apq11Shimmer, hnr05, hnr15, hnr25, hnr35, hnr38) = measurePitch(sound, 75, 1000, "Hertz") localJitter_list.append(localJitter) # make a mean F0 list localabsoluteJitter_list.append(localabsoluteJitter) # make a sd F0 list rapJitter_list.append(rapJitter) ppq5Jitter_list.append(ppq5Jitter) localShimmer_list.append(localShimmer) localdbShimmer_list.append(localdbShimmer) apq3Shimmer_list.append(apq3Shimmer) aqpq5Shimmer_list.append(aqpq5Shimmer) apq11Shimmer_list.append(apq11Shimmer) hnr05_list.append(hnr05) hnr15_list.append(hnr15) hnr25_list.append(hnr25) hnr35_list.append(hnr35) hnr38_list.append(hnr38) toPred = pd.DataFrame(np.column_stack( [localJitter_list, localabsoluteJitter_list, rapJitter_list, ppq5Jitter_list, localShimmer_list, localdbShimmer_list, apq3Shimmer_list, aqpq5Shimmer_list, apq11Shimmer_list, hnr05_list, hnr15_list, hnr25_list]), columns=["Jitter_rel", "Jitter_abs", "Jitter_RAP", "Jitter_PPQ", "Shim_loc", "Shim_dB", "Shim_APQ3", "Shim_APQ5", "Shi_APQ11", "hnr05", "hnr15", "hnr25"]) # add these lists to pandas in the right order resp = clf.predict(toPred) resp = str(resp) if resp == "[1.]": return True else: return False

调用上述库的Python代码如下:

from RecognitionLib import * path = "../trainedModel.sav" #Model path clf = loadModel(path) #Model loading print(predict(clf, "../../audio/ok.wav"))#Predicition

最后

可以通过拥有更大的数据集来改进机器学习模型,从而获得更高的精度(即通过从帕金森氏病患者那里获得更多的音频样本)。

,