본문 바로가기

ML, DL/라이브러리

Tensorflow, Keras

출처 : 

https://wikidocs.net/32105

 

07) 케라스(Keras) 훑어보기

이 책에서는 딥 러닝을 쉽게 할 수 있는 파이썬 라이브러리인 케라스(Keras)를 사용합니다. 케라스는 유저가 손쉽게 딥 러닝을 구현할 수 있도록 도와주는 상위 레벨의 인터 ...

wikidocs.net

 

 

  • Keras 훑어보기 (Keras Sequential API)

Sequential() 을 model 로 선언 한 뒤 model.add() 를 통계 layer 를 단계적으로 추가합니다.

model = Sequential()

 

Dense : Fully Conntect layer 를 추가합니다.

model = Sequential()
model.add(Dense(1, input_dim=3, activation='relu'))

위의 코드에서 Dense()는 한번 사용되었지만 더 많은 층을 추가할 수 있습니다. Dense()의 대표적인 인자를 보겠습니다.

첫번째 인자 = 출력 뉴런의 수.
input_dim = 입력 뉴런의 수. (입력의 차원)
activation = 활성화 함수.

 

 

summary() 로 모델 정보를 요약해서 보여줍니다.

model.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_1 (Dense)              (None, 8)                 40        
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 9         
=================================================================
Total params: 49
Trainable params: 49
Non-trainable params: 0
_________________________________________________________________

 

compile() : 모델을 컴파일 합니다. 손실 함수, 옵티마이저, 메트릭 함수를 선택 합니다.

from tensorflow.keras.layers import SimpleRNN, Embedding, Dense
from tensorflow.keras.models import Sequential

vocab_size = 10000
embedding_dim = 32
hidden_units = 32

model = Sequential()
model.add(Embedding(vocab_size, embedding_dim))
model.add(SimpleRNN(hidden_units))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])

 

fit() : 모델을 학습합니다.

model.fit(X_train, y_train, epochs=10, batch_size=32, verbose=0, validation_data(X_val, y_val))
# 훈련 데이터의 20%를 검증 데이터로 사용.
model.fit(X_train, y_train, epochs=10, batch_size=32, verbose=0, validation_split=0.2))

첫번째 인자 = 훈련 데이터에 해당됩니다.
두번째 인자 = 지도 학습에서 레이블 데이터에 해당됩니다.
epochs = 에포크. 에포크 1은 전체 데이터를 한 차례 훑고 지나갔음을 의미함. 정수값 기재 필요. 총 훈련 횟수를 정의합니다.
batch_size = 배치 크기. 기본값은 32. 미니 배치 경사 하강법을 사용하고 싶지 않을 경우에는 batch_size=None을 기재합니다.

좀 더 많은 인자를 사용할 때를 보겠습니다.

validation_data(x_val, y_val) = 검증 데이터(validation data)를 사용합니다. 일반적으로 검증 데이터를 사용하면 각 에포크마다 검증 데이터의 정확도나 오차를 함께 출력하는데, 이 정확도는 훈련이 잘 되고 있는지를 보여줄 뿐이며 실제로 모델이 검증 데이터를 학습하지는 않습니다. 검증 데이터의 오차(loss)가 낮아지다가 높아지기 시작하면 이는 과적합(overfitting)의 신호입니다.

validation_split = validation_data와 동일하게 검증 데이터를 사용하기 위한 용도로 validation_data 대신 사용할 수 있습니다. 검증 데이터를 지정하는 것이 아니라 훈련 데이터와 훈련 데이터의 레이블인 X_train과 y_train에서 일정 비율 분리하여 이를 검증 데이터로 사용합니다.

verbose = 학습 중 출력되는 문구를 설정합니다.
- 0 : 아무 것도 출력하지 않습니다.
- 1 : 훈련의 진행도를 보여주는 진행 막대를 보여줍니다.
- 2 : 미니 배치마다 손실 정보를 출력합니다.

 

evaluate() : 테스트 데이터를 통해 학습한 모델에 대한 정확도를 평가합니다.

# 위의 fit() 코드의 연장선상인 코드
model.evaluate(X_test, y_test, batch_size=32)

첫번째 인자 = 테스트 데이터에 해당됩니다.
두번째 인자 = 지도 학습에서 레이블 테스트 데이터에 해당됩니다.
batch_size = 배치 크기.

predict() : 임의의 입력에 대한 모델의 출력값을 확인합니다.

