Menu iconMenu icon
Aprendizaje Profundo Generativo Edición Actualizada

Capítulo 2: Comprendiendo los Modelos Generativos

Ejercicios Prácticos

Ejercicio 1: Implementar una GAN Simple

Tarea: Implementa una GAN simple para generar nuevas muestras del conjunto de datos MNIST. Utiliza el ejemplo proporcionado en la sección 2.2.1 y modifícalo para incluir una capa adicional tanto en el generador como en el discriminador.

Solución:

import tensorflow as tf
from tensorflow.keras.layers import Dense, LeakyReLU, Reshape, Flatten, Dropout
from tensorflow.keras.models import Sequential
import numpy as np
import matplotlib.pyplot as plt

# Generator model
def build_generator():
    model = Sequential([
        Dense(256, input_dim=100),
        LeakyReLU(alpha=0.2),
        Dense(512),
        LeakyReLU(alpha=0.2),
        Dense(1024),
        LeakyReLU(alpha=0.2),
        Dense(28 * 28, activation='tanh'),
        Reshape((28, 28, 1))
    ])
    return model

# Discriminator model
def build_discriminator():
    model = Sequential([
        Flatten(input_shape=(28, 28, 1)),
        Dense(1024),
        LeakyReLU(alpha=0.2),
        Dropout(0.3),
        Dense(512),
        LeakyReLU(alpha=0.2),
        Dropout(0.3),
        Dense(256),
        LeakyReLU(alpha=0.2),
        Dropout(0.3),
        Dense(1, activation='sigmoid')
    ])
    return model

# Build and compile the GAN
generator = build_generator()
discriminator = build_discriminator()
discriminator.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

# GAN model
discriminator.trainable = False
gan_input = tf.keras.Input(shape=(100,))
gan_output = discriminator(generator(gan_input))
gan = tf.keras.Model(gan_input, gan_output)
gan.compile(optimizer='adam', loss='binary_crossentropy')

# Training the GAN
(x_train, _), (_, _) = tf.keras.datasets.mnist.load_data()
x_train = (x_train.astype(np.float32) - 127.5) / 127.5  # Normalize to [-1, 1]
x_train = np.expand_dims(x_train, axis=-1)
batch_size = 64
epochs = 10000

for epoch in range(epochs):
    # Train discriminator
    idx = np.random.randint(0, x_train.shape[0], batch_size)
    real_images = x_train[idx]
    noise = np.random.normal(0, 1, (batch_size, 100))
    fake_images = generator.predict(noise)
    d_loss_real = discriminator.train_on_batch(real_images, np.ones((batch_size, 1)))
    d_loss_fake = discriminator.train_on_batch(fake_images, np.zeros((batch_size, 1)))
    d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)

    # Train generator
    noise = np.random.normal(0, 1, (batch_size, 100))
    g_loss = gan.train_on_batch(noise, np.ones((batch_size, 1)))

    # Print progress
    if epoch % 1000 == 0:
        print(f"{epoch} [D loss: {d_loss[0]}, acc.: {d_loss[1] * 100}%] [G loss: {g_loss}]")

# Generate new samples
noise = np.random.normal(0, 1, (10, 100))
generated_images = generator.predict(noise)

# Plot generated images
fig, axs = plt.subplots(1, 10, figsize=(20, 2))
for i, img in enumerate(generated_images):
    axs[i].imshow(img.squeeze(), cmap='gray')
    axs[i].axis('off')
plt.show()

Ejercicio 2: Ajustar Fino un Modelo GPT-4 Preentrenado

Tarea: Ajustar fino un modelo GPT-4 preentrenado para una tarea específica de generación de texto utilizando la API de OpenAI. Usa un prompt personalizado y genera texto basado en ese prompt.

Solución:

import openai

# Set your OpenAI API key
openai.api_key = 'your-api-key-here'

# Define the prompt for GPT-4
prompt = "In a futuristic city, the AI robots started to develop their own consciousness. One day,"

# Generate text using GPT-4
response = openai.Completion.create(
    engine="gpt-4",
    prompt=prompt,
    max_tokens=100,
    n=1,
    stop=None,
    temperature=0.7
)

# Extract the generated text
generated_text = response.choices[0].text.strip()
print(generated_text)

Ejercicio 3: Implementar un VAE Simple

Tarea: Implementa un VAE simple para generar nuevas muestras del conjunto de datos MNIST. Utiliza el ejemplo proporcionado en la sección 2.2.2 y modifícalo para incluir capas adicionales tanto en el codificador como en el decodificador.

Solución:

import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten, Reshape, Lambda, Input, Conv2D, Conv2DTranspose
from tensorflow.keras.models import Model
from tensorflow.keras.losses import binary_crossentropy
from tensorflow.keras import backend as K
import numpy as np
import matplotlib.pyplot as plt

# Sampling function
def sampling(args):
    z_mean, z_log_var = args
    batch = tf.shape(z_mean)[0]
    dim = tf.shape(z_mean)[1]
    epsilon = tf.keras.backend.random_normal(shape=(batch, dim))
    return z_mean + K.exp(0.5 * z_log_var) * epsilon

