블로그 이미지
Flying Mr.Cheon youGom

Recent Comment»

Recent Post»

Recent Trackback»

« 2024/5 »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

 
 

Spinning Up in Deep RL

데이터사이언스 | 2020. 7. 8. 11:18 | Posted by youGom

OpenAI에서 강화 학습 교육 자료인 스피닝 업(Spinning Up)을 공개했습니다. 깃허브에서 관련 코드도 같이 제공됩니다. 아래 알고리즘 트리 중에서 스피닝 업에서 다루는 것은 Policy Gradient, PPO, TRPO, DDPG, TD3, SAC입니다.

rl_alg.tree.png

OpenAI에서 스피닝 업을 만들게 된 이유가 강화 학습을 배우기 위한 적절한 자료가 없기 때문이라고 합니다. 곰곰히 생각해 보면 일리가 있습니다. 딥러닝 관련되어서는 좋은 책과 온라인 자료를 쉽게 찾을 수 있지만 강화 학습은 많이 부족합니다. <핸즈온 머신러닝> 16장에서 강화 학습을 다루고 있지만 제한된 범위입니다. 서튼(Sutton) 교수의 <Reinforcement Learning: An Introduction> 2판이 곧 출간될 예정입니다. 이 책은 강화 학습의 대표적인 텍스트 북입니다. 조금 더 핸즈온 스타일의 강화 학습 책으로는 어떤 것이 있는지 찾아 보았습니다.

71y3a2bdjf3l zai-drl-meap-hi morales_drl_hiresmeap

맥심 라판(Maxim Lapan)이 쓴 팩킷(Packt)의 <Deep Reinforcement Learning Hands-On>이 아마존에서 독자 반응이 좋습니다. 이 책은 DQN, Policy Gradient, A2C, A3C, TRPO, PPO, I2A, AlphaGo Zero 등을 다룹니다.

매닝에서는 <Deep Reinforcement Learning In Action>과 <Grokking Deep Reinforcement Learning>이 준비되고 있습니다. 매닝 책은 출간되려면 아직 한참 기다려야 할 것 같네요. 재미있게도 이 세 책은 모두 파이토치를 사용합니다.

**Complete Draft** Reinforcement Learning: An Introduction

다음은 전체 책의 목차입니다.

  1. Introduction
  2. Multi-armed Bandits
  3. Finite Markov Decision Processes
  4. Dynamic Programming
  5. Monte Carlo Methods
  6. Temporal-Difference Learning
  7. n-step Bootstrapping
  8. Planning and Learning with Tabular Methods
  9. On-policy Prediction with Approximation
  10. On-policy Control with Approximation
  11. *Off-policy Methods with Approximation
  12. Eligibility Traces
  13. Policy Gradient Methods
  14. Psychology
  15. Neuroscience
  16. Applications and Case Studies
  17. Frontiers

(업데이트) 2018년 1월 1일에 마이너한 업데이트가 있었던 것 같습니다. 새로운 PDF를 참고하세요.

모두연의 강화학습 튜토리얼

모두의연구소 이웅원님이 만드신 강화학습(reinforcement learning) 튜토리얼이 깃북으로 공개되었습니다. 이 튜토리얼은 무려 160여 페이지 분량입니다. 한글로 된 강화학습 자료가 많지 않은 가운데 이런 자료가 공개되어 매우 반갑네요. 이 튜토리얼은 데이빗 실버(David Silver) 교수의 강의와 리처드 서튼(Richard S. Sutton) 교수의 ‘Introduction to Reinforcement Learning‘ 책, 유다시티(Udacity)의 강화학습 강의등을 참고했다고 합니다.

참고로 데이빗 실버 교수의 강의는 유튜브에서 볼 수 있으며 리처드 서튼 교수의 Introduction to Reinforcement Learning 책은 2판을 무료로 드롭박스에서 읽을 수 있습니다. 2판은 2012년 부터 쓰여져서 최근까지 마무리 작업이 진행되었는데 지금은 거의 완결된 상태입니다. pdf 버전은 여기서 다운 받을 수 있습니다.

(업데이트) Reinforcement Learning: An Introduction 의 새로운 드래프트가 공개되었습니다. 이 버전은 2016년 9월 입니다.

:

1958년 퍼셉트론이 발표된 후 같은 해 7월 8일자 뉴욕타임즈는 앞으로 조만간 걷고, 말하고 자아를 인식하는 단계에 이르는 컴퓨터 세상이 도래할 것이라는 다소 과격한 기사를 냈습니다.

하지만 1969년, 단순 퍼셉트론은 ​XOR 문제도 풀 수 없다는 사실을 MIT AI 랩 창시자인 Marvin Minsky 교수가 증명하였고, 다층 퍼셉트론(MLP)으로 신경망을 구성하면 XOR 문제를 풀 수 있으나, 이러한 MLP를 학습시키는 방법은 존재하지 않는다고 단정해버렸습니다.

 

이로 인해 떠들석했던 인공신경망과 관련된 학문과 기술은 더 이상 발전되지 않고 침체기를 겪게 됩니다.

 

그런데 1974년, 당시 하버드 대학교 박사과정이었던 Paul Werbos는 MLP를 학습시키는 방법을 찾게 되는데, 이 방법을 Minsky 교수에게 설명하지만 냉랭한 분위기속에 무시되버립니다.

Paul Werbos가 Minsky 교수에게 설명한 MLP를 학습시킬 수 있는 획기적인 방법이 바로 오류 역전파 (Backpropagation of errors)라는 개념입니다.

 

이제 오류 역전파(앞으로 그냥 역전파라고 부르겠습니다)가 무엇인지 살펴보도록 합니다.

심층 신경망을 학습한다는 것은 최종 출력값과 실제값의 오차가 최소가 되도록 심층 신경망을 이루는 각 층에서 입력되는 값에 곱해지는 가중치와 바이어스를 계산하여 결정하는 것을 말합니다.

 

우리는 [6편] 아달라인을 학습할 때 인공 신경망의 출력값과 실제값의 오차가 최소가 되도록 가중치를 결정하는 방법인 경사하강법에 대해 다룬적이 있습니다.

 

경사하강법은 오차 곡선을 따라 일정한 크기로 내려가면서 최소값을 찾아가는 방법인데, 일정한 크기는 해당 지점에서 접선의 기울기와 learning rate으로 결정한다고 했지요.

 

 

심층 신경망을 학습하는데 유용하게 활용되는 역전파(backpropagtion) 알고리즘도 결국 이 경사하강법을 이용합니다. 그러면 역전파가 무엇인지 그 개념에 대해 대충(?) 살펴보도록 합니다.

 

먼저 아래와 같은 2-2-2 다층 퍼셉트론이 있다고 생각해봅니다. 여기서는 역전파의 개념만 살펴볼 예정이므로 각 층에 존재하는 바이어스는 생략했습니다. 또한 용어의 통일성을 위해 입력층의 x1, x2a1(1), a2(1)로 표기하기로 합니다.

 

 

 

[34편]에서 l층의 i번째 노드와 l+1층의 j번째 노드를 연결하는 가중치 w를 다음과 같이 정의했지요~

 

 

 

 

이 구조에서 적용되는 활성 함수는 시그모이드 함수 φ입니다.

 

 

 

입력층 -> 은닉층 사이의 값의 흐름은 다음과 같습니다.

 

[식1] 

 

 

그리고 은닉층 -> 출력층 사이의 값의 흐름은 다음과 같습니다.

 

[식2] 

 

 

이와 같이 입력층의 a1(1), a2(1)을 시작으로 출력층의 a1(3), a2(3) 값이 출력되는 과정을 순전파(feedforward)라 부릅니다.

 

우리는 아달라인을 다룰 때 오차제곱합을 비용함수로 도입해서, 이 비용함수가 최소가 되도록 가중치를 결정했습니다. 물론 가중치를 결정하는 방법은 경사하강법이었죠.

 

여기서도 비용함수 J를 오차제곱합으로 정의를 해보면 다음과 같이 될 겁니다.

 

 

 

여기서 y1, y2는 트레이닝 데이터에 대한 각 노드에 대응되는 실제값입니다. 순전파 1회가 마무리되면 J1J2의 값이 결정되겠죠.

입력값 a1(1), a2(1)과 실제값 y1, y2는 고정된 값이므로 J1J2는 결국 가중치 w1,1(1)~w2,2(2)를 변수로 가지는 함수가 됩니다.

우리의 목표는 J1J2의 값이 최소가 되도록 w1,1(1)~w2,2(2)를 결정해야 합니다.

 

아달라인에서와 마찬가지로 다층 퍼셉트론에서도 비용함수의 최소값을 찾아가는 방법으로 경사하강법을 활용한다고 했습니다. 각 층에서 가중치를 업데이트하기 위해서는 결국 각 층에서의 비용함수(오차로 불러도 됩니다.)의 미분값이 필요하게 되는 것이지요.

 

이를 매우 효율적으로 해결하기 위한 방법이 바로 역전파 알고리즘입니다.

역전파란 역방향으로 오차를 전파시키면서 각층의 가중치를 업데이트하고 최적의 학습 결과를 찾아가는 방법입니다.

 

자, 이 경우를 한번 생각해봅니다.

