안녕하세요, @euncheol 님.
먼저 아래와 같이 말씀해주신 내용을 읽어봤을 때는 학습 데이터를 여러 토막을 낸 뒤, 첫 번째 토막으로 모델을 학습을 다 하고 모델을 저장까지 한 뒤, 다음 토막으로 다시 모델을 추가 학습하는 상황을 말씀하신 것 같습니다. 제가 잘 이해한게 맞을까요?
일반적으로 시계열 데이터의 경우 순서가 중요하기에 데이터를 뽑을 때 섞지 말라(shuffle=False)
고 설명하고 있는데요, 혹시 이 내용과 데이터를 batch(묶음, 배치)로 나누어 학습하는 것을 헷갈리신게 아닐까 싶은 생각이 듭니다. 즉,
1. 순서가 중요한 상황(모델)이라고 하더라도, 학습 데이터셋을 섞지만 않는다면 묶음(batch) 단위로 쪼개어 학습할 수 있습니다.
노파심에 추가 설명을 조금 더 드리면, 전체 입력 데이터가 38만개라고 하더라도, 5천개나 1만개와 같이 GPU의 메모리에 올라갈 정도의 크기로 잘라서 학습을 진행하시면 됩니다.
예를 들어, 아래 튜토리얼의 경우 학습 데이터가 6만개인 Fashion-MNIST 데이터셋을 사용하면서, 한 번에 6만개를 모두 학습을 시키는 것이 아니라, 64개씩의 데이터를 갖는 묶음(batch)으로 나누어 처리하고 있습니다.
# training_data라는 Dataset으로부터 64개씩 하나의 묶음(batch)으로, 데이터를 섞어서 DataLaoder를 생성
train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)
이렇게 batch 단위로 나눠서 학습을 진행하면, 전체 데이터의 일부만 가지고 모델을 학습하고, 학습된 모델을 불러와 나머지 데이터로 학습시키는 형태가 아닌, 전체 데이터를 가지고 조금씩 나누어 학습하게 됩니다. (전체 데이터를 1번 순회하는 것을 1 에폭(epoch)이라고 합니다.)
물론 이러한 경우 각 batch에서 전체 데이터를 보지 못하였기 때문에 모델 내부 가중치의 최적화에 조금 더 시간이 걸릴 수 있지만, 어쨌든 데이터 셋 전체를 사용하여 하나의 모델을 학습하는 것이 됩니다.
2. 전처리 시에 입력들과 출력들의 순서를 맞춰 묶어두신 경우에는 데이터셋을 섞으셔도 됩니다.
위에서 말씀드린 데이터를 섞는 것을 하면 된다 / 안된다는 모델의 종류와 입/출력에 따라서 이러한 내용은 달라질 수 있는데요, 최근 & 대부분의 경우 아래와 같이 학습을 하고 계시므로 가능할 것으로 예상합니다.
(가끔 모델에 따라 전처리 과정에서 행렬 분해(MF; Matrix Factorization) 등을 하는 경우가 있는데, 이런 경우에는 기존 시계열의 순서를 유지하셔야 할 수도 있습니다.)
먼저 아래와 같은 총 n+1개의 데이터가 있는 단변량(univariate) 시계열 데이터를 가정해보겠습니다.
(다변량(multivariate) 데이터의 경우에는 차원이 하나 더 있는거로 생각해주세요 )
X_{raw} = [x_0, x_1, x_2, x_3, x_4, x_5, x_6, ..., x_{n-2}, x_{n-1}, x_n]
이 때, 입력을 5개의 timestep을 받아서 다음 2개의 값을 예측하는 경우, 데이터 셋은 다음과 같이 구성될 것입니다. (n_window= 5, n_hozion=2)
X_{input_k} = [x_{k-4}, x_{k-3}, x_{k-2}, x_{k-1}, x_{k}] \\
Y_{output_k} = [x_{k+1}, x_{k+2}]
이렇게 입/출력이 정해지는 경우, 전처리 과정에서 대략 다음과 같은 식으로 (정규화를 포함한 작업들 후) 입력으로 받아야 하는 5개의 timestep과 출력(예측)에 사용할 2개의 timestep의 쌍으로 묶는 작업
까지 포함하신다면, 전체 데이터 셋의 모양은 아마도 다음과 같을 것입니다.
X_{input} = [ [x_0, x_1, x_2, x_3, x_4], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_1, x_2, x_3, x_4, x_5], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_2, x_3, x_4, x_5, x_6], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_3, x_4, x_5, x_6, x_7], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_4, x_5, x_6, x_7, x_8], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ... \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_{n-8}, x_{n-7}, x_{n-6}, x_{n-5}, x_{n-4}], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_{n-7}, x_{n-6}, x_{n-5}, x_{n-4}, x_{n-3}], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_{n-6}, x_{n-5}, x_{n-4}, x_{n-3}, x_{n-2}]] \\ \ \\
Y_{output} = [ [x_5, x_6 ], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_6, x_7], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_7, x_8], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_8, x_9], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_9, x_{10}], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ... \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_{n-3}, x_{n-2}], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_{n-2}, x_{n-1}], \\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [x_{n-1}, x_{n}]]
위와 같이 데이터셋이 구성된 경우에는 DataLoader로부터 가져오는 각각의 (X, Y) 묶음은 이미 입력과 출력에 대한 순서가 각 데이터셋 내에 정리가 되어 있기 때문에, 학습 시 순서를 섞으셔도 상관이 없습니다.
혹시 위에서 제가 추측한 내용이 아니시라면, 다시금 알려주시기를 부탁드립니다.