DCGAN生成二次元头像实战,Anime Faces数据集下载

一、数据

下载地址1 CSDN 0积分下载https://download.csdn.net/download/sdbyp/87586295
下载地址2 Kaggle:https://www.kaggle.com/datasets/soumikrakshit/anime-faces

二、实现代码

import glob
import torch
from PIL import Image
from torch import nn
from torch.utils import data
from torchvision import transforms
import torch.nn.functional as F
import matplotlib.pyplot as plt
import numpy as np

images_path = glob.glob('./data/anime-faces/*.png')

transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))
])


class FaceDataset(data.Dataset):
    def __init__(self, images_path):
        self.images_path = images_path

    def __getitem__(self, index):
        image_path = self.images_path[index]
        pil_img = Image.open(image_path)
        pil_img = transform(pil_img)
        return pil_img

    def __len__(self):
        return len(self.images_path)


BATCH_SIZE = 32
dataset = FaceDataset(images_path)
data_loader = data.DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True)
image_batch = next(iter(data_loader))


# 定义生成器
class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.linear1 = nn.Linear(100, 256*16*16)
        self.bn1 = nn.BatchNorm1d(256*16*16)
        self.deconv1 = nn.ConvTranspose2d(256, 128, kernel_size=3, padding=1)  # 输出:128*16*16
        self.bn2 = nn.BatchNorm2d(128)
        self.deconv2 = nn.ConvTranspose2d(128, 64, kernel_size=4, stride=2, padding=1)  # 输出:64*32*32
        self.bn3 = nn.BatchNorm2d(64)
        self.deconv3 = nn.ConvTranspose2d(64, 3, kernel_size=4, stride=2, padding=1)  # 输出:3*64*64

    def forward(self, x):
        x = F.relu(self.linear1(x))
        x = self.bn1(x)
        x = x.view(-1, 256, 16, 16)
        x = F.relu(self.deconv1(x))
        x = self.bn2(x)
        x = F.relu(self.deconv2(x))
        x = self.bn3(x)
        x = F.tanh(self.deconv3(x))
        return x


# 定义判别器
class Discrimination(nn.Module):
    def __init__(self):
        super(Discrimination, self).__init__()

        self.conv1 = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=2)  # 64*31*31
        self.conv2 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=2)  # 128*15*15
        self.bn1 = nn.BatchNorm2d(128)
        self.fc = nn.Linear(128*15*15, 1)

    def forward(self, x):
        x = F.dropout(F.leaky_relu(self.conv1(x)), p=0.3)
        x = F.dropout(F.leaky_relu(self.conv2(x)), p=0.3)
        x = self.bn1(x)
        x = x.view(-1, 128*15*15)
        x = torch.sigmoid(self.fc(x))
        return x


device = "cuda:0" if torch.cuda.is_available() else "cpu"
print(device)
gen = Generator().to(device)
dis = Discrimination().to(device)
loss_fn = torch.nn.BCELoss()
gen_opti = torch.optim.Adam(gen.parameters(), lr=0.0001)
dis_opti = torch.optim.Adam(dis.parameters(), lr=0.00001)


# 定义可视化函数
def generate_and_save_images(model, epoch, test_noise_):
    predictions = model(test_noise_).permute(0, 2, 3, 1).cpu().numpy()
    fig = plt.figure(figsize=(20, 160))
    for i in range(predictions.shape[0]):
        plt.subplot(1, 8, i+1)
        plt.imshow((predictions[i]+1)/2)
        # plt.axis('off')
    plt.show()


test_noise = torch.randn(8, 100, device=device)

#############################
D_loss = []
G_loss = []

# 开始训练
for epoch in range(500):
    D_epoch_loss = 0
    G_epoch_loss = 0
    batch_count = len(data_loader)   # 返回批次数
    for step, img, in enumerate(data_loader):
        img = img.to(device)
        size = img.shape[0]
        random_noise = torch.randn(size, 100, device=device)  # 生成随机输入

        # 固定生成器,训练判别器
        dis_opti.zero_grad()
        real_output = dis(img)
        d_real_loss = loss_fn(real_output, torch.ones_like(real_output, device=device))
        d_real_loss.backward()
        generated_img = gen(random_noise)
        # print(generated_img)
        fake_output = dis(generated_img.detach())
        d_fake_loss = loss_fn(fake_output, torch.zeros_like(fake_output, device=device))
        d_fake_loss.backward()

        dis_loss = d_real_loss + d_fake_loss
        dis_opti.step()

        # 固定判别器,训练生成器
        gen_opti.zero_grad()
        fake_output = dis(generated_img)
        gen_loss = loss_fn(fake_output, torch.ones_like(fake_output, device=device))
        gen_loss.backward()
        gen_opti.step()

        with torch.no_grad():
            D_epoch_loss += dis_loss.item()
            G_epoch_loss += gen_loss.item()

    with torch.no_grad():
        D_epoch_loss /= batch_count
        G_epoch_loss /= batch_count
        D_loss.append(D_epoch_loss)
        G_loss.append(G_epoch_loss)

        print("Epoch:", epoch)
        generate_and_save_images(gen, epoch, test_noise)

plt.plot(range(1, len(D_loss)+1), D_loss, label="D_loss")
plt.plot(range(1, len(D_loss)+1), G_loss, label="G_loss")
plt.xlabel('epoch')
plt.legend()
plt.show()

三、截图结果

epoch0
在这里插入图片描述
epoch20
在这里插入图片描述
epoch40
在这里插入图片描述
epoch60
在这里插入图片描述
epoch80
在这里插入图片描述
epoch89
在这里插入图片描述