# Encoder model
input_img = Input(shape=(28, 28, 1))
x = Conv2D(32, 3, activation='relu', padding='same')(input_img)
x = Conv2D(64, 3, activation='relu', padding='same', strides=2)(x)
x = Conv2D(128, 3, activation='relu', padding='same', strides=2)(x)
x = Flatten()(x)
x = Dense(256, activation='relu')(x)
z_mean = Dense(2)(x)
z_log_var = Dense(2)(x)
z = Lambda(sampling, output_shape=(2,))([z_mean, z_log_var])
encoder = Model(input_img, z)

# Decoder model
decoder_input = Input(shape=(2,))
x = Dense(7*7*128, activation='relu')(decoder_input)
x = Reshape((7, 7, 128))(x)
x = Conv2DTranspose(128, 3, activation='relu', padding='same', strides=2)(x)
x = Conv2DTranspose(64, 3, activation='relu', padding='same', strides=2)(x)
x = Conv2DTranspose(32, 3, activation='relu', padding='same')(x)
output_img = Conv2DTranspose(1, 3, activation='sigmoid', padding='same')(x)
decoder = Model(decoder_input, output_img)

# VAE model
output_img = decoder(encoder(input_img))
vae = Model(input_img, output_img)

# VAE loss function
reconstruction_loss = binary_crossentropy(K.flatten(input_img), K.flatten(output_img))
reconstruction_loss *= 28 * 28
kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
kl_loss = K.sum(kl_loss, axis=-1)
kl_loss *= -0.5
vae_loss = K.mean(reconstruction_loss + kl_loss)
vae.add_loss(vae_loss)
vae.compile(optimizer='adam')

# Training the VAE
(x_train, _), (_, _) = tf.keras.datasets.mnist.load_data()
x_train = (x_train.astype(np.float32) / 255.0) - 0.5
x_train = np.expand_dims(x_train, axis=-1)
vae.fit(x_train, epochs=50, batch_size=128, verbose=1)

# Generate new samples
z_sample = np.array([[0.0, 0.0]])
generated_image = decoder.predict(z_sample)

# Plot generated image
plt.imshow(generated_image[0].squeeze(), cmap='gray')
plt.axis('off')
plt.show()

Ejercicio 4: Aplicar Normalización Espectral a un Discriminador

Tarea: Implementa la normalización espectral en un modelo de discriminador simple. Utiliza el ejemplo proporcionado en la sección 2.3.2 y asegúrate de que el discriminador se aplique al conjunto de datos MNIST.

Solución:

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt

# Define a simple discriminator with spectral normalization
class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.model = nn.Sequential(
            nn.utils.spectral_norm(nn.Conv2d(1, 64, 4, stride=2, padding=1)),
            nn.LeakyReLU(0.2, inplace=True),
            nn.utils.spectral_norm(nn.Conv2d(64, 128, 4, stride=2, padding=1)),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Flatten(),
            nn.utils.spectral_norm(nn.Linear(128 * 7 * 7, 1))
        )

    def forward(self, x):
        return self.model(x)

# Load MNIST dataset
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,),

 (0.5,))
])
dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
dataloader = DataLoader(dataset, batch_size=64, shuffle=True)

# Instantiate the discriminator
discriminator = Discriminator()
optimizer = optim.Adam(discriminator.parameters(), lr=0.0002)
criterion = nn.BCELoss()

