본문 바로가기
ML (Hands-On Machine Learning)

Chapter 15. Processing Sequences Using RNNs and CNNs

by xangmin 2020. 5. 26.
반응형

 타자가 공을 치면 외야수는 즉시 공을 따라간다. 공이 어디에 떨어질지 모르지만 야수는 공을 추적하고 마침내 공을 잡습니다. 이처럼 우리는 미래를 예측할 수 있는 RNN에 대해 논의하고자 한다.

 

RNN example

-주가를 분석하여 구매/판매 시기 판단

-자율 주행 시스템에서 차량 궤도를 예측하여 사고 예방

-문서 또는 오디오 샘플을 입력으로 자동 번역 및 텍스트 음성 변환 같은 자연어 처리

 *고정된 크기의 입력뿐만 아니라 임의의 길이의 시퀀스에서 동작할 수 있다.

 

RNN은 시퀀스 데이터를 처리할 수 있는 유일한 유형의 신경망은 아니다. 오디오 샘픙 또는 텍스트와 같은 매우 긴 시퀀스의 경우 컨볼루션 신경망도 실제로 잘 동작할 수 있다.

 

Recurrent Neurons and Layers

-기존에는 입력 레이어에서 출력 레이어로 한 방향으로 흐르는 피드 포워드 신경망에 중점을 두었다.

-RNN은 연결이 뒤로 향한다는 점을 제외하면 피드 포워드 신경망과 매우 유사하다. (backward)

-t단계에서 입력 x(t)와 이전 시간 단계 y(t-1)의 출력을 받는다. (첫 단계에서는 이전 출력은 0으로 설정)

- unrolling the network through time 이라고 한다.

< Figure 15-1. A recurrent neuron (left) unrolled through time (right) >

 각 순환 뉴런은 두 개의 가중치 Wx와 Wy를 가지는데, Wx는 Xt를 위한 것이고 Wy는 이전 타임 스텝의 출력Yt-1을 위한 것이다. 이것을 순환 층(layer) 전체로 생각하면 가중치 벡터 Wx와 Wy를 행렬 Wx와 Wy로 나타낼 수 있으며 다음의 식과 같이 표현할 수 있다.

< Figure 15-2. A layer of recurrent neurons (left) unrolled through time (right) >

 

< Equation 15-1. Output of a recurrent layer for a single instance >

 

 그리고 타임 스텝 t에서의 미니배치(mini-batch)의 입력을 행렬 ​Xt로 나타내어 아래와 같이 순환 층의 출력을 한번에 계산할 수 있다.

< Equation 15-2. Outputs of a layer of recurrent neurons for all instances in a minibatch >

 

Memeory Cells

 타임 스텝 t에서 순환 뉴런의 출력은 이전 타임 스텝의 모든 입력에 대한 함수이기 때문에 이것을 메모리라고 볼 수 있다. 이렇게 타임 스텝에 걸쳐 어떠한 상태를 보존하는 신경망의 구성 요소를 메모리 셀(memory cell) 또는 셀(cell)이라고 한다. 일반적으로 타임 스텝  에서 셀의 상태  ht = (h = hidden)는 아래의 식과 같이 타임 스텝에서의 입력과 이전 타임 스텝의 상태에 대한 함수이다.

 위에서 살펴본 RNN은 출력 yt가 다시 입력으로 들어갔지만, 아래의 그림과 같이 일반적으로 많이 사용되는 RNN은 출력 yt와 히든 상태(state) ht가 구분되며, 입력으로는 ht가 들어간다. RNN에서의 활성화 함수로는 tanh가 주로 사용된다.

 

< Figure 15-3. A cell’s hidden state and its output may be different >

 

Input and Output Sequences

 RNN은 일련의 입력을 동시에 가져 와서 일련의 출력을 생성 할 수 있다.

 

