들어가며

지난 시간까지 케라스의 Sequential API를 이용해서 간단한 선형 신경망을 만들어 회귀와 분류를 진행했습니다.

만약 여러개의 입력, 출력층을 만들고 싶거나 좀 더 복잡한 신경망을 만들고 싶다면 어떻게 해야할까요? 이번에는 함수형 API를 사용해서 이 문제를 해결해보겠습니다.

 

목차

1. 함수형 API란?

2. Wide & Deep 신경망

3. 여러개의 입력,출력층

 

1. 함수형 API란?

함수형 API는 말 그대로 코드에서 함수처럼 신경망 층을 다루는 API입니다. 

input_B = keras.layers.Input(shape=[6], name="deep_input")
hidden1 = keras.layers.Dense(30, activation="relu")(input_B)

두 번째 줄을 보면 새로운 Dense층을 선언하면서 뒤에 인자로 기존에 선언한 input_B를 입력하는 것을 볼 수 있습니다.

이렇게 되면 hidden1층은 input_B를 자신의 입력층으로 정한다는 뜻입니다. 생각보다 매우 간단합니다.

 

2. Wide & Deep 신경망

이를 이용해서 새로운 신경망 구조를 만들어 보겠습니다.

Wide & Deep 신경망은 2016년 헝쯔 청의 논문에서 소개되었습니다. 이 그림은 입력층의 일부 또는 전체가 곧바로 출력층에 연결되는 경우가 있습니다. 이 경우 간단한 규칙과 복잡한 규칙을 모두 학습할 수 있습니다.

출처 : https://bcho.tistory.com/1187

함수형 API를 이용해서 코드를 작성해봅시다.

from tensorflow import keras

input_ = keras.layers.Input(shape=X_train.shape[1:])
hidden1 = keras.layers.Dense(30, activation="relu")(input_)
hidden2 = keras.layers.Dense(30, activation="relu")(hidden1)
concat = keras.layers.concatenate([input_, hidden2])
output = keras.layers.Dense(1)(concat)
model = keras.models.Model(inputs=[input_], outputs=[output])

각 층들이 필요한 입력층은 인자로 선언함으로서 간단하게 구현하는 모습입니다. concatenate층은 두개의 층을 하나로 합치는 층을 의미합니다. 이를 통해서 Wide & Deep모델을 만들 수 있습니다.

summary() 메서드를 통해서 정보를 보면 각층은 인자에 맞게 잘 연결된 모습을 볼 수 있습니다.

colab.research.google.com/drive/1bdwyrHcNh9LXi9jqU_zmDtnoBL6zy2EL?usp=sharing

 

Google Colaboratory

 

colab.research.google.com

3. 여러개의 입력, 출력층

여러개의 출력층을 사용하는 경우는 매우 다양합니다.

예를 들어 사람의 얼굴에서 여러가지 감정의 추정값을 만들거나 이미지 인식에서 물체의 폭, 너비 등의 데이터를 추출할 때입니다. 그렇다면 여러개의 출력층은 어떻게 만들까요? 

결론적으로 keras.models.Model을 선언할 때 출력층은 여러개로 만들면됩니다.

 

코드로 작성해봅시다.

input_A = keras.layers.Input(shape=[5], name="wide_input")
input_B = keras.layers.Input(shape=[6], name="deep_input")
hidden1 = keras.layers.Dense(30, activation="relu")(input_B)
hidden2 = keras.layers.Dense(30, activation="relu")(hidden1)
concat = keras.layers.concatenate([input_A, hidden2])
output = keras.layers.Dense(1, name="main_output")(concat)
aux_output = keras.layers.Dense(1, name="aux_output")(hidden2)
model = keras.models.Model(inputs=[input_A, input_B],
                           outputs=[output, aux_output])

위 코드를 보면 마지막 Model에서 outputs으로 두개의 층을 선언하는 모습을 볼 수 있습니다. aux_output은 층의 중간에서 데이터가 잘 학습되고 있는지 관찰하기 위한 보조출력입니다.

 

마치며

이렇게 함수형  API를 이용해서 복잡한 모델을 간단하게 만들어보았습니다. 하지만 모델 내부에 조건문을 선언하거나 반복문을 선언하는 등 세부적인 프로그래밍은 불가능합니다. 다음에는 이를 해결하기 위한 서브클래싱  API를 만들어 보겠습니다.

들어가며

지난 시간에는 케라스로 간단한 이미지 분류기 모델을 구축,훈련,평가 그리고 결과를 시각화하는 방법에 대해서 알아보았습니다. 이번 시간에는 케라스를 이용해서 회귀 다층퍼셉트론 모델을 만들어보겠습니다.

 

목차

1. Regression MLP 구현 방안

2. Sequential API를 이용해서 모델 구현

