Keras中具有可变序列长度的序列到序列分类

时间:2018-11-14 13:54:49

标签: python keras lstm

我想在TensorFlow / Keras中训练LSTM或GRU网络,以根据运动传感器(加速度计和陀螺仪)的输入连续识别用户是否在行走。我有50个输入序列,长度从581到5629个时间步长不等,还有6个特征和50个布尔值的相应输出序列。我的问题是我不知道如何将训练数据输入到fit()方法。

我大概知道我需要做什么:我想训练5批次,每批次10个序列,对于每一个批次,我必须填充除最长序列之外的所有序列,以便所有10个序列具有相同的长度并应用遮罩。我只是不知道如何建立数据结构。我知道我可以制作一个大小为(50,5629,6)的大3D张量并且可以工作,但是它的速度很慢,所以我真的想使每个批次的序列长度尽可能小。

这是代码中的问题:

import tensorflow as tf
import numpy as np

# Load data from file
x_list, y_list = loadSequences("train.csv")

# x_list is now a list of arrays (n,6) of float64, where n is the timesteps
# and 6 is the number of features, sorted by increasing sequence lengths.
# y_list is a list of arrays (n,1) of Boolean.

x_train = # WHAT DO I WRITE HERE?
y_train = # AND HERE?

model = tf.keras.models.Sequential([
            tf.keras.layers.Masking(),
            tf.keras.layers.LSTM(32, return_sequences=True),
            tf.keras.layers.Dense(2, activation=tf.nn.softmax)
        ])
model.compile(optimizer='adam',
            loss='sparse_categorical_crossentropy',
            metrics=['accuracy'])
model.fit(x_train, y_train, batch_size=10, epochs=100)

2 个答案:

答案 0 :(得分:0)

您可以做这样的事情

使用生成器函数查看此链接fit_generator,查找fit_generator方法。

def data_generater(batch_size):
print("reading data")
training_file = 'data_location', 'r')

# assuming data is in json format so feels free to change accordingly

training_set = json.loads(training_file.read())
training_file.close()

batch_i = 0  # Counter inside the current batch vector
batch_x = []  # The current batch's x data
batch_y = []  # The current batch's y data

while True:

    for obj in training_set:
        batch_x.append(your input sequences one by one)
        if obj['val'] == True:
            batch_y.append([1])
        elif obj['val'] == False:
            batch_y.append([0])
        batch_i += 1

        if batch_i == batch_size:
            # Ready to yield the batch
            # pad input to max length in the batch
            batch_x = pad_txt_data(batch_x)
            yield batch_x, np.array(batch_y)
            batch_x = []
            batch_y = []
            batch_i = 0

def pad_txt_data(arr):
# expecting arr to be in the shape of (10, m, 6)
paded_arr = []
prefered_len = len(max(arr, key=len))

# Now pad all your sequences to preferred length in the batch(arr)

return np.array(paded_arr)

和模型

model = keras.Sequential()
model.add(keras.layers.Masking(mask_value=0., input_shape=(None,6)))
model.add(keras.layers.LSTM(32))
model.add(keras.layers.Dense(1, activation="softmax"))
model.compile(optimizer="Adam", loss='categorical_crossentropy', metrics=['categorical_accuracy'])
model.fit_generator(data_generater(10), steps_per_epoch=5, epochs=10)

batch_size,steps_per_epoch,epoch可以不同。 通常

steps_per_epoch = (number of sequences/batch_size)

注意:阅读您的描述的表格您的任务似乎是二进制分类问题,而不是序列到序列的问题。顺序翻译的一个很好的例子是语言翻译。只是谷歌周围你会发现我的意思。

如果您真的想了解训练时间的差异,我建议使用GPU(如果有)和CuDNNLSTM

答案 1 :(得分:0)

万一它对某人有所帮助,这就是我最终实现解决方案的方式:

import tensorflow as tf
import numpy as np

# Load data from file
x_list, y_list = loadSequences("train.csv")

# x_list is now a list of arrays (m,n) of float64, where m is the timesteps
# and n is the number of features.
# y_list is a list of arrays (m,1) of Boolean.
assert len(x_list) == len(y_list)
num_sequences = len(x_list)
num_features = len(x_list[0][0])
batch_size = 10
batches_per_epoch = 5
assert batch_size * batches_per_epoch == num_sequences

def train_generator():
    # Sort by length so the number of timesteps in each batch is minimized
    x_list.sort(key=len)
    y_list.sort(key=len)
    # Generate batches
    while True:
        for b in range(batches_per_epoch):
            longest_index = (b + 1) * batch_size - 1
            timesteps = len(x_list[longest_index])
            x_train = np.zeros((batch_size, timesteps, num_features))
            y_train = np.zeros((batch_size, timesteps, 1))
            for i in range(batch_size):
                li = b * batch_size + i
                x_train[i, 0:len(x_list[li]), :] = x_list[li]
                y_train[i, 0:len(y_list[li]), 0] = y_list[li]
            yield x_train, y_train

model = tf.keras.models.Sequential([
            tf.keras.layers.Masking(mask_value=0., input_shape=(None,num_features)),
            tf.keras.layers.LSTM(32, return_sequences=True),
            tf.keras.layers.Dense(2, activation=tf.nn.softmax)
        ])
model.compile(optimizer='adam',
            loss='sparse_categorical_crossentropy',
            metrics=['accuracy'])
model.fit_generator(train_generator(), steps_per_epoch=batches_per_epoch, epochs=100)