티스토리 뷰

반응형

Keras는 효율적인 수치 라이브러리 TensorFlow 및 Theano를 사용자가 보다 쉽게 사용할 수 있도록 개발된 딥러닝용 Python 라이브러리입니다.
Keras를 사용하면 신경망과 딥러닝 모델을 빠르고 간단하게 개발하고 학습할 수 있습니다.
이 글에서는 이진 분류 문제를 해결하기 위해서 단계별로 진행하여 딥렁닝 Keras 라이브러리를 효과적으로 사용하는 방법을 알아봅니다.

이 이진분류 문제인 소나데이터 예제를 완료하면 다음을 알게 됩니다.

  • 학습 데이터를 로드하고 Keras에서 사용할 수 있는 방법.
  • 테이블 형식의 데이터를 이용해서 딥러닝 신경망을 개발하고 학습하는 방법.
  • 미지의 데이터에 대해 Keras에서 신경망 모델의 성능을 평가하는 방법.
  • 신경망을 사용할 때 모델 성능과 정확도를 향상시키기 위해서 데이터를 준비하는 전처리 방법.
  • 모델성능향상을 위해 Keras에서 신경망의 구조를 다양하게 구성하고 조정하는 방법.

1. 데이터 세트에 대한 설명

이 튜토리얼에서 사용할 데이터세트는 Sonar 데이터세트 입니다.(출처: 위키백과)

 

소나 - 위키백과, 우리 모두의 백과사전

 

ko.wikipedia.org

소나는 수중 속에 있는 암석, 금석, 모래, 자갈 등 다양한 물체들을 구분하기 위해서 음파를 발사하여 물체에 반사되는 강도를 기록하고 강도의 차이를 통해서 물체를 구분하는 최신 원격탐사 기술 중 하나이다.

여기서 사용되는 자료가 바로 음파 탐지기로 부터 물체에서 반사된 음파신호의 강도를 설명하는 데이터 세트입니다.
60개의 입력 변수는 다양한 반사각도에서 수신된 강도입니다. 특히, 암석과 금속 실린더를 구별하는 자료이고 이를 통해서 딥러닝 모델이 필요한 이진 분류 문제이기도 합니다.
이 소나 데이터세트에 대한 자세한 내용은 UCI Machine Learning 리포지토리 에서 확인할 수 있습니다 .
데이터 세트는 무료로 다운로드 할수 있고 파일 이름이 sonar.csv으로 명칭한 후 이용할 수 있습니다.

잘 알려진 소나 데이터셋의 모든 입력변수는 연속적이며 일반적으로 0에서 1 사이입니다. 출력 변수는 광산의 경우 문자열 "M"이고 암석의 경우 "R"이다. 딥러닝 모델을 수행하기 위해서는 이를 정수 1과 0으로 변환해야 합니다.

반응형

2. 기준 신경망 모델 성능 평가

소나 데이터를 이용해서 광산과 암석을 구별하는 이진 문제에 대한 기본 모델을 개발하고 결과를 평가합니다.

 

즉, 음파탐지기인 소나에서 발사된 음파신호가 물체로 부터
다양한 각도에서 반사된 음파의 강도를 이용해서
광산과 암석을 구분하는 문제이다.

 

이를 위해서 다음 구문처럼 필요한 딥러닝 관련 패키지를 가져오는 것으로 부터 시작합니다.



1) 딥러닝 관련 패키지 불러오기

import pandas as pd
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from scikeras.wrappers import KerasClassifier
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline

이제 pandas를 사용하여 데이터 세트를 로드 하고 열을 60개의 입력 변수(X)와 1개의 출력 변수(Y)로 분할할 수 있습니다. pandas는 문자열(출력 변수)을 쉽게 처리하기 때문에 데이터를 로드하는 데 사용합니다.

2) 입력자료와 출력자료 생성하기

# load dataset
dataframe = pd.read_csv("sonar.csv", header=None)
dataset = dataframe.values
# split into input (X) and output (Y) variables
X = dataset[:,0:60].astype(float)
Y = dataset[:,60]

출력 변수는 광산의 경우 문자열 "M"이고 암석의 경우 "R"인 문자열 값입니다. 우리는 그것들을 정수 값 0과 1로 변환해야 합니다.
scikit-learn의 LabelEncoder 클래스를 사용하여 이 작업을 수행할 수 있습니다. 이 클래스는 fit() 함수를 통해 전체 데이터 세트를 사용하여 필요한 인코딩을 모델링한 다음, transform() 변환함수를 사용하여 새 출력 변수를 생성하기 위해 인코딩을 적용합니다.