< Figure 15-4. Seq-to-seq (top left), seq-to-vector (top right), vector-to-seq (bottom left), and Encoder–Decoder (bottom right) networks >

 RNN은 일련의 입력을 동시에 가져 와서 일련의 출력을 생성 할 수 있습니다 (그림 15-4의 왼쪽 위 네트워크 참조). 이 유형의 시퀀스-시퀀스 네트워크는 주식 가격과 같은 시계열 예측에 유용합니다. 지난 N 일 동안 가격을 공급하고 하루 동안 미래로 이동 한 가격을 출력해야합니다 (: N 1 일 전부터 내일까지).

 

또는 네트워크에 일련의 입력을 공급하고 마지막 입력을 제외한 모든 출력을 무시할 수 있습니다 (그림 15-4의 오른쪽 위 네트워크 참조). 다시 말해서 이것은 시퀀스-벡터 네트워크입니다. 예를 들어, 영화 리뷰에 해당하는 일련의 단어를 네트워크에 공급할 수 있으며 네트워크는 감정 점수를 출력합니다 (: 1 [증오]에서 +1 [사랑]).

 

반대로, 각 시간 단계마다 네트워크에 동일한 입력 벡터를 반복해서 공급하고 시퀀스를 출력 할 수 있습니다 (그림 15-4의 왼쪽 아래 네트워크 참조). 이것은 벡터-시퀀스 네트워크입니다. 예를 들어, 입력은 이미지 (또는 CNN의 출력) 일 수 있으며 출력은 해당 이미지의 캡션 일 수 있습니다.

 

마지막으로, 인코더라는 시퀀스 대 벡터 네트워크와 디코더라는 벡터 대 시퀀스 네트워크가있을 수 있습니다 (그림 15-4의 오른쪽 아래 네트워크 참조). 예를 들어, 한 언어에서 다른 언어로 문장을 번역하는 데 사용할 수 있습니다. 네트워크에 한 언어로 문장을 공급하면 인코더가이 문장을 단일 벡터 표현으로 변환 한 다음 디코더가이 벡터를 다른 언어의 문장으로 디코딩합니다. EncoderDecoder라고하는이 2 단계 모델은 단일 시퀀스-시퀀스 RNN (왼쪽 상단에 표시된 것과 같은)으로 즉석에서 번역하려고 시도하는 것보다 훨씬 더 효과적입니다. 문장의 마지막 단어가 영향을 줄 수 있습니다 번역의 첫 단어이므로 번역하기 전에 문장 전체를 볼 때까지 기다려야합니다. 16 장에서 Encoder-Decoder를 구현하는 방법을 살펴 보겠습니다 (그림 15-4에서 제안한 것보다 약간 더 복잡합니다).

 

위의 그림의 오른쪽에서 세 번째 Sequence-to-Sequence 는 시퀀스를 입력받아 시퀀스를 출력하는 네트워크이며, 주식가격과 같은 시계열 데이터를 예측하는 데 사용할 수 있다. (1)

 

Sequence-to-Vector는 Vector-to-Sequence와는 반대로 입력으로 시퀀스를 받아 하나의 벡터를 출력하는 네트워크로, Sentiment Classification에 사용할 수 있다. (2) 영화 리뷰에 해당하는 일련의 단어를 네트워크에 공급할 수 있으며 네트워크는 감정 점수를 출력합니다 ( : 1 [증오]에서 +1 [사랑]).

 

위의 그림에서 Vector-to-Sequence는 첫 번째 타임 스텝에서 하나의 입력만(다른 모든 타임 스텝에서는 0)을 입력받아 시퀀스를 출력하는 네트워크이며, 이러한 모델은 Image Captioning에 사용할 수 있다. (3)

 

마지막으로 Delayed Sequence-to-Sequence 는 인코더(encoder)에는 seq-to-vec 네트워크를 디코더(decoder)에는 vec-to-seq 네트워크를 연결한 것으로, 기계 번역에 사용된다. (4)

 

Training RNNs

 RNN은 기존 신경망의 역전파(backprop)와는 달리 타임 스텝별로 네트워크를 펼친 다음, 역전파 알고리즘을 사용하는데 이를 BPTT(BackPropagation Through Time)라고 한다.

 