# 위의 fit() 코드의 연장선상인 코드
model.predict(X_input, batch_size=32)

첫번째 인자 = 예측하고자 하는 데이터.
batch_size = 배치 크기.

 

save() : 인공 신경망 모델을 hdf5 파일에 저장합니다.

model.save("model_name.h5")

load_model() : 저장해둔 모델을 불러옵니다.

from tensorflow.keras.models import load_model
model = load_model("model_name.h5")

 

 

  • Keras Functional API

Functional API는 각 층을 일종의 함수(function)로서 정의합니다. 그리고 각 함수를 조합하기 위한 연산자들을 제공하는데, 이를 이용하여 신경망을 설계합니다. Functional API로 FFNN, RNN 등 다양한 모델을 만들면서 기존의 sequential API와의 차이를 이해해봅시다.

- Functional API는 입력의 크기(shape)를 명시한 입력층(Input layer)을 모델의 앞단에 정의해주어야 합니다.

 

Sequential API와는 다르게 functional API에서는 입력 데이터의 크기(shape)를 인자로 입력층을 정의해주어야 합니다. 피드 포워드 신경망(Fully-connected FFNN)을 만든다고 가정해보겠습니다.

inputs = Input(shape=(10,))
hidden1 = Dense(64, activation='relu')(inputs)
hidden2 = Dense(64, activation='relu')(hidden1)
output = Dense(1, activation='sigmoid')(hidden2)
model = Model(inputs=inputs, outputs=output) # <- 새로 추가

 

functional API를 사용하면 아래와 같이 다중 입력과 다중 출력을 가지는 모델도 만들 수 있습니다.

# 최종 완성된 다중 입력, 다중 출력 모델의 예
model = Model(inputs=[a1, a2], outputs=[b1, b2, b3])

이번에는 다중 입력을 받는 모델을 입력층부터 출력층까지 설계해보겠습니다.

from tensorflow.keras.layers import Input, Dense, concatenate
from tensorflow.keras.models import Model

# 두 개의 입력층을 정의
inputA = Input(shape=(64,))
inputB = Input(shape=(128,))

# 첫번째 입력층으로부터 분기되어 진행되는 인공 신경망을 정의
x = Dense(16, activation="relu")(inputA)
x = Dense(8, activation="relu")(x)
x = Model(inputs=inputA, outputs=x)

# 두번째 입력층으로부터 분기되어 진행되는 인공 신경망을 정의
y = Dense(64, activation="relu")(inputB)
y = Dense(32, activation="relu")(y)
y = Dense(8, activation="relu")(y)
y = Model(inputs=inputB, outputs=y)

# 두개의 인공 신경망의 출력을 연결(concatenate)
result = concatenate([x.output, y.output])

z = Dense(2, activation="relu")(result)
z = Dense(1, activation="linear")(z)

model = Model(inputs=[x.input, y.input], outputs=z)

위 모델은 두 개의 입력층으로부터 분기되어 진행된 후 마지막에는 하나의 출력을 예측하는 모델입니다.

 

 

  • Model Class Subclassing

케라스의 구현 방식에는 Sequential API, Functional API 외에도 Subclassing API라는 구현 방식이 존재합니다.

클래스(class) 형태의 모델은 tf.keras.Model을 상속받습니다. 그리고 init()에서 모델의 구조와 동적을 정의하는 생성자를 정의합니다. 이는 파이썬에서 객체가 갖는 속성값을 초기화하는 역할로, 객체가 생성될 때 자동으호 호출됩니다. super() 함수를 부르면 여기서 만든 클래스는 tf.keras.Model 클래스의 속성들을 가지고 초기화 됩니다. call() 함수는 모델이 데이터를 입력받아 예측값을 리턴하는 포워드(forward) 연산을 진행시키는 함수입니다.

import tensorflow as tf
class LinearRegression(tf.keras.Model):
  def __init__(self):
    super(LinearRegression, self).__init__()
    self.linear_layer = tf.keras.layers.Dense(1, input_dim=1, activation='linear')

  def call(self, x):
    y_pred = self.linear_layer(x)

    return y_pred
model = LinearRegression()
X = [1, 2, 3, 4, 5, 6, 7, 8, 9] # 공부하는 시간
y = [11, 22, 33, 44, 53, 66, 77, 87, 95] # 각 공부하는 시간에 맵핑되는 성적
sgd = tf.keras.optimizers.SGD(lr=0.01)
model.compile(optimizer=sgd, loss='mse', metrics=['mse'])
model.fit(X, y, epochs=300)

 

