1 개와 고양이 음성 분류 신경망 코드 설명
=> 코드 진행은 구글 코랩에서 진행합니다.
1. 구글 드라이브를 마운트 합니다.
from google.colab import drive
drive.mount('/content/drive')
2. 구글 드라이브에 데이터 업로드 후 압축해제합니다.
!unzip -qq /content/drive/MyDrive/ColabNotebooks/cats_dogs.zip -d /content/drive/MyDrive/ColabNotebooks/cats_dogs
3. 필요한 패키지를 로드하고 seed값을 설정합니다.
import pandas as pd
import numpy as np
import glob #glob 모듈의 glob 함수는 사용자가 제시한 조건에 맞는 파일명을 리스트 형식으로 반환한다.
# glob을 이용하면 편하게 데이터를 로드할 수 있음
import tensorflow as tf
tf.random.set_seed(777)
4. 데이터를 로드해서 X_path에 담습니다.
Test_root = glob.glob('/content/drive/MyDrive/ColabNotebooks/cats_dogs/test')[0]
Train_root = glob.glob('/content/drive/MyDrive/ColabNotebooks/cats_dogs/train')[0]
X_path = glob.glob(Test_root + "/dogs/*")
X_path = X_path + glob.glob(Test_root + "/cats/*")
X_path = X_path + glob.glob(Train_root + "/dog/*")
X_path = X_path + glob.glob(Train_root + "/cat/*")
print(X_path)
5. 정답 데이터 라벨링을 진행합니다.
#정답 데이터 만드는 코드(고양이 0, 강아지 1)
import ntpath # 특정 경로에서 파일들을 가져오는 라이브러리
y = np.empty((0, 1, )) # 비어있는 리스트를 만듭니다.
for f in X_path:
if 'cat' in ntpath.basename(f): # 음성 데이터가 있는 디렉토리의 데이터가 고양이 음성 데이터라면
resp = np.array([0]) # [0]
resp = resp.reshape(1, 1, ) # [[0]] 2차원 데이터로 생성
y = np.vstack((y, resp)) # 배열을 세로로 결합
elif 'dog' in ntpath.basename(f): # 음성 데이터가 있는 디렉토리의 데이터가 개 음성 데이터라면
resp = np.array([1]) # [1]
resp = resp.reshape(1, 1, ) #[[1]]
y = np.vstack((y, resp)) #
print (len(y))
6. 훈련데이터와 테스트 데이터를 분리합니다.
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X_path, y, test_size=0.25, random_state=42)
7. 파이썬으로 음원 파일이 잘 들어왔는지 확인해봅니다.
import IPython.display as ipd # 음원 파일의 소리를 들을 수 있도록 오디오 플레이 화면을 디스플레이
ipd.Audio(X_train[1])
8. 개와 고양이 음성에서 진폭을 담는 함수를 생성합니다.
# 개와 고양이 음성에서 진폭을 담는 함수 생성
import librosa #음원 데이터를 분석해주는 아주 고마운 라이브러리
# https://hyongdoc.tistory.com/401 음성 파일 로드하는 부분 설명 잘한 블러그
def librosa_read_wav_files(wav_files):
if not isinstance(wav_files, list): # https://brownbears.tistory.com/155 isinstance(1, int) # 1이 int형인지 알아봅니다. 결과는 True 입니다.
wav_files = [wav_files] # wav_files에 있는 데이터가 리스트가 아니라면 리스트시켜라
return [librosa.load(f)[0] for f in wav_files]
9. 첫번째 동물의 sample rate값을 wave_rate에 담고 훈련데이터와 테스트 데이터를 진폭데이터로 변환합니다.
wav_rate = librosa.load(X_train[0])[1] # 훈련데이터 첫번째 동물의 sample rate값을 wave_rate에 담음
X_train = librosa_read_wav_files(X_train) #훈련데이터 207개의 진폭 데이터를 X_train에 담음
X_test = librosa_read_wav_files(X_test) #테스트 데이터 70개의 진폭 데이터를 X_test에 담음
print(len(X_train))
print(len(X_test))
print(X_train[0])
wav_rate = librosa.load(X_train[0])[1]
첫번째 동물을 기준으로 wav_rate를 담은 이유는 개와 고양이 음성에 대한 wav_rate는 비행기 소리, 사람 목소리와는 다른 범위에 있습니다. 그래서 신경망에 입력될 학습 데이터를 만들 때 개와 고양이 중 한마리의 sample_rate만 wav_rate에 담고 이 값을 대표값으로 사용하기 위해서 입니다.
+) 참고 사이트
1. 그림: https://yeji1214.tistory.com/43
2. 그림: https://github.com/p2yeong/Audio-Study/blob/main/Audio_Processing.ipynb
3. 이산 신호 그림 : https://ko.wikipedia.org/wiki/%EC%9D%B4%EC%82%B0_%EC%8B%A0%ED%98%B8
# y, sr = librosa.load(audio_path)
# y: 파형의 amplitude 값(소리의 세기), 파동을 특징지을 수 있는 중요량 . 최고점의 수직 높이, 골의 깊이
# sr : 샘플링 레이트 또는 샘플링 주파수는 이산적인 신호를 만들기 위해 연속적 신호에서 얻어진 단위시간당 샘플링 횟수를 정의한다
# sample rate ? 1초당 들리는 sample 의 개수를 단위로 나타낸것. 오디오 데이터의 표본비율. Hz단위, 1초당 샘플의 빈도수
# 예: 44.1 KHz : 1초에 sample 의 수가 44100개 들어있다.
#sample 이란 ? 아날로그 신호의 소리 신호를 디지털로 표현하기 위해 잘게 쪼개는데 이 잘게 쪼갠 정보를 디지털 정보로 표현한게 sample이다.
10. 음성 진폭 데이터를 시각화해서 파형을 확인합니다.
# 동물들의 음성 진폭 데이터 4개로 각각 plot그래프로 시각화 함
import matplotlib.pyplot as plt
fig, axs = plt.subplots(2, 2, figsize=(16,7)) # 2행 2열로 그래프 4개
axs[0][0].plot(X_train[0]) #개
axs[0][1].plot(X_train[1]) #개
axs[1][0].plot(X_train[2]) #고양이
axs[1][1].plot(X_train[3]) #개
plt.show()
11. 음성의 특징을 추출하는 함수를 생성합니다.
def extract_features(audio_samples, sample_rate): #음성의 특징을 추출하는 함수
extracted_features = np.empty((0, 41, )) # (1,41) 은 아니고 그냥 41개의 값을 받을 메모리를 할당하겠다는 뜻
if not isinstance(audio_samples, list):
audio_samples = [audio_samples]
for sample in audio_samples: #진폭데이터 하나씩 돌리기
zero_cross_feat = librosa.feature.zero_crossing_rate(sample).mean() # 음성신호 파형이 중심축을 통과하는 횟수의 평균을 냄
mfccs = librosa.feature.mfcc(y=sample, sr=sample_rate, n_mfcc=40) # https://youdaeng-com.tistory.com/5
mfccsscaled = np.mean(mfccs.T,axis=0) # 각 주파수별 평균값을 구합니다. #https://stackoverflow.com/questions/36182697/why-does-librosa-librosa-feature-mfcc-spit-out-a-2d-array
mfccsscaled = np.append(mfccsscaled, zero_cross_feat) #주파수 40개에 대한 평균값 40개와 zero_cross_feat값을 가지고
mfccsscaled = mfccsscaled.reshape(1, 41, ) # 총 41개의 값을 학습 데이터로 구성.
extracted_features = np.vstack((extracted_features, mfccsscaled))
return extracted_features
신경망에 입력할 학습 데이터를 만드는 함수입니다.
학습 데이터가 크게 2가지입니다.
1. zero_crossing_rate 값
2. mfcc 값
# zero_cossing_rate 란 ? 음성 신호 파형이 중심축(0) 을 통과하는 횟수이자, 신호의 부호가 바뀌는 비율
12. 훈련데이터와 테스트데이터의 음성 특징을 추출합니다.
# wave_rate 에 개과 고양이에 속하는 주파수 영역을 주어야 합니다.
# 사람의 목소리는 대부분 16000Hz 안에 포함된다고 합니다
#librosa_read_wav_files 함수로 wav파일에서 진폭 리스트를 추출한 X_train, X_test와
#첫번째 동물의 sample_rate를 담은 wav_rate 값을 extract_features함수에 넣어서
#입력된 소리의 mel값과 zero_cross_feat
X_train_features = extract_features(X_train, wav_rate)
X_test_features = extract_features(X_test, wav_rate)
print(len(X_train_features))
print(len(X_test_features))
13. 모델 구성을 위한 패키지 임포트 합니다.
# 모델을 구성하기 위한 패키지들을 임포트
from keras import layers
from keras import models
from keras import optimizers
from keras import losses
from keras.callbacks import ModelCheckpoint,EarlyStopping
from tensorflow.keras.utils import to_categorical
14. 정답데이터를 one hot encoding 합니다.
# 위에서 만들었던 정답 데이터를 one hot encoding
train_labels = to_categorical(y_train)
test_labels = to_categorical(y_test)
print(test_labels)
15. 완전연결계층 3층 신경망을 구성합니다.
# 완전연결계층으로 3층 신경망 구성
model = models.Sequential()
model.add(layers.Dense(100, activation = 'relu', input_shape = (41, ))) # 41개의 입력뉴런으로 flatten 시킨 것을 입력 받음
model.add(layers.Dense(50, activation = 'relu'))
model.add(layers.Dense(2, activation = 'softmax')) # 출력층 2개
model.summary() #모델의 설계도 보기
16. earlystopping과 checkpoint을 설정하여 모델을 생성합니다.
best_model_weights = '/content/drive/MyDrive/ColabNotebooks/base_model.h5'
# https://deep-deep-deep.tistory.com/53
#학습 시킨 모델을 저장할 때 가장 좋은 모델을 알아서 자동으로 생성
checkpoint = ModelCheckpoint(
best_model_weights,
monitor='val_acc', #테스트 데이터에 대한 정확도가 가장 좋은것으로
verbose=1, #모델이 저장되었으면 저장되었다고 표시
save_best_only=True,
mode='max', # monitor를 val_acc로 했으면 정확도는 클수록 좋으니까 max로 해야하고 val_loss로 했으면 오차는 작을수록 좋으니까 min
save_weights_only=False #가중치 뿐만 아니라 모델도 저장되어야 하므로 False
)
estop = EarlyStopping(monitor = 'val_accuracy', patience = 20, verbose = -1) # 얼리스탑
callbacks = [checkpoint, estop]
model.compile(optimizer='adam',
loss=losses.categorical_crossentropy,
metrics=['accuracy'])
17. 모델을 훈련시킵니다.
history = model.fit(
X_train_features, # 훈련데이터 (40개의 mel값 + 1개의 zero_crossing_rate의 평균값)
train_labels, #원핫 인코딩한 값
validation_data=(X_test_features,test_labels),
epochs = 200,
verbose = 1,
callbacks=callbacks
)
18. 훈련데이터와 테스트데이터의 정확도를 시각화 합니다.
print(history.history.keys())
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
epochs = range(1, len(acc)+1)
plt.plot(epochs, acc, 'b', label = "training accuracy")
plt.plot(epochs, val_acc, 'r', label = "validation accuracy")
plt.title('Training and validation accuracy')
plt.legend()
plt.show()
19. 모델을 저장합니다.
model.save_weights('model_wieghts.h5')
model.save('model_keras.h5')
20. 저장한 모델을 가지고 데이터를 넣어 분류예측을 진행해봅니다.
import IPython.display as ipd
nr_to_predict = 6
pred = model.predict(X_test_features[nr_to_predict].reshape(1, 41,))
print("Cat: {} Dog: {}".format(pred[0][0], pred[0][1]))
if (y_test[nr_to_predict] == 0):
print ("This is a cat meowing")
else:
print ("This is a dog barking")
plt.plot(X_test_features[nr_to_predict])
ipd.Audio(X_test[nr_to_predict], rate=wav_rate)
nr_to_predict = 22
pred = model.predict(X_test_features[nr_to_predict].reshape(1, 41,))
print("Cat: {} Dog: {}".format(pred[0][0], pred[0][1]))
if (y_test[nr_to_predict] == 0):
print ("This is a cat meowing")
else:
print ("This is a dog barking")
plt.plot(X_test_features[nr_to_predict])
ipd.Audio(X_test[nr_to_predict], rate=wav_rate)
'Study > class note' 카테고리의 다른 글
딥러닝 / 사물 검출 (0) | 2022.04.27 |
---|---|
딥러닝 / LeNet, cifar10, VGG16 (0) | 2022.04.25 |
딥러닝 / librosa 패키지 실습 및 음성데이터 설명 (0) | 2022.04.21 |
딥러닝 / 사자, 고양이 분류기 만들기 (0) | 2022.04.21 |
딥러닝 / 사과와 파인애플 분류 신경망 만들기 (0) | 2022.04.21 |