안녕하세요 미니빅 입니다.

 

오늘은 RNN 데이터를 list, array 등에서 잘라서 나누는 함수 정의에 대해서

 

얘기해보겠습니다.

 

part 7을 보면, 기존의 모델의 구조와 다르게 행의 개수가 유지되어야 한다는 것을 배웠습니다.

(이해가 안 되시면 part 7을 다시 봐주시고 와주세요)

 

1) 다대일

import numpy as np

dataset=np.array(range(1,11)) #(10,)
#array에서 앞에서부터 4개(처음엔 1~4) 값을 가져와서 그 다음값(5)를 y로 설정하게
#split을 한다.

def split(dataset,time_steps):
    xs=list()
    ys=list()
    for i in range(0,len(dataset)-time_steps):
        x=dataset[i:i+time_steps]
        y=dataset[i+time_steps]
        # print(f"{x}:{y}")
        xs.append(x)
        ys.append(y)
    return np.array(xs),np.array(ys)

xs,ys=split(dataset,4)

print(f"xs:{xs}\n ys:{ys}")

 

매개변수는 두 개(dataset,time_steps)를 받고, 각 나누어진 값들을 저장할 xs, ys 변수를 설정합니다.

 

(x:1~4, y:5)와 같이 앞에서부터 index 순으로 잘라와야하니, for문을 (array의 총길이 - x의 길이) 만큼 반복합니다.

 

이와 같이 함수를 정의하고 실행하면

 

xs:[[1 2 3 4]
 [2 3 4 5]
 [3 4 5 6]
 [4 5 6 7]
 [5 6 7 8]
 [6 7 8 9]]
ys:[ 5  6  7  8  9 10]

 

와 같이 결과가 나옵니다.

 


2) 다대다

 

1번은 y값이 1개였으나, 이번엔 2개가 나오게 하겠습니다.

 

import numpy as np

dataset=np.array(range(1,11))#(10,)

# 2.다대다

#array에서 앞에서부터 4개(처음엔 1~4) 값을 가져와서 그 다음값 2개(5,6)를 y로 설정하게
#split을 한다.

def split_2(dataset,time_steps,y_column):
    xs=list()
    ys=list()
    for i in range(0,len(dataset)-time_steps-y_column+1):#y의 개수가 늘어날수록 반복횟수가 줄어든다.
        x=dataset[i:i+time_steps]
        y=dataset[i+time_steps:i+time_steps+y_column]#y의 개수만큼 범위지정
        xs.append(x)
        ys.append(y)
    return np.array(xs),np.array(ys)

xs,ys=split_2(dataset,4,2)

print(f"xs:{xs}\nys:{ys}")

1번과 비슷하지만, 매개변수에 y의 개수를 받는 변수를 추가하고,

 

그에 따른 값만 변동했습니다.

 

xs:[[1 2 3 4]
 [2 3 4 5]
 [3 4 5 6]
 [4 5 6 7]
 [5 6 7 8]]
ys:[[ 5  6]
 [ 6  7]
 [ 7  8]
 [ 8  9]
 [ 9 10]]

3) 다입력, 다대일(다:1)

 

1번 케이스와는 다르게, 2차원 이상으로 값을 받는 경우입니다.

 

x값의 기본 입력데이터 크기가(3,2), y는 (1,)입니다.

 

import numpy as np

dataset=np.array([range(1,11),range(11,21),range(21,31)])
print(dataset.shape)#(3,10)

dataset=np.transpose(dataset)
print(dataset.shape)#(10,3)

# 3.다대일, 다입력

# array에서 앞에서부터 3*2의 값을 가져와서 3번째 행의 가장 오른쪽 값(열:-1)을 가져온다.


def split_3(dataset,time_steps,y_column):
    xs=list()
    ys=list()
    for i in range(0,len(dataset)-time_steps+1):
        x=dataset[i:(i+time_steps),:-1]#
        y=dataset[i+time_steps-1:(i+time_steps-1)+y_column,-1]

        xs.append(x)
        ys.append(y)
    return np.array(xs),np.array(ys)

print("result")
xs,ys=split_3(dataset,3,1)

print(f"{xs}\n\n{ys}")

우선 앞의 두 가지 경우(1,2번)과 달리 다입력 이기에 행렬 개념이 있어야합니다.

 

RNN에서는 x의 행의 개수y의 벡터의 값(지금은 8 - 3개의 행을 묶으면 8세트가 나옴)이 같아야 하기에,

 

transpose(전치)해줘야 합니다.

 

그에 따라 for문과 인덱스를 정리해주고 출력하면,

 