순전파에 있어서 가중치의 값을 매우 미세하게 변화시키면 비용함수 J1, J2도 매우 미세하게 변화될 겁니다. 매우 미세하게 변화시킨다는 것은 미분을 한다는 이야기입니다. 그런데, 매우 미세한 영역으로 국한할 때 가중치의 미세변화와 이에 따른 비용함수의 미세변화가 선형적인 관계가 된다고 알려져 있습니다. 선형적인 관계라는 이야기는 결국 비용함수를 매우 미세하게 변화시키면 이에 따라 가중치도 매우 미세하게 변화되는데 이 역시 선형적인 관계라는 이야기입니다.

 

이런 원리에 의해, 순전파를 통해 출력층에서 계산된 오차 J1, J2의 각 가중치에 따른 미세변화를 입력층 방향으로 역전파시키면서 가중치를 업데이트하고, 또 다시 입력값을 이용해 순전파시켜 출력층에서 새로운 오차를 계산하고, 이 오차를 또다시 역전파시켜 가중치를 업데이트하는 식으로 반복합니다. 

 

역전파를 이용한 가중치 업데이트 절차는 아래와 같이 요약될 수 있습니다.

 

  1. 주어진 가중치 값을 이용해 출력층의 출력값을 계산함(순전파를 통해 이루어짐)
  2. 오차를 각 가중치로 미분한 값(실제로는 learning rate을 곱한 값)을 기존 가중치에서 빼줌(경사하강법을 적용하는 것이며, 역전파를 통해 이루어짐)
  3. 2번 단계는 모든 가중치에 대해 이루어짐
  4. 1~3단계를 주어진 학습회수만큼 또는 주어진 허용오차값에 도달할 때가지 반복함

 

2번 단계의 가중치 업데이트 식을 수식으로 표현하면 다음과 같습니다.

 

 

 

여기서 Jtotal은 해당 노드가 영향을 미치는 오차의 총합입니다. 예를 들면 출력층의 노드 a1(3)에서는 다른 노드의 오차에 영향을 전혀 미치지 않으므로 해당 노드에서 오차인 J1만 따지면 되지만, 은닉층의 a1(2) 노드는 출력층의 a1(3), a2(3) 노드의 오차에 영향을 미치므로 J1, J2 모두 더한 것이 Jtotal 값이 됩니다.

 

이번에는 역전파를 통한 가중치 업데이트 메커니즘을 살펴볼 것이므로 편의상 learning rate η는 1로 둡니다.

 

자, 그러면 실제로 역전파를 이용해 가중치를 업데이트 해보도록 하죠. 먼저 가중치 w1,1(2)에 대해서 계산을 해봅니다.

 w1,1(2)에 대한 업데이트 식은 아래와 같습니다.

 

 

 

미분의 연쇄법칙에 의해 오차의 가중치에 대한 미분값은 아래의 식으로 표현될 수 있습니다.

 

 

 

이제 위 식의 오른쪽 항에 있는 3개의 미분값을 하나하나 구해보도록 하지요~ 참고로 이 포스팅의 첫부분에서 서술한 순전파를 통한 값의 흐름을 요약한 수식을 참고하기 바랍니다.

 

역전파의 출발노드인 a1(3)에서 Jtotal의 값은 J1입니다. 따라서 위 식 오른쪽 항은 아래와 같이 계산됩니다.

 

 

 

따라서

 

 

 

역전파에서 가중치 업데이트를 위해 사용되는 오차의 가중치에 대한 미분값이 결국 역전파의 출발 노드의 활성 함수 값과 도착 노드의 활성 함수 값, 그리고 실제값만으로 표현되는 것을 알 수 있습니다.

​위 식의 오른쪽 항에서 처음 두 식의 값을 아래와 같이 δ1(3)으로 둡니다.

 

[식3]

 

 

 

역전파에 의해 업데이트 되는 w1,1(2)는 다음과 같습니다.

 

 

 

마찬가지 방법으로 w1,2(2)에 대한 업데이트 수식도 다음과 같습니다.

 

 

 

δ2(3)을 아래와 같은 수식으로 정의하고,

 

[식4]

 

w2,1(2), w2,2(2)에 대해서도 계산을 해보면

 

 

 

여기까지 서술해보니 뭔가 규칙성이 보입니다. 출력층에서 은닉층으로 역전파를 통해 전달되는 값이 결국 δ1(3) 과 δ2(3) 뿐이더라도 관련된 가중치를 업데이트하는데 충분하다는 것을 알 수 있습니다.

 

 

 

이제, 은닉층에서 입력층으로 향하는 역전파를 통해 w1,1(1)의 값을 업데이트 해보겠습니다.

 

 

 

w1,1(1)을 업데이트 하기 위해서 a1(2)에서 Jtotalw1,1(1)로 편미분한 값을 계산해야겠지요? 앞에서 적용한 것과 마찬가지로 미분의 연쇄법칙을 활용하면 다음과 같은 식이 됩니다.

 

 

 

위에서 언급했듯이 a1(2)에서 JtotalJ1J2를 더한 값이 됩니다. 따라서 위 식 오른쪽 항의 첫 번째 편미분값은 아래와 같이 계산됩니다. 

 

 

 

 그런데 출력층 -> 은닉층으로 역전파를 통한 가중치 계산시에 등장한 [식3]과 [식4]와 [식1], [식2]를 참고하여 계산해보면 다음과 같은 결과가 나옵니다.

 

 

 

가 됩니다.

 

 

나머지 편미분 값은 이미 해본 계산이므로 쉽게 계산됩니다.  w1,1(1)을 업데이트 하기 위한 편미분 값은 다음과 같습니다.

 

 

위 식의 오른쪽 항에서 처음 두 식을 δ1(2)로 둡니다. 

 

 

 

최종적으로 w1,1(1)의 업데이트 식은 아래와 같게 됩니다.

 

 

동일하게 w1,2(1)의 업데이트 식은 아래와 같습니다.

 

 

마찬가지로, δ2(2)를 다음과 같이 두고, 

 

 

 

w2,1(1), w2,2(2)에 대한 업데이트 식을 나타내면 다음과 같습니다.

 

 

 

따라서 모든 가중치에 대한 업데이트 식은 아래와 같이 표현할 수 있습니다.

 

 

 

여태까지 다룬 역전파 알고리즘 개념을 그림으로 도식화하여 나타내보면 다음과 같습니다.

 

 

 

 

이와 같이 순전파 -> 역전파 -> 가중치 업데이트 -> 순전파 .... 로 계속 반복해나가면 오차값이 0에 가까와지게 됩니다.  

 

이상으로 역전파 알고리즘 및 가중치 업데이트 원리를 살펴보았습니다. 역전파 알고리즘을 이해하기가 쬐금은 어렵지만, 이 부분이 딥러닝의 핵심적인 역할을 하는 부분이며, 완전한 이해가 힘들더라도 그 개념만이라도 알고 있으면 많은 도움이 됩니다.

:

강화학습 스터디 자료

데이터사이언스 | 2020. 7. 1. 10:37 | Posted by youGom

Online Tutorial(Video)

기본적인 개념 뿐만 아니라 강화학습과 관련된 영상들을 정리하였다.

Online Tutorial(Text)

Book

Github

 

:

cartpole in keras (a2c)

데이터사이언스/Keras로 | 2020. 6. 28. 23:12 | Posted by youGom
 
 
Introduction

This script shows an implementation of Actor Critic method on CartPole-V0 environment.

Actor Critic Method

As an agent takes actions and moves through an environment, it learns to map the observed state of the environment to two possible outputs:

  1. Recommended action: A probabiltiy value for each action in the action space. The part of the agent responsible for this output is called the actor.
  2. Estimated rewards in the future: Sum of all rewards it expects to receive in the future. The part of the agent responsible for this output is the critic.

Agent and Critic learn to perform their tasks, such that the recommended actions from the actor maximize the rewards.

CartPole-V0

A pole is attached to a cart placed on a frictionless track. The agent has to apply force to move the cart. It is rewarded for every time step the pole remains upright. The agent, therefore, must learn to keep the pole from falling over.

References

 

Setup

In [0]:
import gym
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

# Configuration parameters for the whole setup
seed = 42
gamma = 0.99  # Discount factor for past rewards
max_steps_per_episode = 10000
env = gym.make("CartPole-v0")  # Create the environment
env.seed(seed)
eps = np.finfo(np.float32).eps.item()  # Smallest number such that 1.0 + eps != 1.0
 

Implement Actor Critic network

This network learns two functions:

  1. Actor: This takes as input the state of our environment and returns a probability value for each action in its action space.
  2. Critic: This takes as input the state of our environment and returns an estimate of total rewards in the future.

In our implementation, they share the initial layer.

In [0]:
num_inputs = 4
num_actions = 2
num_hidden = 128

inputs = layers.Input(shape=(num_inputs,))
common = layers.Dense(num_hidden, activation="relu")(inputs)
action = layers.Dense(num_actions, activation="softmax")(common)
critic = layers.Dense(1)(common)

model = keras.Model(inputs=inputs, outputs=[action, critic])
 

Train

In [0]:
optimizer = keras.optimizers.Adam(learning_rate=0.01)
huber_loss = keras.losses.Huber()
action_probs_history = []
critic_value_history = []
rewards_history = []
running_reward = 0
episode_count = 0

