Keras LSTM với chuỗi thời gian 1D


10

Tôi đang học cách sử dụng Keras và tôi đã thành công hợp lý với bộ dữ liệu được dán nhãn của mình bằng cách sử dụng các ví dụ trên Deep Learning for Python của Chollet . Tập dữ liệu là ~ 1000 Chuỗi thời gian với độ dài 3125 với 3 lớp tiềm năng.

Tôi muốn vượt xa các lớp Mật độ cơ bản mang lại cho tôi tỷ lệ dự đoán khoảng 70% và cuốn sách tiếp tục thảo luận về các lớp LSTM và RNN.

Tất cả các ví dụ dường như sử dụng bộ dữ liệu với nhiều tính năng cho từng thời gian và tôi đang cố gắng tìm ra cách triển khai dữ liệu của mình.

Ví dụ: nếu tôi có Dòng thời gian 1000x3125, làm cách nào để cung cấp thứ đó vào thứ gì đó như lớp SimpleRNN hoặc LSTM? Tôi có thiếu một số kiến ​​thức cơ bản về những gì các lớp này làm không?

Mã hiện tại:

import pandas as pd
import numpy as np
import os
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM, Dropout, SimpleRNN, Embedding, Reshape
from keras.utils import to_categorical
from keras import regularizers
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

def readData():
    # Get labels from the labels.txt file
    labels = pd.read_csv('labels.txt', header = None)
    labels = labels.values
    labels = labels-1
    print('One Hot Encoding Data...')
    labels = to_categorical(labels)

    data = pd.read_csv('ts.txt', header = None)

    return data, labels

print('Reading data...')
data, labels = readData()

print('Splitting Data')
data_train, data_test, labels_train, labels_test = train_test_split(data, labels)

