簡體   English   中英

ValueError:沒有為任何變量提供梯度 - Tensorflow 2.0

[英]ValueError: No gradients provided for any variable - Tensorflow 2.0

我試圖從訓練有素的 MNIST GAN model 中找到 MNIST 圖像的相應潛在代碼。 我打算做的是對定義為目標和生成樣本之間距離的損失應用梯度下降。 隨着生成的樣本越來越接近目標,損失減少,相應的潛在代碼就是我所需要的。

這是我的代碼:

import numpy as np
import tensorflow as tf
from tensorflow.keras import Model
from tensorflow.keras import Sequential
import tensorflow.keras.backend as K
from tensorflow.keras.datasets import mnist
from tensorflow.keras import layers
from tensorflow.keras.layers import *
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.losses import MeanSquaredError
import random

### Load MNIST data
(data_x, _), _ = mnist.load_data()
data_x = np.reshape(np.asarray(data_x), [60000, 28*28]).astype(float)
train = data_x[:1024]
test = data_x[-10:]

### GAN setting
generator = Sequential([
    Dense(7 * 7 * 64, input_shape=[100]),
    BatchNormalization(),
    LeakyReLU(),
    Reshape([7, 7, 64]),
    UpSampling2D([2, 2]),
    Conv2DTranspose(64, [3, 3], padding='same'),
    BatchNormalization(),
    LeakyReLU(),
    UpSampling2D([2, 2]),
    Conv2DTranspose(1, [3, 3], padding='same', activation='sigmoid')
])

discriminator = Sequential([
    Conv2D(64, [3, 3], padding='same', input_shape=[28, 28, 1]),
    BatchNormalization(),
    LeakyReLU(),
    MaxPool2D([2, 2]),
    Conv2D(64, [3, 3], padding='same'),
    BatchNormalization(),
    LeakyReLU(),
    MaxPool2D([2, 2]),
    Flatten(),
    Dense(128),
    BatchNormalization(),
    LeakyReLU(),
    Dense(1, activation='sigmoid')
])

x_input = Input([28, 28, 1])
g_sample_input = Input([100])

log_clip = Lambda(lambda x: K.log(x + 1e-3))

sample_score = discriminator(generator(g_sample_input))

d_loss = (
    - log_clip(discriminator(x_input)) 
    - log_clip(1.0 - sample_score)
)
fit_discriminator = Model(inputs=[x_input, g_sample_input], outputs=d_loss)
fit_discriminator.add_loss(d_loss)
generator.trainable = False
for layer in generator.layers:
    if isinstance(layer, BatchNormalization):
        layer.trainable = True
fit_discriminator.compile(optimizer=Adam(0.001))
generator.trainable = True

g_loss = (
    - log_clip(sample_score)
)
fit_generator = Model(inputs=g_sample_input, outputs=g_loss)
fit_generator.add_loss(g_loss)
discriminator.trainable = False
for layer in discriminator.layers:
    if isinstance(layer, BatchNormalization):
        layer.trainable = True
fit_generator.compile(optimizer=Adam(0.001))
discriminator.trainable = True

### GAN training
train_x = train.reshape([-1, 28, 28, 1]) / 255
batch_size = 64
for i in range(10000):
    x = train_x[random.sample(range(len(train_x)), batch_size)]
    g_sample = np.random.uniform(-1, 1, [batch_size, 100])
    fit_discriminator.fit([K.constant(x), K.constant(g_sample)])
    fit_generator.fit(g_sample)
    
### Search for latent code
target = (test[0] / 255).reshape([28, 28])
mse = MeanSquaredError()
z = np.random.uniform(-1, 1, [1, 100])
z_t = tf.Variable(z, trainable=True)
opt = SGD(learning_rate=0.1)

for _ in range(10):
    loss_fn = lambda: mse(target,
                          generator(z_t.numpy())[0].numpy().reshape([28, 28]))

    opt.minimize(loss_fn, var_list=[z_t])

我得到這個錯誤:

ValueError:沒有為任何變量提供漸變:['Variable:0']。

似乎 Tensorflow 無法從這種損失中計算梯度。

如果損失來自另一個 model,有沒有辦法計算梯度? 或者有沒有辦法在不計算梯度的情況下實現我的目標?

我想我找到了關鍵點。

Tensorflow 根據圖計算梯度。 所以我們應該總是把每一個操作都放在圖中。

我的代碼的錯誤是由 tensor-numpy 轉換引起的。 因為一旦我們將張量轉換為 numpy 數組,它就會被帶出圖表,Tensorflow 無法再跟蹤它。

這是我的新代碼,現在運行良好:

mse = MeanSquaredError()
target = (test[0] / 255).reshape([28, 28])
target_t = tf.convert_to_tensor(target)
z = np.random.uniform(-1, 1, [1, 100])
z_t = tf.Variable(z, trainable=True)
opt = SGD(learning_rate=0.1)

for _ in range(10):
    loss_fn = lambda: mse(target_t,
                          tf.reshape(tf.cast(generator(z_t), tf.float64), [28, 28]))
    opt.minimize(loss_fn, var_list=[z_t])

(這里只顯示最后一段代碼,其他部分保持不變。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM