Всегда один и тот же выход для автоэнкодера tenorflow - PullRequest
0 голосов
/ 07 ноября 2018

В данный момент я пытаюсь построить автоэнкодер для данных временных рядов в тензорном потоке. У меня есть почти 500 дней данных, где каждый день имеет 24 точки данных. Поскольку это моя первая попытка, моя архитектура очень проста. После моего ввода размера 24 скрытые слои имеют размер: 10; 3; 10 с выводом снова 24. Я нормализовал данные (точки данных находятся в диапазоне [-0.5; 0.5]), использую функцию активации сигмовидной кишки и RMSPropOptimizer.

После тренировки (функция потери на рисунке) выходные данные одинаковы для всех временных данных, которые я передаю в сеть. Кто-то знает, в чем причина? Возможно ли, что мой набор данных является проблемой (код ниже)?

loss function of training

class TimeDataset:
def __init__(self,data):
    self._index_in_epoch = 0
    self._epochs_completed = 0
    self._data = data
    self._num_examples = data.shape[0]
    pass


@property
def data(self):
    return self._data

def next_batch(self, batch_size, shuffle=True):
    start = self._index_in_epoch

    # first call
    if start == 0 and self._epochs_completed == 0:
        idx = np.arange(0, self._num_examples)  # get all possible indexes
        np.random.shuffle(idx)  # shuffle indexe
        self._data = self.data[idx]  # get list of `num` random samples

    if start + batch_size > self._num_examples:
        # not enough samples left -> go to the next batch
        self._epochs_completed += 1
        rest_num_examples = self._num_examples - start
        data_rest_part = self.data[start:self._num_examples]
        idx0 = np.arange(0, self._num_examples)  # get all possible indexes
        np.random.shuffle(idx0)  # shuffle indexes
        self._data = self.data[idx0]  # get list of `num` random samples

        start = 0
        self._index_in_epoch = batch_size - rest_num_examples #avoid the case where the #sample != integar times of batch_size
        end =  self._index_in_epoch  
        data_new_part =  self._data[start:end]  
        return np.concatenate((data_rest_part, data_new_part), axis=0)
    else:
        # get next batch
        self._index_in_epoch += batch_size
        end = self._index_in_epoch
        return self._data[start:end]

* edit: вот несколько примеров вывода (красный оригинал, синий реконструированный): enter image description here

** edit: Я только что видел пример с авто-кодером с более сложной функцией luss, чем у меня. Кто-то знает, достаточно ли функции потерь self.loss = tf.reduce_mean(tf.pow(self.X - self.decoded, 2))?

*** редактировать: еще немного кода, чтобы описать мое обучение Это мой класс автоэнкодера:

class AutoEncoder():
def __init__(self):
    # Training Parameters
    self.learning_rate = 0.005
    self.alpha = 0.5

    # Network Parameters
    self.num_input = 24 # one day as input
    self.num_hidden_1 = 10 # 2nd layer num features
    self.num_hidden_2 = 3 # 2nd layer num features (the latent dim)

    self.X = tf.placeholder("float", [None, self.num_input])

    self.weights = {
        'encoder_h1': tf.Variable(tf.random_normal([self.num_input, self.num_hidden_1])),
        'encoder_h2': tf.Variable(tf.random_normal([self.num_hidden_1, self.num_hidden_2])),
        'decoder_h1': tf.Variable(tf.random_normal([self.num_hidden_2, self.num_hidden_1])),
        'decoder_h2': tf.Variable(tf.random_normal([self.num_hidden_1, self.num_input])),
    }
    self.biases = {
        'encoder_b1': tf.Variable(tf.random_normal([self.num_hidden_1])),
        'encoder_b2': tf.Variable(tf.random_normal([self.num_hidden_2])),
        'decoder_b1': tf.Variable(tf.random_normal([self.num_hidden_1])),
        'decoder_b2': tf.Variable(tf.random_normal([self.num_input])),
    }    

    self.encoded = self.encoder(self.X)
    self.decoded = self.decoder(self.encoded)

    # Define loss and optimizer, minimize the squared error
    self.loss = tf.reduce_mean(tf.pow(self.X - self.decoded, 2))

    self.optimizer = tf.train.RMSPropOptimizer(self.learning_rate).minimize(self.loss)

def encoder(self, x):
    # sigmoid, tanh, relu
    en_layer_1 = tf.nn.sigmoid (tf.add(tf.matmul(x, self.weights['encoder_h1']),
                                   self.biases['encoder_b1']))

    en_layer_2 = tf.nn.sigmoid (tf.add(tf.matmul(en_layer_1, self.weights['encoder_h2']),
                                   self.biases['encoder_b2']))

    return en_layer_2

def decoder(self, x):
    de_layer_1 = tf.nn.sigmoid (tf.add(tf.matmul(x, self.weights['decoder_h1']),
                                   self.biases['decoder_b1']))

    de_layer_2 = tf.nn.sigmoid (tf.add(tf.matmul(de_layer_1, self.weights['decoder_h2']),
                                   self.biases['decoder_b2']))

    return de_layer_2

и вот как я тренирую свою сеть (входные данные имеют форму (число_дней, 24)):

model = autoencoder.AutoEncoder()

num_epochs = 3
batch_size = 50
num_batches = 300

display_batch = 50
examples_to_show = 16

loss_values = []

with tf.Session() as sess:

sess.run(tf.global_variables_initializer())

#training
for e in range(1, num_epochs+1):
    print('starting epoch {}'.format(e))
    for b in range(num_batches):
        # get next batch of data
        batch_x = dataset.next_batch(batch_size)

        # Run optimization op (backprop) and cost op (to get loss value)
        l = sess.run([model.loss], feed_dict={model.X: batch_x})
        sess.run(model.optimizer, feed_dict={model.X: batch_x})            

        # Display logs
        if b % display_batch == 0:
            print('Epoch {}: Batch ({}) Loss: {}'.format(e, b, l))
            loss_values.append(l)


# testing
test_data = dataset.next_batch(batch_size)
decoded_test_data = sess.run(model.decoded, feed_dict={model.X: test_data})

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Выход сигмовидной формы равен 0, поэтому он не может воспроизвести ваши данные ниже 0.

Если вы хотите использовать сигмоидальный вывод, то измените масштаб ваших данных между] 0; 1 [(исключая 0 и 1).

0 голосов
/ 07 ноября 2018

Просто предложение, у меня были некоторые проблемы с автоэнкодерами, использующими функцию sigmoid.

Я переключился на tanh или relu, и это улучшило результаты. С помощью автоматического кодера он в основном учится воссоздавать выходные данные с помощью кодирования и декодирования. Если вы имеете в виду, что это то же самое, что и ввод, то вы получаете то, что хотите. Он изучил набор данных.

В конечном итоге вы можете сравнить, просмотрев среднеквадратичную ошибку между входом и выходом и посмотреть, точно ли она одинакова. Если вы имеете в виду, что выходные данные одинаковы независимо от входных данных, это не то, с чем я столкнулся. Я предполагаю, что если ваш вклад не будет сильно меняться изо дня в день, то я могу представить, что это окажет какое-то влияние. Вы ищете аномалии?

Кроме того, если у вас есть временной ряд для обучения, я бы не стал перемешивать данные в этом конкретном случае. Если временной порядок значительный, вы вносите утечку данных (в основном, вводя будущие данные в обучающий набор) в зависимости от того, чего вы пытаетесь достичь.

Ах, я изначально не видел ваше сообщение с результатами графика .. спасибо за добавление.

...