Почему я получаю ValueError: не предусмотрены градиенты ни для одной переменной: ['Variable: 0']. ошибка?

Я очень новичок в тензорном потоке, и я пытаюсь построить модель передачи стилей, я понимаю концепцию модели, но у меня возникают трудности с ее реализацией, так как я не полностью понимаю, что происходит в tenorflow, пока нет. Когда я пытаюсь запустить оптимизацию сгенерированного изображения, я получаю сообщение об ошибке «Градиенты не указаны», чего я не понимаю, поскольку в моем коде есть:

    loss = total_loss(content_feats, style_feats, output_feats)

    grad = tape.gradient(loss, output_processado)
    optimizer.apply_gradients(zip([grad],[output_processado]))

ValueError Traceback (последний вызов последним)

in () 8 9 grad = tape.gradient (loss, output_processado) ---> 10 optimizer.apply_gradients (zip ([grad], [output_processado])) 11 12 clip = tf.clip_by_value (output_processado, min_value, max_value)

1 кадр

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py в _filter_grads (grads_and_vars) 1217, если не отфильтрован: 1218
поднять ValueError ("Градиенты не предусмотрены для какой-либо переменной :% s. "% -> 1219 ([v.name для _, v в grads_and_vars],)) 1220 если vars_with_empty_grads: 1221 logging.warning (

ValueError: Градиенты не предусмотрены ни для одной переменной: ['Variable: 0'].

import tensorflow as tf
device_name = tf.test.gpu_device_name()
if device_name != '/device:GPU:0':
  raise SystemError('GPU device not found')
print('Found GPU at: {}'.format(device_name))


import numpy as np
from PIL import Image
import requests
from io import BytesIO
from keras.applications.vgg19 import VGG19
from keras.applications.vgg19 import preprocess_input
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.models import Model
import keras.backend as K
from matplotlib import pyplot as plt
from numpy import expand_dims
from tensorflow import GradientTape

ITERATIONS = 10
CHANNELS = 3
IMAGE_SIZE = 500
IMAGE_WIDTH = IMAGE_SIZE
IMAGE_HEIGHT = IMAGE_SIZE
CONTENT_WEIGHT = 0.02
STYLE_WEIGHT = 4.5

MEAN = np.array([103.939, 116.779, 123.68])

CONTENT_LAYERS = ['block4_conv2']
STYLE_LAYERS = ['block1_conv1', 'block2_conv1', 'block3_conv1', 'block4_conv1', 'block5_conv1']

input_image_path = "input.png"
style_image_path = "style.png"
output_image_path = "output.png"
combined_image_path = "combined.png"

san_francisco_image_path = "https://www.economist.com/sites/default/files/images/print-edition/20180602_USP001_0.jpg"

tytus_image_path = "http://meetingbenches.com/wp-content/flagallery/tytus-brzozowski-polish-architect-and-watercolorist-a-fairy-tale-in-warsaw/tytus_brzozowski_13.jpg"


input_image = Image.open(BytesIO(requests.get(san_francisco_image_path).content))
input_image = input_image.resize((IMAGE_WIDTH, IMAGE_HEIGHT))
input_image.save(input_image_path)
#input_image

# Style visualization 
style_image = Image.open(BytesIO(requests.get(tytus_image_path).content))
style_image = style_image.resize((IMAGE_WIDTH, IMAGE_HEIGHT))
style_image.save(style_image_path)
#style_image

def obter_modelo():

  modelo = VGG19(include_top = False, weights = 'imagenet', input_tensor = None)

  c_layer = CONTENT_LAYERS
  s_layers = STYLE_LAYERS

  output_layers = [modelo.get_layer(layer).output for layer in (c_layer + s_layers)]

  return Model(modelo.inputs, output_layers)

def processar_imagem(img):

  imagem = img.resize((IMAGE_HEIGHT, IMAGE_WIDTH))
  imagem = img_to_array(imagem)
  imagem = preprocess_input(imagem)
  imagem = expand_dims(imagem, axis=0)

  return imagem

def desprocessar_imagem(img):
  imagem = img
  mean = MEAN
  imagem[..., 0] += mean[0]
  imagem[..., 1] += mean[1]
  imagem[..., 2] += mean[2]
  imagem = imagem[..., ::-1]

  return imagem.astype(int)

def content_loss(c_mat, out_mat):
  return 0.5 * K.sum(K.square(out_mat - c_mat))


def matriz_gram(mat):
  return K.dot(mat,K.transpose(mat))


def style_loss(s_mat, out_mat):

  style_feat = K.batch_flatten(K.permute_dimensions(s_mat,(2,0,1)))
  output_feat = K.batch_flatten(K.permute_dimensions(out_mat,(2,0,1)))

  style_gram = matriz_gram(style_feat)
  output_gram = matriz_gram(output_feat)

  return K.sum(K.square(style_gram - output_gram)) / (4.0 * (CHANNELS ** 2) * (IMAGE_SIZE ** 2))


def total_loss(c_layer, s_layers, out_layers):

  content_layer = c_layer[0]
  out_content = out_layers[0]

  style_layers = s_layers[1:]
  out_style = out_layers[1:]

  c_loss = content_loss(content_layer[0], out_content[0])

  s_loss = None

  for i in range(len(style_layers)):
    if s_loss is None:
      s_loss = style_loss(style_layers[i][0], out_style[i][0])

    else:
      s_loss += style_loss(style_layers[i][0], out_style[i][0])

  return CONTENT_WEIGHT * c_loss + (STYLE_WEIGHT * s_loss)/len(style_layers)

modelo = obter_modelo()

#content image
content_processado = processar_imagem(input_image)
content_feats = modelo(K.variable(content_processado))

#style image
style_processado = processar_imagem(style_image)
style_feats = modelo(K.variable(style_processado))

#output image
output_processado = preprocess_input(np.random.uniform(0,250,(IMAGE_HEIGHT, IMAGE_WIDTH,CHANNELS)))
output_processado = expand_dims(output_processado, axis=0)
output_processado = K.variable(output_processado)

optimizer = tf.optimizers.Adam(5,beta_1=.99,epsilon=1e-3)
epochs=200

melhor_loss = K.variable(2000000.0)
melhor_imagem = None

min_value = MEAN
max_value = 255 + MEAN
loss = K.variable(0.0)

for e in range(epochs):
  with tf.GradientTape() as tape:
    tape.watch(output_processado)
    output_feats = modelo(output_processado)

    loss = total_loss(content_feats, style_feats, output_feats)

    grad = tape.gradient(loss, output_processado)
    optimizer.apply_gradients(zip([grad],[output_processado]))

    clip = tf.clip_by_value(output_processado, min_value, max_value)
    output_processado.assign(clip)
    print("Epoch: " + str(e) )

person Rodrigo Pina    schedule 16.05.2020    source источник


Ответы (1)


Для tape.gradient вы должны пройти (loss, model.trainable_weights), но вы передаете tape.gradient(loss, output_processado). Также для optimizer.apply_gradients вы должны пройти (grad, model.trainable_variables), но вы передаете (zip([grad],[output_processado]).

Вызов модели внутри GradientTape области позволяет получить градиенты обучаемых весов слоя по отношению к значению потерь. Используя экземпляр оптимизатора, вы можете использовать эти градиенты для обновления этих переменных (которые вы можете получить с помощью model.trainable_weights).

TensorFlow предоставляет tf.GradientTape API для автоматического дифференцирования - вычисления градиента вычисления относительно его входных переменных. Tensorflow «записывает» все операции, выполняемые в контексте tf.GradientTape, на «ленту». Затем Tensorflow использует эту ленту и градиенты, связанные с каждой записанной операцией, для вычисления градиентов «записанного» вычисления с использованием дифференцирования обратных режимов.

Если вы хотите обработать градиенты перед их применением, вы можете вместо этого использовать оптимизатор в три этапа:

  1. Вычислите градиенты с tf.GradientTape.
  2. Обрабатывайте градиенты по своему усмотрению.
  3. Примените обработанные градиенты с помощью apply_gradients().

Вот простой пример для данных mnist. Комментарии присутствуют в коде, чтобы лучше объяснить.

Код-

import tensorflow as tf
print(tf.__version__)
from tensorflow import keras
from tensorflow.keras import layers

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

# Preprocess the data (these are Numpy arrays)
x_train = x_train.reshape(60000, 784).astype('float32') / 255
x_test = x_test.reshape(10000, 784).astype('float32') / 255

y_train = y_train.astype('float32')
y_test = y_test.astype('float32')

# Reserve 10,000 samples for validation
x_val = x_train[-10000:]
y_val = y_train[-10000:]
x_train = x_train[:-10000]
y_train = y_train[:-10000]

# Get the model.
inputs = keras.Input(shape=(784,), name='digits')
x = layers.Dense(64, activation='relu', name='dense_1')(inputs)
x = layers.Dense(64, activation='relu', name='dense_2')(x)
outputs = layers.Dense(10, name='predictions')(x)
model = keras.Model(inputs=inputs, outputs=outputs)

# Instantiate an optimizer.
optimizer = keras.optimizers.SGD(learning_rate=1e-3)
# Instantiate a loss function.
loss_fn = keras.losses.SparseCategoricalCrossentropy(from_logits=True)

# Prepare the training dataset.
batch_size = 64
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(batch_size)

epochs = 3
for epoch in range(epochs):
  print('Start of epoch %d' % (epoch,))

  # Iterate over the batches of the dataset.
  for step, (x_batch_train, y_batch_train) in enumerate(train_dataset):

    # Open a GradientTape to record the operations run
    # during the forward pass, which enables autodifferentiation.
    with tf.GradientTape() as tape:

      # Run the forward pass of the layer.
      # The operations that the layer applies
      # to its inputs are going to be recorded
      # on the GradientTape.
      logits = model(x_batch_train, training=True)  # Logits for this minibatch

      # Compute the loss value for this minibatch.
      loss_value = loss_fn(y_batch_train, logits)

    # Use the gradient tape to automatically retrieve
    # the gradients of the trainable variables with respect to the loss.
    grads = tape.gradient(loss_value, model.trainable_weights)

    # Run one step of gradient descent by updating
    # the value of the variables to minimize the loss.
    optimizer.apply_gradients(zip(grads, model.trainable_weights))

    # Log every 200 batches.
    if step % 200 == 0:
        print('Training loss (for one batch) at step %s: %s' % (step, float(loss_value)))
        print('Seen so far: %s samples' % ((step + 1) * 64))

Вывод -

2.2.0
Start of epoch 0
Training loss (for one batch) at step 0: 2.323657512664795
Seen so far: 64 samples
Training loss (for one batch) at step 200: 2.3156163692474365
Seen so far: 12864 samples
Training loss (for one batch) at step 400: 2.2302279472351074
Seen so far: 25664 samples
Training loss (for one batch) at step 600: 2.131979465484619
Seen so far: 38464 samples
Start of epoch 1
Training loss (for one batch) at step 0: 2.00234317779541
Seen so far: 64 samples
Training loss (for one batch) at step 200: 1.7992427349090576
Seen so far: 12864 samples
Training loss (for one batch) at step 400: 1.8583933115005493
Seen so far: 25664 samples
Training loss (for one batch) at step 600: 1.6005337238311768
Seen so far: 38464 samples
Start of epoch 2
Training loss (for one batch) at step 0: 1.6701987981796265
Seen so far: 64 samples
Training loss (for one batch) at step 200: 1.6237502098083496
Seen so far: 12864 samples
Training loss (for one batch) at step 400: 1.3603084087371826
Seen so far: 25664 samples
Training loss (for one batch) at step 600: 1.246948480606079
Seen so far: 38464 samples

Дополнительную информацию о tf.GradientTape можно найти здесь. Используемый здесь пример взят из здесь.

Надеюсь, что это ответ на ваш вопрос. Удачного обучения.

person Tensorflow Warrior    schedule 10.06.2020