Existe um método para calcular o intervalo de previsão (distribuição de probabilidade) em torno de uma série temporal prevista a partir de uma rede neural LSTM (ou outra rede recorrente)?
Digamos, por exemplo, que estou prevendo 10 amostras no futuro (t + 1 a t + 10), com base nas últimas 10 amostras observadas (t-9 a t), eu esperaria que a previsão em t + 1 fosse mais preciso do que a previsão em t + 10. Normalmente, pode-se desenhar barras de erro ao redor da previsão para mostrar o intervalo. Com um modelo ARIMA (sob a suposição de erros normalmente distribuídos), posso calcular um intervalo de previsão (por exemplo, 95%) em torno de cada valor previsto. Posso calcular o mesmo (ou algo relacionado ao intervalo de previsão) de um modelo LSTM?
Estou trabalhando com LSTMs em Keras / Python, seguindo muitos exemplos de machinelearningmastery.com , nos quais meu código de exemplo (abaixo) se baseia. Estou pensando em reformular o problema como classificação em compartimentos discretos, pois isso gera confiança por classe, mas isso parece uma solução ruim.
Existem alguns tópicos semelhantes (como o abaixo), mas nada parece abordar diretamente a questão dos intervalos de previsão das redes neurais LSTM (ou mesmo outras):
/stats/25055/how-to-calculate-the-confidence-interval-for-time-series-prediction
Previsão de séries temporais usando ARIMA vs LSTM
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from math import sin
from matplotlib import pyplot
import numpy as np
# Build an LSTM network and train
def fit_lstm(X, y, batch_size, nb_epoch, neurons):
X = X.reshape(X.shape[0], 1, X.shape[1]) # add in another dimension to the X data
y = y.reshape(y.shape[0], y.shape[1]) # but don't add it to the y, as Dense has to be 1d?
model = Sequential()
model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True))
model.add(Dense(y.shape[1]))
model.compile(loss='mean_squared_error', optimizer='adam')
for i in range(nb_epoch):
model.fit(X, y, epochs=1, batch_size=batch_size, verbose=1, shuffle=False)
model.reset_states()
return model
# Configuration
n = 5000 # total size of dataset
SLIDING_WINDOW_LENGTH = 30
SLIDING_WINDOW_STEP_SIZE = 1
batch_size = 10
test_size = 0.1 # fraction of dataset to hold back for testing
nb_epochs = 100 # for training
neurons = 8 # LSTM layer complexity
# create dataset
#raw_values = [sin(i/2) for i in range(n)] # simple sine wave
raw_values = [sin(i/2)+sin(i/6)+sin(i/36)+np.random.uniform(-1,1) for i in range(n)] # double sine with noise
#raw_values = [(i%4) for i in range(n)] # saw tooth
all_data = np.array(raw_values).reshape(-1,1) # make into array, add anothe dimension for sci-kit compatibility
# data is segmented using a sliding window mechanism
all_data_windowed = [np.transpose(all_data[idx:idx+SLIDING_WINDOW_LENGTH]) for idx in np.arange(0,len(all_data)-SLIDING_WINDOW_LENGTH, SLIDING_WINDOW_STEP_SIZE)]
all_data_windowed = np.concatenate(all_data_windowed, axis=0).astype(np.float32)
# split data into train and test-sets
# round datasets down to a multiple of the batch size
test_length = int(round((len(all_data_windowed) * test_size) / batch_size) * batch_size)
train, test = all_data_windowed[:-test_length,:], all_data_windowed[-test_length:,:]
train_length = int(np.floor(train.shape[0] / batch_size)*batch_size)
train = train[:train_length,...]
half_size = int(SLIDING_WINDOW_LENGTH/2) # split the examples half-half, to forecast the second half
X_train, y_train = train[:,:half_size], train[:,half_size:]
X_test, y_test = test[:,:half_size], test[:,half_size:]
# fit the model
lstm_model = fit_lstm(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epochs, neurons=neurons)
# forecast the entire training dataset to build up state for forecasting
X_train_reshaped = X_train.reshape(X_train.shape[0], 1, X_train.shape[1])
lstm_model.predict(X_train_reshaped, batch_size=batch_size)
# predict from test dataset
X_test_reshaped = X_test.reshape(X_test.shape[0], 1, X_test.shape[1])
yhat = lstm_model.predict(X_test_reshaped, batch_size=batch_size)
#%% Plot prediction vs actual
x_axis_input = range(half_size)
x_axis_output = [x_axis_input[-1]] + list(half_size+np.array(range(half_size)))
fig = pyplot.figure()
ax = fig.add_subplot(111)
line1, = ax.plot(x_axis_input,np.zeros_like(x_axis_input), 'r-')
line2, = ax.plot(x_axis_output,np.zeros_like(x_axis_output), 'o-')
line3, = ax.plot(x_axis_output,np.zeros_like(x_axis_output), 'g-')
ax.set_xlim(np.min(x_axis_input),np.max(x_axis_output))
ax.set_ylim(-4,4)
pyplot.legend(('Input','Actual','Predicted'),loc='upper left')
pyplot.show()
# update plot in a loop
for idx in range(y_test.shape[0]):
sample_input = X_test[idx]
sample_truth = [sample_input[-1]] + list(y_test[idx]) # join lists
sample_predicted = [sample_input[-1]] + list(yhat[idx])
line1.set_ydata(sample_input)
line2.set_ydata(sample_truth)
line3.set_ydata(sample_predicted)
fig.canvas.draw()
fig.canvas.flush_events()
pyplot.pause(.25)
Previsão conforme como uma palavra da moda pode ser interessante para você, porque funciona sob muitas condições - em particular, não precisa de erro distribuído normal e funciona para quase qualquer modelo de aprendizado de máquina.
Duas boas apresentações são dadas por Scott Locklin e Henrik Linusson .
fonte
Vou divergir um pouco e argumentar que, na prática, o intervalo de confiança do cálculo geralmente não é uma coisa valiosa a ser feita. A razão é que há sempre um monte de suposições que você precisa fazer. Mesmo para a regressão linear mais simples, você precisa ter
Uma abordagem muito mais pragmática é fazer uma simulação de Monte Carlo. Se você já sabe ou deseja assumir a distribuição de suas variáveis de entrada, pegue um monte de amostras e forneça LSTM para você, agora você pode calcular empiricamente o seu "intervalo de confiança".
fonte
Sim você pode. A única coisa que você precisa alterar é a função de perda. Implemente a função de perda usada na regressão quantílica e integre-a. Além disso, você deseja dar uma olhada em como você avalia esses intervalos. Para isso, eu usaria métricas de ICP, MIL e RMIL.
fonte