Ошибка сложения тензорного потока при совместном добавлении результатов из binary_crossentropy()

#python #tensorflow #machine-learning #keras #generative-adversarial-network

#python #тензорный поток #машинное обучение #keras #генеративная-состязательная-сеть

Вопрос:

Я был в середине обучения моего gan, когда возникла очень неожиданная ошибка. Я понятия не имею, как это исправить. Ошибка возникает не сразу, это происходит примерно через 2-3 минуты после моего обучения. Вот ошибка

 Traceback (most recent call last):


File "gan.py", line 103, in <module>
    train(X_train_dataset,200)
  File "gan.py", line 80, in train
    train_step(images) # takes images and improves both the generator and the discriminator
  File "gan.py", line 91, in train_step
    discriminator_loss = get_discriminator_loss(real_output,fake_output)
  File "gan.py", line 48, in get_discriminator_loss
    return fake_loss real_loss
  File "/home/jake/.local/lib/python3.6/site-packages/tensorflow/python/ops/math_ops.py", line 1125, in binary_op_wrapper
    return func(x, y, name=name)
  File "/home/jake/.local/lib/python3.6/site-packages/tensorflow/python/util/dispatch.py", line 201, in wrapper
    return target(*args, **kwargs)
  File "/home/jake/.local/lib/python3.6/site-packages/tensorflow/python/ops/math_ops.py", line 1447, in _add_dispatch
    return gen_math_ops.add_v2(x, y, name=name)
  File "/home/jake/.local/lib/python3.6/site-packages/tensorflow/python/ops/gen_math_ops.py", line 486, in add_v2
    _ops.raise_from_not_ok_status(e, name)
  File "/home/jake/.local/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 6843, in raise_from_not_ok_status
    six.raise_from(core._status_to_exception(e.code, message), None)
  File "<string>", line 3, in raise_from
tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [100] vs. [13] [Op:AddV2]
  

Итак, из этого обратного вызова я могу сказать, что моя ошибка возникает во время моего get_discriminator_loss() итак, вот этот код.

 def get_discriminator_loss(real_predictions,fake_predictions):
    real_predictions = tf.sigmoid(real_predictions)
    fake_predictions = tf.sigmoid(fake_predictions)
    real_loss=tf.losses.binary_crossentropy(tf.ones_like(real_predictions),real_predictions)
    fake_loss=tf.losses.binary_crossentropy(tf.zeros_like(fake_predictions),fake_predictions)
    return fake_loss real_loss
  

У кого-нибудь есть какие-либо идеи? И помните, что это происходит после успешного запуска в течение примерно 2-3 минут. Ошибка не возникает в первые много проходов.

Я нашел источник своей ошибки, но я не знаю, почему это происходит.

Моя реальная потеря при одном из проходов имеет только 13 значений вместо обычных 100

Как это может быть?

Вот мой полный код.

     import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import time
import pickle

pickle_in_X = open("X.pickle","rb")
pickle_in_y = open("y.pickle","rb")

X=pickle.load(pickle_in_X)
y = pickle.load(pickle_in_y)
y = np.array(y)


X_train = X[  int(len(X)*.3):  ]
y_train = y[  int(len(y)*.3 ):  ]

X_test = X[  :int(len(X)*.3)  ]
y_test = X[  :int(len(y)*.3)    ]

X_train = (X_train-127.5)/127.5

BATCH_SIZE = 100
X_train_dataset = tf.data.Dataset.from_tensor_slices(X_train).batch(BATCH_SIZE)

#creates a discriminator model.
#discriminator will ouput 0-1 which represents the probability that the image is real
def make_discriminator():
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Conv2D(7,(3,3),padding="same",input_shape=(40,40,1)))
    model.add(tf.keras.layers.Flatten())
    model.add(tf.keras.layers.LeakyReLU())
    model.add(tf.keras.layers.Dense(50,activation="relu"))
    model.add(tf.keras.layers.Dense(1))
    return model

