Нейронная сеть TensorFlow LSTM: функция потерь для временной ошибки - PullRequest
2 голосов
/ 21 марта 2019

Допустим, мы пытаемся предсказать будущие землетрясения на основе предыдущих землетрясений.Визуализация части набора данных, содержащей последовательности землетрясений, может выглядеть следующим образом (особенности слева, метки справа, x = месяц, y = магнитуда землетрясения): features - labels Вы и я можем видетьмодель здесь такова, что когда два землетрясения магнитудой 5 последовательно, за ними следует землетрясение магнитудой 8, а затем землетрясение магнитудой 4.Эти землетрясения могут возникать с периодом 3-5 месяцев, но магнитуды при них одинаковы.

Обучение LSTM на этих данных с помощью функции среднеквадратичных потерь дает следующие прогнозы (пунктирная линия)строка): predictions Это сделано точно так, как мы просили, оно научилось предсказывать среднее значение для временного шага.Тем не менее, это плохой прогноз с точки зрения того, для чего предназначена модель.

Для вас или для меня, смотря на данные, мы можем предположить, что первое предсказанное землетрясение имеет магнитуду 8, и с учетомдисперсия временного шага Нашим лучшим прогнозом было бы то, что это происходит на временном шаге 8. По сути, мы будем делать среднюю ошибку на временной оси, а также на оси значений.

Какая функция потерь можетбыть использован для этого в TensorFlow?

Я искал, но только находил материал, относящийся к ошибке за промежуток времени.Я начал пробовать несколько методов, которые, по моему мнению, могли бы дать лучшие результаты, такие как tf.sort на метках и предсказаниях, перед выполнением среднеквадратичной ошибки, а затем также tf.argsort на метках и предсказаниях и делать среднеквадратичную ошибку для них, чтобы получить временнуюошибка, но argsort не имеет градиентов для обратного распространения, поэтому начал пытаться писать собственные градиенты, что кажется излишним, когда решение уже должно существовать?(ps я чувствую себя комфортно с TensorFlow, но я не эксперт).

Если кто-то может указать мне правильное направление, я был бы чрезвычайно благодарен!

Вот код, который демонстрируетпример выше:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

features = np.array([[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                     [0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0], 
                     [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                     [0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0], 
                     [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                     [0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0]]).reshape(6, 7, 1).astype(np.float32)
labels = np.array([[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                   [0.8, 0.0, 0.0, 0.4, 0.0, 0.0, 0.0],
                   [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                   [0.0, 0.0, 0.8, 0.0, 0.0, 0.4, 0.0],
                   [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                   [0.0, 0.8, 0.0, 0.0, 0.4, 0.0, 0.0]]).reshape(6, 7, 1).astype(np.float32)

plt.figure(figsize=(20, 2))
plt.plot(np.concatenate((features[:, :, 0].T, labels[:, :, 0].T)) * 10)
plt.axvline(features.shape[1]-1)
plt.title('<- Features vs. Labels ->')
plt.xlabel('Month')
plt.ylabel('Magnitude')
plt.show()

def train_input_fn(features, labels):
    dataset = tf.data.Dataset.from_tensor_slices((features, labels))
    return dataset.shuffle(len(features)).repeat().batch(len(features))
def predict_input_fn(features):
    dataset = tf.data.Dataset.from_tensor_slices(features)
    return dataset.batch(len(features))

def model_fn(features, labels, mode):
    lstm = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(units=100, return_sequences=True, input_shape=(7, 1)))(features)
    outputs = tf.keras.layers.Dense(units=1, activation='linear')(lstm)

    if mode == tf.estimator.ModeKeys.PREDICT:
        return tf.estimator.EstimatorSpec(mode, predictions=outputs)

    loss = tf.losses.mean_squared_error(labels, outputs)
    optimiser = tf.train.AdamOptimizer(learning_rate=0.01)
    train_op = optimiser.minimize(loss, global_step=tf.train.get_global_step())
    return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)

estimator = tf.estimator.Estimator(model_fn=model_fn)
estimator.train(input_fn=lambda:train_input_fn(features, labels), steps=100)
predictions = np.array(list(estimator.predict(input_fn=lambda:predict_input_fn(features))))

plt.figure(figsize=(20, 2))
plt.plot(np.concatenate((features[:, :, 0].T, labels[:, :, 0].T)) * 10)
plt.plot(np.concatenate((features[:, :, 0].T, predictions[:, :, 0].T)) * 10, ls='--')
plt.axvline(features.shape[1]-1)
plt.title('<- Features vs. Labels -> (with model predictions \'--\')')
plt.xlabel('Month')
plt.ylabel('Magnitude')
plt.show()
...