LSTM: Cách đối phó với sự không cố định khi dự đoán chuỗi thời gian


8

Tôi muốn thực hiện các dự đoán trước một bước cho chuỗi thời gian với LSTM. Để hiểu thuật toán, tôi đã xây dựng cho mình một ví dụ về đồ chơi: Một quy trình tự tương quan đơn giản.

def my_process(n, p, drift=0, displacement=0):
    x = np.zeros(n)

    for i in range(1, n):
        x[i] = drift * i + p * x[i-1] + (1-p) * np.random.randn()
    return x + displacement

Sau đó, tôi đã xây dựng một mô hình LSTM trong Keras, theo ví dụ này . Tôi mô phỏng các quá trình với tự tương quan cao p=0.99độ dài n=10000, được đào tạo mạng lưới thần kinh trên 80% đầu tiên của nó và để cho nó làm một bước trước những dự đoán cho remaning 20%.

Nếu tôi đặt drift=0, displacement=0, mọi thứ đều hoạt động tốt: nhập mô tả hình ảnh ở đây

Sau đó, tôi đặt drift=0, displacement=10và mọi thứ trở thành hình quả lê (chú ý tỷ lệ khác nhau trên trục y): nhập mô tả hình ảnh ở đây

Điều này không đáng ngạc nhiên lắm: LSTM nên được cung cấp dữ liệu chuẩn hóa! Vì vậy, tôi đã chuẩn hóa dữ liệu bằng cách thay đổi kích thước dữ liệu thành khoảng . Phew, mọi thứ lại tốt đẹp: [1,1]nhập mô tả hình ảnh ở đây

Sau đó, tôi thiết lập drift=0.00001, displacement=10, chuẩn hóa dữ liệu một lần nữa và chạy thuật toán trên nó. Điều này trông có vẻ không ổn: nhập mô tả hình ảnh ở đây

Rõ ràng LSTM không thể đối phó với sự trôi dạt. Phải làm sao (Vâng, trong ví dụ về đồ chơi này, tôi chỉ có thể trừ đi sự trôi dạt; nhưng đối với chuỗi thời gian thực, điều này khó hơn nhiều). Có lẽ tôi có thể chạy LSTM của mình với sự khác biệt thay vì chuỗi thời gian ban đầuXtXt1Xtnhập mô tả hình ảnh ở đây

Câu hỏi của tôi: Tại sao thuật toán của tôi bị hỏng khi tôi sử dụng nó trên chuỗi thời gian khác nhau? Một cách tốt để đối phó với trôi dạt trong chuỗi thời gian là gì?

Đây là mã đầy đủ cho mô hình của tôi:

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)

from keras.layers.core import Dense, Activation, Dropout
from keras.layers.recurrent import LSTM
from keras.models import Sequential


# The LSTM model
my_model = Sequential()

my_model.add(LSTM(input_shape=(1, 1), units=50, return_sequences=True))
my_model.add(Dropout(0.2))

my_model.add(LSTM(units=100, return_sequences=False))
my_model.add(Dropout(0.2))

my_model.add(Dense(units=1))
my_model.add(Activation('linear'))

my_model.compile(loss='mse', optimizer='rmsprop')


def my_prediction(x, model, normalize=False, difference=False):
    # Plot the process x
    plt.figure(figsize=(15, 7))
    plt.subplot(121)
    plt.plot(x)
    plt.title('Original data')

    n = len(x)
    thrs = int(0.8 * n)    # Train-test split
    # Save starting values for test set to reverse differencing
    x_test_0 = x[thrs + 1]
    # Save minimum and maximum on test set to reverse normalization
    x_min = min(x[:thrs])  
    x_max = max(x[:thrs])

    if difference:
        x = np.diff(x)   # Take difference to remove drift
    if normalize:
        x = (2*x - x_min - x_max) / (x_max - x_min)   # Normalize to [-1, 1]

    # Split into train and test set. The model will be trained on one-step-ahead predictions.
    x_train, y_train, x_test, y_test = x[0:(thrs-1)], x[1:thrs], x[thrs:(n-1)], x[(thrs+1):n]

    x_train, x_test = x_train.reshape(-1, 1, 1), x_test.reshape(-1, 1, 1)
    y_train, y_test = y_train.reshape(-1, 1), y_test.reshape(-1, 1)

    # Fit the model
    model.fit(x_train, y_train, batch_size=200, epochs=10, validation_split=0.05, verbose=0)

    # Predict the test set
    y_pred = model.predict(x_test)

    # Reverse differencing and normalization
    if normalize:
        y_pred = ((x_max - x_min) * y_pred + x_max + x_min) / 2
        y_test = ((x_max - x_min) * y_test + x_max + x_min) / 2  
    if difference:
        y_pred = x_test_0 + np.cumsum(y_pred)
        y_test = x_test_0 + np.cumsum(y_test)

    # Plot estimation
    plt.subplot(122)
    plt.plot(y_pred[-100:], label='One-step-ahead-predictions')
    plt.plot(y_test[-100:], label='Actual data')
    plt.title('Prediction on test set')
    plt.legend()
    plt.show()

