딥러닝

[DL]8. 소리데이터 분석

CodeJaram 2023. 9. 22. 09:02

딥러닝_08_소리데이터 분석

 

[아기울음소리 분류 실습]

  1. 목표
  • librosa 라이브러리를 이용하여 음성처리하는 방법
  • 소리 데이터를 직접 데이터로 입력받아서 소리분류하는 방법
  • 소리데이터를 MFCC로 변환하여 소리를 분류하는 방법

 

2. 데이터 불러오기

  • 아기 울음소리 데이터셋

-3개의 라벨로 구성(silence, crying, laugh)

-훈련데이터 169개, 테스트 데이터 89개로 구성

 

  • 데이터 압축파일 풀기

#데이터 압축풀기

import zipfile

 

file="./data/baby_sound/baby_sound.zip"

 

 

#파일 읽기

zip_ref=zipfile.ZipFile(file, "r")

 

#지정한 폴더경로에 압축 풀기

zip_ref.extractall("./baby_sound")

 

#압축풀기 종료

zip_ref.close()

 

  • 소리데이터 출력하기

#librosa 라이브러리:  오디오 및 음악 신호 처리 라이브러리

 

import librosa

import librosa.display

import numpy as np

import matplotlib.pyplot as plt

import IPython.display

 

#데이터 폴더 경로

data_dir="./data/baby_sound/"

 

#소리데이터 불러와서 출력

#wav: 소리데이터

#sr: sampling rate(초 당 데이터 수)

wav, sr=librosa.load(data_dir+"test_voice.wav")

#소리 정보 출력

print(f"sr: {sr}")

 

#소리데이터의 구조

print(f"wav의 크기: {wav.shape}")

 

#총 재생시간

print(f"재생시간: {wav.shape[0]/float(sr)}")

 

  • 소리데이터 재생하기

IPython.display.Audio(data=wav, rate=sr)

 

3. 소리데이터 시각화

 

#소리데이터 시각화

plt.plot(wav)

plt.show()

 

#소리의 진폭(높낮이 변화)를 나타냄

#주파수로 변환해서 소리데이터를 분석함

 

 

4. 진폭성분으로 구성된 소리데이터를 주파수 성분(초 당 진동 수)으로 변환

  • 사람마다 목소리에 포함된 주파수 성분은 고유함→성대모양이 다르기 때문
  • 주파수 성분을 분석하면 사람 인식, 소리분석, 음악분석, 목소리 복원 등 가능

 

#진폭을 주파수 변환(푸리에 변환)->amplitude_to_db

 

db=librosa.amplitude_to_db(np.abs(librosa.stft(wav[:2048])))

 

plt.plot(db.flatten())

plt.show()

 

 

 

5. mel-spectrum: 이미지학습을 위해 소리 데이터를 이미지 데이터로 변환

  • mel-spectrum: 사람의 귀에 맞게 데이터를 샘플링한 것
  • 사람은 저주파는 잘 듣고, 고주파는 잘 못 들음
  • 저주파→세밀하게 샘플링, 고주파→듬성듬성 샘플링

#멜스펙트럼으로 변환

#->librosa.feature.melspectrogram()

 

#n_mels: mel-spectrum의 수(그래프 세로축의 눈금 수)

S=librosa.feature.melspectrogram(y=wav, sr=sr, n_mels=128)

 

#시각화를 위해 log사용

log_S=librosa.power_to_db(S, ref=np.max)

 

plt.figure(figsize=(8,4))

librosa.display.specshow(log_S, sr=sr, x_axis="time", y_axis="mel")

 

plt.colorbar()

plt.show()

 

#x축 시간, y축 Mel주파수의 개수

#밝은 색일 수록 Mel주파수의 성분의 개수가 많음

#검정색은 Mel주파수 성분이 없는 것(소리 없음)

#저주파에 Mel주파수의 강도가 높음을 알 수 있음

#그래프가 끊긴 것은 말을 끊어서 말하는 것을 나타냄

 

 