< Figure 15-5. Backpropagation through time >

일반적인 역전파와 마찬가지로 롤링되지 않은 네트워크 (파선 화살표로 표시)를 통과하는 첫 번째 전달이 있습니다. 그런 다음 비용 함수 C (Y (0), Y (1),Y (T))를 사용하여 출력 시퀀스를 평가합니다 (여기서 T는 최대 시간 단계 임). 이 비용 함수는 그림 15-5와 같이 일부 출력을 무시할 수 있습니다 (예를 들어, 시퀀스-벡터 RNN에서 마지막 출력을 제외한 모든 출력은 무시 됨). 그런 다음 해당 비용 함수의 그라디언트는 롤링되지 않은 네트워크를 통해 뒤로 전파됩니다 (단색 화살표로 표시). 마지막으로 모델 파라미터는 BPTT 동안 계산 된 그라디언트를 사용하여 업데이트됩니다. 그래디언트는 최종 출력을 통해서가 아니라 비용 함수가 사용하는 모든 출력을 통해 뒤로 흐릅니다 (: 그림 15-5에서 비용 함수는 네트워크의 마지막 세 출력 Y (2)를 사용하여 계산 됨). Y (3) Y (4), 그래디언트는이 3 개의 출력을 통과하지만 Y (0) Y (1)을 통과하지는 않습니다. 더욱이, 각각의 시간 단계에서 동일한 파라미터 W b가 사용되기 때문에, 역 전파가 올바른 일을하고 모든 시간 단계에 걸쳐 합산 할 것이다.

 

BPTT 또한 일반적인 역전파와 같이 먼저 순전파(forward prop)로 각 타임 스텝별 시퀀스를 출력한다. 그런다음 이 출력 시퀀스와 손실(비용)함수를 사용하여 각 타임 스텝별 Loss를 구한다. 그리고 손실 함수의 그래디언트는 위의 그림과 같이 펼쳐진 네트워크를 따라 역방향으로 전파된다. BPTT는 그래디언트가 마지막 타임 스텝인 출력뿐만 아니라 손실함수를 사용한 모든 출력에서 역방향으로 전파된다.

RNN은 각 타임 스텝마다 같은 매개변수 W와 b가 사용되기 때문에 역전파가 진행되면서 모든 타임 스텝에 걸쳐 매개변수 값이 합산된다. 이렇게 업데이트된 가중치는 순전파 동안에는 모든 타임 스텝에 동일한 가중치가 적용된다.

 

state를 업데이트하다보니까 앞에서 상태를 변화 시키면 이후에 있는 이 상태까지 변화를 시킨다는 겁니다 

Forecasting a Time Series

여러 측정 항목을 사용하여 분기별로 측정 한 웹 사이트, 도시의 일일 온도 또는 회사의 재무 상태에서 시간당 활성 사용자 수를 연구한다고 가정합니다. 이러한 모든 경우에, 데이터는 시간 단계 당 하나 이상의 값 시퀀스 일 것이다. 이것을 시계열이라고합니다. 처음 두 예제에는 시간 단계 당 단일 값이 있으므로이 값은 일 변량 시계열이며 재무 예제에서는 시간 단계 당 여러 값 (: 회사의 수입, 부채 등)이 있으므로 다음과 같습니다. 다변량 시계열. 일반적인 작업은 예측이라고하는 미래 가치를 예측하는 것입니다. 또 다른 일반적인 작업은 빈칸을 채우는 것입니다. 과거의 결 측값을 예측 (또는포스트”)하는 것입니다. 이것을 대치라고합니다. 예를 들어, 그림 15-63 개의 일 변량 시계열을 보여줍니다. 각 시계열의 길이는 50 시간 간격이며, 여기서 목표는 다음 시간 단계에서 값을 예측하는 것입니다 (X로 표시).

 

간단히하기 위해 generate_time_series () 함수로 생성 된 시계열을 사용합니다.

 

