Вероятность Tensorflow возвращает нестабильные прогнозы

Я использую модель вероятности Tensorflow. Конечно, это вероятностный результат, и производная ошибки не стремится к нулю (иначе модель была бы детерминированной). Прогноз нестабилен, потому что у нас есть диапазон производной убытка, скажем, при выпуклой оптимизации, от 1,2 до 0,2 в качестве примера.

Этот интервал генерирует разные прогнозы каждый раз, когда модель обучается. Иногда я получаю отличный результат (красные = реальные, синие линии = прогнозируемое +2 стандартного отклонения и -2 стандартного отклонения):

Хорошо подходит

Иногда нет, с такими же гиперпараметрами:

Плохо подходит

Иногда зеркально отражается:

Зеркально

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

Вот код:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
import tensorflow_probability as tfp
np.random.seed(42)
dataframe = pd.read_csv('Apple_Data_300.csv').ix[0:800,:]
dataframe.head()

plt.plot(range(0,dataframe.shape[0]),dataframe.iloc[:,1])

x1=np.array(dataframe.iloc[:,1]+np.random.randn(dataframe.shape[0])).astype(np.float32).reshape(-1,1)

y=np.array(dataframe.iloc[:,1]).T.astype(np.float32).reshape(-1,1)

tfd = tfp.distributions

model = tf.keras.Sequential([
  tf.keras.layers.Dense(1,kernel_initializer='glorot_uniform'),
  tfp.layers.DistributionLambda(lambda t: tfd.Normal(loc=t, scale=1)),
  tfp.layers.DistributionLambda(lambda t: tfd.Normal(loc=t, scale=1)),
  tfp.layers.DistributionLambda(lambda t: tfd.Normal(loc=t, scale=1))
])
negloglik = lambda x, rv_x: -rv_x.log_prob(x)

model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.0001), loss=negloglik)

model.fit(x1,y, epochs=500, verbose=True)

yhat = model(x1)
mean = yhat.mean()

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    mm = sess.run(mean)    
    mean = yhat.mean()
    stddev = yhat.stddev()
    mean_plus
Epoch 498/500
801/801 [==============================] - 0s 32us/sample - loss: 2.4169
Epoch 499/500
801/801 [==============================] - 0s 30us/sample - loss: 2.4078
Epoch 500/500
801/801 [==============================] - 0s 31us/sample - loss: 2.3944
std = sess.run(mean - 2. * stddev) mean_minus
Epoch 498/500
801/801 [==============================] - 0s 32us/sample - loss: 2.4169
Epoch 499/500
801/801 [==============================] - 0s 30us/sample - loss: 2.4078
Epoch 500/500
801/801 [==============================] - 0s 31us/sample - loss: 2.3944
std = sess.run(mean + 2. * stddev) plt.figure(figsize=(8,6)) plt.plot(y,color='red',linewidth=1) #plt.plot(mm) plt.plot(mean_minus
Epoch 498/500
801/801 [==============================] - 0s 32us/sample - loss: 2.4169
Epoch 499/500
801/801 [==============================] - 0s 30us/sample - loss: 2.4078
Epoch 500/500
801/801 [==============================] - 0s 31us/sample - loss: 2.3944
std,color='blue',linewidth=1) plt.plot(mean_plus
Epoch 498/500
801/801 [==============================] - 0s 32us/sample - loss: 2.4169
Epoch 499/500
801/801 [==============================] - 0s 30us/sample - loss: 2.4078
Epoch 500/500
801/801 [==============================] - 0s 31us/sample - loss: 2.3944
std,color='blue',linewidth=1)

Потеря:

Epoch 498/500
801/801 [==============================] - 0s 32us/sample - loss: 2.4169
Epoch 499/500
801/801 [==============================] - 0s 30us/sample - loss: 2.4078
Epoch 500/500
801/801 [==============================] - 0s 31us/sample - loss: 2.3944

Есть ли способ контролировать результат прогноза для вероятностной модели? Потеря останавливается на 1,42, даже при снижении скорости обучения и увеличении эпох обучения. Что мне здесь не хватает?

РАБОЧИЙ КОД ПОСЛЕ ОТВЕТА:

init = tf.global_variables_initializer()

with tf.Session() as sess:

    model = tf.keras.Sequential([
      tf.keras.layers.Dense(1,kernel_initializer='glorot_uniform'),
      tfp.layers.DistributionLambda(lambda t: tfd.Normal(loc=t, scale=1))
    ])
    negloglik = lambda x, rv_x: -rv_x.log_prob(x)

    model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.0001), loss=negloglik)

    model.fit(x1,y, epochs=500, verbose=True, batch_size=16)

    yhat = model(x1)
    mean = yhat.mean()

    sess.run(init)
    mm = sess.run(mean)    
    mean = yhat.mean()
    stddev = yhat.stddev()
    mean_plus_2_std = sess.run(mean - 3. * stddev)
    mean_minus_2_std = sess.run(mean + 3. * stddev)

person razimbres    schedule 19.03.2019    source источник
comment
Я нашел это и ваше размещение tf.global_variables_initializer очень интересным: Variable initializers must be run explicitly before other ops in your model can be run. The easiest way to do that is to add an op that runs all the variable initializers, and run that op before using the model. stackoverflow.com/questions/44433438/. Вы бежите tf.global_variables_initializer слишком поздно?   -  person Scott Skiles    schedule 19.03.2019
comment
@ScottSkiles да и нет, по гиперпараметрам убыток может составить 1,42. И ДА, tf.global_variables_initializer должен быть первым. У меня есть код, который теперь отлично работает. Вы хотите опубликовать ответ, или я могу ответить рабочим кодом?   -  person razimbres    schedule 19.03.2019
comment
Ответил! Не стесняйтесь редактировать с помощью рабочего кода.   -  person Scott Skiles    schedule 19.03.2019
comment
Спасибо! Код добавлен.   -  person razimbres    schedule 19.03.2019


Ответы (1)


Вы бежите tf.global_variables_initializer слишком поздно?

Я нашел это в ответе Общие сведения о tf.global_variables_initializer:

Инициализаторы переменных должны запускаться явно, прежде чем можно будет запускать другие операции в вашей модели. Самый простой способ сделать это - добавить операцию, которая запускает все инициализаторы переменных, и запустить эту операцию перед использованием модели.

person Scott Skiles    schedule 19.03.2019