while True:  # Run until solved
    state = env.reset()
    episode_reward = 0
    with tf.GradientTape() as tape:
        for timestep in range(1, max_steps_per_episode):
            # env.render(); Adding this line would show the attempts
            # of the agent in a pop up window.

            state = tf.convert_to_tensor(state)
            state = tf.expand_dims(state, 0)

            # Predict action probabilities and estimated future rewards
            # from environment state
            action_probs, critic_value = model(state)
            critic_value_history.append(critic_value[0, 0])

            # Sample action from action probability distribution
            action = np.random.choice(num_actions, p=np.squeeze(action_probs))
            action_probs_history.append(tf.math.log(action_probs[0, action]))

            # Apply the sampled action in our environment
            state, reward, done, _ = env.step(action)
            rewards_history.append(reward)
            episode_reward += reward

            if done:
                break

        # Update running reward to check condition for solving
        running_reward = 0.05 * episode_reward + (1 - 0.05) * running_reward

        # Calculate expected value from rewards
        # - At each timestep what was the total reward received after that timestep
        # - Rewards in the past are discounted by multiplying them with gamma
        # - These are the labels for our critic
        returns = []
        discounted_sum = 0
        for r in rewards_history[::-1]:
            discounted_sum = r + gamma * discounted_sum
            returns.insert(0, discounted_sum)

        # Normalize
        returns = np.array(returns)
        returns = (returns - np.mean(returns)) / (np.std(returns) + eps)
        returns = returns.tolist()

        # Calculating loss values to update our network
        history = zip(action_probs_history, critic_value_history, returns)
        actor_losses = []
        critic_losses = []
        for log_prob, value, ret in history:
            # At this point in history, the critic estimated that we would get a
            # total reward = `value` in the future. We took an action with log probability
            # of `log_prob` and ended up recieving a total reward = `ret`.
            # The actor must be updated so that it predicts an action that leads to
            # high rewards (compared to critic's estimate) with high probability.
            diff = ret - value
            actor_losses.append(-log_prob * diff)  # actor loss

            # The critic must be updated so that it predicts a better estimate of
            # the future rewards.
            critic_losses.append(
                huber_loss(tf.expand_dims(value, 0), tf.expand_dims(ret, 0))
            )

        # Backpropagation
        loss_value = sum(actor_losses) + sum(critic_losses)
        grads = tape.gradient(loss_value, model.trainable_variables)
        optimizer.apply_gradients(zip(grads, model.trainable_variables))

        # Clear the loss and reward history
        action_probs_history.clear()
        critic_value_history.clear()
        rewards_history.clear()

    # Log details
    episode_count += 1
    if episode_count % 10 == 0:
        template = "running reward: {:.2f} at episode {}"
        print(template.format(running_reward, episode_count))

    if running_reward > 195:  # Condition to consider the task solved
        print("Solved at episode {}!".format(episode_count))
        break
 

Visualizations

In early stages of training:

Imgur

In later stages of training:

Imgur
 
:
https://towardsdatascience.com/plotting-in-pandas-just-got-prettier-289d0e0fe5c0 pandas dataframe에서 plot을 사용할 수 있는데 bokeh, plotly를 사용할 수 있다는 것.
:

LSTM 이해하기

데이터사이언스 | 2020. 5. 20. 18:57 | Posted by youGom
 

기존의 인공 신경망의 은닉층에는 맥락이 고려되지 않은 단순한 뉴런만 배치되어 있는 구조이다. 과거의 은닉층(hidden layer)을 도입하여 시계열 데이터를 예측할 수 있지만 vanishing gradient 문제가 발생한다.

 

반면, 순환신경망(RNN)은 과거의 이벤트가 미래의 결과에 영향을 줄 수 있는 순환 구조(directed cycle)를 가지고 있다. 데이터 중에서도 연속적인 속성(sequence)을 띄고 있는 번역, 문자, 음성 인식 등 다양한 분야에서 RNN이 활용되고 있다. LSTM은 RNN의 주요 알고리즘으로 각광받고 있는 모델이다.

 

LSTM(Long Short Term Memory) 배경

  • Recurrent Nenural Network(RNN) 컨셉
  • RNN 구조RNN 모델 구조
    • Recurrent란, 이전에서 어떤 정보가 추가적으로 오는 것  (a.k.a 메모리)
    • RNN은 시간적으로 상관관계가 있는 데이터에서 주로 사용됨
      (예: The clouds are in the sky 문장에서 'sky'를 예측하는 경우)
    • 직전 데이터(t-1)과 현재 데이터(t) 간의 상관관계(correlation)을 고려하여 다음의 데이터(t+1)를 예측하고자,
      과거의 데이터도 반영한 신경망 모델을 만듦
    • 시간을 많이 거슬러 올라갈수록(long term) 경사를 소실하는 문제가 있음
      > 선형 함수가 아닌 비선형 함수를 활성함수로 쓰는 것과 비슷한 이유로, 초기값에 따라서 과거 데이터를 계속 곱할수록 작아지는 문제가 발생하게 됨.
      > LSTM은 구조를 개선하여 이 문제를 해결함
      > Le, Q. V., Jaitly, N., & Hinton, G. E. (2015) 연구에 따르면, 활성함수를 ReLU로 사용하고 가중치를 단위행렬로 초기화하면 long-term을 학습시킬 수 있음.
    • Vanilla RNN: RNN의 대표적인 모델로, 이전의 정보(xt-1)와 현재 정보(xt)를 취합(tanh, 하이퍼볼릭탄젠트)한 정보를 신경망에 들어가서 아웃풋(ht)을 만듦
  • 장기 의존성 (Long-Term Dependency) 문제
    • RNN 처럼 직전 정보만 참고하는 것이 아니라,  그 전 정보를 고려해야 하는 경우(longer-term) 가 있음
      (예: 책을 읽을 때, 몇 페이지/챕터 전에 있는 정보를 머리 속에 기억하고 있어야 하는 경우
      I grew up in France... I speak fluent French. 문장에서 'french'를 예측하는 경우)
    • 시퀀스가 있는 문장에서 문장 간의 간격(gap, 입력 위치의 차이)이 커질 수록, RNN은 두 두 정보의 맥락을 파악하기 어려워짐
    • 따라서, 한참 전의 데이터도 함께 고려하여 출력을 만들어보자! -> LSTM의 목적
 

LSTM이란?

  • LSTM
LSTM이 필요한 이유
장기 기억을 보존하는 LSTM

 

LSTM 컨셉은 Hochreiter, S., & Schmidhuber, J. (1997)이 제안했으며, 많은 개선을 통해 언어, 음성인식 등 다양한 분야에서 사용되고 있다.

    • RNN의 주요 모델 중 하나로, 장기 의존성 문제를 해결할 수 있음
    • 직전 데이터뿐만 아니라, 좀 더 거시적으로 과거 데이터를 고려하여 미래의 데이터를 예측하기 위함

 

  • LSTM 구조를 살펴보는 목적
  1. 바닐라 RNN보다 복잡한 구조가 왜 long-term dependency 한지 이해해보자
  2. 어떻게 이 구조가 long term과 short term, 둘 다 잡을 수 있는지 살펴보자

 

LSTM 구조
LSTM 구조

 

 

 

 

 

LSTM 구조

 

 

 

  •  Neural Network Layer
    > 웨이트(weight)와 바이어스(bias) 둘 다 있음 
  •  Pointwise Operation
    > Pointwise Operation으로 연산이 되면, 각각의 차원(dimension)에 맞게 곱하거나 더하게 됨
  • input과 output의 차원이 같다고 가정한다면,
    > 100 dimension과 100dimension이 concatenate 하게 되면 200 dimension이 되지만, 
    Neural Network Layer는 200 dimension을 100dimension으로 가는 네트워크가 되는 걸 유추해볼 수 있음.
    (실제로도 input과 output의 차원이 같음)

 

 

LSTM 네트워크 구조

 

 

 

 

[이미지 출처: [강의자료] Week9a Basics of RNN]

** Input Gate 와 Forget Gate 텍스트 위치 바꿔 적음 ** 

총 여섯 개의 파라미터가 있으며, 네 개의 게이트(gate)로 이루어져 있다.

 

1. Input (Xt)

2. (Cell) State 

  • 회전목마 같은 구조로 인해 오차가 사라지지 않고, 전체 체인을 관통함
  • (x) 게이트 메커니즘: 정보를 여닫는 역할

 

3. Hidden State

 

: 이전 출력(previous output)
 

4. Gates (Forget Gate, Input Gate, Output Gate)

세 개의 게이트는 정보들이 어느 시점에서 정보를 버리거나 유지하여 선택적으로 흘러갈 수 있게(=long term과 short term을 잘 고려하는) 하기 위함이다. 

LSTM에서 cell state와 함께 input gate와 output gate이 도입된 이유는 <스고모리 유우스케의 '정석으로 배우는 딥러닝'> 책의 설명을 인용한다. 

입력 웨이트 충돌(input weight conflict)과 출력 웨이트 충돌(output weight conflict) 

자신이 발화해야 할 신호가 전파돼 왔을 때는 웨이트를 크게 해서 활성화해야 하지만, 관계가 없는 신호가 전파됐을 때는 웨이트를 작게 해서 비활성인 채로 있어야 한다. 
시계열 데이터를 입력에서 받을 경우와 비교해보면, 이것은 시간 의존성이 있는 신호를 받았을 때는 웨이트를 크게 하고,
의존성이 없는 신호를 받았을 때는 웨이트를 작게 하는 것입니다. 그러나 뉴런이 동일한 웨이트로 연결돼 있다면 두 가지 경우에 서로 상쇄하는 형태의 웨이트 변경이 이뤄지므로 특히 장기의존성 학습이 잘 실행되지 않게 됩니다.

 

Step 1. Forget Gate: 과거 정보를 버릴지 말지 결정하는 과정

 

Forget gate
Forget Gate(망각 게이트) 구조

 