# Training loop
num_epochs = 5
for epoch in range(num_epochs):
    for images, _ in dataloader:
        optimizer.zero_grad()
        labels = torch.ones(images.size(0), 1)
        outputs = discriminator(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

# Generate fake data (for demonstration purposes)
noise = torch.randn(64, 1, 28, 28)
fake_images = noise

# Evaluate discriminator on fake data
with torch.no_grad():
    fake_outputs = discriminator(fake_images)
    print("Discriminator output on fake images:", fake_outputs[:5])

Ejercicio 5: Implementar una GAN 3D para la Generación de Objetos Basados en Vóxeles

Tarea: Implementa una GAN 3D simple para generar objetos basados en vóxeles. Utiliza el ejemplo proporcionado en la sección 2.3.3 y visualiza los objetos 3D generados.

Solución:

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Define a simple 3D GAN for voxel-based object generation
class VoxelGenerator(nn.Module):
    def __init__(self):
        super(VoxelGenerator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(100, 128),
            nn.ReLU(inplace=True),
            nn.Linear(128, 256),
            nn.ReLU(inplace=True),
            nn.Linear(256, 512),
            nn.ReLU(inplace=True),
            nn.Linear(512, 32*32*32),
            nn.Tanh()
        )

    def forward(self, z):
        return self.model(z).view(-1, 32, 32, 32)

# Instantiate the generator
voxel_generator = VoxelGenerator()

# Generate random latent vectors
num_voxels = 5
latent_vectors = torch.randn(num_voxels, 100)

# Generate 3D voxel objects
generated_voxels = voxel_generator(latent_vectors)

# Visualize the generated 3D objects
fig = plt.figure(figsize=(15, 15))
for i in range(num_voxels):
    ax = fig.add_subplot(1, num_voxels, i+1, projection='3d')
    ax.voxels(generated_voxels[i].detach().numpy() > 0, edgecolor='k')
    ax.axis('off')

plt.show()

Estos ejercicios prácticos deberían ayudar a reforzar tu comprensión de los conceptos cubiertos en este capítulo. Al implementar estos modelos y experimentar con diferentes configuraciones, obtendrás experiencia práctica con los modelos generativos y sus aplicaciones prácticas. ¡Sigue practicando y no dudes en explorar más por tu cuenta!

Ejercicios Prácticos

Ejercicio 1: Implementar una GAN Simple

Tarea: Implementa una GAN simple para generar nuevas muestras del conjunto de datos MNIST. Utiliza el ejemplo proporcionado en la sección 2.2.1 y modifícalo para incluir una capa adicional tanto en el generador como en el discriminador.

Solución:

import tensorflow as tf
from tensorflow.keras.layers import Dense, LeakyReLU, Reshape, Flatten, Dropout
from tensorflow.keras.models import Sequential
import numpy as np
import matplotlib.pyplot as plt

# Generator model
def build_generator():
    model = Sequential([
        Dense(256, input_dim=100),
        LeakyReLU(alpha=0.2),
        Dense(512),
        LeakyReLU(alpha=0.2),
        Dense(1024),
        LeakyReLU(alpha=0.2),
        Dense(28 * 28, activation='tanh'),
        Reshape((28, 28, 1))
    ])
    return model

# Discriminator model
def build_discriminator():
    model = Sequential([
        Flatten(input_shape=(28, 28, 1)),
        Dense(1024),
        LeakyReLU(alpha=0.2),
        Dropout(0.3),
        Dense(512),
        LeakyReLU(alpha=0.2),
        Dropout(0.3),
        Dense(256),
        LeakyReLU(alpha=0.2),
        Dropout(0.3),
        Dense(1, activation='sigmoid')
    ])
    return model

# Build and compile the GAN
generator = build_generator()
discriminator = build_discriminator()
discriminator.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

# GAN model
discriminator.trainable = False
gan_input = tf.keras.Input(shape=(100,))
gan_output = discriminator(generator(gan_input))
gan = tf.keras.Model(gan_input, gan_output)
gan.compile(optimizer='adam', loss='binary_crossentropy')

# Training the GAN
(x_train, _), (_, _) = tf.keras.datasets.mnist.load_data()
x_train = (x_train.astype(np.float32) - 127.5) / 127.5  # Normalize to [-1, 1]
x_train = np.expand_dims(x_train, axis=-1)
batch_size = 64
epochs = 10000

for epoch in range(epochs):
    # Train discriminator
    idx = np.random.randint(0, x_train.shape[0], batch_size)
    real_images = x_train[idx]
    noise = np.random.normal(0, 1, (batch_size, 100))
    fake_images = generator.predict(noise)
    d_loss_real = discriminator.train_on_batch(real_images, np.ones((batch_size, 1)))
    d_loss_fake = discriminator.train_on_batch(fake_images, np.zeros((batch_size, 1)))
    d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)

    # Train generator
    noise = np.random.normal(0, 1, (batch_size, 100))
    g_loss = gan.train_on_batch(noise, np.ones((batch_size, 1)))

    # Print progress
    if epoch % 1000 == 0:
        print(f"{epoch} [D loss: {d_loss[0]}, acc.: {d_loss[1] * 100}%] [G loss: {g_loss}]")

# Generate new samples
noise = np.random.normal(0, 1, (10, 100))
generated_images = generator.predict(noise)

# Plot generated images
fig, axs = plt.subplots(1, 10, figsize=(20, 2))
for i, img in enumerate(generated_images):
    axs[i].imshow(img.squeeze(), cmap='gray')
    axs[i].axis('off')
plt.show()

Ejercicio 2: Ajustar Fino un Modelo GPT-4 Preentrenado

Tarea: Ajustar fino un modelo GPT-4 preentrenado para una tarea específica de generación de texto utilizando la API de OpenAI. Usa un prompt personalizado y genera texto basado en ese prompt.

Solución:

import openai

# Set your OpenAI API key
openai.api_key = 'your-api-key-here'

# Define the prompt for GPT-4
prompt = "In a futuristic city, the AI robots started to develop their own consciousness. One day,"

# Generate text using GPT-4
response = openai.Completion.create(
    engine="gpt-4",
    prompt=prompt,
    max_tokens=100,
    n=1,
    stop=None,
    temperature=0.7
)

# Extract the generated text
generated_text = response.choices[0].text.strip()
print(generated_text)

Ejercicio 3: Implementar un VAE Simple

Tarea: Implementa un VAE simple para generar nuevas muestras del conjunto de datos MNIST. Utiliza el ejemplo proporcionado en la sección 2.2.2 y modifícalo para incluir capas adicionales tanto en el codificador como en el decodificador.

Solución:

import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten, Reshape, Lambda, Input, Conv2D, Conv2DTranspose
from tensorflow.keras.models import Model
from tensorflow.keras.losses import binary_crossentropy
from tensorflow.keras import backend as K
import numpy as np
import matplotlib.pyplot as plt

# Sampling function
def sampling(args):
    z_mean, z_log_var = args
    batch = tf.shape(z_mean)[0]
    dim = tf.shape(z_mean)[1]
    epsilon = tf.keras.backend.random_normal(shape=(batch, dim))
    return z_mean + K.exp(0.5 * z_log_var) * epsilon