3. 시각화

1. Regression MLP 구현 방안

Regression MLP를 구현하는 방법은 이전 글에서 이미지 분류기 모델을 만들었다면 매우 간단히 해결할 수 있습니다.

회귀는 수치를 예상하는 것이므로 훈련전에 스케일링을 하고 모델의 출력층에서 활성화함수를 사용하지 않으면 쉽게 구현할 수 있습니다. Sequentail API를 이용해서 직접구현해보겠습니다. (Sequential API를 모른다면 이전 글을 참조하시기바랍니다.)

2. Sequential API를 이용해서 모델 구현

여기서는 예시로 california_housing데이터를 이용해서 주택 가격을 예측하는 모델을 구현해보겠습니다.

우선, 데이터를 다운로드하고 세트를 나눈 다음 스케일링을 해보겠습니다.

from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

housing = fetch_california_housing()

#훈련, 검증 그리고 테스트 세트 추출
X_train_full, X_test, y_train_full, y_test = train_test_split(housing.data, housing.target, random_state=42)
X_train, X_valid, y_train, y_valid = train_test_split(X_train_full, y_train_full, random_state=42)

#회귀를 위한 스케일링 전처리
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_valid = scaler.transform(X_valid)
X_test = scaler.transform(X_test)

데이터가 준비되었으니 은닉층 1개(뉴런 수는 30)와 출력층 1개로 구성된 MLP를 Sequential API로 구축,컴파일 그리고 훈련과 평가를 수행합니다.

model = keras.models.Sequential([
    keras.layers.Dense(30, activation="relu", input_shape=X_train.shape[1:]),
    keras.layers.Dense(1)
])
model.compile(loss="mean_squared_error", optimizer=keras.optimizers.SGD(lr=1e-3))
history = model.fit(X_train, y_train, epochs=20, validation_data=(X_valid, y_valid))
mse_test = model.evaluate(X_test, y_test)
X_new = X_test[:3]
y_pred = model.predict(X_new)

3. 시각화

위 데이터를 시각화해봅시다.

plt.plot(pd.DataFrame(history.history))
plt.grid(True)
plt.gca().set_ylim(0, 1)
plt.show()

들어가며

지난 글까지 인공 신경망과 학습 모델들에 대해서 알아보고 이를 사이킷런으로 구현해 보았습니다. 

이번에는 google 의 tensorflow에서 지원하는 keras라이브러리를 사용해서 간편하게 신경망을 구현, 학습, 그리고 평가하는 방법에 대해서 알아보겠습니다.

 

목차

1. 텐서플로2 설치

2. Sequential API로 이미지 분류기 구현하기

    1. 데이터 다운로드

    2. Sequential Model 구축

    3. 모델 알아보기

    4. 모델 컴파일하기

    5.모델 학습하기

    6. 학습 시각화하기

    7. 테스트 데이터로 평가하기

    8. 예측하기

 

Tensorflow 2.0 설치하기

tensorflow 2.0을 설치하는 환경이 여러 가지가 있으므로 이는 tensorflow.org에 게재된 공식문서를 참조하는 것이 좋습니다.

https://www.tensorflow.org/install/pip?hl=ko

 

pip를 사용하여 TensorFlow 설치

TensorFlow 2 패키지 사용 가능 tensorflow - CPU와 GPU 지원이 포함된 안정적인 최신 출시(Ubuntu 및 Windows) tf-nightly - 미리보기 빌드(불안정). Ubuntu 및 Windows에는 GPU 지원이 포함되어 있습니다. 이전 버전의 TensorFlow TensorFlow 1.x의 경우 CPU와 GPU 패키지는 다음과 같이 구분됩니다. tensorflow==1.15 - CPU 전용 출시 tensorflow-gpu=

www.tensorflow.org

Seauential API로 이미지 분류기 만들기

1. 데이터 다운로드

이미지 분류기를 만들기 전에 분류할 이미지 데이터를 다운해봅시다.

여기서는 fashion_mnist 데이터를 사용합니다. keras 라이브러리를 통해서 쉽게 다운이 가능합니다.

from tensorflow import keras

fashion_mnist = keras.datasets.fashion_mnist
(X_train_full, y_train_full), (X_test, y_test) = fashion_mnist.load_data()

데이터를 간단히 살펴봅시다.

하나의 패션 샘플은 28x28의 배열로 이루어져있으며 하나의 픽셀은 0~255의 정수로 이루어져 있습니다.

이미 데이터는 어느정도 전처리가 진행되어있으니 바로 keras를 통해 모델을 구축해봅시다.

2. Sequential Model 구축

keras.models.Sequential은 케라스로 MLP를 구현하는 가장 기본적이고 쉬운 방법입니다.