print('Building Model...')
#Create model
model = Sequential()
## LSTM / RNN goes here ##
model.add(Dense(3, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

print('Training NN...')
history = model.fit(data_train, labels_train, epochs=1000, batch_size=50,
    validation_split=0.25,verbose=2)

results = model.evaluate(data_test, labels_test)

predictions = model.predict(data_test)

print(predictions[0].shape)
print(np.sum(predictions[0]))
print(np.argmax(predictions[0]))

print(results)

acc = history.history['acc']
val_acc = history.history['val_acc']
epochs = range(1, len(acc) + 1)

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and Validation Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()

Câu trả lời:


10

Các lớp LSTM yêu cầu dữ liệu có hình dạng khác nhau.

Từ mô tả của bạn, tôi hiểu bộ dữ liệu bắt đầu có 3125 hàng và 1000 cột, trong đó mỗi hàng là một bước thời gian. Biến mục tiêu sau đó sẽ có 3125 hàng và 1 cột, trong đó mỗi giá trị có thể là một trong ba giá trị có thể. Vì vậy, có vẻ như bạn đang làm một vấn đề phân loại. Để kiểm tra điều này trong mã, tôi sẽ làm:

>>> X.shape
(3125, 1000)

>>> y.shape
(1000,)

Lớp LSTM yêu cầu mỗi mẫu đơn phải bao gồm một 'khối' thời gian. Giả sử bạn muốn có một khối 100 bước thời gian. Điều này có nghĩa X[0:100]là một mẫu đầu vào duy nhất, tương ứng với biến mục tiêu tại y[100]. điều này có nghĩa là kích thước cửa sổ của bạn (còn gọi là số bước thời gian hoặc số độ trễ) bằng 100. Như đã nêu ở trên, bạn có 3125 mẫu, vì vậy N = 3125. Để tạo khối đầu tiên, chúng tôi không may phải loại bỏ 100 mẫu đầu tiên y, vì chúng tôi không thể tạo toàn bộ khối 100 từ dữ liệu có sẵn (cuối cùng chúng tôi sẽ cần các điểm dữ liệu trước đó X[0]).

Với tất cả điều này, một LSTM yêu cầu bạn cung cấp các lô hình dạng (N - window_size, window_size, num_features), dịch thành (3125 - 100, 100, 1000)== (3025, 100, 1000).

Tạo các khối thời gian này là một chút rắc rối, nhưng tạo một chức năng tốt một lần, sau đó lưu nó :)

Còn nhiều việc phải làm, có lẽ xem xét sâu hơn các ví dụ về lời giải thích của tôi ở trên đây ... hoặc đọc tài liệu LSTM , (hoặc tốt hơn là mã nguồn! ).

Mô hình cuối cùng sau đó sẽ đủ đơn giản (dựa trên mã của bạn):

#Create model
model = Sequential()
model.add(LSTM(units=32, activation='relu',
               input_shape=(100, 1000))    # the batch size is neglected!
model.add(Dense(3, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam',
              metrics=['accuracy'])

Có một cái nhìn vào các tài liệu liên quan đến hình dạng đầu vào cho Sequentialmô hình . Về cơ bản nó nói rằng chúng ta không cần chỉ định số lượng lô trong input_shape. Nó có thể được thực hiện với ví dụ batch_size=50, nếu bạn yêu cầu nó phải là một số cố định.

Tôi biết input_shapeđối số không có trong tài liệu cho LSTM, nhưng bản thân lớp kế thừa từ RNNđó, từ đó thừa hưởng từ Layer- vì vậy nó sẽ có thể sử dụng thông tin bạn cung cấp.

Một mẹo cuối cùng: nếu bạn có kế hoạch thêm một số lớp LSTM ('xếp chồng' chúng), thì bạn sẽ cần thêm một đối số nữa cho tất cả trừ lớp cuối cùng LSTM , cụ thể là , return_sequences=True.


Cảm ơn bạn đã trả lời toàn diện Dexter (!). Liên quan đến nhận xét của bạn về kích thước lô, liệu batch_size được chỉ định trong đối số model.fit có phải là một tham số siêu khác so với tạo lô tùy chỉnh của riêng tôi không? Tôi đã quản lý để có được mã của mình ít nhất là chạy bằng cách định hình lại dữ liệu của mình từ ma trận 1000x3125 thành ma trận 3D bằng cách sử dụng data = np.reshape (dữ liệu, (1000,1,3125)). Điều này cho phép tôi chạy LSTM với input_shape (1.3125) nhưng một lần nữa, tôi không thực sự chắc chắn những gì tôi đang làm. Một lần nữa, cảm ơn bạn rất nhiều vì đã trả lời. Tôi sẽ xem xét các liên kết bạn cung cấp và nghiên cứu thêm câu trả lời của bạn.
dùng1147964

Không có gì! Có, bạn đã nhận nó, nếu bạn bỏ qua batch_sizekhi xác định mô hình, nó sẽ được lấy từ cùng một đối số bên trong model.fit(). Bạn nên định hình lại để có được (3025, 100, 1000), có nghĩa là 3025 lô, mỗi đợt 100 (hàng) dấu thời gian và 1000 (cột) biến. np.reshapeĐáng buồn là việc sử dụng sẽ không hiệu quả cho việc này (bạn sẽ gặp lỗi), vì thực tế là bạn sẽ có dữ liệu chồng chéo ... hình dạng cuối cùng có nhiều dữ liệu hơn đầu vào. 3025x100x1000> 3125x1000 - np.reshapekhông như thế vì nó mơ hồ. Tôi đề nghị chỉ cần lặp qua tập dữ liệu, 1 vòng lặp = 1 mẫu.
n1k31t4

Tôi nghĩ rằng tôi có một chút bối rối ở đây và có thể là do tôi có thể đã vô tình thực hiện quy trình xử lý. Tôi sẽ sử dụng các giá trị cụ thể ở đây. Tôi đã lấy mẫu 3 phép đo khác nhau ở 6,25 kHz trong khoảng 3 phút, kết quả là chuỗi 3 thời gian dài 1093750. Điều này tạo ra ma trận 3x1093750. Sau đó, tôi phân đoạn mỗi TS thành gia số 0,5 giây, dẫn đến ma trận 1050x3125. Về mặt kỹ thuật tôi có thể tái cấu trúc nó thành ma trận 3D với kích thước 3x350x3125. Điều này mang lại cho tôi "lô" dài 350, 0,5 giây. Việc định hình lại của bạn dường như tạo ra nhiều giá trị hơn Cảm ơn bạn đã phản hồi lại. Xin lỗi
dùng1147964

Chỉ cần thêm, đọc liên kết đầu tiên bạn đăng lên khiến tôi nghĩ rằng tôi đang định hình lại mọi thứ một cách chính xác. Xin lỗi nếu tôi thiếu thứ gì đó rõ ràng nhưng ở đây họ bắt đầu với TS có độ dài 5000 và biến nó thành ma trận 3D có kích thước [1 25 200].
dùng1147964

So với phương pháp trong liên kết của bạn, cách của tôi sẽ tạo ra nhiều mẫu hơn. Điều này là do tôi đang sử dụng một loại cửa sổ 'lăn'. Có một cái nhìn vào mô tả này . Họ không sử dụng cửa sổ cuộn . Làm 3 phút thành các khối 350x0,5 giây là ổn (có thể không cần thiết - bạn có thường dự đoán không?), Mỗi khối nên là 3x3125. "Tôi có thể cấu trúc lại nó thành ma trận 3D với kích thước 3x350x3125" - điều này nghe có vẻ tốt hơn, nhưng sau khi thực hiện các phân tách tôi mong đợi 350x3x3125 (350 khối 3x3125). Mỗi khối này sau đó có thể được xử lý như tôi mô tả.
n1k31t4
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.