LSTM zaman serisi tahmini etrafında tahmin aralığı


14

LSTM (veya başka bir tekrarlayan) sinir ağından bir zaman serisi tahmini etrafında tahmin aralığını (olasılık dağılımı) hesaplamak için bir yöntem var mı?

Örneğin, son 10 gözlemlenen örneğe (t-9 ila t) dayanarak, gelecekteki 10 örneği (t + 1 ila t + 10) tahmin ediyorum, t + 1'deki tahminin daha fazla olmasını beklerim t + 10'daki tahminden daha doğru. Genellikle, aralığı göstermek için tahminin etrafına hata çubukları çizilebilir. Bir ARIMA modeliyle (normal olarak dağıtılan hatalar varsayımı altında), tahmin edilen her değerin etrafında bir tahmin aralığı (örneğin% 95) hesaplayabilirim. Bir LSTM modelinden aynı (veya tahmin aralığı ile ilgili bir şey) hesaplayabilir miyim?

Ben örneklerle dolu sonrasında Keras / Python LSTMs birlikte çalışıyor ediyorum machinelearningmastery.com benim örnek kod (aşağıda) dayanmaktadır hangi. Sorunu ayrık kutulara sınıflandırma olarak yeniden yapılandırmayı düşünüyorum, çünkü bu sınıf başına güven üretiyor, ancak bu kötü bir çözüm gibi görünüyor.

Birkaç benzer konu var (aşağıdaki gibi), ancak hiçbir şey doğrudan LSTM (veya gerçekten de diğer) sinir ağlarından tahmin aralıkları konusunu ele almıyor gibi görünüyor:

/stats/25055/how-to-calculate-the-confidence-interval-for-time-series-prediction

ARIMA vs LSTM kullanarak zaman serisi tahmini

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)

Yanıtlar:


10

Doğrudan, bu mümkün değil. Ancak, farklı bir şekilde modellerseniz, güven aralıkları elde edebilirsiniz. Normal bir regresyon yaklaşımı yerine sürekli olasılık dağılımını tahmin edebilirsiniz. Bunu her adımda yaparak dağıtımınızı çizebilirsiniz. Bunu yapmanın yolları Çekirdek Karışım Ağları ( https://janvdvegt.github.io/2017/06/07/Kernel-Mixture-Networks.html , açıklama, blogum) veya Yoğunluk Karışım Ağları'dır ( http: //www.cedar .buffalo.edu / ~ srihari / CSE574 / Chap5 / Chap5.7-MixDensityNetworks.pdf ), ilki çekirdek olarak taban kullanır ve ikincisi bu Çekirdekler üzerinden bir karışım tahmin eder ve ikincisi her birinin parametreleri de dahil olmak üzere dağılımların bir karışımını tahmin eder dağılımları. Günlük olasılığını, modeli eğitmek için kullanırsınız.

Belirsizliği modellemek için bir başka seçenek, eğitim sırasında ve ardından çıkarım sırasında bırakma kullanmaktır. Bunu birden çok kez yaparsınız ve posteriorunuzdan her numune aldığınızda. Dağıtımları almazsınız, sadece örnekler alırsınız, ancak uygulanması en kolay olanıdır ve çok iyi çalışır.

Sizin durumunuzda, t + 2'yi t + 10'a kadar üretme şeklinizi düşünmelisiniz. Mevcut kurulumunuza bağlı olarak, bir önceki zaman adımından örneklemeniz ve bir sonraki adım için bunu beslemeniz gerekebilir. Bu ne ilk yaklaşımda ne de ikinci yaklaşımda çok işe yaramaz. Zaman adımı başına 10 çıkışınız varsa (t + 1 ila t + 10), bu yaklaşımların hepsi daha temiz ama biraz daha sezgiseldir.


2
Karışım ağlarını kullanmak ilginç, bunu uygulamaya çalışacağım. Burada bırakma konusunda bazı sağlam araştırmalar var: arxiv.org/abs/1709.01907 ve arxiv.org/abs/1506.02142
4Oh4

Bırakma için bir not, aslında monte carlo bırakma tahmininin varyansını hesaplayabilir ve bunu belirsizlik ölçümü olarak kullanabilirsiniz
Charles Chow

Bu @CharlesChow doğrudur ancak bu bağlamda bir güven aralığı oluşturmanın kötü bir yoludur. Potansiyel olarak çok çarpık dağılım nedeniyle değerleri sıralamak ve kantilleri kullanmak daha iyi olacaktır.
Jan van der Vegt

@JanvanderVegt kabul edin, ancak yine de çıkış dağılımı varsayımı olmadan MC bırakma istatistiklerini tahmin edebilirsiniz, yani MC bırakma CI'sını oluşturmak için yüzdelik veya önyükleme de kullanabilirsiniz
Charles Chow

2

Bir vızıltı kelimesi olarak Konformal Tahmin sizin için ilginç olabilir, çünkü birçok koşulda çalışır - özellikle normal dağıtılmış hataya ihtiyaç duymaz ve hemen hemen her makine öğrenme modeli için çalışır.

Scott Locklin ve Henrik Linusson tarafından iki güzel tanıtım yapıldı .


1

Biraz uzaklaşacağım ve hesaplama güven aralığının pratikte olduğunu genellikle yapmak için değerli bir şey olmadığını savunacağım. Nedeni her zaman yapman gereken bir sürü varsayım olması. En basit doğrusal regresyon için bile,

  • Doğrusal ilişki.
  • Çok değişkenli normallik.
  • Çoklu doğrusallık yok veya çok az.
  • Otomatik korelasyon yok.
  • Homoscedasticity.

Çok daha pragmatik bir yaklaşım Monte Carlo simülasyonu yapmaktır. Girdi değişkenlerinizin dağılımı hakkında zaten bir varsayım yapmak veya varsaymak istiyorsanız, bir sürü örnek alın ve LSTM'ye besleyin, şimdi "güven aralığınızı" ampirik olarak hesaplayabilirsiniz.


1

Evet yapabilirsin. Değiştirmeniz gereken tek şey kayıp fonksiyonudur. Kantil regresyonda kullanılan kayıp fonksiyonunu uygular ve bütünleştirir. Ayrıca, bu aralıkları nasıl değerlendirdiğinize de bakmak istersiniz. Bunun için ICP, MIL ve RMIL metriklerini kullanırdım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.