# Changing the training/test split between epochs in neural net models, when doing hyperparameter optimization

Consider a predictive modeling case where the number of samples is limited, but the data on the samples is rich. For context, I'm doing a multivariate time series prediction, with a few thousand (pseudo-) independent time series of about 50 variables each, over about 100 periods. Obviously, because I'm pooling them, I'm attempting to learn a function that fits each of the few thousand time series in an average sense.

Essentially, my model is $$\mathbf{Y}_{it} = f(\mathbf{Y}_{lags}, \Lambda) + \epsilon_{it}$$

where $$\mathbf{Y}$$ is a matrix of outcome variables indexed by the cross-sectional unit and time (in keras, it has dimension $$i \times t \times p$$ where $$p$$ is the number of variables), $$\Lambda$$ is a vector of hyperparameters -- things like regularization penalties and dropout rates, and $$f$$ is some time series network, like a temporal convolutional network or a LSTM.

Rather than explicitly trying to find one optimal value of $$\Lambda$$, I'm using the following algorithm to train $$f$$. It's a form of Bayesian Hyperparameter Optimization (I guess), only it allows for optimal $$\Lambda$$ to change over the course of training:

1. Split data into training/testing set
2. For initial $$\theta$$ (defining $$\theta$$ as the weights/parameters that make up the actual model), compute test loss, put it in $$L^{old}$$, and put $$\theta$$ in $$\theta^{old}$$
3. Draw from some distribution of candidate values of $$\Lambda$$, use to train model to get $$\theta^{new}$$ and $$L^{new}$$. If $$L^{new} < L^{old}$$, put $$\theta^{new}$$ into $$\theta^{old}$$. Otherwise retain $$\theta^{old}$$ for the next epoch.
4. Repeat (3) until satisfied

Here's my question: is there anything wrong with redefining the train/test split between epochs?

The algorithm would become:

1. Initialize $$\theta$$, call it $$\theta^{old}$$
2. Define a random train test split, then compute $$L^{old}$$ on the new test set
3. Draw from some distribution of candidate values of $$\Lambda$$, use to train model to get $$\theta^{new}$$ and $$L^{new}$$. If $$L^{new} < L^{old}$$, put $$\theta^{new}$$ into $$\theta^{old}$$. Otherwise retain $$\theta^{old}$$ for the next epoch.
4. Repeat (2) and then (3) until satisfied

Obviously I'd have to use some moving average of loss over epochs, because losses between testing sets won't be comparable.

I don't see why this should overfit necessarily. It's akin to bagging in that it uses many different train/test splits, but I'm not building many models to average. Instead I'm making the different observations "take turns" at the test set. The reason that I'm considering it is that I don't have millions of cross-sectional units, and I want to avoid bias stemming from too-big of a test set, as well as the expense of bagging.

It could be said that a given epoch could overfit to a specific observation, and then that could persist when that observation does its turn in the test set. But it seems to me that this effect would eventually wash out, especially if for each epoch I enforce that the training set and the testing set are together smaller than the total number of samples.

I'd appreciate suggestions on the algorithm! Or, has someone already invented this technique and called it something that I haven't been able to find on google? That'd be helpful too.

Edit It should be mentioned that my population has a fixed size $$i$$ -- new data will come in the form of more time $$t$$, rather than more cross-sectional units $$i$$. Many time series ML models only use some future period as a target, but I explicitly want my model to both explain the past (using cross-sectional variation) as well as predict the future.

To be more specific, I have about 2000 locations, from 1900 to present. The first thing I'm going to do is to train my model up to 1980, and see how well it predicts the present day. If it does, I'll follow this approach to train the model up to the present, and then project it into the future.

The answer is No. You should never do such a thing.

What you are proposing is this: train a model for a number of epochs until it converges. At each epoch, divide the dataset into a training and a testing set. Train on the training set and test on the test set. Repeat this process.

Now note that when your system has been deployed, it will get inputs that it had never seen during the training phase. This is because during training you only have access to a small subset of all real-life scenarios. Hence, you would need to know in advance how good your system performs on these "unseen" inputs. So this is where you need to be careful with the testing phase. You would want to test your model on "unseen" inputs - inputs that it has never seen during training. So your test set must consist of inputs not present in the training set. In other words, you training and test sets should have as little overlap as possible.

Now lets see what happens with your algorithm: after the first epoch, the model redivides the entire dataset into a training set and a test set. However, now the test set contains (possibly all) examples that it has already "seen" during the first epoch. Which means that your test set does not mimic deployment conditions accurately. Hence, your test accuracy on the second epoch will not be reflective of the accuracy you would get at deployment.

If you are worried about, wasting some portion of the dataset on the test set then you could use a technique called cross-validation. Here you divide your dataset in k parts. Say, k is 3. So, you would then train your model on parts 1 and 2 and test on part 3. Then, you would retrain your model (from scratch by initializing randomly) on parts 1 and 3 and test on part 2. Finally, you again retrain your model (from scratch again), but this time on parts 2 and 3 and then test it on part 1. During deployment, you run each of the three models separately and then combine their outputs in an appropriate way (e.g. weighting and linearly combining them).

So, in short you can not change the train/test split between epochs because the testing conditions must mimic the "unseen" deployment conditions which means that a model must never be trained on the testing data.

• Thanks for the answer. While I'm not entirely sure that my idea is valid, I'm not sure that you've convinced me that my idea is wrong either. Also, what you're proposing isn't cross-validation, but model averaging. I've got reasons for not wanting to do that in my specific case, for reasons that don't really relate to my specific question. Another specific that does relate to my question: since this is a time series problem, my true test set is future data, not entirely new time series. I'll add that to the question. Commented Mar 12, 2019 at 17:24
• What I said is cross validation (or more correctly k-fold cross validation). Check out its Wikepedia article if you have any doubts: en.wikipedia.org/wiki/Cross-validation_(statistics) Commented Mar 15, 2019 at 3:15
• The term "Unseen" or "new" data does not necessarily refer to a new timeseries. It only means that the inputs at test time are different than at training time. For example, if at training time the time series the model saw was 1,2,3 and at test time it was fed 1,4,3 (which might be a continuation of the same time series at the training time aka future data), then the training data and the test data are different. But what we assume is that their underlying distribution is the same (which is what we are trying to model). Commented Mar 15, 2019 at 3:22
• So, your test set should give you an idea of how good your model will perform if got some new data such as 1,4,3. But if you are only evaluating it on your training data (which you are proposing) then you can never know how well it will perform on this new data (which again is not necessarily a new time series but just some future data of the old time series) Commented Mar 15, 2019 at 3:25
• You're reasoning makes sense to me, but seems to conflict with the documentation below. Can anyone explain the nuance I'm missing? pytorch.org/tutorials/beginner/basics/… Commented Oct 20, 2022 at 3:08