#python #tensorflow #neural-network #lstm #loss-function
#python #tensorflow #нейронная сеть #lstm #функция потери
Вопрос:
Допустим, мы пытаемся предсказать будущие землетрясения на основе предыдущих землетрясений. Визуализация части набора данных, содержащего последовательности землетрясений, может выглядеть следующим образом (объекты слева, метки справа, x = месяц, y = магнитуда землетрясения): Мы с вами можем видеть, что схема здесь такова: когда происходят два землетрясения магнитудой 5 подряд, за ними следует землетрясение магнитудой 8, а затем землетрясение магнитудой 4. Эти землетрясения могут возникать с интервалом в 3-5 месяцев, но их магнитуда остается такой же, когда они происходят.
Обучение LSTM на этих данных с помощью среднеквадратичной функции потери ошибок приводит к следующим прогнозам (пунктирная линия): Это сделано именно так, как мы просили, оно научилось предсказывать среднее значение за каждый временной шаг. Однако это плохое предсказание с точки зрения того, для чего предназначена модель.
Для вас или меня, просматривающих данные, мы могли бы предположить, что первое предсказанное землетрясение имеет магнитуду 8, и, принимая во внимание разницу во временном интервале, нашим лучшим прогнозом было бы то, что это произойдет с временным интервалом 8. По сути, мы бы вычисляли среднюю ошибку по временной оси, а также по оси значений.
Какую функцию потерь можно использовать для этого в TensorFlow?
Я искал, но нашел только материал, относящийся к ошибке каждого временного шага. Я начал пробовать несколько методов, которые, как я думал, могли бы дать лучшие результаты, например, tf.sort
для меток и прогнозов перед выполнением среднеквадратичной ошибки, а затем также tf.argsort
для меток и прогнозов и выполнения среднеквадратичной ошибки для них, чтобы выдать временную ошибку, но у argsort нет градиентов для обратного распространения, поэтому я начал пытаться писать пользовательские градиенты, что, по-моему, просто излишне, когда решение уже должно существовать? (p.s. Мне нравится 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()