과거의 정보를 통해 맥락을 고려하는 것도 중요하지만, 그 정보가 필요하지 않을 경우에는 과감히 버리는 것도 중요하다!
  • Decide what information we’re going to throw away from the cell state.
  • 이전 output과 현재 input을 넣어, cell state로 가는 과거 정보값이 나옴
  • 활성함수로 시그모이드(sigmoid)를 사용하므로, 0 또는 1 값이 나옴
    > '0'일 경우, 이전의 cell state값은 모두 '0'이 되어 미래의 결과에 아무런 영향을 주지 않음 
    > '1'일 경우, 미래의 예측 결과에 영향을 주도록 이전의 cell state 값(Ct-1)을 그대로 보내 완전히 유지함
  • 즉, Forget Gate는 현재 입력과 이전 출력을 고려해서,
    cell state의 어떤 값을 버릴지/지워버릴지('0'이 출력되면 날려버림) 결정하는 역할

Step 2. Input Gate: 현재 정보를 저장할지 결정하는 과정

Input Gate
Input Gate 구조

 

  • Decide what new information we’re going to store in the cell state.
  • 현재의 cell state값에 얼마나 더할지 말지를 정하는 역할 (tanh는 -1 에서 1 사이의 값이 나옴)

* Forget Gate와 Input Gate의 주요 역할

: 이전 cell state 값을 얼마나 버릴지, 지금 입력과 이전 출력으로 얻어진 값을 얼마나 cell state에 반영할지 정하는 역할

Step 3. Update (cell state): 과거 cell state(Ct-1)를 새로운 state(Ct)로 업데이트 하는 과정

Update Gate
Update Gate 구조

 

  • Update, scaled by now much we decide to update. 
  • Forget Gate를 통해서 얼마나 버릴지, Input Gate에서 얼마나 더할지를 정했으므로,
    > input gate * current state + forget * previous state

Step 4. Output Gate (hidden state): 어떤 출력값을 출력할지 결정하는 과정

Output Gate
Output Gate 구조

 

  • Output based on the updated state.
  • 최종적으로 얻어진 cell state 값을 얼마나 빼낼지 결정하는 역할
    > output gate * updated state

5. Output (ht)

  • output state 는 다음 hidden state와 항상 동일함

6. Next (Cell) State

7. Next Hidden State

 

LSTM이 문제점, 핍홀 연결(peephole connections)

Output 게이트가 C(t)를 전달하기 때문에, LSTM 블록별 cell state는 output 게이트에 따라 달라진다. (input, forget 게이트는 C(t-1)를 전달함) 
Output 게이트가 계속 닫혀있는 경우(시그모이드에서 0을 보내는 경우를 의미하는 것 같음) cell state에 접근할 수 없다는 문제가 발생한다. 이 문제를 해결하기 위해 도입된 것이 '핍홀 연결' 이다. (<정석으로 배우는 딥러닝> 책에서는 핍홀 결합으로 번역되었지만, 핍홀 연결이 잘 표현된 번역같다!)
 
  • cell state에 각 게이트를 연결하여, cell state를 각 게이트에 전달함
  • Gers & Schmidhuber (2000)이 제안한 모델은 핍홀 결함을 가지고 있음.
  • 핍홀 연결에 대한 자세한 설명은 이 블로그를 참고하세요!
 

LSTM 구조에 대한 설명을 마치며

  • 바닐라 RNN에 비해 LSTM 하나의 구조에도 네 개의 뉴럴 네트워크가 들어가 있지만, 실제로 TensorFlow 를 이용하서 사용할 땐 간단함
  • 입력과 출력을 정해주고, 초기화만 잘 시켜주면, 텐서플로우에서 LSTM 모듈을 사용할 수 있음
  • CEC(constant error carousal, 상수 오류 회전기)를 통해서 vanishing gradient 문제를 해결한다는 점에 대해서는 더 공부가 필요하다...
    Why can Constant Error Carousels (CECs) prevent LSTM from the problems of vanishing/exploding gradients?
    > https://bi.snu.ac.kr/Courses/ML2016/LectureNote/LectureNote_ch7.pdf

 

참고 자료

 

:

keras.layers.Flatten() 

이 함수를 활용하면 된다.

model.summary()를 통해 확인해보면, input shape와 output shape가 동일하게 나오는게 보이는데,

별도 옵션이나 함수에서 output shape를 변경하는 건 없다.

 

Flatten() 의 역할은 n dimension을 직렬화시켜버린다. Flatten()을 통해 shape을 단순화시키고,

최종 값을 낼지, 추가 학습 모델을 넣을지 선택하면 된다.

 

stackoverflow에 대략 적인 답이 있어서, 이 내용을 참고 했다.

그리고 stackoverflow 뿐만 아니라, flatten()에 대한 내용은 tutorial이나 책에도 항상 나오고 있지만,

본인이 코드 작성하다보면, 실수나 생각나지 않을 수 있어서 메모해둔다.

 

참조 : https://github.com/keras-team/keras/issues/6351

내 코드에서 발생한 에러코드

expected ... to have 3 dimensions, but got array with shape ...

 

:

딥러닝을 위한 고급도구

데이터사이언스/Keras로 | 2020. 5. 7. 15:18 | Posted by youGom

 

7.1 Sequential 모델을 넘어서: 케라스의 함수형 API

 
Sequential
 
 
 
 
input
output
Sequential 모델: 차례대로 쌓은 층

이 책에서는 지금까지 위의 모델을 이용해서만 문제를 해결했습니다. 이런 가정은 많은 문제에 적용할 수 있지만, 아닌 경우도 존재합니다.

일부 네트워크는 개별 입력이 여러 개 필요하거나 출력이 여러 개 필요합니다. 층을 차례대로 쌓지 않고 층 사이를 연결하여 그래프처럼 만드는 네트워크도 있습니다.

예를 들어 어떤 작업은 다양한 종류의 입력이 필요합니다. 다양한 입력 소스에서 전달된 데이터를 다른 종류의 신경망 층을 사용하여 처리하고 합칩니다. 다음과 같은 모델이 만들어질 수 있는 것입니다.

 
 
 
 
 
 
 
모듈 병합
가격 예측
완전 연결 데이터
RNN 모듈
컨브넷 모듈
메타데이터
텍스트 설명
사진
다중 입력 모델

또한 다중 출력 모델도 가능합니다.

 
 
 
 
 
소설 텍스트
텍스트 처리 모듈
장르를 위한 분류 모델
시대를 위한 회귀 모델
장르
시대
다중 출력 모델

최근에 개발된 많은 신경망 구조는 선형적이지 않은 네트워크 토폴로지가 필요합니다. 비순환 유향 그래프(DAG) 같은 네트워크 구조입니다. 인셉션 모듈을 사용하는 인셉션 계열의 네트워크가 그 예시입니다. 이 모듈은 나란히 놓인 여러개의 합성곱 층을 거쳐 하나의 텐서로 출력이 합쳐집니다.

 
 
 
 
 
 
 
 
 
 
 
 
 
입력
Conv2D
1 * 1, strides=2
Conv2D
1 * 1
AvgPool2D
3 * 3, strides=2
Conv2D
1 * 1
Conv2D
3 * 3, strides=2
Conv2D
3 * 3
Conv2D
3 * 3
Conv2D
3 * 3, strides=2
concatenate
output
인셉션 모듈: 나란히 놓인 합성곱 층으로 구성된 서브그래프

최근에는 모델에 잔차 연결 을 추가하는 경향도 있습니다. ResNet 계열의 네트워크들이 이런 방식을 사용하기 시작했습니다. 잔차 연결은 하위 층의 출력 텐서를 상위 층의 출력 텐서에 더해서 아래층의 표현이 네트워크 위쪽으로 흘러갈 수 있도록 합니다. 하위 층에서 학습된 정보가 데이터 처리 과정에서 손실되는 것을 방지합니다.

 
 
 
 
잔차 연결
+
잔차 연결: 하위 층의 출력을 상위 층의 특성 맵에 더한다.

여러 경우에 다중 입력 모델, 다중 출력 모델, 그래프 구조를 띈 모델이 필요하지만 Sequential 모델로는 한계가 있습니다. 이런 경우 케라스의 함수형 API 를 사용할 수 있습니다.

7.1.1 함수형 API 소개

함수형 API(functional API) 에서는 직접 텐서들의 입출력을 다룹니다. 함수처럼 층을 사용하여 텐서를 입력받고 출력합니다.

간단한 예시 코드를 이용해서 Sequential과 비교해보겠습니다.

from keras.models import Sequential, Model
from keras import layers
from keras import Input

# Sequential model
seq_model = Sequential()
seq_model.add(layers.Dense(32, activation='relu', input_shape=(64,)))
seq_model.add(layers.Dense(32, activation='relu'))
seq_model.add(layers.Dense(10, activation='softmax'))

# Functianal API
input_tensor = Input(shape=(64,))
x = layers.Dense(32, activation='relu')(input_tensor)
x = layers.Dense(32, activation='relu')(x)
output_tensor = layers.Dense(10, activation='softmax')(x)

model = Model(input_tensor, output_tensor)

위 코드에서 주의할 점은 output 텐서는 반드시 input 텐서를 반복변환하여 만들 수 있어야 한다는 점입니다. 만약 그렇지 못한 입력을 줄 경우, Runtime Error가 발생합니다. 컴파일, 훈련, 평가는 다음과 같습니다.

# 컴파일
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')

import numpy as np
x_train = np.random.random((1000, 64))
y_train = np.random.random((1000, 10))

# 훈련
model.fit(x_train, y_train, epochs=10, batch_size = 128)

# 평가
score = model.evalutate(x_train, y_train)

7.1.2 다중 입력 모델

함수형 API로 간단한 다중 입력 모델을 만들어봅시다. 일반적으로 이런 모델은 입력 가지를 합치기 위해 여러 텐서를 연결할 수 있는 층을 사용합니다.

예시의 모델은 질문-응답 모델입니다. 전형적인 질문-응답 모델은 2개의 입력을 가집니다.(자연어 질문, 답변에 필요한 정보가 담긴 텍스트) 그러면 모델은 답을 출력해야 합니다. 가장 간단한 구조는 미리 정의한 어휘 사전에서 소프트맥스 함수를 통해 한 단어로 된 답을 출력하는 것입니다.

 
 
 
 
 
 
 
 
참고 텍스트
Embedding
질문
Embedding
LSTM
LSTM
Concatenate
Dense
응답
질문-응답 모델

텍스트와 질문을 벡터로 인코딩하여 독립된 입력 2개를 정의합니다. 그다음 이 벡터를 연결하고 그 위에 소프트맥스 분류기를 추가합니다.

# 코드 7-1 2개의 입력을 가진 질문-응답 모델의 함수형 API 구현하기

from keras.models import Model
from keras import layers
from keras import Input

text_vocabulary_size = 10000
question_vocabulary_size = 10000
answer_vocabulary_size = 500

# 텍스트 입력은 길이가 정해지지 않은 정수 시퀀스입니다.
# 입력 이름은 지정할 수 있습니다.
text_input = Input(shape=(None, ), dtype='int32', name='text')
embedded_text = layers.Embedding(text_vocabulary_size, 64)(text_input)
encoded_text = layers.LSTM(32)(embedded_text)

# 질문도 동일한 변환을 취합니다.
question_input = Input(shape=(None, ), dtype='int32', name='question')
embedded_question = layers.Embedding(question_vocabulary_size, 64)(question_input)
encoded_question = layers.LSTM(32)(embedded_question)

# 연결합니다.
concatenated = layers.concatenate([encoded_text, encoded_question])

# softmax 분류기를 추가합니다.
answer = layers.Dense(answer_vocabulary_size, activation='softmax')(concatenated)

# 모델 객체를 만들고 2개의 입력과 출력을 주입합니다.
model = Model([text_input, question_input], answer)
model.complie(optimizer='rmsprop',loss='categorical_crossentropy',metricss=['acc'])

이렇게 입력이 2개인 모델은 2가지 방법을 훈련할 수 있습니다.

  1. 넘파이 배열의 리스트에 주입
  2. 입력 이름과 넘파이 배열로 이루어진 딕셔너리를 모델의 입력으로 주입 (입력 이름 설정시 가능)
# 코드 7-2 다중 입력 모델에 데이터 주입하기
import numpy as np
from keras.utils import to_categorical

num_samples = 1000
max_length = 100

text = np.random.randint(1, text_vocabulary_size, size=(num_samples, max_length))
question = np.random.randint(1, question_vocabulary_size, size=(num_samples, max_length))

answers = np.random.randomint(0, answer_vocabulary_size, size=num_samples)
answers = to_categorical(answers) # 원핫 인코딩

# 1.리스트 입력 사용
model.fit([text, question], answers, epochs=10, batch_size=128)
# 2. 딕셔너리 입력을 사용하여 학습
model.fit({'text':text, 'question':question}, answers, epochs=10, batch_size=128)

7.1.3 다중 출력 모델

다중 출력 모델의 예시는 소셜 미디어에서 익명 사용자의 포스트를 받아 나이, 성별, 소득을 예측하는 것입니다. 모델은 다음과 같이 생각해볼 수 있습니다.

 
 
 
 
 
 
 
소설 미디어 포스트
1D 컨브넷
Dense
Dense
Dense
나이
소득
성별
3개의 출력을 가진 소셜 미디어 모델
# 코드 7-3 3개의 출력을 가진 함수형 API 구현하기

from keras import layers
from keras import Input
from keras.models import Model

vocabulary_size = 50000
num_income_groups = 10