# Encoder model
input_img = Input(shape=(28, 28, 1))
x = Conv2D(32, 3, activation='relu', padding='same')(input_img)
x = Conv2D(64, 3, activation='relu', padding='same', strides=2)(x)
x = Conv2D(128, 3, activation='relu', padding='same', strides=2)(x)
x = Flatten()(x)
x = Dense(256, activation='relu')(x)
z_mean = Dense(2)(x)
z_log_var = Dense(2)(x)
z = Lambda(sampling, output_shape=(2,))([z_mean, z_log_var])
encoder = Model(input_img, z)

# Decoder model
decoder_input = Input(shape=(2,))
x = Dense(7*7*128, activation='relu')(decoder_input)
x = Reshape((7, 7, 128))(x)
x = Conv2DTranspose(128, 3, activation='relu', padding='same', strides=2)(x)
x = Conv2DTranspose(64, 3, activation='relu', padding='same', strides=2)(x)
x = Conv2DTranspose(32, 3, activation='relu', padding='same')(x)
output_img = Conv2DTranspose(1, 3, activation='sigmoid', padding='same')(x)
decoder = Model(decoder_input, output_img)

# VAE model
output_img = decoder(encoder(input_img))
vae = Model(input_img, output_img)

# VAE loss function
reconstruction_loss = binary_crossentropy(K.flatten(input_img), K.flatten(output_img))
reconstruction_loss *= 28 * 28
kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
kl_loss = K.sum(kl_loss, axis=-1)
kl_loss *= -0.5
vae_loss = K.mean(reconstruction_loss + kl_loss)
vae.add_loss(vae_loss)
vae.compile(optimizer='adam')

# Training the VAE
(x_train, _), (_, _) = tf.keras.datasets.mnist.load_data()
x_train = (x_train.astype(np.float32) / 255.0) - 0.5
x_train = np.expand_dims(x_train, axis=-1)
vae.fit(x_train, epochs=50, batch_size=128, verbose=1)

# Generate new samples
z_sample = np.array([[0.0, 0.0]])
generated_image = decoder.predict(z_sample)

# Plot generated image
plt.imshow(generated_image[0].squeeze(), cmap='gray')
plt.axis('off')
plt.show()

Ejercicio 4: Aplicar Normalización Espectral a un Discriminador

Tarea: Implementa la normalización espectral en un modelo de discriminador simple. Utiliza el ejemplo proporcionado en la sección 2.3.2 y asegúrate de que el discriminador se aplique al conjunto de datos MNIST.

Solución:

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt

# Define a simple discriminator with spectral normalization
class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.model = nn.Sequential(
            nn.utils.spectral_norm(nn.Conv2d(1, 64, 4, stride=2, padding=1)),
            nn.LeakyReLU(0.2, inplace=True),
            nn.utils.spectral_norm(nn.Conv2d(64, 128, 4, stride=2, padding=1)),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Flatten(),
            nn.utils.spectral_norm(nn.Linear(128 * 7 * 7, 1))
        )

    def forward(self, x):
        return self.model(x)

# Load MNIST dataset
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,),

 (0.5,))
])
dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
dataloader = DataLoader(dataset, batch_size=64, shuffle=True)

# Instantiate the discriminator
discriminator = Discriminator()
optimizer = optim.Adam(discriminator.parameters(), lr=0.0002)
criterion = nn.BCELoss()