2. 언제 서브클래싱 API를 써야 할까?

Sequential API는 간단한 모델을 구현하기에 적합합니다. Functional API로는 Sequential API로 구현할 수 없는 복잡한 모델들을 구현가능합니다. 그런데 Subclassing API로는 Functional API가 구현할 수 없는 모델들조차 구현할 수 있는 경우가 있습니다. Functional API는 기본적으로 딥 러닝 모델을 DAG(directed acyclic graph)로 취급합니다. 실제로 대부분의 딥 러닝 모델이 이에 속하기는 하지만, 항상 그렇지는 않습니다. 예를 들어서 재귀 네트워크나 트리 RNN은 이 가정을 따르지 않으며 Functional API에서 구현할 수 없습니다.

이를 반대로 해석하면 대부분의 딥 러닝 모델은 Functional API 수준에서도 전부 구현이 가능하다는 의미이기도 합니다. 그래서 Subclassing API는 밑바닥부터 새로운 수준의 아키텍처를 구현해야 하는 실험적 연구를 하는 연구자들에게 적합합니다.

3. 세 가지 구현 방식 비교.

1) Sequential API

장점 : 단순하게 층을 쌓는 방식으로 쉽고 사용하기가 간단합니다.
단점 : 다수의 입력(multi-input), 다수의 출력(multi-output)을 가진 모델 또는 층 간의 연결(concatenate)이나 덧셈(Add)과 같은 연산을 하는 모델을 구현하기에는 적합하지 않습니다. 이런 모델들의 구현은 Functional API를 사용해야 합니다.

2) Functional API

장점 : Sequential API로는 구현하기 어려운 복잡한 모델들을 구현할 수 있습니다.
단점 : 입력의 크기(shape)를 명시한 입력층(Input layer)을 모델의 앞단에 정의해주어야 합니다. 가령, 아래의 코드를 봅시다.

# 선형 회귀 구현 코드의 일부 발췌

inputs = Input(shape=(1,)) # <-- 해당 부분
output = Dense(1, activation='linear')(inputs)
linear_model = Model(inputs, output)

sgd = optimizers.SGD(lr=0.01)

linear_model.compile(optimizer=sgd, loss='mse', metrics=['mse'])
linear_model.fit(X, y, epochs=300)

3) Subclassing API

장점 : Functional API로도 구현할 수 없는 모델들조차 구현이 가능합니다.
단점 : 객체 지향 프로그래밍(Object-oriented programming)에 익숙해야 하므로 코드 사용이 가장 까다롭습니다.

 

 

  • Model 저장하고 불러오기

Parameter 만 저장하고 불러오기

 

model.save_weights('model.ckpt')

model2 = create_model()

model2.load_weights('model.skpt')

model2.compile(...)

model2.evaluate(test_dataset)

 

Model 전체를 저장하고 불러오기

model.save('model')

model2 = keras.models.load_model('model')

model2.evaluate(dataset)

 

  • Tensorboard 사용하여 시각화하기

%load_ext tensorboard

 

Keras Callback 사용

new_model = create_seq_model()

new_model.compile(...)

new_model.evaluate(dataset)

 

log_dir = './logs/new_model_1'

tensorboard_cb = keras.callbacks.RensorBoard(log_dir, histogram_freq=1)  # 1 : 매 epoch 마다 저장을 하겠다.

model.fit(..., callbacks = [tensorboard_cb]) # callback 에 종류에는 여러개가 있음

 

%tensorboard --logdir $log_dir #Jupyter-notebook Magick command, 인터넷 연결 안 되면 알 될 수도 있음

 

  • Summary Writer 사용

import datetime

current_time = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")

train_log_dir = 'logs/gradient_tape/' + current_time + '/train'

test_log_dir = 'logs/gradient_tape/' + current_time + '/test'

train_summary_writer = tf.summary.create_file_writer(train_log_dir)

test_summary_writer = tf.summary.create_file_writer(test_log_dir)

 

 

for epoch inrange(EPOCHS):

    ...

    ...

with train_summary_writer.as_default():    

    tf.summary.sclar('loss', train_loss.result(), step=epoch)

 

'ML, DL > 라이브러리' 카테고리의 다른 글

tensorflow, keras GPU 메모리 문제  (0) 2022.09.20
Tensorflow checkpoint  (0) 2022.08.24
Pytorch  (0) 2022.08.02