post_input = Input(shape=(None,), dtype='int32', name='posts')
embedded_posts = layers.Embedding(vocabulary_size,256)(posts_input)
x = layers.Conv1D(128, 5, activation='relu')(embedded_posts)
x = layers.MaxPooling1D(5)(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.MaxPooling1D(5)(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.GlobalMaxPooling1D()(x)
x = layers.Dense(128, activation='relu')(x)

# 출력 층에 이름 붙이기
age_prediction  = layers.Dense(1, name='age')(x)
income_prediction = layers.Dense(num_income_groups, activation='softmax', name='income')(x)
gender_prediction = layers.Dense(1, activation='sigmoid', name='gender')(x)

model= = Model(post_input, [age_prediction, income_prediction, gender_prediction])

이런 모델을 예측하기 위해서는 네트워크 출력마다 다른 손실 함수를 지정해야 합니다. 손실 값을 합치는 가장 간단한 방법은 모두 더하는 것입니다. 케라스에서는 compile 메서드에서 리스트나 딕셔너리를 사용하여 출력마다 다른 손실을 지정할 수 있습니다. 계산된 손실 값은 전체 손실 하나로 더해지고 훈련 과정에서 최소화됩니다.

# 코드 7-4 다중 출력 모델의 컴파일 옵션: 다중 손실

# 1. 리스트로 손실함수 지정
model.compile(optimizer='rmsprop', loss=['mse','categorical_crossentropy', 'binary_crossentroypy'])

# 2. 딕셔너리로 손실함수 지정
model.compile(optimizer='rmsprop', loss={'age':'mse', 'income':'categorical_crossentropy', 'gender':'binary_crossentroypy'})

하지만 단순한 합으로 하게 될 경우, 개별 손실이 가장 큰 작업 기준으로 최적화가 진행되기에 특정 값의 결과가 매우 부정확 해질 수 있습니다. 이를 해결하기 위해 가중치를 설정할 수 있습니다.

# 코드 7-5 다중 출력 모델의 컴파일 옵션: 손실 가중치
# 1. 리스트로 손실함수 지정 + 가중치
model.compile(optimizer='rmsprop', loss=['mse','categorical_crossentropy', 'binary_crossentroypy'], loss_weights=[0.25, 1., 10.])

# 2. 딕셔너리로 손실함수 지정 + 가중치
model.compile(optimizer='rmsprop', loss={'age':'mse', 'income':'categorical_crossentropy', 'gender':'binary_crossentroypy'}, loss_weights={'age':0.25, 'income':1., 'gender':10.})

다중 입력과 마찬가지로 입력 전달은 두 가지 방법으로 할 수 있습니다.

# 코드 7-6 다중 출력 모델에 데이터 주입하기

# 1. 리스트
model.fit(posts, [age_targets, income_targets, gender_targets], epochs=10, batch_size=64)

# 2. 딕셔너리
model.fit(posts, {'age' : age_targets, 'incomde' : income_targets, 'gender' : gender_targets}, epochs=10, batch_size=64)

7.1.4 층으로 구성된 비순향 유향 그래프

함수형 API는 내부 토폴로지가 복잡한 네트워크도 만들 수 있습니다. DAG에서 말이죠. 순환은 불가능합니다. 만들 수 있는 루프는 순환 층 내부에 있는 것만 가능합니다.

그래프로 구현된 몇 개의 신경망 컴포넌트가 널리 사용됩니다. 가장 유명한 2개가 앞서 언급한 인셉션 모듈과 잔차 연결입니다.

인셉션 모듈

인셉션 은 합성곱 신경망에서 인기 있는 네트워크 구조입니다. network-in-network 구조에 영감을 받은 구글러들이 만들었습니다. 가장 기본적인 인셉션 모듈 형태는 3~4개의 가지를 가집니다. 1by1 합성곱에서 3by3 합성곱이 뒤따르고 마지막에 전체 출력 특성이 합쳐집니다. 이런 구성은 네트워크가 따로따로 공간 특성과 채널 방향의 특성을 학습하도록 돕습니다. 한꺼번에 합성하는 것보다 효과가 좋습니다.

위에서 flowchart로 나타낸 모델은 인셉션V3로 케라스에서는 keras.applications.inception_v3.InceptionV3에 준비되어 있으며, ImageNet에서 사전 훈련된 가중치를 포함하고 있습니다. 이와 비슷한 엑셉션 모델도 케라스에 포함되어 있습니다. 이 합성곱 구조는 채널 방향의 학습과 공간 방향의 학습을 극단적으로 분리한다는 아이디어에 착안하여 인셉션 모듈을 깊이별 분리 합성곱으로 바꿉니다. 이 합성곱은 깊이별 합성곱 다음에 점별 합성곱이 뒤따릅니다. 인셉션 모듈의 극한 형태로 공간 특성과 채널 방향 특성을 완전히 분리합니다. 엑셉션은 인셉션V3와 거의 동일한 개수의 모델 파라미터를 가지지만 실행 속도가 더 빠르고 대규모 데이터셋에서 정확도가 더 높습니다. (효율적 사용)

잔차 연결

잔차 연결residual connection) 은 엑셉션을 포함하여 2015년 이후 등장한 많은 네트워크 구조에 있는 그래프 형태의 네트워크 컴포넌트입니다. 대규모 딥러닝 모델에서 흔히 나타나는 두 가지 문제인 그래디언트 소실과 표현 병목(representational bottleneck)을 해결했습니다. 일반적으로 10개 층 이상을 가진 모델에 잔차 연결을 추가하면 도움이 됩니다.

잔차 연결은 하위 층의 출력을 상위 층의 입력으로 사용합니다. 순서대로 놓인 네트워크를 질러가는 연결이 만들어집니다. 하위 층의 출력이 상위 층의 출력에 연결되는 것이 아니라 더해집니다. 따라서 두 출력의 크기가 동일해야 합니다. 크기가 다르면 선형 변환을 사용하여 하위 층의 활성화 출력을 목표 크기로 변환합니다.

7.1.5 층 가중치 공유

함수형 API의 중요한 또 하나의 기능은 층 객체를 여러 번 재사용할 수 있다는 것입니다. 층 객체를 두 번 호출하면 새로운 객체를 만들지 않고 각 호출에 동일한 가중치를 재사용합니다. 이런 기능 때문에 공유 가지를 가진 모델을 만들 수 있습니다.

7.1.6 층과 모델

함수형 API에서는 모델을 층처럼 사용할 수 있습니다. Sequential 클래스와 Model 클래스에서 모두 동일합니다.

7.1.7 정리

생략

7.2 케라스 콜백과 텐서보드를 사용한 딥러닝 모델 검사와 모니터링

model.fit()이나 model.fit_generator을 사용하면 실행과 동시에 결과는 제어할 방법이 없습니다. 이 절에서는 위 함수의 호출을 스스로 판단하고 동적으로 결정하는 방법을 살펴봅니다.

7.2.1 콜백을 사용하여 모델의 훈련 과정 제어하기

1장부터 6장까지 예제들을 진행하면서 가장 의문인 점은 ‘왜 과대적합이 되고난 후에도 에포크를 훈련하는가’ 였습니다. 심지어 최적의 에포크 횟수로 처음부터 새로운 훈련을 시작했습니다. 이런 방법은 낭비가 많습니다.

더 좋은 방법은 검증 손실을 관측하여 더 이상 향상되지 않는 지점에서 훈련을 멈추는 것입니다. 이를 케라스의 콜백을 이용해서 구현할 수 있습니다. 콜백(callback) 은 모델의 fit() 메서드가 호출된 때 전달되는 객체입니다. 훈련하는 동안 모델은 여러 지점에서 콜백을 호출합니다. 콜백은 모델의 상태와 성능에 대한 모든 정보에 접근하고 훈련 중지, 모델 저장, 가중치 적재 또는 모델 상태 변경 등을 처리할 수 있습니다. 다음의 사례들에서 사용할 수 있습니다.

  • 모델 체크포인트 저장 : 훈련하는 동안 어떤 지점에서 모델의 현재 가중치를 저장합니다.
  • 조기 종료(early stopping) : 검증 손실이 더 이상 향상되지 않을 때 훈련을 중지합니다.
  • 훈련하는 동안 하이퍼파라미터 값을 동적으로 조정합니다. : 옵티마이저의 학습률 같은 경우입니다.
  • 훈련과 검증 지표를 로그에 기록하거나 모델이 학습한 표현이 업데이트될 때마다 시각화합니다. : 진행 표시줄이 하나의 콜백입니다.

이제 이 예들을 살펴보겠습니다.

ModelCheckpoint와 EarlyStopping 콜백

EarlyStopping 콜백을 사용하면 정해진 에포크 동안 모니터링 지표가 향상되지 않을 때 훈련을 중지할 수 있습니다. 예를 들면 과대적합 등에서 사용할 수 있습니다. 일반적으로 이 콜백은 훈련하는 동안 모델을 계속 저장해주는 ModelCheckpoint와 함께 사용합니다. (지금까지 가장 좋은 모델만 저장가능)

import keras

# fit() 메서드의 callbacks 매개변수를 사용하여 원하는 개수만큼 콜백을 모델로 전달
callback_list = [
  keras.callbacks.EarlyStopping(
    monitor='val_acc', # 모델의 검증 정확도 모니터링
    patience=1, # 1 에포크보다 더 길게 향상되지 않으면 중단
  ),
  keras.callbacks.ModelCheckpoint(
    filepath='my_model.h5', # 저장
    monitor='val_loss',
    save_best_only=True, # 가장 좋은 모델
  )
]

model.compile(optimizer='rmsprop', loss='binary_crossentroypy', metrics['acc'])
model.fit(x,y, epochs=10, batch_size=32, callbacks=callback_list, validation_data=(x_val, y_val))

ReduceLRONPlateau 콜백

이 콜백을 사용하면 검증 손실이 향상되지 않을 때 학습률을 작게 할 수 있습니다. 손실 곡선이 평탄할 때 학습률을 작게 하거나 크게 하면 훈련 도중 지역 최솟값에서 효과적으로 빠져나올 수 있습니다.

callback_list = [
  keras.callbacks.ReduceLRONPlateau(
    monitor='val_acc',
    factor=0.1, # 콜백이 호출되면 학습률을 10배로 줄임
    patience=10,
  )
]

자신만의 콜백 만들기

내장 콜백에서 제공하지 않는 경우 필요에 따라 콜백을 만들 수 있습니다. 콜백은 keras.callbacks.Callback 클래스를 상속받아 구현합니다. 그다음 훈련하는 동안 호출될 여러 지점을 나타내기 위해 약속된 다음 메서드를 구현합니다.

method 설명
on_epoch_begin 각 에포크가 시작할 때 호출합니다.
on_epoch_end 각 에포크가 끝날 때 호출합니다.
on_batch_begin 각 배치 처리가 시작되기 전에 호출합니다.
on_batch_end 각 배치 처리가 끝난 후에 호출합니다.
on_train_begin 훈련이 시작될 때 호출합니다.
on_train_end 훈련이 끝날 때 호출합니다.

이 메서드들은 모두 log 매개변수와 함께 호출됩니다. 이 매개변수에는 이전 배치, 에포크에 대한 훈련과 검증 측정값이 담겨 있는 딕셔너리가 전달됩니다. 콜백은 다음 속성을 참조할 수 있습니다.

  • self.model: 콜백을 호출하는 모델 객체
  • self.validation_data: fit() 메서드에 전달된 검증 데이터

다음은 매 에포크의 끝에서 검증 세트의 첫 번째 샘플로 모델에 있는 모든 층의 활성화 출력을 계산하여 디스크에 저장하는 자작 콜백의 예입니다.

from keras
import numpy as np

class ActivationLogger(keras.callbacks.Callback):
  def set_model(self, model):
    self.model = model
    layer_output = [layer.output for layer in model.layers ]
    self.activation_model = keras.models.Model(model.input, layer_outputs)

  def on_epoch_end(self, epoch, log=None):
    if self.validation_data is None:
      raise RuntimeError('Requires validation_data.')
    validation_sample = self.validation_data[0][0:1]
    activation = self.activations_model.predict(validation_sample)
    f = open('activaions_at_epoch_' + str(epoch) + '.npz', 'wb')
    np.savez(f, activations)
    f.close()

7.2.2 텐서보드 소개: 텐서플로의 시각화 프레임워크

본 장의 예제 코드는 embeddings_data 매개변수의 에러로 실행을 하지 못했습니다. 링크에 같은 오류가 있음에도 원하는 결과를 찾지 못하였고, 이는 후에 수정하도록 하겠습니다.

이 장에서는 실험 결과를 처리하는 효율적인 도구인 텐서보드 를 소개하고자 합니다. 텐서플로로 백엔드를 설정하면 케라스 모델에서 사용가능합니다. 텐서보드의 핵심 목적은 훈련 모델의 내부에서 일어나는 모든 것을 시각적으로 모니터링할 수 있도록 돕는 것입니다. 모델의 최종 손실 외에 더 많은 정보를 모니터링하면 모델 작동에 대한 명확한 그림을 그릴 수 있고, 개선을 빠르게 할 수 있습니다. 텐서보드는 여러 가지 멋진 기능을 제공합니다. (모든 브라우저에서 작동)

  • 훈련하는 동안 측정 지표를 시각적으로 모니터링
  • 모델 구조를 시각화
  • 활성화 출력과 그래디언트의 히스토그램
  • 3D로 임베딩 표현

예시로 IMDB 감성 분석 문제를 위해 1D 컨브넷을 훈련합니다. 이번엔 빈도가 높은 2,000개 단어만 사용합니다.

# 코드 7-7 텐서보드를 사용한 텍스트 분류 모델
import keras
from keras import layers
from keras.datasets import imdb
from keras.preprocessing import sequence

max_features = 2000
max_len = 500

(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
x_train = sequence.pad_sequences(x_train, maxlen=max_len)
x_test = sequence.pad_sequences(x_test, maxlen=max_len)

model = keras.models.Sequential()
model.add(layers.Embedding(max_features, 128, input_length=max_len, name='embed'))
model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.MaxPooling1D(5))
model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.GlobalMaxPooling1D())
model.add(layers.Dense(1))
model.summary()
model.compile(optimizer="rmsprop",loss="binary_crossentroypy",metrics=['acc'])

텐서보드 시작하기 전에 로그 파일이 저장될 디렉터리를 만들어야 합니다.

# 코드 7-8 텐서보드 로그 파일을 위한 디렉터리 생성하기
mkdir my_log_dir

텐서보드 콜백 객체와 함께 훈련을 진행합니다. 이 콜백은 지정된 디스크 위치에 로그 이벤트를 기록할 것입니다.