def generate_time_series(batch_size, n_steps):

freq1, freq2, offsets1, offsets2 = np.random.rand(4, batch_size, 1)

time = np.linspace(0, 1, n_steps)

series = 0.5 * np.sin((time - offsets1) * (freq1 * 10 + 10)) # wave 1

series += 0.2 * np.sin((time - offsets2) * (freq2 * 20 + 20)) # + wave 2

series += 0.1 * (np.random.rand(batch_size, n_steps) - 0.5) # + noise

return series[..., np.newaxis].astype(np.float32)

>>고정 진폭의 임의 사인파와 임의 주파수 및 위상의 2 개의 사인파와 약간의 노이즈의 합

 

n_steps = 50

series = generate_time_series(10000, n_steps + 1)

X_train, y_train = series[:7000, :n_steps], series[:7000, -1]

X_valid, y_valid = series[7000:9000, :n_steps], series[7000:9000, -1]

X_test, y_test = series[9000:, :n_steps], series[9000:, -1]

 

X_train에는 7,000 개의 시계열 (: 모양이 [7000, 50, 1])이 있고 X_valid에는 2,000 (7,000 번째 시계열에서 8,999 번째까지)가 있고 X_test에는 1,000 (9,000 번째에서 9,999 번째까지)이 있습니다. . 각 계열에 대해 단일 값을 예측하고자하므로 대상은 열 벡터입니다 (: y_train의 모양은 [7000, 1]입니다).

Baseline Metrics

 RNN을 사용하기 전에 몇 가지 기준 메트릭을 갖는 것이 좋습니다. 그렇지 않으면 기본 모델보다 성능이 저하 될 때 모델이 제대로 작동한다고 생각할 수 있습니다. 예를 들어, 가장 간단한 방법은 각 계열의 마지막 값을 예측하는 것입니다. 이를 순진한 예측이라고 하며 때로는 성과를 달성하기가 매우 어렵습니다. 이 경우 약 0.020의 평균 제곱 오류가 발생합니다.

mse = 0.02

>>> y_pred = X_valid[:, -1]

>>> np.mean(keras.losses.mean_squared_error(y_valid, y_pred)) 0.020211367

 

또 다른 간단한 방법은 Fully connected network 사용하는 것입니다. 각 입력에 대해 평평한 기능 목록이 필요하므로 Flatten 레이어를 추가해야합니다. 각 예측이 시계열 값의 선형 조합이되도록 간단한 선형 회귀 모델을 사용하겠습니다.

 

model = keras.models.Sequential([

keras.layers.Flatten(input_shape=[50, 1]),

keras.layers.Dense(1)

])

 

MSE 손실과 기본 Adam 옵티 마이저를 사용하여이 모델을 컴파일 한 후 20 에포크에 대한 훈련 세트에 맞추고 유효성 검증 세트에서 평가하면 약 0.004MSE를 얻습니다. 순진한 접근 방식보다 훨씬 낫습니다!

 

Implementing a Simple RNN 

model = keras.models.Sequential([

keras.layers.SimpleRNN(1, input_shape=[None, 1]) 

])

(이전 모델과 달리) 입력 시퀀스의 길이를 지정할 필요가 없습니다.

하이퍼볼릭탄젠트 함수

초기 상태 h (init)0으로 설정되고 첫 번째 단계 값 x (0)와 함께 단일 재귀 뉴런으로 전달됩니다

최종 출력만 반환합니다. 시간 단계 당 하나의 출력을 반환하도록하려면 return_sequences = True를 설정해야합니다.

 

 

Trend and Seasonality

