基于CNN和MFCC的語音情感識別

      網友投稿 1255 2025-03-31

      語音情感識別的主要任務是將蘊含在語音中的情感信息提取出來并識別出其類別。目前對于情感的描述主要有兩種方法。第一種是基于離散的情感劃分,將人類日常生活中廣泛使用的基本情感分為憤怒、開心、興奮、悲傷、厭惡等;另一種是基于連續維度情感劃分,主要通過不同的效價度和激活程度來對不同情感進行區分的。

      那么作為一個分類任務,特征選擇是最關鍵的一步。本文中使用的語音特征是梅爾倒譜系數,有關梅爾倒譜系數是什么和怎樣提取的知識,可參閱文章《Python語音信號處理》。

      本文在一定程度上參考了MITESHPUTHRANNEU/Speech-Emotion-Analyzer這個項目,下面開始介紹如何通過卷積神經網絡進行語音情感分析。

      神經網絡結構

      使用到的架構其實還是很簡單的,如下

      數據集

      我使用到是CASIA的語音情感數據庫。CASIA漢語情感語料庫由中國科學院自動化所(Institute of Automation, Chinese Academy of Sciences)錄制,共包括四個專業發音人,六種情緒生氣(angry)、高興(happy)、害怕(fear)、悲傷(sad)、驚訝(surprise)和中性(neutral),共9600句不同發音。其中300句是相同文本的,也即是說對相同的文本賦以不同的情感來閱讀,這些語料可以用來對比分析不同情感狀態下的聲學及韻律表現;另外100句是不同文本的,這些文本從字面意思就可以看出其情感歸屬,便于錄音人更準確地表現出情感。

      但是完整的CASIA數據集是收費的,因此我只找到了1200句殘缺數據集。我把我找到的數據集放在我的網盤上:https://pan.baidu.com/s/1EsRoKaF17Q_3s2t7OMNibQ。

      特征提取

      我使用librosa模塊進行MFCC的提取,提取代碼如下。

      %matplotlib inline

      import librosa

      import matplotlib.pyplot as plt

      import numpy as np

      path=r'D:\NLP\dataset\語音情感\test.wav'

      y,sr = librosa.load(path,sr=None)

      def normalizeVoiceLen(y,normalizedLen):

      nframes=len(y)

      y = np.reshape(y,[nframes,1]).T

      #歸一化音頻長度為2s,32000數據點

      if(nframes

      res=normalizedLen-nframes

      res_data=np.zeros([1,res],dtype=np.float32)

      y = np.reshape(y,[nframes,1]).T

      y=np.c_[y,res_data]

      else:

      y=y[:,0:normalizedLen]

      return y[0]

      def getNearestLen(framelength,sr):

      framesize = framelength*sr

      #找到與當前framesize最接近的2的正整數次方

      nfftdict = {}

      lists = [32,64,128,256,512,1024]

      for i in lists:

      nfftdict[i] = abs(framesize - i)

      sortlist = sorted(nfftdict.items(), key=lambda x: x[1])#按與當前framesize差值升序排列

      framesize = int(sortlist[0][0])#取最接近當前framesize的那個2的正整數次方值為新的framesize

      return framesize

      VOICE_LEN=32000

      #獲得N_FFT的長度

      N_FFT=getNearestLen(0.25,sr)

      #統一聲音范圍為前兩秒

      y=normalizeVoiceLen(y,VOICE_LEN)

      print(y.shape)

      #提取mfcc特征

      mfcc_data=librosa.feature.mfcc(y=y, sr=sr,n_mfcc=13,n_fft=N_FFT,hop_length=int(N_FFT/4))

      # 畫出特征圖,將MFCC可視化。轉置矩陣,使得時域是水平的

      plt.matshow(mfcc_data)

      plt.title('MFCC')

      上面代碼的作用是加載聲音,取聲音的前兩秒進行情感分析。getNearestLen()函數根據聲音的采樣率確定一個合適的語音幀長用于傅立葉變換。然后通過librosa.feature.mfcc()函數提取mfcc特征,并將其可視化。

      下面的代碼將數據集中的mfcc特征提取出來,并對每幀的mfcc取平均,將結果保存為文件。

      #提取特征

      import os

      import pickle

      counter=0

      fileDirCASIA = r'D:\NLP\dataset\語音情感\CASIA database'

      mfccs={}

      mfccs['angry']=[]

      mfccs['fear']=[]

      mfccs['happy']=[]

      mfccs['neutral']=[]

      mfccs['sad']=[]

      mfccs['surprise']=[]

      mfccs['disgust']=[]

      listdir=os.listdir(fileDirCASIA)

      for persondir in listdir:

      if(not r'.' in persondir):

      emotionDirName=os.path.join(fileDirCASIA,persondir)

      emotiondir=os.listdir(emotionDirName)

      for ed in emotiondir:

      if(not r'.' in ed):

      filesDirName=os.path.join(emotionDirName,ed)

      files=os.listdir(filesDirName)

      for fileName in files:

      if(fileName[-3:]=='wav'):

      counter+=1

      fn=os.path.join(filesDirName,fileName)

      print(str(counter)+fn)

      y,sr = librosa.load(fn,sr=None)

      y=normalizeVoiceLen(y,VOICE_LEN)#歸一化長度

      mfcc_data=librosa.feature.mfcc(y=y, sr=sr,n_mfcc=13,n_fft=N_FFT,hop_length=int(N_FFT/4))

      feature=np.mean(mfcc_data,axis=0)

      mfccs[ed].append(feature.tolist())

      with open('mfcc_feature_dict.pkl', 'wb') as f:

      pickle.dump(mfccs, f)

      數據預處理

      代碼如下:

      %matplotlib inline

      import pickle

      import os

      import librosa

      import matplotlib.pyplot as plt

      import numpy as np

      from keras import layers

      from keras import models

      from keras import optimizers

      from keras.utils import to_categorical

      #讀取特征

      mfccs={}

      with open('mfcc_feature_dict.pkl', 'rb') as f:

      mfccs=pickle.load(f)

      #設置標簽

      emotionDict={}

      emotionDict['angry']=0

      emotionDict['fear']=1

      emotionDict['happy']=2

      emotionDict['neutral']=3

      emotionDict['sad']=4

      emotionDict['surprise']=5

      data=[]

      labels=[]

      data=data+mfccs['angry']

      print(len(mfccs['angry']))

      for i in range(len(mfccs['angry'])):

      labels.append(0)

      data=data+mfccs['fear']

      print(len(mfccs['fear']))

      for i in range(len(mfccs['fear'])):

      labels.append(1)

      print(len(mfccs['happy']))

      data=data+mfccs['happy']

      for i in range(len(mfccs['happy'])):

      labels.append(2)

      print(len(mfccs['neutral']))

      data=data+mfccs['neutral']

      for i in range(len(mfccs['neutral'])):

      labels.append(3)

      print(len(mfccs['sad']))

      data=data+mfccs['sad']

      for i in range(len(mfccs['sad'])):

      labels.append(4)

      print(len(mfccs['surprise']))

      data=data+mfccs['surprise']

      for i in range(len(mfccs['surprise'])):

      labels.append(5)

      print(len(data))

      print(len(labels))

      #設置數據維度

      data=np.array(data)

      data=data.reshape((data.shape[0],data.shape[1],1))

      labels=np.array(labels)

      labels=to_categorical(labels)

      #數據標準化

      DATA_MEAN=np.mean(data,axis=0)

      DATA_STD=np.std(data,axis=0)

      data-=DATA_MEAN

      data/=DATA_STD

      接下來保存好參數,模型預測的時候需要用到。

      paraDict={}

      paraDict['mean']=DATA_MEAN

      paraDict['std']=DATA_STD

      paraDict['emotion']=emotionDict

      with open('mfcc_model_para_dict.pkl', 'wb') as f:

      pickle.dump(paraDict, f)

      最后是打亂數據集并劃分訓練數據和測試數據。

      ratioTrain=0.8

      numTrain=int(data.shape[0]*ratioTrain)

      permutation = np.random.permutation(data.shape[0])

      data = data[permutation,:]

      labels = labels[permutation,:]

      x_train=data[:numTrain]

      x_val=data[numTrain:]

      y_train=labels[:numTrain]

      y_val=labels[numTrain:]

      print(x_train.shape)

      print(y_train.shape)

      print(x_val.shape)

      print(y_val.shape)

      定義模型

      使用keras定義模型,代碼如下:

      from keras.utils import plot_model

      from keras import regularizers

      model = models.Sequential()

      model.add(layers.Conv1D(256,5,activation='relu',input_shape=(126,1)))

      model.add(layers.Conv1D(128,5,padding='same',activation='relu',kernel_regularizer=regularizers.l2(0.001)))

      model.add(layers.Dropout(0.2))

      model.add(layers.MaxPooling1D(pool_size=(8)))

      model.add(layers.Conv1D(128,5,activation='relu',padding='same',kernel_regularizer=regularizers.l2(0.001)))

      model.add(layers.Dropout(0.2))

      model.add(layers.Conv1D(128,5,activation='relu',padding='same',kernel_regularizer=regularizers.l2(0.001)))

      model.add(layers.Dropout(0.2))

      model.add(layers.Conv1D(128,5,padding='same',activation='relu',kernel_regularizer=regularizers.l2(0.001)))

      model.add(layers.Dropout(0.2))

      model.add(layers.MaxPooling1D(pool_size=(3)))

      model.add(layers.Conv1D(256,5,padding='same',activation='relu',kernel_regularizer=regularizers.l2(0.001)))

      model.add(layers.Dropout(0.2))

      model.add(layers.Flatten())

      model.add(layers.Dense(6,activation='softmax'))

      plot_model(model,to_file='mfcc_model.png',show_shapes=True)

      model.summary()

      訓練模型

      編譯并訓練模型

      opt = optimizers.rmsprop(lr=0.0001, decay=1e-6)

      model.compile(loss='categorical_crossentropy', optimizer=opt,metrics=['accuracy'])

      import keras

      callbacks_list=[

      keras.callbacks.EarlyStopping(

      monitor='acc',

      patience=50,

      ),

      keras.callbacks.ModelCheckpoint(

      filepath='speechmfcc_model_checkpoint.h5',

      monitor='val_loss',

      save_best_only=True

      ),

      keras.callbacks.TensorBoard(

      log_dir='speechmfcc_train_log'

      )

      ]

      history=model.fit(x_train, y_train,

      batch_size=16,

      epochs=200,

      validation_data=(x_val, y_val),

      callbacks=callbacks_list)

      model.save('speech_mfcc_model.h5')

      model.save_weights('speech_mfcc_model_weight.h5')

      可視化訓練結果:

      plt.plot(history.history['loss'])

      plt.plot(history.history['val_loss'])

      plt.title('model loss')

      plt.ylabel('loss')

      plt.xlabel('epoch')

      plt.legend(['train', 'test'], loc='upper left')

      plt.show()

      plt.plot(history.history['acc'])

      plt.plot(history.history['val_acc'])

      plt.title('model acc')

      plt.ylabel('acc')

      plt.xlabel('epoch')

      plt.legend(['train', 'test'], loc='upper left')

      plt.show()

      從上圖中可以發現,模型在訓練了60輪后開始過擬合,此時訓練精度達到70%,驗證精度達到50%。最終訓練到200輪后,訓練精度達到95%。

      測試

      最后對訓練好的模型進行測試。

      #單元測試,載入模型

      from keras.models import load_model

      import pickle

      model=load_model('speech_mfcc_model.h5')

      paradict={}

      with open('mfcc_model_para_dict.pkl', 'rb') as f:

      paradict=pickle.load(f)

      DATA_MEAN=paradict['mean']

      DATA_STD=paradict['std']

      emotionDict=paradict['emotion']

      edr = dict([(i, t) for t, i in emotionDict.items()])

      import librosa

      filePath=r'record1.wav'

      y,sr = librosa.load(filePath,sr=None)

      y=normalizeVoiceLen(y,VOICE_LEN)#歸一化長度

      mfcc_data=librosa.feature.mfcc(y=y, sr=sr,n_mfcc=13,n_fft=N_FFT,hop_length=int(N_FFT/4))

      feature=np.mean(mfcc_data,axis=0)

      feature=feature.reshape((126,1))

      feature-=DATA_MEAN

      feature/=DATA_STD

      feature=feature.reshape((1,126,1))

      result=model.predict(feature)

      基于CNN和MFCC的語音情感識別

      index=np.argmax(result, axis=1)[0]

      print(edr[index])

      由于數據集太小的原因,效果也就那樣。

      機器學習 神經網絡 語音通話

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:現在好用的零代碼開發平臺或者低代碼開發平臺有哪些呢?
      下一篇:在word中怎么設定打印紙張的打印方向(打印的時候怎么設置紙張方向)
      相關文章
      亚洲女初尝黑人巨高清| 亚洲精品无码你懂的网站| 亚洲精品成人片在线观看精品字幕| 亚洲成人一区二区| 国产精品无码亚洲一区二区三区| 亚洲色中文字幕在线播放| 亚洲最大av资源站无码av网址| 国产亚洲精品VA片在线播放| 亚洲一级在线观看| 亚洲女人18毛片水真多| 亚洲国产日韩在线| 亚洲精品第一国产综合野| 亚洲www在线观看| 亚洲午夜理论片在线观看| 日韩亚洲人成在线| 在线a亚洲老鸭窝天堂av高清| 亚洲 日韩 色 图网站| 亚洲七久久之综合七久久| 亚洲AV无码一区二区三区久久精品 | 亚洲色大成网站WWW久久九九| 亚洲线精品一区二区三区| 亚洲精品中文字幕乱码三区| 久久久久久久尹人综合网亚洲| 亚洲AV综合色区无码一区爱AV| 久久亚洲精品国产精品黑人| 亚洲嫩模在线观看| 亚洲导航深夜福利| 亚洲色偷偷综合亚洲AV伊人蜜桃| jzzijzzij在线观看亚洲熟妇| 亚洲福利在线播放| 亚洲乱码日产一区三区| 亚洲AV乱码久久精品蜜桃| 亚洲国产精品成人综合久久久| 在线亚洲午夜片AV大片| 无码一区二区三区亚洲人妻| 久久久久国产亚洲AV麻豆| 亚洲精品人成在线观看| 亚洲一区二区三区不卡在线播放| 亚洲中文无码永久免费| 日韩亚洲国产综合久久久| 国产aⅴ无码专区亚洲av麻豆|