сигнализировать о педиксии используя RNN и Keras - PullRequest
1 голос
/ 19 марта 2019

Я пытаюсь воспроизвести хорошую работу здесь и адаптировать ее так, чтобы она считывала реальные данные из файла. Я начал с генерации случайных сигналов (вместо методов генерации, представленных в приведенной выше ссылке). Unfortoutanyl, я не мог генерировать правильные сигналы, которые может принять модель.

вот код:

import numpy as np
import keras
from keras.utils import plot_model
input_sequence_length = 15 # Length of the sequence used by the encoder
target_sequence_length = 15 # Length of the sequence predicted by the decoder
import random

def getModel():# Define an input sequence.

    learning_rate = 0.01
    num_input_features = 1
    lambda_regulariser = 0.000001 # Will not be used if regulariser is None
    regulariser = None # Possible regulariser: keras.regularizers.l2(lambda_regulariser)
    layers = [35, 35]
    num_output_features=1
    decay = 0 # Learning rate decay
    loss = "mse" # Other loss functions are possible, see Keras documentation.



    optimiser = keras.optimizers.Adam(lr=learning_rate, decay=decay) # Other possible optimiser "sgd" (Stochastic Gradient Descent)


    encoder_inputs = keras.layers.Input(shape=(None, num_input_features))

    # Create a list of RNN Cells, these are then concatenated into a single layer
    # with the RNN layer.
    encoder_cells = []
    for hidden_neurons in layers:
        encoder_cells.append(keras.layers.GRUCell(hidden_neurons, kernel_regularizer=regulariser,recurrent_regularizer=regulariser,bias_regularizer=regulariser))

    encoder = keras.layers.RNN(encoder_cells, return_state=True)
    encoder_outputs_and_states = encoder(encoder_inputs)

    # Discard encoder outputs and only keep the states.
    # The outputs are of no interest to us, the encoder's
    # job is to create a state describing the input sequence.
    encoder_states = encoder_outputs_and_states[1:]

    # The decoder input will be set to zero (see random_sine function of the utils module).
    # Do not worry about the input size being 1, I will explain that in the next cell.
    decoder_inputs = keras.layers.Input(shape=(None, 1))

    decoder_cells = []
    for hidden_neurons in layers:
        decoder_cells.append(keras.layers.GRUCell(hidden_neurons,
                                                  kernel_regularizer=regulariser,
                                                  recurrent_regularizer=regulariser,
                                                  bias_regularizer=regulariser))

    decoder = keras.layers.RNN(decoder_cells, return_sequences=True, return_state=True)

    # Set the initial state of the decoder to be the ouput state of the encoder.
    # This is the fundamental part of the encoder-decoder.
    decoder_outputs_and_states = decoder(decoder_inputs, initial_state=encoder_states)

    # Only select the output of the decoder (not the states)
    decoder_outputs = decoder_outputs_and_states[0]

    # Apply a dense layer with linear activation to set output to correct dimension
    # and scale (tanh is default activation for GRU in Keras, our output sine function can be larger then 1)
    decoder_dense = keras.layers.Dense(num_output_features,
                                       activation='linear',
                                       kernel_regularizer=regulariser,
                                       bias_regularizer=regulariser)

    decoder_outputs = decoder_dense(decoder_outputs)

    # Create a model using the functional API provided by Keras.
    # The functional API is great, it gives an amazing amount of freedom in architecture of your NN.
    # A read worth your time: https://keras.io/getting-started/functional-api-guide/ 
    model = keras.models.Model(inputs=[encoder_inputs, decoder_inputs], outputs=decoder_outputs)
    model.compile(optimizer=optimiser, loss=loss)
    print(model.summary())
    return model

def getXY():

    X, y = list(), list()
    for _ in range(100):
        x = [random.random() for _ in range(input_sequence_length)]
        y = [random.random() for _ in range(target_sequence_length)]
        X.append([x,[0 for _ in range(input_sequence_length)]])
        y.append(y)
    return np.array(X), np.array(y)

X,y = getXY()
print(X,y)
model = getModel()
model.fit(X,y)

Полученное сообщение об ошибке:

ValueError: Ошибка при проверке ввода модели: список массивов Numpy то, что вы передаете своей модели, не соответствует ожидаемому размеру. Ожидается увидеть 2 массива (ов), но вместо этого получил следующий список 1 Массивы:

какова правильная форма входных данных для модели?

1 Ответ

0 голосов
/ 19 марта 2019

Если вы внимательно прочитаете источник вашего вдохновения , вы обнаружите, что он говорит о данных "decoder_input".

Он говорит о технике "принуждения учителя", которая состоит изподача декодера с некоторыми задержанными данными.Но также говорит, что это не очень хорошо работает в его случае, поэтому он устанавливает исходное состояние декодера в группу 0, так как эта строка показывает :

decoder_input = np.zeros((decoder_output.shape[0], decoder_output.shape[1], 1))

в егоВ дизайне авто-кодера они представлены двумя отдельными моделями, которые имеют разные входы, затем он связывает их со статистикой RNN друг от друга.

Я вижу, что вы пытались сделать то же самое, но вы добавили np.array([x_encoder, x_decoder]), где вы должны были сделать [np.array(x_encoder), np.array(x_decoder)].Каждый вход в сеть должен быть массивом numpy, который вы помещаете в список входов, а не один большой массив numpy.

Я также нашел некоторые опечатки в вашем коде, вы добавляете y к себе, где вместо этого вы должны создать Y переменную

def getXY():

    X_encoder, X_decoder, Y = list(), list(), list()
    for _ in range(100):
        x_encoder = [random.random() for _ in range(input_sequence_length)]
        # the decoder input is a sequence of 0's same length as target seq
        x_decoder = [0]*len(target_sequence_length)
        y = [random.random() for _ in range(target_sequence_length)]
        X_encoder.append(x_encoder)
        # Not really optimal but will work
        X_decoder.append(x_decoder)
        Y.append(y)
    return [np.array(X_encoder), np.array(X_decoder], np.array(Y)

теперь, когда вы делаете:

X, Y = getXY()

вы получаете X, представляющий собой список из 2-х числовых массивов (как запрашивает ваша модель), и Y, представляющий собой единый массив-пустышку.

Надеюсь, это поможет

EDIT

Действительно, в коде, который генерирует набор данных, вы можете видеть, что они создают 3 np массива для ввода.Для RNN нужны 3-мерные входные данные :-)

Следующий код должен решить проблему формы:

def getXY():

    X_encoder, X_decoder, Y = list(), list(), list()
    for _ in range(100):
        x_encoder = [random.random() for _ in range(input_sequence_length)]
        # the decoder input is a sequence of 0's same length as target seq
        x_decoder = [0]*len(target_sequence_length)
        y = [random.random() for _ in range(target_sequence_length)]
        X_encoder.append(x_encoder)
        # Not really optimal but will work
        X_decoder.append(x_decoder)
        Y.append(y)

        # Make them as numpy arrays
        X_encoder = np.array(X_encoder)
        X_decoder = np.array(X_decoder)
        Y = np.array(Y)

        # Make them 3 dimensional arrays (with third dimension being of size 1) like the 1d vector: [1,2] can become 2 de vector [[1,2]]
        X_encoder = np.expand_dims(X_encoder, axis=2)
        X_decoder = np.expand_dims(X_decoder, axis=2)
        Y = np.expand_dims(Y, axis=2)

    return [X_encoder, X_decoder], Y
...