본문 바로가기

Data Scientist

와인 종류 예측하기(체크포인트_모델저장, 그래프, Early stopping)

반응형

목표 : 레드와인, 화이트 와인 구분하기

데이터: UCI repository 데이터

  • 6497개 행
  • 레드와인 1599개, 화이트와인이 4898개
  • 13개 컬럼
  • 12개 feature : 주석산 농도, 아세트산 농도, 구연산 농도, 잔류 당분 농도, 염화나트륨 농도, 유리 아황산 농도, 총 아황산 농도, 밀도, PH, 황산칼륨 농도, 알코올 도수, 와인 맛(0~10등급)
  • class: 레드와인(1), 화이트와인(0)

 

from keras.models import Sequential
from keras.layers import Dense
from keras.callbacks import ModelCheckpoint, EarlyStopping  # 모델 최고값 저장,

import numpy
import pandas as pd
import os
import tensorflow as tf
import matplotlib.pyplot as plt

라이브러리들 임포트하기

import os의 os는 operating system 의 약자로서

운영체제에서 제공되는 여러 기능을 파이썬에서 수행할 수 있게 해준다.

파이썬을 이용한 파일 복사, 디렉터리 생성, 특정 디렉터리 내의 파일 목록 구할 때,

사용하면 된다. 이번엔 폴더를 생성할 때 사용했다.

# seed값 설정
seed = 0
numpy.random.seed(seed)
tf.set_random_seed(seed)

난수 생성하면서 시드값을 주어

동일한 결과값이 나올 수 있게 해준다.

df_pre = pd.read_csv('./dataset/wine.csv') ; df_pre

판다스를 이용하여 와인데이터를 불러오면

다음과 같이 데이터가 불려온다. 

그런데 컬럼명이 난잡하게 되어있다. 

 

#데이터 입력
df_pre = pd.read_csv('./dataset/wine.csv', header = None)
df_pre

깔끔하게 컬럼명을 정리해주기 위해서

header = None 을 이용해주었다.

 

# 데이터 샘플링
df = df_pre.sample(frac = 0.5)  # 랜덤 샘플을 가져오는데 그중 50%만 가져오겠다.
df

만약 데이터 중에 일부만을 추출하고 싶다면

frac(분수, 비율)을 이용하여 추출할 수 있다. 

0.5면 절반의 랜덤 데이터를 추출한다. 

기존의 6497 행에서 3248행이 된 것을 확인할 수 있다.

df = df_pre.sample(frac = 1)
df

물론 'frac = 1'을 하면 모두 가져온다.

dataset = df.values ; dataset


array([[ 6.3 ,  0.24,  0.22, ...,  9.3 ,  6.  ,  0.  ],
       [ 6.7 ,  0.3 ,  0.44, ...,  9.1 ,  5.  ,  0.  ],
       [ 8.1 ,  0.12,  0.38, ..., 12.  ,  6.  ,  0.  ],
       ...,
       [ 8.  ,  0.28,  0.42, ..., 10.6 ,  5.  ,  0.  ],
       [ 7.5 ,  0.26,  0.3 , ..., 12.  ,  7.  ,  0.  ],
       [ 7.7 ,  0.31,  0.36, ..., 12.  ,  5.  ,  0.  ]])

dataset은 df.values라고 정의해줌으로써

값들만 가져온다.

X = dataset[:, 0:12 ]   #와인의 features
Y = dataset[:, 12]  #레드(1)인지 화이트(0)인지

X는 features들이며 모든행, 0번부터 11번까지[12개]의 열로 정의한다.

Y는 class 결과값이며 12번째 열로 정의한다. 

print(X.shape)
X


(6497, 12)
array([[ 6.3 ,  0.24,  0.22, ...,  0.58,  9.3 ,  6.  ],
       [ 6.7 ,  0.3 ,  0.44, ...,  0.53,  9.1 ,  5.  ],
       [ 8.1 ,  0.12,  0.38, ...,  0.55, 12.  ,  6.  ],
       ...,
       [ 8.  ,  0.28,  0.42, ...,  0.43, 10.6 ,  5.  ],
       [ 7.5 ,  0.26,  0.3 , ...,  0.38, 12.  ,  7.  ],
       [ 7.7 ,  0.31,  0.36, ...,  0.48, 12.  ,  5.  ]])

