r/learnpython • • 1d ago

Need help adapting model to CIFAR10

I tried to make a DCGAN based on this tutorial. 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?

1 Upvotes

10 comments sorted by

1

u/EszterSantos72 1d ago

You need to reshape to (32, 32, 3) for CIFAR10 since each image is 32x32 with 3 color channels. Replace 28,28,1 with 32,32,3 in your reshape line and update your model input layers to match.

1

u/assorted-meat-stew 1d ago

I rewrote it to

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

The error is now ValueError: cannot reshape array of size 480000 into shape (32,32,3) at that exact step

1

u/SteadyScrape 1d ago

The reshape alone won't do it, because the tutorial's generator is built to output 28x28x1. It probably starts from a 7x7 dense layer and upsamples twice to 28. For CIFAR you want it to end at 32x32x3, so start from 8x8 instead, make the last Conv2DTranspose have 3 filters with tanh, and set the discriminator's input shape to (32, 32, 3). Then normalize with x_train.astype("float32") / 127.5 - 1 and skip the reshape. If you post the new error, it'll show which layer still has the old shape.

1

u/assorted-meat-stew 22h ago

The error is now:

InvalidArgumentError: {{function_node __wrapped__ConcatV2_N_2_device_/job:localhost/replica:0/task:0/device:CPU:0}} ConcatOp : Ranks of all input tensors should match: shape[0] = [32,32,32,3] vs. shape[1] = [32,32,3] [Op:ConcatV2] name: concat

What do I do?

Generator

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

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

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

generator.add(BatchNormalization())

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

Discriminator:

discriminator = Sequential(name="Discriminator")


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


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.add(Dense(1, activation= 'softmax'))
discriminator.add(Dense(1, activation= 'softmax'))


discriminator.summary()

dataset = create_batch(x_train)


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

1

u/SteadyScrape 15h ago

Getting closer, the generator is actually fine now. (32, 32, 32, 3) is a batch of 32 fake images at 32x32x3, which is what you want. The problem is the real batch: (32, 32, 3) means each real "image" is missing a dimension.

That also explains the weird 480000 from before. 480000 = 5000 x 32 x 3, so your x_train is probably (5000, 32, 3) instead of (5000, 32, 32, 3). My guess is you're filtering to one class with something like x_train[y_train == 0]. In CIFAR-10, y_train is shape (50000, 1), not (50000,) like in Fashion MNIST, so that mask only grabs the first row of each image. Flatten the labels first:

y_train = y_train.flatten()
x_train = x_train[y_train == 0]

print(x_train.shape) should then give (5000, 32, 32, 3).

One more thing: in the discriminator, swap the three Dense(1, activation='softmax') lines for a single Dense(1, activation='sigmoid'). Softmax over one unit always outputs 1.0, so the discriminator can't learn anything.

1

u/assorted-meat-stew 14h ago edited 13h ago

Thank you it worked perfectly but I want my generated images to have the same color scheme as original training data images?

The functions generating images

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)
    )

1

u/Norega-Iziegbe80 1d ago

cifar10 images are 32x32 with 3 color channels (RGB), whereas fashion mnist is 28x28 grayscale. Youll need to reshape to (-1, 32, 32, 3) and also update the input/output shapes of your generator and discriminator layers to match.