# Training loop
num_epochs = 5
for epoch in range(num_epochs):
    for images, _ in dataloader:
        optimizer.zero_grad()
        labels = torch.ones(images.size(0), 1)
        outputs = discriminator(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

# Generate fake data (for demonstration purposes)
noise = torch.randn(64, 1, 28, 28)
fake_images = noise

# Evaluate discriminator on fake data
with torch.no_grad():
    fake_outputs = discriminator(fake_images)
    print("Discriminator output on fake images:", fake_outputs[:5])

Ejercicio 5: Implementar una GAN 3D para la Generación de Objetos Basados en Vóxeles

Tarea: Implementa una GAN 3D simple para generar objetos basados en vóxeles. Utiliza el ejemplo proporcionado en la sección 2.3.3 y visualiza los objetos 3D generados.

Solución:

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Define a simple 3D GAN for voxel-based object generation
class VoxelGenerator(nn.Module):
    def __init__(self):
        super(VoxelGenerator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(100, 128),
            nn.ReLU(inplace=True),
            nn.Linear(128, 256),
            nn.ReLU(inplace=True),
            nn.Linear(256, 512),
            nn.ReLU(inplace=True),
            nn.Linear(512, 32*32*32),
            nn.Tanh()
        )

    def forward(self, z):
        return self.model(z).view(-1, 32, 32, 32)

# Instantiate the generator
voxel_generator = VoxelGenerator()

# Generate random latent vectors
num_voxels = 5
latent_vectors = torch.randn(num_voxels, 100)

# Generate 3D voxel objects
generated_voxels = voxel_generator(latent_vectors)

# Visualize the generated 3D objects
fig = plt.figure(figsize=(15, 15))
for i in range(num_voxels):
    ax = fig.add_subplot(1, num_voxels, i+1, projection='3d')
    ax.voxels(generated_voxels[i].detach().numpy() > 0, edgecolor='k')
    ax.axis('off')

plt.show()

Estos ejercicios prácticos deberían ayudar a reforzar tu comprensión de los conceptos cubiertos en este capítulo. Al implementar estos modelos y experimentar con diferentes configuraciones, obtendrás experiencia práctica con los modelos generativos y sus aplicaciones prácticas. ¡Sigue practicando y no dudes en explorar más por tu cuenta!

Ejercicios Prácticos

Ejercicio 1: Implementar una GAN Simple

Tarea: Implementa una GAN simple para generar nuevas muestras del conjunto de datos MNIST. Utiliza el ejemplo proporcionado en la sección 2.2.1 y modifícalo para incluir una capa adicional tanto en el generador como en el discriminador.

Solución:

import tensorflow as tf
from tensorflow.keras.layers import Dense, LeakyReLU, Reshape, Flatten, Dropout
from tensorflow.keras.models import Sequential
import numpy as np
import matplotlib.pyplot as plt

# Generator model
def build_generator():
    model = Sequential([
        Dense(256, input_dim=100),
        LeakyReLU(alpha=0.2),
        Dense(512),
        LeakyReLU(alpha=0.2),
        Dense(1024),
        LeakyReLU(alpha=0.2),
        Dense(28 * 28, activation='tanh'),
        Reshape((28, 28, 1))
    ])
    return model

# Discriminator model
def build_discriminator():
    model = Sequential([
        Flatten(input_shape=(28, 28, 1)),
        Dense(1024),
        LeakyReLU(alpha=0.2),
        Dropout(0.3),
        Dense(512),
        LeakyReLU(alpha=0.2),
        Dropout(0.3),
        Dense(256),
        LeakyReLU(alpha=0.2),
        Dropout(0.3),
        Dense(1, activation='sigmoid')
    ])
    return model

# Build and compile the GAN
generator = build_generator()
discriminator = build_discriminator()
discriminator.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

# GAN model
discriminator.trainable = False
gan_input = tf.keras.Input(shape=(100,))
gan_output = discriminator(generator(gan_input))
gan = tf.keras.Model(gan_input, gan_output)
gan.compile(optimizer='adam', loss='binary_crossentropy')

# Training the GAN
(x_train, _), (_, _) = tf.keras.datasets.mnist.load_data()
x_train = (x_train.astype(np.float32) - 127.5) / 127.5  # Normalize to [-1, 1]
x_train = np.expand_dims(x_train, axis=-1)
batch_size = 64
epochs = 10000

for epoch in range(epochs):
    # Train discriminator
    idx = np.random.randint(0, x_train.shape[0], batch_size)
    real_images = x_train[idx]
    noise = np.random.normal(0, 1, (batch_size, 100))
    fake_images = generator.predict(noise)
    d_loss_real = discriminator.train_on_batch(real_images, np.ones((batch_size, 1)))
    d_loss_fake = discriminator.train_on_batch(fake_images, np.zeros((batch_size, 1)))
    d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)

    # Train generator
    noise = np.random.normal(0, 1, (batch_size, 100))
    g_loss = gan.train_on_batch(noise, np.ones((batch_size, 1)))

    # Print progress
    if epoch % 1000 == 0:
        print(f"{epoch} [D loss: {d_loss[0]}, acc.: {d_loss[1] * 100}%] [G loss: {g_loss}]")

# Generate new samples
noise = np.random.normal(0, 1, (10, 100))
generated_images = generator.predict(noise)

# Plot generated images
fig, axs = plt.subplots(1, 10, figsize=(20, 2))
for i, img in enumerate(generated_images):
    axs[i].imshow(img.squeeze(), cmap='gray')
    axs[i].axis('off')
plt.show()

Ejercicio 2: Ajustar Fino un Modelo GPT-4 Preentrenado

Tarea: Ajustar fino un modelo GPT-4 preentrenado para una tarea específica de generación de texto utilizando la API de OpenAI. Usa un prompt personalizado y genera texto basado en ese prompt.

Solución:

import openai

# Set your OpenAI API key
openai.api_key = 'your-api-key-here'

# Define the prompt for GPT-4
prompt = "In a futuristic city, the AI robots started to develop their own consciousness. One day,"

# Generate text using GPT-4
response = openai.Completion.create(
    engine="gpt-4",
    prompt=prompt,
    max_tokens=100,
    n=1,
    stop=None,
    temperature=0.7
)

# Extract the generated text
generated_text = response.choices[0].text.strip()
print(generated_text)

Ejercicio 3: Implementar un VAE Simple

Tarea: Implementa un VAE simple para generar nuevas muestras del conjunto de datos MNIST. Utiliza el ejemplo proporcionado en la sección 2.2.2 y modifícalo para incluir capas adicionales tanto en el codificador como en el decodificador.

Solución:

import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten, Reshape, Lambda, Input, Conv2D, Conv2DTranspose
from tensorflow.keras.models import Model
from tensorflow.keras.losses import binary_crossentropy
from tensorflow.keras import backend as K
import numpy as np
import matplotlib.pyplot as plt

# Sampling function
def sampling(args):
    z_mean, z_log_var = args
    batch = tf.shape(z_mean)[0]
    dim = tf.shape(z_mean)[1]
    epsilon = tf.keras.backend.random_normal(shape=(batch, dim))
    return z_mean + K.exp(0.5 * z_log_var) * epsilon