6. MFCC: 멜스펙트럼(아날로그 데이터)을 log를 씌워서 디지털화하는 것

 

#MFCC

#n_nfcc: mfcc의 구분 수(y축 눈금 수)

mfcc=librosa.feature.mfcc(S=log_S, n_nfcc=13)

 

plt.figure(figsize=(8,4))

librosa.display.specshow(mfcc)

 

plt.colorbar()

plt.show()

 



7. 아기 울음소리 분류

 

(1)wav 데이터를 Dense층에 직접 입력하여 학습

1)원본 데이터를 학습용 데이터로 변환

-소리 데이터를 신경망 모델에 입력하기 위해 같은 길이로 조절하는 기능

  • 1차원 wav 데이터 변환함수: 기준길이에 맞추어 데이터 가로 길이 조절

#1차원 wav 데이터 변환하는 함수

#소리데이터(wav), 기준길이(i)

def pad1d(wav, i):

  #소리데이터가 기준길이보다 긴 경우

  if wav.shape[0]>i:

    return wav[: i] #기준길이만큼 자르기

  #소리데이터가 기준길이보다 짧은 경우

  else:

    #hstack(): 1차원 데이터를 가로방향으로 병합하는 함수

    return  np.hstack(wav, np.zeros(i-wav.shape[0])) #기준길이에서 부족한 길이만큼 0을 채움

 

  • 2차원 MFCC 데이터 변환함수: 기준열에 맞춰 데이터 열 길이 조절

#2차원 MFCC 데이터 변환하는 함수

#소리데이터(wav), 기준열(i)

def pad2d(wav, i):

  #mfcc 데이터(2차원)가 기준열보다 긴 경우

  if wav.shape[1]<i:

    return wav[:,:i] #열만 기준열만큼 자르기

 

  #mfcc 데이터(2차원)가 기준열보다 짧은 경우

  else:

    return np.hstack(wav, np.zeros(wav.shape[0], i-wav.shape[1]))

    #행은 그대로 두고 열은 기준열에서 부족한 길이만큼 0을 채움

 

 

2)학습용/평가용 데이터 만들기

 

import os

 

#학습용/평가용 문제/정답 데이터 저장할 리스트

X_train=[]

X_test=[]

y_train=[]

y_test=[]

 

#소리데이터 폴더 경로

baby_dir="./baby_sound/"

 

#train 데이터 폴더 경로

train_dir=baby_dir+"train/"

 

#trian 폴더에 있는 소리 데이터를 함수를 이용하여 학습 데이터로 변환

 

# os.listdir: 폴더의 파일 읽는 함수

for fname in os.listdir(train_dir):

  #label: 파일명을 공백으로 분리하고 0번 인덱스 저장

  label=fname.split(" ")[0]

 

  #y_train에 label 저장

  y_train.append(label)

 

  #wav 파일을 읽은 후 pad1d 함수를 이용하여 같은 길이로 자르기

  wav, sr=librosa.load(train_dir+fname)

  pad_x=pad1d(wav, 30000)

 

 #train 데이터에 저장

  X_train.append(pad_x)

 

#test 폴더에 있는 소리 데이터를 함수를 이용하여 학습 데이터로 변환

 

#test 데이터 폴더 경로

test_dir=baby_dir+"test/"

 

# os.listdir: 폴더의 파일 읽는 함수

for fname in os.listdir(test_dir):

  #label: 파일명을 공백으로 분리하고 0번 인덱스 저장

  label=fname.split(" ")[0]

 

  #y_train에 label 저장

  y_test.append(label)

 

  #wav 파일을 읽은 후 pad1d 함수를 이용하여 같은 길이로 자르기

  wav, sr=librosa.load(test_dir+fname)

  pad_x=pad1d(wav, 30000)

 

 #train 데이터에 저장

  X_test.append(pad_x)



  • 학습용/평가용 데이터 개수 확인

#train/test 데이터 개수 확인

len(X_train), len(X_train[0]), len(X_test), len(X_test[0])

 