매월 판매되는 선 스크린 로션의 양을 예측하려는 경우 계절별로 강한 계절성을 느낄 수 있습니다. 매년 여름에 잘 판매되므로 매년 비슷한 패턴이 반복됩니다. 예를 들어 각 시간 단계의 값과 1 년 전의 값의 차이를 계산하여 시계열에서이 계절성을 제거해야합니다 (이 기법을 차이라고합니다). 모델이 학습되고 예측이 끝나면 계절 패턴을 다시 추가하여 최종 예측을 가져와야합니다. RNN을 사용할 때 일반적으로이 모든 것을 수행 할 필요는 없지만 모델이 추세 나 계절성을 알 필요가 없기 때문에 경우에 따라 성능이 향상 될 수 있습니다.

 

 Deep RNNs 

 심층 RNN(deep RNN)은 아래의 그림처럼 RNN Cell을 여러 층으로 쌓은 것을 말한다. 일반적으로 딥러닝에서는 이러한 Deep RNN 모델이 많이 사용된다.

tf.keras를 사용하여 심층 RNN을 구현하는 것은 매우 간단합니다. 반복 레이어 만 스택하면됩니다. 이 예에서는 3 개의 SimpleRNN 계층을 사용합니다.

 

model = keras.models.Sequential([

keras.layers.SimpleRNN(20, return_sequences=True, input_shape=[None, 1]),

keras.layers.SimpleRNN(20, return_sequences=True),

keras.layers.SimpleRNN(1)

])

 

MSE0.003 도달

 

또한 SimpleRNN 레이어는 기본적으로 tanh 활성화 기능을 사용하므로 예측 된 값은 1에서 1 사이 여야합니다. 그러나 다른 활성화 기능을 사용하려면 어떻게해야합니까? 이 두 가지 이유로 출력 레이어를 고밀도 레이어로 바꾸는 것이 바람직 할 수 있습니다. 약간 더 빠르게 실행되고 정확도는 거의 같으며 원하는 출력 활성화 기능을 선택할 수 있습니다. 이 변경을 수행하는 경우 두 번째 (현재 마지막) 반복 레이어에서 return_sequences = True를 제거해야합니다.

 

Forecasting Several Time Steps Ahead

 지금까지는 다음 시간 단계에서 값만 예측했지만 목표를 적절하게 변경하여 몇 단계 앞뒤로 값을 쉽게 예측할 수있었습니다 (: 10 단계 앞으로 예측하려면 대상을 값 10으로 변경). 1 단계가 아닌 앞서서 진행합니다. 그러나 다음 10 개의 값을 예측하려면 어떻게해야합니까? 첫 번째 옵션은 이미 학습 한 모델을 사용하여 다음 값을 예측 한 다음 해당 값을 입력에 추가하고 (예상된 값이 실제로 발생한 것처럼 작동) 모델을 다시 사용하여 다음 값을 예측하는 것입니다.

 

series = generate_time_series(1, n_steps + 10)

 X_new, Y_new = series[:, :n_steps], series[:, n_steps:]

 X = X_new

 for step_ahead in range(10):

    y_pred_one = model.predict(X[:, step_ahead:])[:, np.newaxis, :]

    X = np.concatenate([X, y_pred_one], axis=1)


Y_pred = X[:, n_steps:]

 

예상한대로 다음 단계에 대한 예측은 오류가 누적될 수 있기 때문에 일반적으로 이후 단계에 대한 예측보다 더 정확합니다. 0.029MSE

 

두 번째 옵션은 한 번에 10 개의 다음 값을 모두 예측하도록 RNN을 훈련시키는 것입니다. 시퀀스 대 벡터 모델을 계속 사용할 수 있지만 1 대신 10 개의 값을 출력합니다. 그러나 먼저 대상을 다음 10 개의 값을 포함하는 벡터로 변경해야합니다. MSE는 약 0.008

 

시간 단계 0에서, 모델은 시간 단계 1 내지 10에 대한 예측을 포함하는 벡터를 출력 할 것이고, 시간 단계 1에서 모델은 시간 단계 2 내지 11 등을 예측할 것이다. 따라서 각 대상은 각 단계에서 10 차원 벡터를 포함하는 입력 시퀀스와 동일한 길이의 시퀀스 여야합니다.

 

 

 

https://excelsior-cjh.tistory.com/183

반응형

댓글