以下是ACGAN自动生成动漫头像的PyTorch代码和数据集: ## 数据集 我们将使用动漫头像数据集,该数据集包含10,000个大小为64x64的图像。您可以从以下链接下载数据集: https://drive.google.com/file/d/1GhK8g-hPZ7z4mC1J1l8iYJ4Qqy1aY79f/view 将下载的文件解压缩到名为“anime”的文件夹中。 ## PyTorch代码 ```python import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import Dataset, DataLoader from torchvision import transforms from torchvision.utils import save_image from PIL import Image import glob # 超参数 batch_size = 128 lr = 0.0002 latent_dim = 100 num_classes = 10 num_epochs = 200 # 设备 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 转换图像 transform = transforms.Compose([ transforms.Resize((64, 64)), transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)) ]) # 动漫头像数据集 class AnimeDataset(Dataset): def __init__(self, root_dir, transform=None): self.root_dir = root_dir self.transform = transform self.images = glob.glob(root_dir + '/*.png') def __len__(self): return len(self.images) def __getitem__(self, idx): img_path = self.images[idx] image = Image.open(img_path) if self.transform: image = self.transform(image) return image # 生成器 class Generator(nn.Module): def __init__(self): super(Generator, self).__init__() self.label_emb = nn.Embedding(num_classes, num_classes) self.model = nn.Sequential( nn.Linear(latent_dim + num_classes, 128), nn.BatchNorm1d(128, 0.8), nn.LeakyReLU(0.2, inplace=True), nn.Linear(128, 256), nn.BatchNorm1d(256, 0.8), nn.LeakyReLU(0.2, inplace=True), nn.Linear(256, 512), nn.BatchNorm1d(512, 0.8), nn.LeakyReLU(0.2, inplace=True), nn.Linear(512, 1024), nn.BatchNorm1d(1024, 0.8), nn.LeakyReLU(0.2, inplace=True), nn.Linear(1024, 64*64*3), nn.Tanh() ) def forward(self, noise, labels): gen_input = torch.cat((self.label_emb(labels), noise), -1) img = self.model(gen_input) img = img.view(img.size(0), 3, 64, 64) return img # 判别器 class Discriminator(nn.Module): def __init__(self): super(Discriminator, self).__init__() self.label_emb = nn.Embedding(num_classes, num_classes) self.model = nn.Sequential( nn.Linear(num_classes + 64*64*3, 512), nn.LeakyReLU(0.2, inplace=True), nn.Linear(512, 512), nn.Dropout(0.4), nn.LeakyReLU(0.2, inplace=True), nn.Linear(512, 512), nn.Dropout(0.4), nn.LeakyReLU(0.2, inplace=True), nn.Linear(512, 1), nn.Sigmoid() ) def forward(self, img, labels): img = img.view(img.size(0), -1) d_in = torch.cat((img, self.label_emb(labels)), -1) validity = self.model(d_in) return validity # 损失函数 adversarial_loss = nn.BCELoss() auxiliary_loss = nn.CrossEntropyLoss() # 初始化生成器和判别器 generator = Generator().to(device) discriminator = Discriminator().to(device) # 优化器 optimizer_G = optim.Adam(generator.parameters(), lr=lr) optimizer_D = optim.Adam(discriminator.parameters(), lr=lr) # 动漫头像数据集 anime_data = AnimeDataset('anime', transform=transform) dataloader = DataLoader(anime_data, batch_size=batch_size, shuffle=True) # 训练模型 for epoch in range(num_epochs): for i, imgs in enumerate(dataloader): # 真实图像标签为1 valid = torch.ones((imgs.size(0), 1)).to(device) # 假的图像标签为0 fake = torch.zeros((imgs.size(0), 1)).to(device) # 训练判别器 optimizer_D.zero_grad() # 真实图像损失 real_imgs = imgs.to(device) real_labels = torch.randint(0, num_classes, (imgs.size(0),)).to(device) d_loss_real = adversarial_loss(discriminator(real_imgs, real_labels), valid) # 生成生成的图像损失 noise = torch.randn((imgs.size(0), latent_dim)).to(device) fake_labels = torch.randint(0, num_classes, (imgs.size(0),)).to(device) fake_imgs = generator(noise, fake_labels).detach() d_loss_fake = adversarial_loss(discriminator(fake_imgs, fake_labels), fake) # 总损失 d_loss = 0.5 * (d_loss_real + d_loss_fake) d_loss.backward() optimizer_D.step() # 训练生成器 optimizer_G.zero_grad() # 生成生成的图像损失 noise = torch.randn((imgs.size(0), latent_dim)).to(device) fake_labels = torch.randint(0, num_classes, (imgs.size(0),)).to(device) fake_imgs = generator(noise, fake_labels) g_loss = adversarial_loss(discriminator(fake_imgs, fake_labels), valid) g_loss.backward() optimizer_G.step() if i % 50 == 0: print('[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f]' % (epoch, num_epochs, i, len(dataloader), d_loss.item(), g_loss.item())) # 保存生成器的图像 if epoch % 10 == 0: save_image(fake_imgs.data[:25], 'images/%d.png' % epoch, nrow=5, normalize=True) ``` 您可以将上述代码保存为“acgan.py”文件并在命令行中运行以下命令以训练模型: ``` python acgan.py ``` 注意:训练可能需要一段时间,具体取决于您的计算机性能。您可以通过调整超参数来加速训练,例如减少批量大小或减少训练时期。同时,您还可以在训练过程中查看生成的图像,这些图像将保存在名为“images”的文件夹中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值