如何在损失函数中将一个模型的预测用于另一个模型?

时间:2019-05-30 07:58:14

标签: python tensorflow keras

我正在尝试使用tensorflow和keras,基于有关UPSET和ANGRI(链接:https://arxiv.org/pdf/1707.01159.pdf)的论文构建一个演示程序。如本文所述,损失函数需要预训练模型的预测结果。但是,损失函数应由张量组成。一种选择是使用

model.predict(new_image)

表示损失函数中的C_i(new_image)。定义时new_image没有任何值,因此存在问题。我也尝试使用

session.run(model.output, feed_dict={'flatten_1_input:0': tf.get_session_handle(tf.reshape(new_image, [-1, 28, 28]))}) 

替换占位符,但feed_dict的元素不能为张量。

Ubuntu 18.04; Python 3.6; 最新的Tensorflow和Keras 与cuda&cudnn

import tensorflow as tf
import numpy as np
import keras
import loader

fashion_mnist = keras.datasets.fashion_mnist
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
(train_images, train_labels), (test_images, test_labels) = loader.load_data()
train_images = train_images / 255.0
test_images = test_images / 255.0

model = keras.Sequential([
    keras.layers.Flatten(input_shape=(28, 28)),
    keras.layers.Dense(128, activation=tf.nn.relu),
    keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer=tf.train.AdamOptimizer(),
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=5)

for layer in model.layers:
    layer.trainable = False

batch_size = 8

# t
train_x = tf.placeholder(tf.float32, shape=(None, 10), name='x-input')
# x
train_y = tf.placeholder(tf.float32, shape=(None, 784), name='y-input')

arg_s = 2
arg_w = 0.1


def flatten(images):
    return np.array(images).reshape(len(images), -1)


def get_weight(shape, lam):
    var = tf.Variable(tf.random_normal(shape), dtype=tf.float32)
    # tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(lam)(var))
    return var


layer_dimension = [10, 128, 256, 512, 1024, 512, 784]

num_layers = len(layer_dimension)
current_layer = train_x

in_dimension = layer_dimension[0]

for i in range(1, num_layers):
    out_dimension = layer_dimension[i]
    weight = get_weight([in_dimension, out_dimension], 0.001)
    bias = tf.Variable(tf.constant(0.1, shape=[out_dimension]))
    current_layer = tf.nn.relu((tf.matmul(current_layer, weight)))
    in_dimension = layer_dimension[i]

with tf.Session() as session:
    new_image = tf.maximum(tf.minimum(arg_s * current_layer + train_y, 1), -1)
    session.run(model.output, feed_dict={'flatten_1_input:0': tf.get_session_handle(tf.reshape(new_image, [-1, 28, 28]))})
    lc = -tf.reduce_mean(train_x * tf.log(tf.clip_by_value(model.output, 1e-10, 1.0)))
    lf = 0.08 * tf.reduce_mean(tf.square(new_image - train_y))
    loss = lc + lf

    # tf.add_to_collection('losses', loss)

    # total_loss = tf.add_n(tf.get_collection('losses'))

    train_step = tf.train.AdamOptimizer(0.001).minimize(loss)

    dataset_size = 50000

    init_op = tf.global_variables_initializer()
    session.run(init_op)
    steps = 5000
    for i in range(steps):
        start = (i * batch_size) % dataset_size
        end = min(start + batch_size, dataset_size)

        session.run(train_step,
                    feed_dict={train_x: np.array([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0]]).repeat(batch_size, axis=0),
                               train_y: flatten(train_images[start:end])})

        if i % 1000 == 0:
            total_cross_entropy = session.run(loss, feed_dict={
                train_x: np.array([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0]]).repeat(batch_size, axis=0),
                train_y: flatten(train_images)})

            print("After %d training step(s), cross entropy on all data is %g" % (i, total_cross_entropy))

请注意,对于代码:

  session.run(model.output, feed_dict={'flatten_1_input:0': tf.get_session_handle(tf.reshape(new_image, [-1, 28, 28]))})
lc = -tf.reduce_mean(train_x * tf.log(tf.clip_by_value(model.output, 1e-10, 1.0)))

我也尝试过:

lc = -tf.reduce_mean(train_x * tf.log(tf.clip_by_value(model.predict(new_image), 1e-10, 1.0)))

而且我也尝试过更改

的位置
with tf.Session() as session:

这些是错误消息(当我尝试输入张量时)

Traceback (most recent call last):
  File "I:/grade3/software_testing/upset/upset.py", line 64, in <module>
    session.run(model.output, feed_dict={'flatten_1_input:0': tf.get_session_handle(tf.reshape(new_image, [-1, 28, 28]))})
  File "D:\anaconda\envs\python37\lib\site-packages\tensorflow\python\client\session.py", line 929, in run
    run_metadata_ptr)
  File "D:\anaconda\envs\python37\lib\site-packages\tensorflow\python\client\session.py", line 1103, in _run
    'feed with key ' + str(feed) + '.')
TypeError: The value of a feed cannot be a tf.Tensor object. Acceptable feed values include Python scalars, strings, lists, numpy ndarrays, or TensorHandles. For reference, the tensor object was Tensor("GetSessionHandle:0", shape=(), dtype=string) which was passed to the feed with key flatten_1_input:0.

如果我使用model.predict:

Traceback (most recent call last):
  File "I:/grade3/software_testing/upset/upset.py", line 65, in <module>
    lc = -tf.reduce_mean(train_x * tf.log(tf.clip_by_value(model.predict(new_image), 1e-10, 1.0)))
  File "D:\anaconda\envs\python37\lib\site-packages\keras\engine\training.py", line 1149, in predict
    x, _, _ = self._standardize_user_data(x)
  File "D:\anaconda\envs\python37\lib\site-packages\keras\engine\training.py", line 751, in _standardize_user_data
    exception_prefix='input')
  File "D:\anaconda\envs\python37\lib\site-packages\keras\engine\training_utils.py", line 92, in standardize_input_data
    data = [standardize_single_array(x) for x in data]
  File "D:\anaconda\envs\python37\lib\site-packages\keras\engine\training_utils.py", line 92, in <listcomp>
    data = [standardize_single_array(x) for x in data]
  File "D:\anaconda\envs\python37\lib\site-packages\keras\engine\training_utils.py", line 25, in standardize_single_array
    'Got tensor with shape: %s' % str(shape))
ValueError: When feeding symbolic tensors to a model, we expect thetensors to have a static batch size. Got tensor with shape: (None, 784)

0 个答案:

没有答案