Keras - 최적 모델 찾기

|

와인 감별 머신 러닝

와인의 속성을 체크하여 레드 와인과 화이트 와인을 구분하는 예제입니다. 학습에 사용하는 데이터 세트는 여기에서 받을 수 있습니다.


기본 예제 코드

먼저 아주 기본적인 머신러닝 코드를 구현합니다.

from keras.models import Sequential
from keras.layers import Dense

import pandas as pd

df = pd.read_csv('wine.csv', header=None)
df = df.sample(frac=1)
data_set = df.values

X = data_set[:, 0:12]
Y = data_set[:, 12]

model = Sequential()
model.add(Dense(30, input_dim=12, activation='relu'))
model.add(Dense(12, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy', optimizer='adam',
              metrics=['accuracy'])

model.fit(X, Y, epochs=200, batch_size=200)

print('\nAccuracy: {:.4f}'.format(model.evaluate(X, Y)[1]))


모델의 저장과 불러오기

모델은 다음 코드를 이용해서 저장하고 불러올 수 있습니다.

from kera.models import load_model

# 모델 저장
model.save('snowdeer_model.h5')

# 모델 불러오기
model = load_model('snowdeer_model.h5')


모델 체크포인터 콜백

ModelCheckpoint 콜백 함수는 Keras에서 모델을 학습할 때마다 중간중간에 콜백 형태로 알려줍니다. 다음과 같은 코드를 이용해서 사용할 수 있습니다.

from keras.callbacks import ModelCheckpoint
import os

# ...

MODEL_SAVE_FOLDER_PATH = './model/'
if not os.path.exists(MODEL_SAVE_FOLDER_PATH):
  os.mkdir(MODEL_SAVE_FOLDER_PATH)

model_path = MODEL_SAVE_FOLDER_PATH + '{epoch:02d}-{val_loss:.4f}.hdf5'

cb_checkpoint = ModelCheckpoint(filepath=model_path, monitor='val_loss',
                                verbose=1, save_best_only=True)

# ...

model.fit(X, Y, validation_split=0.2, epochs=200, batch_size=200, verbose=0,
          callbacks=[cb_checkpoint])

ModelCheckpoint의 속성으로 verbose는 해당 함수의 진행 사항의 출력 여부, save_best_only는 모델의 정확도가 최고값을 갱신했을 때만 저장하도록 하는 옵션입니다.

전체 코드는 다음과 같습니다.

from keras.models import Sequential
from keras.layers import Dense
from keras.callbacks import ModelCheckpoint
import os
import pandas as pd

MODEL_SAVE_FOLDER_PATH = './model/'

df = pd.read_csv('wine.csv', header=None)
df = df.sample(frac=1)
data_set = df.values

X = data_set[:, 0:12]
Y = data_set[:, 12]

if not os.path.exists(MODEL_SAVE_FOLDER_PATH):
  os.mkdir(MODEL_SAVE_FOLDER_PATH)

model_path = MODEL_SAVE_FOLDER_PATH + '{epoch:02d}-{val_loss:.4f}.hdf5'

cb_checkpoint = ModelCheckpoint(filepath=model_path, monitor='val_loss',
                                verbose=1, save_best_only=True)

model = Sequential()
model.add(Dense(30, input_dim=12, activation='relu'))
model.add(Dense(12, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy', optimizer='adam',
              metrics=['accuracy'])

model.fit(X, Y, validation_split=0.2, epochs=200, batch_size=200, verbose=0,
          callbacks=[cb_checkpoint])

print('\nAccuracy: {:.4f}'.format(model.evaluate(X, Y)[1]))

실행해보면 ./model 폴더 아래에 수많은 .hdf5 파일들이 생겼음을 확인할 수 있습니다. 파일명은 epoch 값과 val_loss(오차율)이므로 가장 최종적으로 생긴 파일이 가장 성능이 좋은 모델이 됩니다.


학습 자동 중단

반복문을 돌면서 최고 성능의 모델을 찾아낼 때, 초반에 최고 성능의 모델이 찾아져서 그 보다 더 좋은 성능의 모델이 더 이상 발견되지 않는 경우가 있습니다. 이런 경우 학습을 중단하도록 하는 기능을 Keras에서는 EarlyStopping()이라는 함수로 제공하고 있습니다.

from keras.callbacks import EarlyStopping

# ...

cb_early_stopping = EarlyStopping(monitor='val_loss', patience=100)

# ...

model.fit(X, Y, validation_split=0.2, epochs=5000, batch_size=500,
          callbacks=[EarlyStopping])

위와 같은 코드를 이용해서 구현하면 epoch 횟수가 총 5,000번이지만, 중간에 더 좋은 성능의 모델이 100번동안 발견이 되지 않으면 학습을 멈추게 됩니다.

Keras - Overfitting 회피하기

|

Overfitting

과적합(Overfitting)은 머신러닝에 자주 등장하는 용어입니다. 학습 데이터에 과하게 최적화하여, 실제 새로운 데이터가 등장했을 때 잘 맞지 않는 상황을 의미합니다.

Image

학습 데이터에도 Noise나 예외가 섞인 데이터들이 포함되어 있을 수 있고, 신경망의 층이 너무 많거나 변수가 복잡해서 Overfitting이 발생하기도 합니다.

과적합을 방지하는 건 머신러닝의 큰 숙제였고, Regularization과 Validation 등을 이용해서 과적합을 회피하는 방법들이 많이 연구되었습니다.


Regularization, Validation

Regularization은 학습 데이터를 조금 나누어서 테스트 데이터로 활용하는 방법입니다. 예를 들어 학습 데이터의 80%만 학습을 시키고, 나머지 20%는 학습을 시키지 않고 테스트에 활용하는 방법입니다. 나머지 20%로 검증을 하는 것을 Validation이라고 합니다.

Image

그리고 아래 이미지와 같이 검증용 데이터를 고정하지 않고 무작위로 바꿔가면서 사용하는 ‘K겹 교차검증(K-fold Cross Validation)’ 기법도 있습니다.

Image


학습 데이터와 테스트 데이터로 분리하는 예제 코드

sklearn 모듈을 이용하면 주어진 데이터를 학습 데이터와 테스트 데이터로 쉽게 나눌 수 있습니다.

from sklearn.model_selection import train_test_split

...

# 주어진 데이터를 학습 데이터와 테스트 데이터로 분리
X_train, X_validation, Y_train, Y_validation = train_test_split(X, Y, test_size=0.2)

...

# 학습 데이터를 이용해서 학습
model.fit(X_train, Y_train, epochs=100, batch_size=5)

# 테스트 데이터를 이용해서 검증
print('\nAccuracy: %.4f' % (model.evaluate(X_validation, Y_validation)[1]))


전체 코드는 다음과 같습니다. (기존의 아이리스 품종 분류 코드에 적용했습니다.)

from keras.models import Sequential
from keras.layers import Dense
from keras.utils import np_utils
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split

import pandas as pd

df = pd.read_csv('iris.csv',
                 names=["sepal_length", "sepal_width", "petal_length",
                        "petal_width", "species"])

data_set = df.values
X = data_set[:, 0:4].astype(float)
obj_y = data_set[:, 4]

encoder = LabelEncoder()
encoder.fit(obj_y)
Y_encodered = encoder.transform(obj_y)

Y = np_utils.to_categorical(Y_encodered)

# 주어진 데이터를 학습 데이터와 테스트 데이터로 분리
X_train, X_validation, Y_train, Y_validation = train_test_split(X, Y,
                                                                test_size=0.2)

model = Sequential()

model.add(Dense(16, input_dim=4, activation='relu'))
model.add(Dense(3, activation='softmax'))

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

# 학습 데이터를 이용해서 학습
model.fit(X_train, Y_train, epochs=100, batch_size=5)

# 테스트 데이터를 이용해서 검증
print('\nAccuracy: {:.4f}'.format(model.evaluate(X_validation, Y_validation)[1]))


K겹 교차 검증 예제 코드

K겹 교차 검증도 sklearn 모듈을 이용해서 쉽게 적용할 수 있습니다.

from keras.models import Sequential
from keras.layers import Dense
from keras.utils import np_utils
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import KFold

import pandas as pd

df = pd.read_csv('iris.csv',
                 names=["sepal_length", "sepal_width", "petal_length",
                        "petal_width", "species"])

data_set = df.values
X = data_set[:, 0:4].astype(float)
obj_y = data_set[:, 4]

encoder = LabelEncoder()
encoder.fit(obj_y)
Y_encodered = encoder.transform(obj_y)

Y = np_utils.to_categorical(Y_encodered)

# 주어진 데이터를 학습 데이터와 테스트 데이터로 분리
skf = KFold(n_splits=5, shuffle=True)

accuracy = []

for train, validation in skf.split(X, Y):
  model = Sequential()

  model.add(Dense(16, input_dim=4, activation='relu'))
  model.add(Dense(3, activation='softmax'))

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

  # 학습 데이터를 이용해서 학습
  model.fit(X[train], Y[train], epochs=100, batch_size=5)

  # 테스트 데이터를 이용해서 검증
  k_accuracy = '%.4f' % (model.evaluate(X[validation], Y[validation])[1])
  accuracy.append(k_accuracy)

# 전체 검증 결과 출력
print('\nK-fold cross validation Accuracy: {}'.format(accuracy))

Keras - 아이리스 꽃 품종 예측하기(다중 범주 분류)

|

아이리스 꽃 품종 예측

Keras를 활용하여 아이리스 꽃 품종 예측하는 예제 코드입니다.

예제 데이터는 여기에서 받을 수 있습니다.


iris.py

from keras.models import Sequential
from keras.layers import Dense
from keras.utils import np_utils
from sklearn.preprocessing import LabelEncoder

import pandas as pd

df = pd.read_csv('iris.csv',
                 names=["sepal_length", "sepal_width", "petal_length",
                        "petal_width", "species"])

data_set = df.values
X = data_set[:, 0:4].astype(float)
obj_y = data_set[:, 4]

encoder = LabelEncoder()
encoder.fit(obj_y)
Y_encodered = encoder.transform(obj_y)

Y = np_utils.to_categorical(Y_encodered)

model = Sequential()

model.add(Dense(16, input_dim=4, activation='relu'))
model.add(Dense(3, activation='softmax'))

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

model.fit(X, Y, epochs=100, batch_size=1)

print('\nAccuracy: {:.4f}'.format(model.evaluate(X, Y)[1]))


결과 출력

...

  1/150 [..............................] - ETA: 0s - loss: 8.4639e-06 - acc: 1.0000
 40/150 [=======>......................] - ETA: 0s - loss: 0.0309 - acc: 1.0000    
 76/150 [==============>...............] - ETA: 0s - loss: 0.0623 - acc: 0.9868
100/150 [===================>..........] - ETA: 0s - loss: 0.0760 - acc: 0.9800
128/150 [========================>.....] - ETA: 0s - loss: 0.0673 - acc: 0.9844
150/150 [==============================] - 0s 2ms/step - loss: 0.0638 - acc: 0.9867
Epoch 97/100

  1/150 [..............................] - ETA: 0s - loss: 7.2273e-04 - acc: 1.0000
 34/150 [=====>........................] - ETA: 0s - loss: 0.0260 - acc: 1.0000    
 75/150 [==============>...............] - ETA: 0s - loss: 0.0778 - acc: 0.9600
112/150 [=====================>........] - ETA: 0s - loss: 0.0857 - acc: 0.9643
148/150 [============================>.] - ETA: 0s - loss: 0.0762 - acc: 0.9730
150/150 [==============================] - 0s 1ms/step - loss: 0.0752 - acc: 0.9733
Epoch 98/100

  1/150 [..............................] - ETA: 0s - loss: 7.1290e-05 - acc: 1.0000
 29/150 [====>.........................] - ETA: 0s - loss: 0.0513 - acc: 1.0000    
 57/150 [==========>...................] - ETA: 0s - loss: 0.0419 - acc: 1.0000
 92/150 [=================>............] - ETA: 0s - loss: 0.0826 - acc: 0.9783
115/150 [======================>.......] - ETA: 0s - loss: 0.0699 - acc: 0.9826
141/150 [===========================>..] - ETA: 0s - loss: 0.0596 - acc: 0.9858
150/150 [==============================] - 0s 2ms/step - loss: 0.0750 - acc: 0.9800
Epoch 99/100

  1/150 [..............................] - ETA: 0s - loss: 0.2667 - acc: 1.0000
 46/150 [========>.....................] - ETA: 0s - loss: 0.1332 - acc: 0.9565
 90/150 [=================>............] - ETA: 0s - loss: 0.0866 - acc: 0.9778
126/150 [========================>.....] - ETA: 0s - loss: 0.0755 - acc: 0.9841
150/150 [==============================] - 0s 1ms/step - loss: 0.0726 - acc: 0.9800
Epoch 100/100

  1/150 [..............................] - ETA: 0s - loss: 0.0023 - acc: 1.0000
 53/150 [=========>....................] - ETA: 0s - loss: 0.0485 - acc: 0.9811
108/150 [====================>.........] - ETA: 0s - loss: 0.0768 - acc: 0.9815
150/150 [==============================] - 0s 956us/step - loss: 0.0717 - acc: 0.9800

 32/150 [=====>........................] - ETA: 0s
150/150 [==============================] - 0s 120us/step

Accuracy: 0.9800

Windows 10 - Ubuntu on Windows 10 서로간 파일 시스템 접근하기

|

Ubuntu on Windows 10

Windows 10에서는 Ubnutu가 Native로 동작할 수 있습니다. 스토어에서 Ubuntu를 내려받아 설치하면 됩니다. 물론, 제어판에서 아래와 같은 작업 후 ‘재부팅’을 해주어야 Ubuntu가 정상동작합니다.

제어판 → 프로그램 제거 및 변경

image

image


Windows에서 Ubuntu 파일 시스템에 접근

Windows 상에서 Ubuntu가 설치되었을 때 해당 파일 시스템은 아래와 같은 폴더에 저장됩니다.

C:\Users\<username>\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState

가상화가 아닌 Native로 동작하는 리눅스이다보니 압축된 파일이 아니라, 파일 시스템 자체에 그대로 접근이 가능합니다. 물론, Ubuntu 상에서 작성한 파일을 Windows에서 수정할 수도 있고, 반대로 Windows에 있는 파일을 Ubuntu로 밀어넣을 수도 있습니다. (단, 이 때는 chmod 명령어로 권한 변경을 해주어야 매끄럽게 동작합니다.)


Ubuntu에서 Windows 파일 시스템에 접근

반대로 Ubuntu에서 Windows의 파일 시스템에 접근할 수 있습니다. 아래의 경로를 이용하면 Ubuntu에서 Windows 파일 시스템이 보입니다.

/mnt/c

Keras - 피마 인디언들의 당뇨병 예측

|

피마 인디언들의 당뇨병 예측

Keras를 활용하여 피마 인디언들의 당뇨병 예측하는 예제 코드입니다.

예제 데이터는 여기에서 받을 수 있습니다.


pima.py

from keras.models import Sequential
from keras.layers import Dense

import numpy

data_set = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
X = data_set[:, 0:8]
Y = data_set[:, 8]

model = Sequential()

model.add(Dense(12, input_dim=8, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy', optimizer='adam',
              metrics=['accuracy'])

model.fit(X, Y, epochs=100, batch_size=10)

print('\nAccuracy: {:.4f}'.format(model.evaluate(X, Y)[1]))


결과 출력

...

 10/768 [..............................] - ETA: 0s - loss: 0.5410 - acc: 0.7000
540/768 [====================>.........] - ETA: 0s - loss: 0.5159 - acc: 0.7426
768/768 [==============================] - 0s 95us/step - loss: 0.5130 - acc: 0.7383
Epoch 98/100

 10/768 [..............................] - ETA: 0s - loss: 0.3326 - acc: 1.0000
470/768 [=================>............] - ETA: 0s - loss: 0.4856 - acc: 0.7681
768/768 [==============================] - 0s 104us/step - loss: 0.4867 - acc: 0.7682
Epoch 99/100

 10/768 [..............................] - ETA: 0s - loss: 0.6921 - acc: 0.6000
400/768 [==============>...............] - ETA: 0s - loss: 0.5100 - acc: 0.7625
768/768 [==============================] - 0s 132us/step - loss: 0.5060 - acc: 0.7539
Epoch 100/100

 10/768 [..............................] - ETA: 0s - loss: 0.7137 - acc: 0.6000
300/768 [==========>...................] - ETA: 0s - loss: 0.4650 - acc: 0.7733
620/768 [=======================>......] - ETA: 0s - loss: 0.4836 - acc: 0.7645
768/768 [==============================] - 0s 153us/step - loss: 0.4948 - acc: 0.7617

 32/768 [>.............................] - ETA: 0s
768/768 [==============================] - 0s 38us/step

Accuracy: 0.7721