The way we treat stockouts on my team is to remove them from the input time series and replace them with an estimate of what the sales would have been had there been no stock out as a preprocessing step that happens before we apply the main forecasting model (whatever that model is).
Different methods can be used for replacing the stockout sales with the estimated sales. You can use the:
- mean value of all sales.
- median value of all sales.
- mean of n days before the stockout and n days after the stockout.
- weighted average of n days before and n days after the stockout.
- exponential smoothing based on n days before and n days after.
Note that we typically replace the stockout sales value with the estimate only if the stockout value is less than the estimate. If the estimate is smaller, then we keep the original sales value, even if there was a stockout.
An example, here using the average of 2 days before and 2 days after the stockout event:
Raw sales
Day 1 Day 2 Day 3 Day 4 Day 5 Day 6 Day 7 Day 8 Day 9
2 3 1 3 4 3 4 2 2
Stockout indicator
Day 1 Day 2 Day 3 Day 4 Day 5 Day 6 Day 7 Day 8 Day 9
x x 1 x x x 1 x x
Adjusted sales
Day 1 Day 2 Day 3 Day 4 Day 5 Day 6 Day 7 Day 8 Day 9
2 3 3 3 4 2 3 1 1
Here we see that we have stockouts on day 3 and on day 7.
For day 3 we calculate the average of the sales on days 1,2,4, and 5, and then replace the raw sales with that value.
On day 7, we calculate the average of the sales on days 5,6,8, and 9, but it turns out to be less than the raw sales value for day 7, so we just keep the original value.
The logic here is that it doesn't make sense to adjust the sales down, since a stockout would be less then the estimated sales not more.
We then take the adjusted sales time series as the input to our forecasting model, instead of the raw sales.
As for doing this in LSTM? In theory you could feed it the stockout vector as a separate categorical feature and then it would somehow figure out the above mentioned logic on its own (NNets are universal approximators), in practice you might have a hard time pulling that off, and you would be better off pre-processing the data and then feeding it to the LSTM.