X를 출력해보면 이와 같다.

print(Y.shape)
Y


(6497,)
array([0., 0., 0., ..., 0., 0., 0.])

Y도 0과 1로 이루어진 값들로 출력된다.

여긴 0밖에 안보이지만..

모델 짜기

# 모델 설정

model = Sequential()
model.add(Dense(32, input_dim = 12, activation = 'relu' ))   #인풋딤 피쳐가 12개, 히든레이어 1
model.add(Dense(16, activation = 'relu'))   #히든레이어2
model.add(Dense(8, activation = 'relu'))   #히든레이어3
model.add(Dense(1, activation = 'sigmoid'))

Dense층은 사용자의 마음이다.

컴퓨터가 2진수를 사용하기 때문에

2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, ...

2의 배수를 사용해주면 좋다는 설이 있다.

 

input 데이터는 features의 개수인 12개이고

0또는 값을 출력해주는(positive) relu를 사용한다.

마지막 결과값은 0또는 1로만 출력되면 되므로

sigmoid함수를 사용해준다. 

# 모델 컴파일
model.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy'])

모델을 만들었으면 컴파일을 해주어야 한다. 

화이트인지 레드인지를 결정하는 이진분류이므로

binary_crossentropy를 사용한다.

체크포인트 만들어서 모델 저장하기

# 모델 저장 폴더 설정
MODEL_DIR = './model/'   #같은 폴더 내에 model이라는 폴더가 없다면 만들어줘라
if not os.path.exists(MODEL_DIR):      
    os.mkdir(MODEL_DIR)    #mkdir이 폴더 생성 함수
    
# 모델 저장 조건 설정
modelpath = './model/{epoch:02d}-{val_loss:.4f}.hdf5'
checkpointer = ModelCheckpoint(filepath = modelpath, monitor='val_loss', verbose = 1, save_best_only = True)

Earlystopping 설정

과적합 방지하려고 사용
트레인 셋에만 과적합(overfitting)된 모델을 만들지 않고 테스트 셋에도 잘 작동하는 모델을 만들기 위함.

# 학습 자동중단 설정
early_stopping_callback = EarlyStopping(monitor = 'val_loss', patience=10) 
#10번 똑같은 정확도가 나오면 중단. 몇번 참느냐

그래프 없이 실행

# 모델 실행
model.fit(X, Y, validation_split = 0.2, epochs=500, batch_size=200, verbose = 0,\
         callbacks=[checkpointer, early_stopping_callback])   # 트레인셋의 일부를 떼서 시험(split)
         
         
Epoch 00001: val_loss improved from inf to 0.32031, saving model to ./model/01-0.3203.hdf5
.
.
.
Epoch 00157: val_loss improved from 0.06108 to 0.06034, saving model to ./model/157-0.0603.hdf5

Epoch 00158: val_loss did not improve from 0.06034

Epoch 00159: val_loss did not improve from 0.06034
.
.
.
Epoch 00167: val_loss did not improve from 0.06034
<keras.callbacks.History at 0x1d924c35688>

위쪽에 조기 종료를 설정(10번)해놔서 167번째에

학습이 종료된 것을 확인할 수 있다. 

개선이 안되는 것이 10번이 되면 학습을 종료하는 것이다.

157번째에는 이전보다 나은 결과값이기 때문에 저장을 해주었다.

그래프로 테스트셋 오차, 학습셋 정확도 확인

history = model.fit(X,Y,validation_split=0.3, epochs= 500, batch_size=200, verbose = 1, callbacks=[checkpointer, early_stopping_callback])


Train on 4547 samples, validate on 1950 samples
Epoch 1/500
4547/4547 [==============================] - 1s 166us/step - loss: 0.5568 - acc: 0.7581 - val_loss: 0.3416 - val_acc: 0.8026
.
.
.
Epoch 00160: val_loss did not improve from 0.06593
Epoch 161/500
4547/4547 [==============================] - 0s 29us/step - loss: 0.0502 - acc: 0.9837 - val_loss: 0.0690 - val_acc: 0.9836

