A model that predicts tomorrow's demand or next week's churn will be used on data that arrives after it was trained. The leakage topic of the ML System Design course explains that a random train and validation split lets rows from the future sit next to rows from the past, which makes the validation score better than anything the model will achieve live. The fix is a split along time, with a gap between the two parts so that nothing that straddles the cutoff can leak across it. This problem asks you to build that split.
You are given a list of timestamps, one per row, which may be in any order, together with three integers.
Rows whose timestamp is before train_end belong to the training set. Rows whose timestamp is at or after train_end plus gap and before val_end belong to the validation set. Rows that fall inside the gap, from train_end up to but not including train_end plus gap, are excluded. Rows at or after val_end are ignored.
Return a dictionary with two keys. The value for train_idx is a one-dimensional integer NumPy array holding the positions of the training rows in ascending order, and the value for val_idx is the same for the validation rows. Positions refer to the original list, so an unsorted input does not change which position a row has.
Worked example. The timestamps are 5, 1, 9, 14, 3, 12, 20 and 7, with train_end equal to 8, gap equal to 2 and val_end equal to 15. Positions 0, 1, 4 and 7 hold timestamps 5, 1, 3 and 7, all before 8, so they form the training set. Position 2 holds timestamp 9, which lies in the gap from 8 up to 10, so it is dropped.
Positions 3 and 5 hold timestamps 14 and 12, which are at or after 10 and before 15, so they form the validation set. Position 6 holds timestamp 20, which is at or after 15 and is ignored. The answer is train_idx equal to 0, 1, 4, 7 and val_idx equal to 3, 5.
Input: timestamps = [5, 1, 9, 14, 3, 12, 20, 7], train_end = 8, gap = 2, val_end = 15
Output: {"train_idx": [0, 1, 4, 7], "val_idx": [3, 5]}
Explanation: Timestamps before 8 train, the row at 9 falls in the gap, timestamps from 10 up to 14 validate, and the row at 20 is past val_end.
Input: timestamps = [1, 2, 3, 4], train_end = 3, gap = 0, val_end = 5
Output: {"train_idx": [0, 1], "val_idx": [2, 3]}
Explanation: With no gap, the row at exactly train_end is the first validation row.
Convert the timestamps to a NumPy array and build one boolean mask per set, then use np.arange(len(timestamps)) with each mask to get the positions.
The validation mask combines two conditions, at or after train_end plus gap and strictly before val_end.
Accepts: array
Accepts: number
Accepts: number
Accepts: number
A model that predicts tomorrow's demand or next week's churn will be used on data that arrives after it was trained. The leakage topic of the ML System Design course explains that a random train and validation split lets rows from the future sit next to rows from the past, which makes the validation score better than anything the model will achieve live. The fix is a split along time, with a gap between the two parts so that nothing that straddles the cutoff can leak across it. This problem asks you to build that split.
You are given a list of timestamps, one per row, which may be in any order, together with three integers.
Rows whose timestamp is before train_end belong to the training set. Rows whose timestamp is at or after train_end plus gap and before val_end belong to the validation set. Rows that fall inside the gap, from train_end up to but not including train_end plus gap, are excluded. Rows at or after val_end are ignored.
Return a dictionary with two keys. The value for train_idx is a one-dimensional integer NumPy array holding the positions of the training rows in ascending order, and the value for val_idx is the same for the validation rows. Positions refer to the original list, so an unsorted input does not change which position a row has.
Worked example. The timestamps are 5, 1, 9, 14, 3, 12, 20 and 7, with train_end equal to 8, gap equal to 2 and val_end equal to 15. Positions 0, 1, 4 and 7 hold timestamps 5, 1, 3 and 7, all before 8, so they form the training set. Position 2 holds timestamp 9, which lies in the gap from 8 up to 10, so it is dropped.
Positions 3 and 5 hold timestamps 14 and 12, which are at or after 10 and before 15, so they form the validation set. Position 6 holds timestamp 20, which is at or after 15 and is ignored. The answer is train_idx equal to 0, 1, 4, 7 and val_idx equal to 3, 5.
Input: timestamps = [5, 1, 9, 14, 3, 12, 20, 7], train_end = 8, gap = 2, val_end = 15
Output: {"train_idx": [0, 1, 4, 7], "val_idx": [3, 5]}
Explanation: Timestamps before 8 train, the row at 9 falls in the gap, timestamps from 10 up to 14 validate, and the row at 20 is past val_end.
Input: timestamps = [1, 2, 3, 4], train_end = 3, gap = 0, val_end = 5
Output: {"train_idx": [0, 1], "val_idx": [2, 3]}
Explanation: With no gap, the row at exactly train_end is the first validation row.
Convert the timestamps to a NumPy array and build one boolean mask per set, then use np.arange(len(timestamps)) with each mask to get the positions.
The validation mask combines two conditions, at or after train_end plus gap and strictly before val_end.
Accepts: array
Accepts: number
Accepts: number
Accepts: number