# Encoder model
input_img = Input(shape=(28, 28, 1))
x = Conv2D(32, 3, activation='relu', padding='same')(input_img)
x = Conv2D(64, 3, activation='relu', padding='same', strides=2)(x)
x = Conv2D(128, 3, activation='relu', padding='same', strides=2)(x)
x = Flatten()(x)
x = Dense(256, activation='relu')(x)
z_mean = Dense(2)(x)
z_log_var = Dense(2)(x)
z = Lambda(sampling, output_shape=(2,))([z_mean, z_log_var])
encoder = Model(input_img, z)

# Decoder model
decoder_input = Input(shape=(2,))
x = Dense(7*7*128, activation='relu')(decoder_input)
x = Reshape((7, 7, 128))(x)
x = Conv2DTranspose(128, 3, activation='relu', padding='same', strides=2)(x)
x = Conv2DTranspose(64, 3, activation='relu', padding='same', strides=2)(x)
x = Conv2DTranspose(32, 3, activation='relu', padding='same')(x)
output_img = Conv2DTranspose(1, 3, activation='sigmoid', padding='same')(x)
decoder = Model(decoder_input, output_img)

# VAE model
output_img = decoder(encoder(input_img))
vae = Model(input_img, output_img)

# VAE loss function
reconstruction_loss = binary_crossentropy(K.flatten(input_img), K.flatten(output_img))
reconstruction_loss *= 28 * 28
kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
kl_loss = K.sum(kl_loss, axis=-1)
kl_loss *= -0.5
vae_loss = K.mean(reconstruction_loss + kl_loss)
vae.add_loss(vae_loss)
vae.compile(optimizer='adam')

# Training the VAE
(x_train, _), (_, _) = tf.keras.datasets.mnist.load_data()
x_train = (x_train.astype(np.float32) / 255.0) - 0.5
x_train = np.expand_dims(x_train, axis=-1)
vae.fit(x_train, epochs=50, batch_size=128, verbose=1)

# Generate new samples
z_sample = np.array([[0.0, 0.0]])
generated_image = decoder.predict(z_sample)

# Plot generated image
plt.imshow(generated_image[0].squeeze(), cmap='gray')
plt.axis('off')
plt.show()

Ejercicio 4: Aplicar Normalización Espectral a un Discriminador

Tarea: Implementa la normalización espectral en un modelo de discriminador simple. Utiliza el ejemplo proporcionado en la sección 2.3.2 y asegúrate de que el discriminador se aplique al conjunto de datos MNIST.

Solución:

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt

# Define a simple discriminator with spectral normalization
class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.model = nn.Sequential(
            nn.utils.spectral_norm(nn.Conv2d(1, 64, 4, stride=2, padding=1)),
            nn.LeakyReLU(0.2, inplace=True),
            nn.utils.spectral_norm(nn.Conv2d(64, 128, 4, stride=2, padding=1)),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Flatten(),
            nn.utils.spectral_norm(nn.Linear(128 * 7 * 7, 1))
        )

    def forward(self, x):
        return self.model(x)

# Load MNIST dataset
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,),

 (0.5,))
])
dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
dataloader = DataLoader(dataset, batch_size=64, shuffle=True)

# Instantiate the discriminator
discriminator = Discriminator()
optimizer = optim.Adam(discriminator.parameters(), lr=0.0002)
criterion = nn.BCELoss()