Epoch 00161: val_loss did not improve from 0.06593
history.history


{'val_loss': [0.3416376977394789,
  0.292307999653694,
  0.2607175287527916,
  0.2369998051570012,
  .
  .
  'val_acc': [0.8025641013414432,
  0.8974358882659521,
  0.9256410369506249,
  0.9271794970218952,
  .
  .
  'loss': [0.5568385381789844,
  0.31718681494115286,
  0.2812257196016041,
  0.256641304451003,
  .
  .
  'acc': [0.7580822551410382,
  0.8878381381277097,
  0.909830655046471,
  0.9225863215685782,
  0.9307235562594246,

history를 찍어보면 객체 네가지가 나온다.

loss는 매 에포크 마다의 훈련 손실값

acc는 매 에포크 마다의 훈련 정확도

val_loss는 매 에포크 마다의 검증 손실값

val_acc는 매 에포크 마다의 검증 정확도이다.

앞의 val은 validation이다. 

validation loss가 증가하기 시작한다면, 모델이

과적합이 되고 있다고 판단할 수 있다.

버전이 2.0이상이라면 'val_accuracy'같이

다르게 나올 수 있으므로 history로 확인해주자

y_vloss = history.history['val_loss']   # 테스트셋 오차
#print(len(y_vloss))   # shape함수는 리스트에 적용안됨

# 학습셋 정확도
y_acc = history.history['acc']
#y_acc

# 테스트셋 정확도
y_val_accuracy = history.history['val_acc']
#y_val_accuracy
x_len = numpy.arange(len(y_acc))

#학습셋 정확도 라인
plt.plot(x_len, y_acc, 'o', c='blue', markersize=3, label = 'Trainset_accuarcy')

#테스트셋 오차 라인
plt.plot(x_len, y_vloss, 'o', c='red', markersize=3, label = 'Testset_loss')

plt.legend(loc='best')   #location  right, left, upper rigtht 등등 
plt.grid()   # 격자 
plt.xlabel('epoch')
plt.ylabel('score')

plt.show()

# 테스트 정확도 출력
print(' Accuracy: %.4f' % y_val_accuracy[-1])  
#제일 마지막 정확도를 가져오고 싶어서 인덱싱 -1번 

 

 

감사합니다~~

 

😁

 

 

참고한 곳: https://tykimos.github.io/2017/07/09/Training_Monitoring/

 

학습과정 표시하기 (텐서보드 포함)

케라스로 딥러닝 모델 개발할 때, 가장 많이 보게 되는 것이 fit 함수가 화면에 찍어주는 로그입니다. 이 로그에 포함된 수치들은 학습이 제대로 되고 있는 지, 학습을 그만할 지 등 판단하는 중요한 척도가 됩니다. 수치 자체도 큰 의미가 있지만 수치들이 에포코마다 바뀌는 변화 추이를 보는 것이 중요하기 때문에 그래프로 표시하여 보는 것이 더 직관적입니다. 본 절에서는 케라스에서 제공하는 기능을 이용하는 방법, 텐서보드와 연동하여 보는 방법, 콜백함수를 직

tykimos.github.io

https://doorbw.tistory.com/172

 

pandas(판다스) 기초 정리

Pandas_clear 안녕하세요. 문범우입니다. 이번 포스팅에서는 파이썬 라이브러리인 pandas(판다스)에 대해서 알아보도록 하겠습니다. 해당 내용은 flearning의 김길호님의 강의를 바탕으로 작성되..

doorbw.tistory.com

https://kevinthegrey.tistory.com/136

 

3. Convolutional Networks / L2. Convolutional Neural Networks - Model Validation in Keras, When do MLPs (not) work well?

Model Validation in Keras - 컴파일이 끝나면 모델을 학습시킬 준비가 다 됐다. - 모델을 학습시키는 과정에서 모델이 수정되는 과정을 이해하기위해 - 모델 유효화의 개념에 대해 먼저 알고있어야한다. - 우리..

kevinthegrey.tistory.com

 

반응형