model_discriminator = make_discriminator()
discriminator_optimizer = tf.optimizers.Adam(1e-3)

#real_loss is the amount of error when trying to guess that the real images are in fact real. i.e loss will be if our discriminator guesses that there is a 100% chance that this real image is real
#fake_loss is the amount of error when trying to guess that the fake images are in fact fake. i.e loss will be zero if our discriminator guesses there is a 0% chance that this fake image is fake
#returns the total of our loss
def get_discriminator_loss(real_predictions,fake_predictions):
    real_predictions = tf.sigmoid(real_predictions)
    fake_predictions = tf.sigmoid(fake_predictions)
    real_loss=tf.losses.binary_crossentropy(tf.ones_like(real_predictions),real_predictions)
    fake_loss=tf.losses.binary_crossentropy(tf.zeros_like(fake_predictions),fake_predictions)
    return fake_loss real_loss

#take an input of a random string of numbers. and output either a dog or a cat
def make_generator():
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Dense(10*10*256,input_shape = (100,)))
    model.add(tf.keras.layers.BatchNormalization())
    model.add(tf.keras.layers.Reshape((10,10,256)))
    model.add(tf.keras.layers.Conv2DTranspose(128,(3,3),padding="same"))
    model.add(tf.keras.layers.BatchNormalization())
    model.add(tf.keras.layers.Conv2DTranspose(64,(3,3),strides=(2,2),padding="same"))
    model.add(tf.keras.layers.BatchNormalization())
    model.add(tf.keras.layers.Conv2DTranspose(1,(3,3),strides=(2,2),padding="same"))
    return model

model_generator = make_generator()

#generator gets rewarded when it fools the discriminator
def get_generator_loss(fake_predictions):
    fake_predictions = tf.sigmoid(fake_predictions)
    fake_loss=tf.losses.binary_crossentropy(tf.ones_like(fake_predictions),fake_predictions)
    return fake_loss

generator_optimizer = tf.optimizers.Adam(1e-3)


#training

def train(X_train_dataset,epochs):
    for _ in range(epochs):
        for images in X_train_dataset:
            images = tf.cast(images,tf.dtypes.float32)
            train_step(images) # takes images and improves both the generator and the discriminator


def train_step(images):
    fake_image_noise = np.random.randn(BATCH_SIZE,100)#produces 100 random numbers that wll be converted to images
    with tf.GradientTape() as generator_gradient, tf.GradientTape() as discriminator_gradient:
        generated_images = model_generator(fake_image_noise)
        real_output = model_discriminator(images)
        fake_output = model_discriminator(generated_images)

        generator_loss = get_generator_loss(fake_output)
        discriminator_loss = get_discriminator_loss(real_output,fake_output)

        gradients_of_generator = generator_gradient.gradient(generator_loss,model_generator.trainable_variables)#gradient of gen loss with respect to trainable variables
        gradients_of_discriminator = discriminator_gradient.gradient(discriminator_loss,model_discriminator.trainable_variables)
        
        discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator,model_discriminator.trainable_variables))
        generator_optimizer.apply_gradients(zip(gradients_of_generator,model_generator.trainable_variables))

        print("generator loss: ", np.mean(generator_loss))
        print("discriminator loss: ",np.mean(discriminator_loss))


train(X_train_dataset,200)

model_generator.save('genModel')

model_discriminator.save('discModel')
  

Комментарии:

1. Можете ли вы попробовать использовать tf.data.Dataset.from_tensor_slices(X_train).batch(BATCH_SIZE, drop_remainder=True) ? Это может быть из-за того, что пакет в конце эпохи меньше, чем другие пакеты.

2. @jakub большое вам спасибо. Я бы никогда не разобрался в этом самостоятельно.

Ответ №1:

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

 tf.data.Dataset.from_tensor_slices(X_train).batch(BATCH_SIZE, drop_remainder=True)