3)데이터 변환

  • 가로 형태의 데이터를 세로 형태의 데이터로 변환

#가로 형태로 되어있는 데이터를 세로 형태로 변환

X_train=np.vstack(X_train)

X_test=np.vstack(X_test)

 

len(X_train), len(X_train[0]), len(X_test), len(X_test[0])



  • 정답 데이터 원핫인코딩

import pandas as pd

y_train_en=pd.get_dummies(y_train)

y_test_en=pd.get_dummies(y_test)

 

y_train_en.shape, y_test_en.shape

 

 

4)신경망 구조 설계

 

from tensorflow.keras.models import Sequential

from tensorflow.keras.layers import Dense, Dropout

 

#뼈대

model1=Sequential()

 

#입력층

 

model1.add(Dense(units=512, input_dim=30000, activation='relu'))

 

#은닉층+Dropout으로 과대적합 제어

model1.add(Dropout(0.2))

model1.add(Dense(units=410, activation='relu'))

 

model1.add(Dropout(0.2))

model1.add(Dense(units=350, activation='relu'))

 

model1.add(Dropout(0.2))

model1.add(Dense(units=210, activation='relu'))

 

 

#출력층

model1.add(Dense(units=3, activation='softmax'))

 

model1.summary()

 

 

5)학습방법 및 평가방법 설정

#학습방법 및 평가방법 설정

model1.compile(loss='categorical_crossentropy',

               optimizer='adam',metrics=['accuracy'])

 

 

6)학습

#학습

 

h1=model1.fit(X_train, y_train_en,epochs=20, batch_size=32,

           validation_data=(X_test, y_test_en))

 

#시각화

import matplotlib.pyplot as plt

import numpy as np

 

ep=np.arange(1,21)

 

plt.plot(ep, h1.history['accuracy'], color='red', label='train')

plt.plot(ep, h1.history['val_accuracy'], color='blue', label='test')

 

plt.legend()

plt.show()

 

 

7)예측

#예측

 

pred=model1.predict(X_test)

 

print(pred[10])

print(y_test_en.iloc[10])

 

(2)wav 데이터를 Conv1D 층에 직접 입력하여 학습(시계열 분석)

  1)차원 추가: CNN층에 데이터 입력하기 위해 차원 추가해야 함

#X_train의 끝에 차원 추가

X_train=np.expand_dims(X_train, -1)

 

#X_test의 끝에 차원 추가

X_test=np.expand_dims(X_test, -1)

 

    2)신경망 구조 설계

from tensorflow.keras.models import Sequential

from tensorflow.keras.layers import Dense, Dropout

from tensorflow.keras.layers import Conv1D, MaxPooling1D, GlobalMaxPooling1D

 

 

#뼈대

model2=Sequential()

 

#CNN층

#1차원 데이터

model2.add(Conv1D(filters=64, kernel_size=3, input_shape=(30000,1), activation='relu')) #입력층

model2.add(Conv1D(filters=64, kernel_size=3, activation='relu'))

model2.add(MaxPooling1D(pool_size=3))

 

model2.add(Conv1D(filters=128, kernel_size=3, activation='relu'))

model2.add(Conv1D(filters=128, kernel_size=3, activation='relu'))

 

#GlobalMaxPooling1D: MaxPooling1D+Flatten()

#과대적합 제어

model2.add(GlobalMaxPooling1D())

 

#분류기

model2.add(Dense(units=3, activation='softmax')) #출력층

 

model2.summary()

 

3)학습방법 및 평가방법 설정: 이전과 동일함

4)학습: 이전과 동일함

5)예측: 이전과 동일함

6)평가: 이전과 동일함

 

 

(3)wav 데이터를 MFCC로 변환하여 Conv2D에 입력하여 학습

  1)학습용, 평가용 데이터 만들기: wav→MFCC로 변환

import os

 

X_train=[]

X_test=[]

y_train=[]

y_test=[]

 

baby_dir="./baby_sound/"

train_dir=baby_dir+"train/"

 

