Тренировка GP + Tensorflow

Я пытаюсь совместить модель георадара и модель тензорного потока. Обучающая часть не имеет проблем. Но для прогнозирования с использованием обученной модели я получаю ошибку типа в операторе tf.placeholder.

pred, uncp=sess.run([my, yv], feed_dict={X:xtr})

Код похож на 2-й пример из https://gpflow.readthedocs.io/en/master/notebooks/advanced_usage.html

import numpy as np
import tensorflow as tf

import gpflow
float_type = gpflow.settings.float_type
gpflow.reset_default_graph_and_session()

def cnn_fn(x, output_dim):    
    out= tf.layers.dense(inputs=x, units=output_dim, activation=tf.nn.relu)
    print(out)    
    return out

N = 150
xtr = np.random.rand(N,1)
ytr = np.sin(12*xtr) + 0.66*np.cos(25*xtr) + np.random.randn(N,1)*0.1 + 3
xtr = np.random.rand(N,28)
print(xtr.shape, ytr.shape)
nepoch=50
gp_dim=xtr.shape[1]
print(gp_dim)
minibatch_size = 16

X = tf.placeholder(tf.float32, [None, gp_dim]) 
Y = tf.placeholder(tf.float32, [None, 1])

with tf.variable_scope('cnn'):
    f_X = tf.cast(cnn_fn(X, gp_dim), dtype=float_type)

k = gpflow.kernels.Matern52(gp_dim)
gp_model = gpflow.models.GPR(f_X, tf.cast(Y, dtype=float_type), k)

loss = -gp_model.likelihood_tensor
m, v = gp_model._build_predict(f_X)
my, yv = gp_model.likelihood.predict_mean_and_var(m, v)

with tf.variable_scope('adam'):
    opt_step = tf.train.AdamOptimizer(0.001).minimize(loss)

tf_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='adam')
tf_vars += tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='cnn')

## initialize
sess = tf.Session()
sess.run(tf.variables_initializer(var_list=tf_vars))
gp_model.initialize(session=sess)

for i in range(nepoch):
    shind=np.array(range(len(xtr)))
    np.random.shuffle(shind)
    for j in range(int(len(xtr)/minibatch_size)):
        ind=shind[j*minibatch_size: (j+1)*minibatch_size]
        sess.run(opt_step, feed_dict={X:xtr[ind], Y:ytr[ind]})

Выполнение кода выше работает нормально. Но добавление следующей строки дает ошибку:

 pred, uncp=sess.run([my, yv], feed_dict={X:xtr})

со следующей ошибкой:

<ipython-input-25-269715087df2> in <module>
----> 1 pred, uncp=sess.run([my, yv], feed_dict={X:xtr})

[...]

InvalidArgumentError: You must feed a value for placeholder tensor 'Placeholder_1' with dtype float and shape [?,1]
     [[node Placeholder_1 (defined at <ipython-input-24-39ccf45cd248>:2)  = Placeholder[dtype=DT_FLOAT, shape=[?,1], _device="/job:localhost/replica:0/task:0/device:GPU:0"]()]]

2 ответа

Решение

Причина, по которой ваш код дает сбой, заключается в том, что вы фактически не передаете значение одному из заполнителей. Это легче заметить, если вы действительно дадите им имена:

X = tf.placeholder(tf.float32, [None, gp_dim], name='X') 
Y = tf.placeholder(tf.float32, [None, 1], name='Y')

Tensorflow требует, чтобы весь вычислительный граф был четко определен, а GPR модель, которую вы используете, зависит от обоих X а также Y, Если вы запустите следующую строку, она работает нормально:

pred, uncp = sess.run([my, yv], feed_dict={X: xtr, Y: ytr})

Обновление: как указано в комментарии user1018464, вы используете GPR модель, в которой прогнозы напрямую зависят от данных обучения (например, см. уравнения (2.22) и (2.23) на стр. 16 http://www.gaussianprocess.org/gpml/chapters/RW2.pdf). Следовательно, вам нужно будет пройти оба xtr а также ytr делать прогнозы.

Другие модели, такие как SVGP представлять функцию с помощью "индуцирующих функций", обычно пар "псевдо ввод / вывод", которые суммируют данные, и в этом случае вам вообще не нужно вводить исходные входные значения (я ошибся, когда впервые ответил).

Вы можете настроить модель следующим образом:

gp_model = gpflow.models.SVGP(f_X, tf.cast(Y, dtype=float_type), k, gpflow.likelihoods.Gaussian(), xtr.copy(), num_data=N)

затем pred, uncp=sess.run([my, yv], feed_dict={X:xtr}) работает как положено.

Если вы хотите прогнозировать в разных точках Xtest, вам нужно установить отдельный заполнитель и повторно использовать cnn (обратите внимание на reuse=True в переменную_области с тем же именем), как в примере 2 записной книжки:

Xtest = tf.placeholder(tf.float32, [None, Mnist.input_dim], name='Xtest')

with tf.variable_scope('cnn', reuse=True):
    f_Xtest = tf.cast(cnn_fn(Xtest, gp_dim), dtype=float_type)

Настройте модель как перед использованием f_X, но использовать f_Xtest в призыве к _build_predict:

m, v = gp_model._build_predict(f_Xtest)
my, yv = gp_model.likelihood.predict_mean_and_var(m, v)

Теперь нужно пройти оба X, Y и Xtest во время сеанса ():

pred, uncp = sess.run([my, yv], feed_dict={X: xtr, Y: Ytr, Xtest: xtest})

где xtest это массив с точками, в которых вы хотите предсказать.

GPflow управляет сессиями TensorFlow для вас, и вам не нужно создавать свой собственный сеанс TF, когда вы используете только GPflow. В твоем случае, tf.layers.dense создает новые переменные, которые должны быть инициализированы, и я бы посоветовал использовать сеанс, который был создан GPflow. По сути, вам нужно заменить эти строки

## initialize
sess = tf.Session()
sess.run(tf.variables_initializer(var_list=tf_vars))
gp_model.initialize(session=sess)

с:

sess = gpflow.get_default_session()
sess.run(tf.variables_initializer(var_list=tf_vars)

или оберните ваш код контекстом сеанса по умолчанию:

with tf.Session() as session:
    ... build and run
Другие вопросы по тегам