3) 문자로 구성된 출력자료를 0과 1로 변환하기

# encode class values as integers
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)

이제 Keras를 사용하여 신경망 모델을 만들 준비가 되었습니다.

모델을 평가하기 의해서 scikit-learn을 사용하여 계층화된 k-겹 교차 검증방법을 사용하여 모델을 평가할 것입니다.
이 방법은 데이터를 k-파트로 분할하고 모델의 성능을 평가하기 위해 테스트 세트로 유지되는 부분을 제외한 모든 부분에 대해 모델을 학습함으로써 모델평가를 수행합니다. 이 과정은 k번 반복되며 구성된 모든 모델의 평균 점수는 성능평가를 위한 강력한 추정치로 사용됩니다.

scikit-learn과 함께 Keras 모델을 사용하려면 SciKeras 모듈의 KerasClassifier 래퍼를 사용해야 합니다.
이 클래스는 신경망 모델을 생성하고 반환하는 함수를 사용합니다. 또한 에포크 수 및 배치 크기와 같은 fit() 호출에 전달할 인수를 취합니다.

베이스라인 모델(기준모델)을 생성하는 함수를 정의하는 것으로 시작하겠습니다.
기준모델은 입력 변수와 동일한 수의 뉴런을 가진 하나의 완전히 연결된 은닉층을 가질 것입니다. 이것은 신경망을 생성할 때 좋은 기본 시작점입니다.
출력 레이어는 예측을 위해 단일 뉴런을 포함하고 0에서 1 범위의 확률 출력 값을 생성하기 위해 시그모이드 활성화 함수를 사용합니다.
마지막으로 훈련 중에 이진 분류 문제에 대해 선호되는 손실 함수는 binary_crossentropy를 사용합니다.
모델을 최적화하기 위해서 기울기 하강을 위한 효율적인 adam 최적화 알고리즘을 사용합니다.
모델이 학습될 때 성능평가는 정확도 척도인 accuracy를 사용합니다.

4) 소나데이터를 바탕으로 이진분류문제를 해결하기 위한 딥러닝 기본모델 정의하기

# baseline model
def create_baseline():
	# create model
	model = Sequential()
	model.add(Dense(60, input_shape=(60,), activation='relu'))
	model.add(Dense(1, activation='sigmoid'))
	# Compile model
	model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
	return model

이제 scikit-learn 프레임워크에서 계층화된 교차 검증을 사용하여 이 모델을 평가할 때입니다.
다시 합리적인 기본값을 사용하여 교육 에포크 수를 KerasClassifier에 전달합니다.

수행되는 10겹 교차 검증에 대해 모델이 10번 생성된다는 점을 감안할 때 Verbose 출력도 꺼집니다.

5) 이진 분류문제 해결을 위한 딥러닝 모델 학습하기

# evaluate model with standardized dataset
estimator = KerasClassifier(model=create_baseline, epochs=100, batch_size=5, verbose=0)
kfold = StratifiedKFold(n_splits=10, shuffle=True)
results = cross_val_score(estimator, X, encoded_Y, cv=kfold)
print("Baseline: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))

이를 종합하면 전체 코드가 다음과 같습니다.

# Binary Classification with Sonar Dataset: Baseline
from pandas import read_csv
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from scikeras.wrappers import KerasClassifier
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
# load dataset
dataframe = read_csv("sonar.csv", header=None)
dataset = dataframe.values
# split into input (X) and output (Y) variables
X = dataset[:,0:60].astype(float)
Y = dataset[:,60]
# encode class values as integers
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)
# baseline model
def create_baseline():
	# create model
	model = Sequential()
	model.add(Dense(60, input_shape=(60,), activation='relu'))
	model.add(Dense(1, activation='sigmoid'))
	# Compile model
	model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
	return model
# evaluate model with standardized dataset
estimator = KerasClassifier(model=create_baseline, epochs=100, batch_size=5, verbose=0)
kfold = StratifiedKFold(n_splits=10, shuffle=True)
results = cross_val_score(estimator, X, encoded_Y, cv=kfold)
print("Baseline: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))

기준모델을 평가한 결과는 별다른 노력없이 정확도 81.68%와 표준편차 7.26%를 보여주고 이는 우수한 성능이라 할 수 있다.

Baseline: 81.68% (7.26%)
 
반응형
댓글