Interval prediksi sekitar perkiraan seri waktu LSTM

13

Apakah ada metode untuk menghitung interval prediksi (distribusi probabilitas) di sekitar perkiraan deret waktu dari jaringan saraf LSTM (atau berulang lainnya)?

Katakanlah, misalnya, saya memprediksi 10 sampel ke masa depan (t + 1 hingga t + 10), berdasarkan pada 10 sampel terakhir yang diamati (t-9 hingga t), saya berharap prediksi pada t + 1 menjadi lebih akurat daripada prediksi di t + 10. Biasanya, orang mungkin menggambar bar kesalahan di sekitar prediksi untuk menunjukkan interval. Dengan model ARIMA (dengan asumsi kesalahan berdistribusi normal), saya dapat menghitung interval prediksi (misalnya 95%) di sekitar setiap nilai prediksi. Bisakah saya menghitung yang sama, (atau sesuatu yang berhubungan dengan interval prediksi) dari model LSTM?

Saya telah bekerja dengan LSTM di Keras / Python, mengikuti banyak contoh dari machinelearningmastery.com , dari mana kode contoh saya (di bawah) didasarkan pada. Saya sedang mempertimbangkan membingkai ulang masalah sebagai klasifikasi ke dalam tempat sampah terpisah, karena hal itu menghasilkan kepercayaan per kelas, tetapi itu tampaknya solusi yang buruk.

Ada beberapa topik serupa (seperti di bawah), tetapi sepertinya tidak ada yang secara langsung mengatasi masalah interval prediksi dari LSTM (atau memang lainnya) jaringan saraf:

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

Prediksi seri waktu menggunakan 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)
4Oh4
sumber

Jawaban:

9

Secara langsung, ini tidak mungkin. Namun, jika Anda memodelkannya dengan cara yang berbeda, Anda bisa keluar interval kepercayaan. Anda bisa bukannya menggunakan pendekatan regresi normal sebagai estimasi distribusi probabilitas kontinu. Dengan melakukan ini untuk setiap langkah Anda dapat merencanakan distribusi Anda. Cara untuk melakukan ini adalah Kernel Mixture Networks ( https://janvdvegt.github.io/2017/06/07/Kernel-Mixture-Networks.html , pengungkapan, blog saya) atau Density Mixture Networks ( http: //www.cedar .buffalo.edu / ~ srihari / CSE574 / Chap5 / Chap5.7-MixDensityNetworks.pdf ), yang pertama menggunakan kernel sebagai basis dan memperkirakan campuran di atas kernel ini dan yang kedua memperkirakan campuran distribusi, termasuk parameter dari masing-masing distribusi. Anda menggunakan kemungkinan log untuk melatih model.

Pilihan lain untuk memodelkan ketidakpastian adalah menggunakan dropout selama pelatihan dan kemudian juga selama inferensi. Anda melakukan ini beberapa kali dan setiap kali Anda mendapatkan sampel dari posterior Anda. Anda tidak mendapatkan distribusi, hanya sampel, tetapi ini yang paling mudah diterapkan dan berfungsi dengan sangat baik.

Dalam kasus Anda, Anda harus memikirkan cara Anda menghasilkan t + 2 hingga t + 10. Bergantung pada pengaturan Anda saat ini, Anda mungkin harus mengambil sampel dari langkah waktu sebelumnya dan memasukkannya ke langkah berikutnya. Itu tidak bekerja dengan baik dengan pendekatan pertama, atau dengan yang kedua. Jika Anda memiliki 10 output per langkah waktu (t + 1 hingga t + 10) maka semua pendekatan ini lebih bersih tetapi sedikit kurang intuitif.

Jan van der Vegt
sumber
1
Menggunakan jaringan campuran itu menarik, saya akan mencoba mengimplementasikannya. Ada beberapa penelitian kuat tentang penggunaan dropout di sini: arxiv.org/abs/1709.01907 dan arxiv.org/abs/1506.02142
4Oh4
Catatan untuk dropout, Anda sebenarnya dapat menghitung varians prediksi dropout monte carlo, dan menggunakannya sebagai kuantifikasi ketidakpastian
Charles Chow
Itu benar @CharlesChow tapi itu cara yang buruk untuk membangun interval kepercayaan dalam konteks ini. Akan lebih baik untuk menyortir nilai-nilai dan menggunakan kuantil karena distribusi yang berpotensi sangat miring.
Jan van der Vegt
Setuju @JanvanderVegt, tetapi Anda masih dapat memperkirakan statistik dropout MC tanpa asumsi distribusi output, maksud saya Anda juga dapat menggunakan persentil atau bootstrap untuk membangun CI dropout MC
Charles Chow
2

Prediksi Konformal sebagai kata buzz mungkin menarik bagi Anda karena berfungsi dalam banyak kondisi - khususnya tidak memerlukan kesalahan terdistribusi normal dan berfungsi untuk hampir semua model pembelajaran mesin.

Dua perkenalan yang bagus diberikan oleh Scott Locklin dan Henrik Linusson .

Boris W
sumber
1

Saya akan menyimpang sedikit dan berpendapat bahwa interval kepercayaan perhitungan dalam praktek biasanya bukan hal yang berharga untuk dilakukan. Alasannya adalah selalu ada sejumlah asumsi yang perlu Anda buat. Bahkan untuk regresi linear paling sederhana, Anda harus memilikinya

  • Hubungan linear.
  • Normalitas multivarian.
  • Tidak ada atau sedikit multikolinearitas.
  • Tidak ada korelasi otomatis.
  • Homoscedasticity.

Pendekatan yang jauh lebih pragmatis adalah melakukan simulasi Monte Carlo. Jika Anda sudah tahu atau mau membuat asumsi seputar distribusi variabel input Anda, ambil sejumlah besar sampel dan berikan kepada Anda LSTM, sekarang Anda dapat secara empiris menghitung "interval kepercayaan" Anda.

Louis T
sumber
1

Ya kamu bisa. Satu-satunya hal yang perlu Anda ubah adalah fungsi kerugian. Menerapkan fungsi kerugian yang digunakan dalam regresi kuantil dan mengintegrasikannya. Anda juga ingin melihat bagaimana Anda mengevaluasi interval tersebut. Untuk itu, saya akan menggunakan metrik ICP, MIL dan RMIL.

Inigo
sumber