Sequential 클래스를 선언하고 층을 순서대로 추가함으로써 MLP구현이 가능합니다.

model = keras.models.Sequential()
model.add(keras.layers.Flatten(input_shape=[28, 28]))
model.add(keras.layers.Dense(300, activation="relu"))
model.add(keras.layers.Dense(100, activation="relu"))
model.add(keras.layers.Dense(10, activation="softmax"))

Flatten은 입력데이터의 shape를 일렬로 변경하는 클래스입니다.(reshape(-1,1)과 동일합니다.) Flatten은 선언하면 뉴런층이 생성되는 것이 아니라 단순히 데이터의 형태를 변경합니다. InputLayer(input_shape=[28, 28])를 통해서 대체가 가능합니다.

 

Dense는 이전 뉴런과 완전연결된 밀집 뉴런층을 의미합니다. 이를 선언하고 모델에 추가함으로써 모델 내부에 새로운 뉴런층을 생성할 수 있으며 첫 번째 파라미터로 뉴런 수를 서정하고 activation 파라미터를 통해서 활성화 함수를 지정할 수 있습니다.

 

마지막 Dense는 softmax를 활성화 함수를 사용하고 있는데 이는 우리가 원하는 모델은 분류기이기 때문에 각 샘플의 타깃레이블에 대한 예측확률을 측정하기 위해서입니다.

3. 모델 알아보기

모델을 생성했으니 이를 분석해봅시다.

model.summary()

summary를 통해서 모델의 정보를 대략 알 수 있습니다. 

hidden1 = model.layers[1]
hidden1.name #'dense'추출
weights, biases = hidden1.get_weights()

model에서 인덱스를 통해서 레이어를 추출하고 name을 통해서 이름을 알고 get_weight() 메서드를 통해서 weight와 bias를 알 수 있습니다. (set_weight()를 통해서 설정도 가능합니다.)

4. 모델 컴파일하기

keras모델은 층을 생성한 후 비용함수, 최적화방법을 설정하여 어떻게 학습을 진행할지 설정해주어야하는데 이를 컴파일이라고 합니다.

model.compile(loss="sparse_categorical_crossentropy",
              optimizer="sgd",
              metrics=["accuracy"])

분류기이기 때문에 CEE를 비용함수로 정하고 최적화 방법은 SGD를 사용하였습니다. 만약 SVM같은 다른 모델을 사용하고싶으면 loss="hinge"로 지정하는 등 다른 비용함수를 정하면 되며 최적화 방식은 optimizer를 설정하여 변경 할 수 있습니다.(AdaGrad 등이 있습니다.)

metrics를 통해서 학습을 진행할 때마다 출력할 평가방식을 지정할 수 있습니다.

5.모델 학습하기

history = model.fit(X_train, y_train, epochs=30,
                    validation_data=(X_valid, y_valid))

fit 메서드를 통해서 학습시킬수 있으며 이 때 훈련 샘플,레이블 에폭수 그리고 검증 샘플,레이블을 입력할 수 있습니다.

fit 메서드를 실행하면 위와 같이 학습을 진행하며 에폭이 끝날 때마다 훈련데이터와 검증데이터의 손실함수 그리고 metrics에서 지정한 평가점수를 출력합니다.

학습이 끝나면 fit 메서드는 학습과정의 데이터를 저장한 history 클래스를 리턴합니다.

6. 학습 시각화하기

fit 메서드에서 리턴받은 history를 통해서 쉽게 구현가능합니다.

import pandas as pd

pd.DataFrame(history.history).plot(figsize=(8, 5))
plt.grid(True)
plt.gca().set_ylim(0, 1)
save_fig("keras_learning_curves_plot")
plt.show()

출처 : https://github.com/ageron/handson-ml2/blob/master/10_neural_nets_with_keras.ipynb

7. 테스트 데이터로 평가하기

evalute()메서드를 통해서 평가 할 수있습니다.

model.evaluate(X_test, y_test)
'''
result :
10000/10000 [==============================] - 0s 21us/sample - loss: 0.3378 - accuracy: 0.8781
'''

8. 예측하기

predict()메서드를 통해서 새로운 샘플을 예측하고 클래스별 확률을 알 수 있습니다.

X_new = X_test[:3]
y_proba = model.predict(X_new)
y_proba.round(2)
'''
result:

array([[0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.01, 0.  , 0.99],
       [0.  , 0.  , 0.99, 0.  , 0.01, 0.  , 0.  , 0.  , 0.  , 0.  ],
       [0.  , 1.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  ]],
      dtype=float32)
'''

predict_calsses()메서드를 통해서 예측 클래스만 출력할 수 있습니다.

y_pred = model.predict_classes(X_new)
y_pred
'''
result:
array([9, 2, 1])
'''

+ Recent posts