# Make plots
x = my_process(10000, 0.99, drift=0, displacement=0)
my_prediction(x, my_model, normalize=False, difference=False)

x = my_process(10000, 0.99, drift=0, displacement=10)
my_prediction(x, my_model, normalize=False, difference=False)

x = my_process(10000, 0.99, drift=0, displacement=10)
my_prediction(x, my_model, normalize=True, difference=False)

x = my_process(10000, 0.99, drift=0.00001, displacement=10)
my_prediction(x, my_model, normalize=True, difference=False)

x = my_process(10000, 0.99, drift=0.00001, displacement=10)
my_prediction(x, my_model, normalize=True, difference=True)

Câu trả lời:


1

Nhìn lại quá trình tự tương quan của bạn:

    def my_process(n, p, drift=0, displacement=0):
        x = np.zeros(n)

        for i in range(1, n):
            x[i] = drift * i + p * x[i-1] + (1-p) * np.random.randn()
    return x + displacement

Có vẻ như mọi thứ đang bị phá vỡ khi giá trị của displacementcao. Điều này có ý nghĩa, như bạn nói, bởi vì các LSTM cần dữ liệu chuẩn hóa.

Các drifttham số là một chút khác nhau. Khi bao gồm một lượng nhỏ độ lệch, vì plớn, lượng độ trôi tương tự như lượng nhiễu ngẫu nhiên được thêm vào thông qua np.random.randn().

Trong các âm mưu cho drift=0.00001, displacement=10, có vẻ như các dự đoán sẽ ổn ngoại trừ thay đổi y. Bởi vì điều này, tôi nghĩ rằng gốc rễ của vấn đề vẫn nằm trong displacementtham số chứ không phải drifttham số. Sự khác biệt, như đã được thực hiện, sẽ không giúp với displacementtham số; thay vào đó, nó sửa cho trôi.

Tôi không thể nói từ mã của bạn, nhưng có vẻ như có lẽ displacementkhông được tính đến model.predict. Đó là dự đoán tốt nhất của tôi.


displacement(Xt+1+c)-(Xt+c)= =Xt+1-Xt

1
Xin chào lần nữa, được rồi, điểm tốt! Hừm. Tôi nghĩ những gì bạn gọi là 'trôi', tôi sẽ gọi là trung bình di động (tôi hy vọng). Bạn có thể thử đưa một số loại đồng biến vào mô hình của mình để tính trung bình di chuyển. Lý tưởng nhất là một LSTM sẽ tự mình khám phá ra điều đó, nhưng ở đây dường như bị mắc kẹt.
Số liệu thống kê

Tôi hơi lo ngại về điều này vì tôi muốn áp dụng LSTM vào giá cổ phiếu. Họ có một trung bình trôi / di chuyển, và cách tiếp cận tiêu chuẩn (ít nhất là trong thống kê) là áp dụng sự khác biệt, tức là sử dụng lợi nhuận thay vì giá cả. Vì vậy, tôi muốn hiểu tại sao điều này dường như không hoạt động (ngay cả đối với một mô hình đơn giản như vậy) với các LSTM.
Elias Stroundle

1
Bạn đã theo dõi các lần chuyển tiếp và lùi với các giá trị ban đầu của bạn so với các giá trị khác biệt chưa? Tôi tự hỏi nếu có một số loại vấn đề độ dốc biến mất xảy ra với các giá trị khác nhau. LSTM tất nhiên mạnh mẽ hơn cho vấn đề này, nhưng chúng có thể gặp phải các loại vấn đề này, vì vậy nó có thể đáng xem.
Số liệu thống kê

1

Khi bạn chọn x_minx_max, bạn đang chọn nó từ 1:thresholdmột mình. Vì chuỗi của bạn đang tăng đơn điệu (gần như ..), các giá trị thử nghiệm là tất cả các giá trị> 1. Điều này, mô hình LSTM chưa bao giờ thấy trong quá trình đào tạo.

Có phải đó là lý do tại sao bạn đang nhìn thấy những gì bạn đang thấy?

Bạn có thể thử tương tự với x_minx_maxđến từ toàn bộ dữ liệu thay thế?


Điều này có thể làm việc trong ví dụ đồ chơi của tôi; nhưng nếu tôi sử dụng các LSTM để thực sự dự đoán điều gì đó, thì điều này sẽ đòi hỏi phải nhìn vào tương lai.
Elias Stroundle 23/07/18
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.