8-6 텐서플로우를 넘어 Keras API에 의한 뉴럴네트워크(NN)학습

codingart(66)
Published in
#kr
Words
900
Reading
4 min
Listen
Play
8y

Back end 소프트웨어인 Keras 는 Front end인 아나콘다 설치 시에 함께 설치하도록 되어 있으므로 인해서 파이선 머신 러닝 분야에서 상당히 높은 사용률을 보여 주고 있으며 그 다음이 PyTorch이다. Caffe 는 버클리 대학이, Theano 는 몬트리올 대학이 제공하는 머신 러닝 라이브러리이다. Back end 라 함은 쉽게 말해서 Solver 소프트웨어라는 의미이다.

noname11.png

이미 아나콘다에서 TensorFlow에 의한 Low 레벨 API 와 High 레벨 API를 경험해 보았으면 Keras를 사용해 보도록 하자. 아무런 파이선 에디터에서 Keras를 사용할 수 있는 것은 아니며 반드시 Installation 과정이 있어야 할 것이다. 이미 아나콘다에서 TensorFlow를 사용하고 있다면 이미 Keras 가 설치되어 있다고 보아야 할 것이다.

noname02.png

필자의 저서 “파이선 코딩 초보자를 위한 텐서플로우 OpenCV 머신 러닝” 1-1장에 아나콘다설치와 머신 러닝 예제 편을 참조해 보면 윈도우즈 10에서 TensorFlow를 설치하고 버전을 확인한 후 Keras 설치과정이 뒤따른다. 아울러 matplotlib, pandas, pyQt5, spyder 도 함께 설치하도록 되어 있다. 즉 Keras를 잘 몰라도 아나콘다 매뉴얼에 따라서 설치하면 되게끔 되어 있으므로 import 해서 사용이 가능하다.

noname03.png

Keras 학습을 위한 데이터를 준비하되 앞서의 TensorFlow High 레벨 API 예제와 동일하게 준비하여 실행 후 결과를 체크해 보기로 한다.

noname04.png

실행 결과는 다음과 같다.

noname05.png

이어서 파라메터 설정, Graph 설정, cost함수 구성, 옵티마이저 설정, 배치생성 및 Session 실행 유닛으로 구성된다. 이 과정을 Keras 로 재현해 보도록 한다.

데이터는 읽어 들였지만 y_train은 클라스 형태로 들어있으므로 확인해 본 후 다음 명령을 실행하여
y_train_onehot = keras.utils.to_categorical(y_train)
one hot code 로 변환하도록 하자.

noname06.png

TensorFlow High 레벨 API 문제는 3개의 레이어로 구성되었다. 첫 2개의 레이어는 50개의 은닉 층과 tanh를 사용하고 있으며 3번째 레이어는 10개의 클라스 라벨을 사용하며 각 클라스별 확률 계산을 위해 Softmax 로 처리한다.

다음과 같이 Keras 로 이러한 태스크를 간결하게 코딩해보자. 첫 시작은 Sequencial() 모델을 정의한다. Sequencial 모델은 원하는 만큼의 레이어들을 추가할 수 있다. TensorFlow CCC 의 예를 들어 보면 합계 10개 층을 사용하도록 구성한다. Keras 에서는 model.add{∙∙∙}를 3회 사용하여 코드를 작성한다.

noname07.png

TensorFlow High 레벨 API 문제에서는 tf.labels.dense 가 사용되지만 Keras에서는 keras.layers.Dense가 사용된다.
model.add{∙∙∙}의 파라메터로 units=50은 은닉 층(hidden layer)의 폭(Wide)을 나타내도록 784개의 rows에 대응하여 웨이트를 즉 w(784, 50)으로 설정한다는 의미이다.
input_dim=X_train_centered.shape[1]은 TensorFlow 의 X_train_centered( [None,784])와 비교하여 784개를 나타낸다. TensorFlow에서 shape[0]의 값은 None 은 Session에서 batch 로 입력하게 되는 샘플 수를 뜻하며 Graph 단계에서는 아직 정해지지 않은 상태이다.

kernel_initializer=’Glorot_unifirm’은 TensorFlow에서 아주 효율적으로 초기 값을 설정해주는 Xavier initializer를 뜻하는데 하나는 초기 값 설정을 연구했던 사람의 본명이며 다른 하나는 성을 나타낸다. bias_initializer 는 대개 ‘zero’를 사용한다. activation 함수는 TensorFlow High 레벨 API 문제에서처럼 tanh를 그대로 사용하기로 하자.

두 번째 model.add{∙∙∙}에서는 50x50 웨이트 매트릭스를 사용하기로 한다. 앞 부분의 50은 전 단계 레이어로부터 생성되는 매트릭스의 column 값과 매치 되어야 한다. 마차가지로 units=50은 다음 세 번째 단계의 input_dim과 일치 되어야 할 것이다.

세 번째 model.add{∙∙∙}에서는 10개의 클라스 라벨 값 확률을 계산하기 위해서 activation 함수는 Softmax가 사용된다.

Stochastic Gradient Descent 옵티마이저를 사용하도록 하며 learning rate = 0.001, decay=1e-07, momentum=0.7 로 설정한다, decay=1e-07은 learning rate 업데이트 마다 그 만큼씩 감쇠 시킨다는 의미이다. momentum 은 경사 하강 벙향으로 SGD 작업을 가속화 시키되 심한 변동을 감쇠시켜주는(dampening) 역할을 한다.