# Training loop
num_epochs = 5
for epoch in range(num_epochs):
    for images, _ in dataloader:
        optimizer.zero_grad()
        labels = torch.ones(images.size(0), 1)
        outputs = discriminator(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

# Generate fake data (for demonstration purposes)
noise = torch.randn(64, 1, 28, 28)
fake_images = noise

# Evaluate discriminator on fake data
with torch.no_grad():
    fake_outputs = discriminator(fake_images)
    print("Discriminator output on fake images:", fake_outputs[:5])

Ejercicio 5: Implementar una GAN 3D para la Generación de Objetos Basados en Vóxeles

Tarea: Implementa una GAN 3D simple para generar objetos basados en vóxeles. Utiliza el ejemplo proporcionado en la sección 2.3.3 y visualiza los objetos 3D generados.

Solución:

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Define a simple 3D GAN for voxel-based object generation
class VoxelGenerator(nn.Module):
    def __init__(self):
        super(VoxelGenerator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(100, 128),
            nn.ReLU(inplace=True),
            nn.Linear(128, 256),
            nn.ReLU(inplace=True),
            nn.Linear(256, 512),
            nn.ReLU(inplace=True),
            nn.Linear(512, 32*32*32),
            nn.Tanh()
        )

    def forward(self, z):
        return self.model(z).view(-1, 32, 32, 32)

# Instantiate the generator
voxel_generator = VoxelGenerator()

# Generate random latent vectors
num_voxels = 5
latent_vectors = torch.randn(num_voxels, 100)

# Generate 3D voxel objects
generated_voxels = voxel_generator(latent_vectors)

# Visualize the generated 3D objects
fig = plt.figure(figsize=(15, 15))
for i in range(num_voxels):
    ax = fig.add_subplot(1, num_voxels, i+1, projection='3d')
    ax.voxels(generated_voxels[i].detach().numpy() > 0, edgecolor='k')
    ax.axis('off')

plt.show()

Estos ejercicios prácticos deberían ayudar a reforzar tu comprensión de los conceptos cubiertos en este capítulo. Al implementar estos modelos y experimentar con diferentes configuraciones, obtendrás experiencia práctica con los modelos generativos y sus aplicaciones prácticas. ¡Sigue practicando y no dudes en explorar más por tu cuenta!

Ejercicios Prácticos

Ejercicio 1: Implementar una GAN Simple

Tarea: Implementa una GAN simple para generar nuevas muestras del conjunto de datos MNIST. Utiliza el ejemplo proporcionado en la sección 2.2.1 y modifícalo para incluir una capa adicional tanto en el generador como en el discriminador.

Solución:

import tensorflow as tf
from tensorflow.keras.layers import Dense, LeakyReLU, Reshape, Flatten, Dropout
from tensorflow.keras.models import Sequential
import numpy as np
import matplotlib.pyplot as plt

# Generator model
def build_generator():
    model = Sequential([
        Dense(256, input_dim=100),
        LeakyReLU(alpha=0.2),
        Dense(512),
        LeakyReLU(alpha=0.2),
        Dense(1024),
        LeakyReLU(alpha=0.2),
        Dense(28 * 28, activation='tanh'),
        Reshape((28, 28, 1))
    ])
    return model

# Discriminator model
def build_discriminator():
    model = Sequential([
        Flatten(input_shape=(28, 28, 1)),
        Dense(1024),
        LeakyReLU(alpha=0.2),
        Dropout(0.3),
        Dense(512),
        LeakyReLU(alpha=0.2),
        Dropout(0.3),
        Dense(256),
        LeakyReLU(alpha=0.2),
        Dropout(0.3),
        Dense(1, activation='sigmoid')
    ])
    return model

# Build and compile the GAN
generator = build_generator()
discriminator = build_discriminator()
discriminator.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

# GAN model
discriminator.trainable = False
gan_input = tf.keras.Input(shape=(100,))
gan_output = discriminator(generator(gan_input))
gan = tf.keras.Model(gan_input, gan_output)
gan.compile(optimizer='adam', loss='binary_crossentropy')

# Training the GAN
(x_train, _), (_, _) = tf.keras.datasets.mnist.load_data()
x_train = (x_train.astype(np.float32) - 127.5) / 127.5  # Normalize to [-1, 1]
x_train = np.expand_dims(x_train, axis=-1)
batch_size = 64
epochs = 10000

for epoch in range(epochs):
    # Train discriminator
    idx = np.random.randint(0, x_train.shape[0], batch_size)
    real_images = x_train[idx]
    noise = np.random.normal(0, 1, (batch_size, 100))
    fake_images = generator.predict(noise)
    d_loss_real = discriminator.train_on_batch(real_images, np.ones((batch_size, 1)))
    d_loss_fake = discriminator.train_on_batch(fake_images, np.zeros((batch_size, 1)))
    d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)

    # Train generator
    noise = np.random.normal(0, 1, (batch_size, 100))
    g_loss = gan.train_on_batch(noise, np.ones((batch_size, 1)))

    # Print progress
    if epoch % 1000 == 0:
        print(f"{epoch} [D loss: {d_loss[0]}, acc.: {d_loss[1] * 100}%] [G loss: {g_loss}]")

# Generate new samples
noise = np.random.normal(0, 1, (10, 100))
generated_images = generator.predict(noise)

# Plot generated images
fig, axs = plt.subplots(1, 10, figsize=(20, 2))
for i, img in enumerate(generated_images):
    axs[i].imshow(img.squeeze(), cmap='gray')
    axs[i].axis('off')
plt.show()

Ejercicio 2: Ajustar Fino un Modelo GPT-4 Preentrenado

Tarea: Ajustar fino un modelo GPT-4 preentrenado para una tarea específica de generación de texto utilizando la API de OpenAI. Usa un prompt personalizado y genera texto basado en ese prompt.

Solución:

import openai

# Set your OpenAI API key
openai.api_key = 'your-api-key-here'

# Define the prompt for GPT-4
prompt = "In a futuristic city, the AI robots started to develop their own consciousness. One day,"

# Generate text using GPT-4
response = openai.Completion.create(
    engine="gpt-4",
    prompt=prompt,
    max_tokens=100,
    n=1,
    stop=None,
    temperature=0.7
)

# Extract the generated text
generated_text = response.choices[0].text.strip()
print(generated_text)

Ejercicio 3: Implementar un VAE Simple

Tarea: Implementa un VAE simple para generar nuevas muestras del conjunto de datos MNIST. Utiliza el ejemplo proporcionado en la sección 2.2.2 y modifícalo para incluir capas adicionales tanto en el codificador como en el decodificador.

Solución:

import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten, Reshape, Lambda, Input, Conv2D, Conv2DTranspose
from tensorflow.keras.models import Model
from tensorflow.keras.losses import binary_crossentropy
from tensorflow.keras import backend as K
import numpy as np
import matplotlib.pyplot as plt

# Sampling function
def sampling(args):
    z_mean, z_log_var = args
    batch = tf.shape(z_mean)[0]
    dim = tf.shape(z_mean)[1]
    epsilon = tf.keras.backend.random_normal(shape=(batch, dim))
    return z_mean + K.exp(0.5 * z_log_var) * epsilon

# Encoder model
input_img = Input(shape=(28, 28, 1))
x = Conv2D(32, 3, activation='relu', padding='same')(input_img)
x = Conv2D(64, 3, activation='relu', padding='same', strides=2)(x)
x = Conv2D(128, 3, activation='relu', padding='same', strides=2)(x)
x = Flatten()(x)
x = Dense(256, activation='relu')(x)
z_mean = Dense(2)(x)
z_log_var = Dense(2)(x)
z = Lambda(sampling, output_shape=(2,))([z_mean, z_log_var])
encoder = Model(input_img, z)

