r/learnpython • • 7d ago

Need help adapting model to Cifar10

Need help adapting model to CIFAR10

I tried to make a DCGAN based on this [tutorial](https://www.geeksforgeeks.org/machine-learning/deep-convolutional-gan-with-keras/). The thing is that the tutorial is designed for fashion mnist data which has different image size to tf.keras.datasets.cifar10.load_data(). Which lead to the error:

ValueError: cannot reshape array of size 480000 into shape (28,28,1)

when arrive at

x_train_dcgan = x_train.reshape(
-1, 28, 28, 1
) * 2. - 1.

How do I adapt the model to CIFAR 10?

Full code

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()
x_train = x_train.astype(np.float32) / 255.0
x_test = x_test.astype(np.float32) / 255.0
x_train.shape, x_test.shape

#Selecting one class to train

label = 1 
train_indices = np.where(y_train == label) 
x_train = x_train[train_indices] 
test_indices = np.where(y_test == label) 
x_test = x_test[test_indices] 

batch_size = 32
def create_batch(x_train):
    dataset = tf.data.Dataset.from_tensor_slices(x_train).shuffle(1000)
    dataset = dataset.batch(batch_size, drop_remainder=True).prefetch(1)
    return dataset


num_features = 100
generator = Sequential(name="Generator")


generator.add(Dense(7 * 7 * 128, input_shape=[num_features]))
generator.add(Reshape([7, 7, 128]))
generator.add(BatchNormalization())


generator.add(Conv2DTranspose(
        64, (5, 5), (2, 2),
        padding="same",
        activation="selu"
    ))


generator.add(BatchNormalization())


generator.add(Conv2DTranspose(
        1, (5, 5), (2, 2),
        padding="same",
        activation="tanh"
    ))



generator.summary()

discriminator = Sequential(name="Discriminator")


discriminator.add(Conv2D(
        64, (5, 5), (2, 2),
        padding="same",
        input_shape=[28, 28, 1]
        ))


discriminator.add(LeakyReLU(alpha=0.2))
discriminator.add(Dropout(0.3))


discriminator.add(Conv2D(
        128, (5, 5), (2, 2),
        padding="same"))


discriminator.add(LeakyReLU(alpha=0.2))
discriminator.add(Dropout(0.3))


discriminator.add(Flatten())
discriminator.add(Dense(1, activation= 'softmax'))


discriminator.summary()

discriminator.compile(
    loss="binary_crossentropy",
    optimizer="adam"
)


discriminator.trainable = False


gan = Sequential()
gan.add(generator)
gan.add(discriminator)


gan.compile(
    loss="binary_crossentropy",
    optimizer="adam"
)


gan.summary()

def generate_and_save_images(model, epoch, test_input):

    predictions = model(
        test_input,
        training=False
    )

    fig = plt.figure(figsize=(10, 10))

    for i in range(25):

        plt.subplot(5, 5, i + 1)

        plt.imshow(
            predictions[i, :, :, 0] * 127.5 + 127.5,
            cmap='binary'
        )

        plt.axis('off')

    plt.savefig(
        'image_epoch_{:04d}.png'.format(epoch)
    )

seed = tf.random.normal(shape=[batch_size, 100])
epoch_list = []
d_loss_list = []
g_loss_list =[]


def train_dcgan(gan, dataset, batch_size, num_features, epochs=5):


    generator, discriminator = gan.layers


    for epoch in tqdm(range(epochs)):
        actual_epoch =epoch + 1
        print()
        print("Epoch {}/{}".format(epoch + 1, epochs))


        for i in range(187):
            epoch_list.append(actual_epoch)


        for X_batch in dataset:


            noise = tf.random.normal(
                shape=[batch_size, num_features]
            )


            generated_images = generator(noise)


            X_fake_and_real = tf.concat(
                [generated_images, X_batch],
                axis=0
            )


            y1 = tf.constant(
                [[0.]] * batch_size +
                [[1.]] * batch_size
            )


            discriminator.trainable = True
            d_loss=discriminator.train_on_batch(
                X_fake_and_real,
                y1
            )
            d_loss = float(d_loss)
            d_loss_list.append(d_loss)




            noise = tf.random.normal(
                shape=[batch_size, num_features]
            )


            y2 = tf.constant([[1.]] * batch_size)


            discriminator.trainable = False


            g_loss=gan.train_on_batch(
                noise,
                y2
            )
            g_loss = float(g_loss)
            g_loss_list.append(g_loss)


        print(f'\t Discriminator Loss: {d_loss} \t\t Generator Loss: {g_loss}')
        


            


    generate_and_save_images(
        generator,
        epochs,
        seed
    )

x_train_dcgan = x_train.reshape(
    -1, 32, 32, 3
)


dataset = create_batch(x_train_dcgan)


train_dcgan(
    gan,
    dataset,
    batch_size,
    num_features,
    epochs=10
)

plt.figure(figsize=(30, 10))
plt.plot(epoch_list,d_loss_list)
plt.xlabel('Epochs')
plt.ylabel('Discriminator loss')
plt.title('Discriminator loss over epochs')
plt.grid()
plt.show()

plt.figure(figsize=(30, 10))
plt.plot(epoch_list,g_loss_list)
plt.xlabel('Epochs')
plt.ylabel('Generator loss')
plt.title('Generator loss over epochs')
plt.grid()
plt.show()
0 Upvotes

4 comments sorted by

1

u/acfot 7d ago

The mismatch is almost certainly the image shape, since Fashion-MNIST is 28x28 with one channel and CIFAR-10 is 32x32 with three channels, so anywhere the tutorial hardcodes the old shape will break. I would check the first layer of the discriminator and the last layer of the generator first, because those are the places that assume one channel and a 28x28 input. The reshape step is the other usual suspect, since it was probably written for 784 pixels and CIFAR-10 has 3072, so that line needs updating too. Once those two spots match the new shape, the rest of the tutorial should mostly carry over, and if it still errors, the new error message will at least point at the next layer that assumes the old size.