model.compile{∙∙∙}에서는 SGD 옵티마이저 설정과 함께 Cross Entropy 함수를 cost 함수로 설정한다. 여기까지가 TensorFlow 의 Session 실행 전까지의 단계인 Computational Graph 단계로 볼 수 있다.

model.fit∙∙∙}에서 학습을 실행한다. batch 사이즈와 epochs를 설정한다. verbose = 0은 아무런 출력이 없지만 =1은 progrsess bar를 보여준다. validation_split = 0.1은 학습 샘플 수 대비 10% 만큼의 테스트 데이터 수를 사용한다는 의미이다.

noname08.png

학습 결과를 이용하여 테스트 샘플을 조사해 보면 인식율이 얻어진다.

noname09.png

tensorFlow 의 Session에서 다소 복잡스럽게 느껴졌던 부분이 말끔하게 해소된 모양이다. 아울러 파이선 문법 차원에서 봐도 indentation이 전혀 없어 대단히 깔끔해 보인다. Keras를 사용하여 상당히 복잡한 구조를 가지는 Wide Deep 코드 작성이 더욱 편리해 질 것이다.

물론 Keras부터 머신 러닝을 배워나갈 수도 있겠으나 그래도 TensorFlow를 거치지 않는다면 보다 High 레벨 코딩이 어려울 수도 있다. 왜냐하면 Keras 단계에서 이미 많이 다듬어졌기 때문에 머신 러닝의 알고리듬 개량은 대단히 어려워 보이기 때문이다.

하지만 속단은 금물이다. Keras를 사용해 보면서 텐서 플로우에서처럼 과연 창의적인 알고리듬 개량이 가능할 것인지 충분한 시간을 가지고 알아 보기로 한다.

첨부된 코드를 아나콘다에서 실행시켜보자.
#ch13_Keras_01.py

import sys
import gzip
import shutil
import os
import struct
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import tensorflow.contrib.keras as keras

unzips mnist

if (sys.version_info > (3, 0)):
writemode = 'wb'
else:
writemode = 'w'

zipped_mnist = [f for f in os.listdir('./') if f.endswith('ubyte.gz')]
for z in zipped_mnist:
with gzip.GzipFile(z, mode='rb') as decompressed, open(z[:-3], writemode) as outfile:
outfile.write(decompressed.read())

def load_mnist(path, kind='train'):
"""Load MNIST data from path"""
labels_path = os.path.join(path,
'%s-labels-idx1-ubyte' % kind)
images_path = os.path.join(path,
'%s-images-idx3-ubyte' % kind)

with open(labels_path, 'rb') as lbpath:
    magic, n = struct.unpack('>II', 
                             lbpath.read(8))
    labels = np.fromfile(lbpath, 
                         dtype=np.uint8)

with open(images_path, 'rb') as imgpath:
    magic, num, rows, cols = struct.unpack(">IIII", 
                                           imgpath.read(16))
    images = np.fromfile(imgpath, 
                         dtype=np.uint8).reshape(len(labels), 784)
    images = ((images / 255.) - .5) * 2

return images, labels

#Developing Multilayer Neural Networks with Keras
#loading the data
X_train, y_train = load_mnist('./', kind='train')
print('Rows: %d, Columns: %d' %(X_train.shape[0],
X_train.shape[1]))
X_test, y_test = load_mnist('./', kind='t10k')
print('Rows: %d, Columns: %d' %(X_test.shape[0],
X_test.shape[1]))

#mean centering and normalization:
mean_vals = np.mean(X_train, axis=0)
std_val = np.std(X_train)

X_train_centered = (X_train - mean_vals)/std_val
X_test_centered = (X_test - mean_vals)/std_val

del X_train, X_test

print(X_train_centered.shape, y_train.shape)
print(X_test_centered.shape, y_test.shape)

#================================================
np.random.seed(123)
tf.set_random_seed(123)

y_train_onehot = keras.utils.to_categorical(y_train)

print('First 3 labels: ', y_train[:3])
print('\nFirst 3 labels (one-hot):\n', y_train_onehot[:3])

model = keras.models.Sequential()

model.add( keras.layers.Dense(units=50,
input_dim=X_train_centered.shape[1],kernel_initializer='glorot_uniform',
bias_initializer='zeros', activation='tanh'))

model.add( keras.layers.Dense(units=50,
input_dim=50, kernel_initializer='glorot_uniform',
bias_initializer='zeros',activation='tanh'))

model.add( keras.layers.Dense(units=y_train_onehot.shape[1],
input_dim=50, kernel_initializer='glorot_uniform',
bias_initializer='zeros', activation='softmax'))

sgd_optimizer = keras.optimizers.SGD(lr=0.001, decay=1e-7, momentum=.9)
model.compile(optimizer=sgd_optimizer,loss='categorical_crossentropy')

history = model.fit(X_train_centered, y_train_onehot,
batch_size=64, epochs=50, verbose=1, validation_split=0.1)

y_train_pred = model.predict_classes(X_train_centered, verbose=0)
correct_preds = np.sum(y_train == y_train_pred, axis=0)
train_acc = correct_preds / y_train.shape[0]

print('First 3 predictions: ', y_train_pred[:3])
print('Training accuracy: %.2f%%' % (train_acc * 100))

y_test_pred = model.predict_classes(X_test_centered, verbose=0)
correct_preds = np.sum(y_test == y_test_pred, axis=0)
test_acc = correct_preds / y_test.shape[0]
print('Test accuracy: %.2f%%' % (test_acc * 100))

마나마인로고.png

8-6 텐서플로우를 넘어 Keras API에 의한 뉴럴네트워크(NN)학습 | Ecency