# Decoder model
decoder_input = Input(shape=(2,))
x = Dense(7*7*128, activation='relu')(decoder_input)
x = Reshape((7, 7, 128))(x)
x = Conv2DTranspose(128, 3, activation='relu', padding='same', strides=2)(x)
x = Conv2DTranspose(64, 3, activation='relu', padding='same', strides=2)(x)
x = Conv2DTranspose(32, 3, activation='relu', padding='same')(x)
output_img = Conv2DTranspose(1, 3, activation='sigmoid', padding='same')(x)
decoder = Model(decoder_input, output_img)

# VAE model
output_img = decoder(encoder(input_img))
vae = Model(input_img, output_img)

# VAE loss function
reconstruction_loss = binary_crossentropy(K.flatten(input_img), K.flatten(output_img))
reconstruction_loss *= 28 * 28
kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
kl_loss = K.sum(kl_loss, axis=-1)
kl_loss *= -0.5
vae_loss = K.mean(reconstruction_loss + kl_loss)
vae.add_loss(vae_loss)
vae.compile(optimizer='adam')

# Training the VAE
(x_train, _), (_, _) = tf.keras.datasets.mnist.load_data()
x_train = (x_train.astype(np.float32) / 255.0) - 0.5
x_train = np.expand_dims(x_train, axis=-1)
vae.fit(x_train, epochs=50, batch_size=128, verbose=1)

# Generate new samples
z_sample = np.array([[0.0, 0.0]])
generated_image = decoder.predict(z_sample)

# Plot generated image
plt.imshow(generated_image[0].squeeze(), cmap='gray')
plt.axis('off')
plt.show()

Ejercicio 4: Aplicar Normalización Espectral a un Discriminador

Tarea: Implementa la normalización espectral en un modelo de discriminador simple. Utiliza el ejemplo proporcionado en la sección 2.3.2 y asegúrate de que el discriminador se aplique al conjunto de datos MNIST.

Solución:

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt

# Define a simple discriminator with spectral normalization
class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.model = nn.Sequential(
            nn.utils.spectral_norm(nn.Conv2d(1, 64, 4, stride=2, padding=1)),
            nn.LeakyReLU(0.2, inplace=True),
            nn.utils.spectral_norm(nn.Conv2d(64, 128, 4, stride=2, padding=1)),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Flatten(),
            nn.utils.spectral_norm(nn.Linear(128 * 7 * 7, 1))
        )

    def forward(self, x):
        return self.model(x)

# Load MNIST dataset
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,),

 (0.5,))
])
dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
dataloader = DataLoader(dataset, batch_size=64, shuffle=True)

# Instantiate the discriminator
discriminator = Discriminator()
optimizer = optim.Adam(discriminator.parameters(), lr=0.0002)
criterion = nn.BCELoss()

# Training loop
num_epochs = 5
for epoch in range(num_epochs):
    for images, _ in dataloader:
        optimizer.zero_grad()
        labels = torch.ones(images.size(0), 1)
        outputs = discriminator(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

# Generate fake data (for demonstration purposes)
noise = torch.randn(64, 1, 28, 28)
fake_images = noise

# Evaluate discriminator on fake data
with torch.no_grad():
    fake_outputs = discriminator(fake_images)
    print("Discriminator output on fake images:", fake_outputs[:5])

Ejercicio 5: Implementar una GAN 3D para la Generación de Objetos Basados en Vóxeles

Tarea: Implementa una GAN 3D simple para generar objetos basados en vóxeles. Utiliza el ejemplo proporcionado en la sección 2.3.3 y visualiza los objetos 3D generados.

Solución:

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Define a simple 3D GAN for voxel-based object generation
class VoxelGenerator(nn.Module):
    def __init__(self):
        super(VoxelGenerator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(100, 128),
            nn.ReLU(inplace=True),
            nn.Linear(128, 256),
            nn.ReLU(inplace=True),
            nn.Linear(256, 512),
            nn.ReLU(inplace=True),
            nn.Linear(512, 32*32*32),
            nn.Tanh()
        )

    def forward(self, z):
        return self.model(z).view(-1, 32, 32, 32)

# Instantiate the generator
voxel_generator = VoxelGenerator()

# Generate random latent vectors
num_voxels = 5
latent_vectors = torch.randn(num_voxels, 100)

# Generate 3D voxel objects
generated_voxels = voxel_generator(latent_vectors)

# Visualize the generated 3D objects
fig = plt.figure(figsize=(15, 15))
for i in range(num_voxels):
    ax = fig.add_subplot(1, num_voxels, i+1, projection='3d')
    ax.voxels(generated_voxels[i].detach().numpy() > 0, edgecolor='k')
    ax.axis('off')

plt.show()

Estos ejercicios prácticos deberían ayudar a reforzar tu comprensión de los conceptos cubiertos en este capítulo. Al implementar estos modelos y experimentar con diferentes configuraciones, obtendrás experiencia práctica con los modelos generativos y sus aplicaciones prácticas. ¡Sigue practicando y no dudes en explorar más por tu cuenta!