안녕하세요 미니빅 입니다.
오늘은 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 데이터를 나누는 함수를 작성해봤습니다.
순서대로 천천히 해보시면 이해하실 수 있을 거예요
변수들이 각각 의미하는 것들을 생각하며, 엑셀이나 연습장 등에 변수 내 값의 변화를
확인하며 이해하시길 바랍니다.
그럼 이번 포스팅은 이정도로 마치겠습니다.
안녕!