#trian 폴더 소리 파일 하나씩 읽어서 학습 데이터로 변환

 

# os.listdir: 폴더의 파일 읽는 함수

for fname in os.listdir(train_dir):

  #label: 파일명을 공백으로 분리하고 0번 인덱스 저장

  label=fname.split(" ")[0]

 

  #y_train에 label 저장

  y_train.append(label)

 

  #wav 파일 읽기

  wav, sr=librosa.load(train_dir+fname)

 

  #wav 파일을 MFCC로 변환하고 pad2d함수로 같은 길이로 조절하기

  S=librosa.feature.melspectrogram(y=wav, sr=sr, n_mels=128)

  log_S=librosa.power_to_db(S, ref=np.max)

  mfcc2 = librosa.feature.mfcc(S=log_S, n_mfcc=20)

  pad_x = pad2d(mfcc2, 40)

 

 

  #train 데이터에 저장

  X_train.append(pad_x)

 

 

#test 폴더 소리 파일 하나씩 읽어서 학습 데이터로 변환

   test_dir=baby_dir+"test/"

 

 # os.listdir: 폴더의 파일 읽는 함수

 for fname in os.listdir(test_dir):

  #label: 파일명을 공백으로 분리하고 0번 인덱스 저장

  label=fname.split(" ")[0]

 

  #y_train에 label 저장

  y_test.append(label)

 

  #wav 파일 읽기

  wav, sr=librosa.load(test_dir+fname)

 

  #wav 파일을 MFCC로 변환하고 pad2d함수로 같은 길이로 조절하기

  S=librosa.feature.melspectrogram(y=wav, sr=sr, n_mels=128)

  log_S=librosa.power_to_db(S, ref=np.max)

  mfcc2 = librosa.feature.mfcc(S=log_S, n_mfcc=20)

  pad_x = pad2d(mfcc2, 40)

 

 #train 데이터에 저장

  X_test.append(pad_x)

 

2)데이터 변환

  • 문제데이터 리스트→배열로 변환하기

#리스트->배열

 

X_train=np.array(X_train)

X_test=np.array(X_test)

 

X_train.shape, X_test.shape

 

  • 정답 데이터 원핫인코딩

#정답 데이터 원핫인코딩

y_train_en=pd.get_dummies(y_train)

y_train_en=pd.get_dummies(y_train)

 

y_train_en.shape, y_test_en.shape

 

  • 차원 추가

#차원 추가

X_train=np.expand_dims(X_train, -1)

X_test=np.expand_dims(X_test, -1)

 

3)신경망 구조 설계

from tensorflow.keras.models import Sequential

from tensorflow.keras.layers import Dense, Dropout

from tensorflow.keras.layers import Conv2D, MaxPooling2D, GlobalMaxPooling2D

 

 

#뼈대

model3=Sequential()

 

#CNN층

#1차원 데이터

model3.add(Conv2D(filters=32, kernel_size=(3,3), input_shape=(20,40,1), activation='relu')) #입력층

 

 

#GlobalMaxPooling2D: MaxPooling1D+Flatten()

#과대적합 제어

model3.add(GlobalMaxPooling2D())

 

#분류기

model3.add(Dense(units=128, activation='relu'))

model3.add(Dense(units=64, activation='relu'))

model3.add(Dense(units=32, activation='relu'))

 

model3.add(Dense(units=3, activation='softmax')) #출력층

 

model3.summary()

 

4)학습방법 및 평가방법 설정: 이전과 동일함

5)학습 및 학습결과 시각화: 이전과 동일함

6)예측: 이전과 동일함

7)평가: 이전과 동일함

 

'딥러닝' 카테고리의 다른 글

[DL]10. 객체 탐지  (0) 2023.10.04
[DL]9. 네이버 영화리뷰 감성분석  (0) 2023.09.27
[DL]7. 과대적합 제어 및 전이학습  (1) 2023.09.21
[DL]6. CNN  (0) 2023.09.20
[DL]5. 오차 역전파  (0) 2023.09.15