callbacks = [
  keras.callbacks.TensorBoard(
    log_dir='my_log_dir', # 저장될 path
    histogram_freq=1, # 1 에포크마다 활성화 출력의 히스토그램을 기록
    embeddings_freq=1, # 1 에포크마다 임베딩 데이터를 기록
  )
]
hitory = model.fit(x_train, y_train, epochs=20, batch_size=128, validation_split=0.2 callbacks=callbacks)

이제 명령행에서 콜백이 사용하는 로그 디렉터리를 지정하여 텐서보드 서버를 실행합니다. 텐서플로 설치시에 자동으로 설치됩니다.

tensorboard --logdir=my_log_dir

이 부분은 좀 더 공부해봐야곘습니다. :-(

7.2.3 정리

생략

7.3 모델의 성능을 최대로 끌어올리기

7.3.1 고급 구조 패턴

이전 절에서 본 잔차 연결 외에 알아야 할 디자인 패턴이 2개가 더 있습니다. 정규화와 깊이별 분리 합성곱입니다. 고성능 심층 컨브넷을 만들 때 유용합니다.

배치 정규화

정규화(normalization) 는 머신 러닝 모델에 주입되는 샘플들을 균일하게 만드는 광범위한 방법입니다. 이미 이전 예제에서 많이 사용한 방법이 있습니다. 평균을 빼고, 표준 편차로 나누어 분산을 1로 만듭니다.

normalized_data = (data - np.mean(data, axis=...)) / np.std((data, axis=...))

이전 예제에는 모델에 데이터를 주입하기 전에 정규화했습니다. 하지만 데이터 정규화는 네트워크에서 일어나는 모든 변환 후에도 고려되어야 합니다. Dense나 Conv2D 층에 들어가는 데이터의 평균이 0이고 분산이 1이라도 출력되는 데이터가 동일한 분포를 가질 것이라고 기대하기는 어렵습니다.

배치 정규화는 2015년에 아이오페와 세게디가 제안한 층의 한 종류입니다. 케라스는 BatchNormalization 클래스로 제공합니다. 훈련한는 동안 평균과 분산이 바뀌더라도 이에 적응하여 데이터를 정규화합니다. 훈련 과정에서 사용된 배치 데이터의 평균과 분산에 대한 지수 이동 평균을 내부에 유지합니다. (momentum 기본값 0.99)

배치 정규화의 주요 효과는 잔차 연결과 매우 흡사하게 그래디언트의 전파를 도와주는 것입니다. (입력과 출력의 분포가 유지) 그렇기에 더 깊은 네트워크를 구성할 수 있습니다. ResNet50, 인셉션 V3, 엑셉션 등이 있습니다. 다음은 사용하는 예시입니다.

# Conv2D 층
conv_model.add(layers.Conv2D(32, 3 activation='relu'))
conv_model.add(layers.BatchNormalization())
# Dense 층
dense_model.add(layers.Dense(32, activation='relu'))
dense_model.add(layers.BatchNormalization())

BatchNormalization 클래스에는 정규화할 특성 축을 지정하는 axis 매개변수가 있습니다. 이 매개변수의 기본값은 입력 텐서의 마지막 축을 나타내는 -1 입니다. (data_format"chanels_last"인 경우, "chanels_first"인 경우는 매개변수를 1로 설정)

2017년에는 배치 재정규화 라는 방법이 소개되었습니다. 정규화에 대해서 보다 recent한 논문을 주제로 포스팅해도 재밌을 것 같습니다.

깊이별 분리 합성곱

Conv2D를 대체하면서 더 가볍고 더 빨라 모델의 성능을 높일 수 있는 층을 소개합니다. 깊이별 분리 합성곱(depthwise separable convolution) 층은 입력 채널별로 따로따로 공간 방향의 합성곱을 수행합니다. (SeparableConv2D으로 사용합니다.) 그리고 점별 합성곱을 통해 출력 채널을 합칩니다. 공간 특성과 채널 방향 특성을 독립적으로 인식하여 학습하고, 모델 파라미터와 연산수를 줄여줍니다. 더 빠르고 효율적인 학습을 할 수 있습니다.

제한된 데이터로 작은 모델을 처음부터 훈련시킬 때 특히 더 중요합니다. 작은 데이터셋에서 이미지 분류 문제를 위한 가벼운 깊이별 분리 컨브넷을 만드는 예입니다.

 
깊이별합성곱
 
 
 
 
 
 
 
 
 
채널 분리
3 * 3 합성곱
3 * 3 합성곱
3 * 3 합성곱
합침
 
1 * 1 합성곱
 
깊이별 분리 합성곱: 깊이별 합성곱 다음에 합성곱이 뒤따른다.
from keras.models import Sequential, Model
from keras import layers

height = 64
width = 64
channels = 3
num_classes = 10

model = Sequential()
model.add(layers.SeparableConv2D(32, 3, activation='relu', input_shape=(height. width, channels,)))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layer.MaxPooling2D(2))

model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.MaxPooling2D(2))

model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.GlobalAveragePooling2D())

model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(num_classes, activation='softmax'))

model.compile(optimizer='rmsprop', loss='categorical_crossentropy')

대규모 모델은 엑셉션이 그 예시이다.

7.3.2 하이퍼파라미터 최적화

딥러닝 모델은 무작위 선택의 연속입니다. 층의 수, 유닛과 필터 수, 활성화 함수의 종류 등 설계자의 이유있는 랜덤한 선택의 연속입니다. 이런 구조에 관련된 파라미터를 역전파로 훈련되는 모델 파라미터와 구분하여 하이퍼파라미터(hyperparameter) 라고 합니다.

하이퍼파라미터 튜닝에 공식적인 규칙은 없습니다. 직관은 있을 수 있으나 정해를 찾을 수는 없습니다. 그렇다고 하이퍼파라미터 튜닝을 모두 사람이 하고 있을 수는 없기에 이것도 기계의 힘을 빌립니다. 가능한 결정 공간을 자동적, 조직적, 규칙적 방법으로 탐색해야합니다. 전형적인 최적화 과정은 다음과 같습니다.

  1. 일련의 하이퍼파라미터를 자동으로 선택합니다.
  2. 선택된 하이퍼파라미터로 모델을 만듭니다.
  3. 훈련 데이터에 학습하고 검증 데이터에서 최종 성능을 측정합니다.
  4. 다음으로 시도할 하이퍼파라미터를 자동으로 선택합니다.
  5. 이 과정을 반복합니다.
  6. 마지막으로 테스트 데이터에서 성능을 측정합니다.

주어진 하이퍼파라미터에서 얻은 검증 성능을 사용하여 다음 번에 시도할 하이퍼파라미터를 선택하는 알고리즘이 핵심입니다. 베이지안 최적화, 유전 알고리즘, 간단한 랜덤 탐색 등을 사용할 수 있습니다. 하지만 선택하는 것은 실로 어려운 일입니다. 비용이 너무 많이 들기 때문입니다. 그렇기에 가장 간단하게 하는 방법은 랜덤 탐색입니다.

랜덤 탐색보다 나은 방법으로는 파이썬 라이브러리인 Hyperopt, Hyperas 를 사용하는 것입니다. 아직은 조금 부족할 수 있는 도구지만 앞으로 발전될 가능성이 큽니다.

7.3.3 모델 앙상블

모델 앙상블(model ensemble) 은 여러 개 다른 모델의 예측을 합쳐 더 좋은 예측을 만드는 기법입니다. 캐글 같은 머신 러닝 경연 대회에서는 우승자들이 대규모 모델 앙상블을 사용합니다. 단일 모델보다 성능이 좋기 때문이죠.

가장 기본적인 앙상블은 추론에 나온 예측을 평균내는 방법입니다. 이제 더 나아가서는 가중치를 주고 평균을 내는 방법도 있습니다. 좋은 앙상블 가중치는 랜덤 서치나 넬더-미드 방법 같은 간단한 최적화 방법이 있습니다. 이외에도 지수 값을 평균할 수 있겠습니다.

앙상블이 잘 작동하게 만드는 핵심은 분류기의 다양성입니다. 모델이 서로 다른 방향으로 편향되어 있다면 상쇄를 통해 더 정확한 모델이 되는 것입니다.

모든 문제에 적용하지 못하지만 실전에서 잘 작동하는 한 가지 방법은 트리 기반 모델(랜덤 포레스트나 그래디언트 부스팅 트리)이나 심층 신경망을 앙상블하는 것입니다. 최근에 실전에서 매우 성공적으로 사용되는 기본 앙상블 스타일은 딥러닝과 얕은 모델을 섞은 넓고 깊은 모델입니다. 이런 모델은 심층 신경망과 많은 선형 모델을 함께 훈련합니다. 다양한 종류의 모델들을 함께 훈련하는 것은 모델 앙상블을 만드는 또 다른 방법입니다.

7.3.4 정리

생략

7.4 요약

생략

 

 

출처 : https://subinium.github.io/Keras-7/

 

"케라스 창시자에게 배우는 딥러닝" 에 있는 책 내용의 그림이 많이 담겨있어서 담아둠,

그런데.. 그림이 좀 깨지니.. 출처로 가서 살펴보는게 어쩌면 더 나을 수도 있음,

간단히 코드 볼때는 문제 없는 듯..

 

:

https://yougome.tistory.com/558

 

은근히 시간이 걸린 내용이라 정리해 두려고 한다.

LSTM을 살펴보면 대부분 Sequence layer를 활용해서 설명하고 있어서,

찾는시간에도, 오류를 잡고, 내용을 이해하는데에도 시간이 좀 들었다.

주요 오류는 Input(...) 다음에 LSTM(...) 을 읽는 위치에서 계속 막혔다.