xs:[[[ 1 11]
  [ 2 12]
  [ 3 13]]

 [[ 2 12]
  [ 3 13]
  [ 4 14]]

 [[ 3 13]
  [ 4 14]
  [ 5 15]]

 [[ 4 14]
  [ 5 15]
  [ 6 16]]

 [[ 5 15]
  [ 6 16]
  [ 7 17]]

 [[ 6 16]
  [ 7 17]
  [ 8 18]]

 [[ 7 17]
  [ 8 18]
  [ 9 19]]

 [[ 8 18]
  [ 9 19]
  [10 20]]]

 ys:[[23]
 [24]
 [25]
 [26]
 [27]
 [28]
 [29]
 [30]]

 

와 같은 결과가 나옵니다.


4) 다입력, 다대다(1)

 

3번에서 이번엔, y값을 여러 개 받는 경우입니다.

 

import numpy as np

dataset=np.array([range(1,11),range(11,21),range(21,31)])
print(dataset.shape)#(3,10)

dataset=np.transpose(dataset)
print(dataset.shape)#(10,3)

# 4.다대다, 다입력

# array에서 앞에서부터 3*2의 값을 가져와서
# 3번째 행의 가장 오른쪽 값(열:-1) 여러 개(여기선 2개)를 가져온다.


def split_3(dataset,time_steps,y_column):
    xs=list()
    ys=list()
    for i in range(0,len(dataset)-time_steps+1):
        x=dataset[i:(i+time_steps),:-1]#
        y=dataset[i+time_steps-1:(i+time_steps-1)+y_column,-1]

        xs.append(x)
        ys.append(y)
    return np.array(xs),np.array(ys)

print("result")
xs,ys=split_3(dataset,3,2)

print(f"{xs}\n\n{ys}")

3번에서 변한 것은 실제로 값을 넣는 매개변수(y_column)의 값을 2로 바꾼 것 뿐입니다.

 

y=dataset[i+time_steps-1:(i+time_steps-1)+y_column,-1]

해당 코드에서 y_column이 늘어남에 따라 가져오는 값의 index 범위가 늘어나기 때문입니다.

 


5) 다입력, 다대다(2)

 

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

 

위의 행렬에서 x에서는 3개의 행[[1,11,21],[2,12,22],[3,13,23]]이 들어가고,

 

다음행 값인 [[4,14,24],[5,15,25]]가 y값이 될 수 있게 split 함수를 만들려고 합니다.

 

import numpy as np

dataset=np.array([range(1,11),range(11,21),range(21,31)])
print(dataset.shape)#(3,10)

dataset=np.transpose(dataset)
print(dataset.shape)#(10,3)

#5. 다입력, 다대다 모델(2)
def split_5(dataset,time_steps,y_column):
    xs,ys=list(),list()
    for i in range(len(dataset)-time_steps-y_column+1):
        x=dataset[i:i+time_steps,:]#0:3
        y=dataset[i+time_steps:i+time_steps+y_column,:]
        
        xs.append(x)
        ys.append(y)
    return np.array(xs), np.array(ys)

xs,ys=split_5(dataset,3,2)

print(f"xs:{xs} \n\n\n ys:{ys}")

 

앞의 모델들과 대부분의 코드가 비슷합니다.

 

        x=dataset[i:i+time_steps,:]#0:3
        y=dataset[i+time_steps:i+time_steps+y_column,:]

 

변경된 부분은, 열(time_steps) 부분전체( : )로 잡아줍니다. 

 

그 외의 부분은 4번과 동일합니다.

 

xs:[[[ 1 11 21]
  [ 2 12 22]
  [ 3 13 23]]

 [[ 2 12 22]
  [ 3 13 23]
  [ 4 14 24]]

 [[ 3 13 23]
  [ 4 14 24]
  [ 5 15 25]]

 [[ 4 14 24]
  [ 5 15 25]
  [ 6 16 26]]

 [[ 5 15 25]
  [ 6 16 26]
  [ 7 17 27]]

 [[ 6 16 26]
  [ 7 17 27]
  [ 8 18 28]]]


 ys:[[[ 4 14 24]
  [ 5 15 25]]

 [[ 5 15 25]
  [ 6 16 26]]

 [[ 6 16 26]
  [ 7 17 27]]

 [[ 7 17 27]
  [ 8 18 28]]

 [[ 8 18 28]
  [ 9 19 29]]

 [[ 9 19 29]
  [10 20 30]]]

다섯번째까지 해서 다양한 경우에 RNN 데이터를 나누는 함수를 작성해봤습니다.

 

순서대로 천천히 해보시면 이해하실 수 있을 거예요

 

변수들이 각각 의미하는 것들을 생각하며, 엑셀이나 연습장 등에 변수 내 값의 변화

 

확인하며 이해하시길 바랍니다.

 

그럼 이번 포스팅은 이정도로 마치겠습니다.

 

안녕!

+ Recent posts