Допустим, мы пытаемся предсказать будущие землетрясения на основе предыдущих землетрясений.Визуализация части набора данных, содержащей последовательности землетрясений, может выглядеть следующим образом (особенности слева, метки справа, x = месяц, y = магнитуда землетрясения): Вы и я можем видетьмодель здесь такова, что когда два землетрясения магнитудой 5 последовательно, за ними следует землетрясение магнитудой 8, а затем землетрясение магнитудой 4.Эти землетрясения могут возникать с периодом 3-5 месяцев, но магнитуды при них одинаковы.
Обучение LSTM на этих данных с помощью функции среднеквадратичных потерь дает следующие прогнозы (пунктирная линия)строка): Это сделано точно так, как мы просили, оно научилось предсказывать среднее значение для временного шага.Тем не менее, это плохой прогноз с точки зрения того, для чего предназначена модель.
Для вас или для меня, смотря на данные, мы можем предположить, что первое предсказанное землетрясение имеет магнитуду 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()