inputs = Input(shape=( ..., ))

outputs = LSTM(1, ... )(inputs) 

오류의 포인트는 shape 값 때문이었다.

찾아봐도 명쾌한 답이 잘 안나오니 답답할 뿐이었다.

 

대부분 알고 있겠지만, LSTM의 shape의 의미는 size, seq, feature다. 

이 내용을 토대로 계속 입력하지만 계속 오류가 발생한다.

여기서 오류를 범할 수 있는 부분이 바로, size 부분이다. input shape를 seq, feautre로 두고 처리하면 해결된다.

 

size는 결국에 model을 compile한 후, fit을 할 때 사용되는 loop의 크기로 보면 좋을 것 같다.

 

이렇게 간단히 해결될 것을.. 왜이리 오래 걸렸을까?

기본 tutorial 코드를 보면, LSTM( ) 함수에는 몇가지 추가된 파라미터들이 있다.

stateful, return_sequence 등을 추가되어 있다.

입문자나 초보자 입장에서는 이게 없으면 안될 것 같은,,

느낌적인 느낌때문에 지운 후 쓰기도 그대로 쓰기도

어떻게 할지 몰라서 망설여지게 된다.

 

오류를 잘 살펴보면, stateful을 쓰려면 batch_input_shape 쓰라고 하고,

batch_input_shape를 빼면, input_shape가 맞지 않다고 하니,

어느 장단에 맞춰야할지 무척 난감해진다.

 

에러를 해석해보면,

stateful은 batch의 총 크기를 알았을 때 안정적으로 사용할 수 있다는 것이고,

stateful을 쓰지 않는다면, 굳이 없어도 동작한다. ( 확인했음 )

 

즉, Model의 Input(...) 이용해서 LSTM을 처리하고자 한다면 아래 두개 코드중에 하나를 선택해서 쓰면되겠다.

간단한 코드가 좋으니.. 아래와 같이 정리한다.

첫줄의 Input(..)함수의 batch_shape shape부분을 살펴보면 좋겠다.

 

# stateful 파라미터를 쓰고 싶다! 그러면 batch_shape로 하면된다.

#site : https://yougome.tistory.com/558

input_tensor = Input(batch_shape=(1, 10, 2, ))
hidden_tensor = LSTM(1, batch_input_shape=(1, 10, 2), stateful=True, return_sequences=True )(input_tensor)
hidden_tensor = LSTM(1, stateful=True)(hidden_tensor)
output_tensor = Dense(2, )(hidden_tensor)
m_model = Model(inputs=input_tensor, outputs = output_tensor)
m_model.summary()

 

# stateful 파라미터에 관심없다! 동작만 하면된다!! 그러면 shape로 하면된다.

#site : https://yougome.tistory.com/558

input_tensor = Input(shape=(10, 2, ))
hidden_tensor = LSTM(1, input_shape=(10, 2), return_sequences=True )(input_tensor)
hidden_tensor = LSTM(1)(hidden_tensor)
output_tensor = Dense(2)(hidden_tensor)
m_model = Model(inputs=input_tensor, outputs = output_tensor)
m_model.summary()

 

위에 있는 코드가 좀 더 상세히 쓴 것이고,

케라스의 특성상, 이전에 입력받은 Layer는 다음 Layer에서 알아서 척척(?) 잘 받아주니,

아래 처럼 써도 전혀 문제가 없다.

 

# stateful 파라미터를 쓰고 싶다! 그러면 batch_shape로 하면된다.

#site : https://yougome.tistory.com/558

input_tensor = Input(batch_shape=(1, 10, 2, ))
hidden_tensor = LSTM(1, stateful=True, return_sequences=True )(input_tensor)
hidden_tensor = LSTM(1, stateful=True)(hidden_tensor)
output_tensor = Dense(2, )(hidden_tensor)
m_model = Model(inputs=input_tensor, outputs = output_tensor)
m_model.summary()

summary 결과 값 보고 싶다면, 아래 '더보기' 클릭

더보기

Model: "model_x"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_24 (InputLayer)        (1, 10, 2)                0         
_________________________________________________________________
lstm_30 (LSTM)               (1, 10, 1)                16        
_________________________________________________________________
lstm_31 (LSTM)               (1, 1)                    12        
_________________________________________________________________
dense_11 (Dense)             (1, 2)                    4         
=================================================================
Total params: 32
Trainable params: 32
Non-trainable params: 0
_________________________________________________________________

 

# stateful 파라미터에 관심없다! 동작만 하면된다!! 그러면 shape로 하면된다.

#site : https://yougome.tistory.com/558

input_tensor = Input(shape=(10, 2, ))
hidden_tensor = LSTM(1, return_sequences=True )(input_tensor)
hidden_tensor = LSTM(1)(hidden_tensor)
output_tensor = Dense(2)(hidden_tensor)
m_model = Model(inputs=input_tensor, outputs = output_tensor)
m_model.summary()

summary 결과 값 보고 싶다면, 아래 '더보기' 클릭

더보기

Model: "model_x" 
_________________________________________________________________ 
Layer (type)                 Output Shape              Param #    
================================================================= 
input_23 (InputLayer)        (None, 10, 2)             0          
_________________________________________________________________ 
lstm_28 (LSTM)               (None, 10, 1)             16         
_________________________________________________________________ 
lstm_29 (LSTM)               (None, 1)                 12         
_________________________________________________________________ 
dense_10 (Dense)             (None, 2)                 4          
================================================================= 
Total params: 32 
Trainable params: 32 
Non-trainable params: 0

 

 

아차, 다 쓰고 나서 읽어보니, 헷갈릴 수 있는 부분이 있어서 덧붙인다.

 

input의 shape 크기가 ( 10, 2 ) 인지,

output의 shape 크기가 2 인지,

>> input shape는 2개의 특징을 가진 10개의 연속된 데이터 N개를 사용하고 있고,

>> ouput shape는 2개의 특징으로 분류되는 N의 결과값을 사용하고 있다

 

( 10, 2 ) 이 부분은 큰 의미는 없고,

model 관련 dummy data로 테스트하던 중에 사용하던 코드여서,

그대로 붙여넣게 되었다.

 

ref : https://keras.io/getting-started/functional-api-guide/

:

LSTM을 사용해보려고 하는데 입력과 출력에 대해서 자세히 나온 부분이 없어서 정리해 보았습니다.
기본적인 내용은 아래 참조 링크를 사용하였습니다.

참조 링크 : https://medium.com/@shivajbd/understanding-input-and-output-shape-in-lstm-keras-c501ee95c65e

 

참조 링크 : https://towardsdatascience.com/predicting-stock-price-with-lstm-13af86a74944

위 링크 저자도 처음에 혼란스러웠다고 되어있네요.

LSTM을 하기 위해서는 3차원적 데이터가 필요합니다. (대부분의 예제의 경우 batch(일괄처리)값 설정없이 input_shape을 사용합니다. 만약 batch를 설정하려면 batch_input_shape 값에 batch값을 추가하여 차원을 추가한 입력을 사용해야합니다.)

[data_size, time_steps, features] 3차원 array로 구성됩니다.

Keras input_shape 예제

model = keras.models.Sequential() model.add(keras.layers.LSTM(unit=3, input_shape=(3, 5)))


위 예에서 (2,10)은 time_steps=3, features=5 가 됩니다. data_size는 따로 넘기지 않습니다. data_size 정보는 없어도 넘어오는 크기로 부터 전체 data size를 알 수 있기 때문입니다.

이것을 그림으로 그려보면 다음과 같습니다.


time_steps는 Network에 사용할 시간 단위입니다. 이 값은 LSTM에서 과거의 몇개 데이터를 볼것인가 가지고 결정합니다. 위 그림에서 녹색 box부분을 보면 3개 데이터를 이용해서 다음 한개를 추론 하기 때문에 time_steps:3 이 됩니다.
data_size는 데이터의 크기 입니다. 위 그림에서는 N으로 표시 하였습니다. 커다란 박스의 개수가 3개 있고, 추가로 2개 더 그릴수 있으므로 데이터는 5개가 될 것입니다.
Features 는 일반적인 경우 X의 차원을 의미합니다. LSTM에서는 input이 time_steps에 의해서 여러개의 입력 나타내지는데 그것의 속성의 수가 됩니다. 여기에서는 Open, High, Low, Close, Volume 이렇게 5개가 들어갑니다.

Batch에 대하여

Batch는 일괄 처리되는 작업의 양이다. 위에서 설명된 data_size를 한번에 처리하는 갯수를 의미하며, batch크기에 의해 weight 변화가 일어나며 batch크기 단위로 data loading 함수도 구현이 가능하다. 주의할점은 data_size/batch_size일때 나머지가 없어야 한다.

batch 되는 양이 있다면 아래와 같이 설정할 수도 있습니다.

Keras batch_input_shape 예제 

model = keras.models.Sequential() model.add(keras.layers.LSTM(unit=4, batch_input_shape=(3, 4, 6)))

batch_size, time_steps, features 각각은 3,4,6이 됩니다.

 

실제 데이터의 크기는 [6,4,6]으로 준비가 된 모습입니다. batch_size로 차원을 구성하는것이 아닙니다. batch_size = 3으로 6/3이 되므로 나머지가 없기 때문에 문제가 없습니다. 나머지가 생기게 되면 batch 작업시 문제가 생깁니다.


unit=4 은 해당 layer의 출력 크기가 된다.

출처 : http://swlock.blogspot.com/2019/04/keras-lstm-understanding-input-and.html

: