最近在学习gan模型,基于pytorch在使用gan训练minist时,将全连接层增加了卷积层,但是代码一直有问题,寻求解答
import torch
from torchvision import datasets, transforms
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=0.5,std=0.5)
])
mnist_data = datasets.MNIST(root='D:/data/FashionMNIST', train=True, transform=transform, download=True)
data_loader = torch.utils.data.DataLoader(mnist_data, batch_size=128, shuffle=True, drop_last=True, num_workers=6)
import torch
import torch.nn as nn
import torch.nn.functional as F
# 定义生成器
class Generator(nn.Module):
def __init__(self, z_dim=100, hidden_dim=128):
super(Generator, self).__init__() # 继承 nn.Module 类并初始化
self.z_dim = z_dim # 输入向量的维度
self.hidden_dim = hidden_dim # 隐藏层维度
self.fc1 = nn.Linear(z_dim, hidden_dim) # 全连接层,输入为 z_dim 维,输出为 hidden_dim 维
self.fc2 = nn.Linear(hidden_dim, 7 * 7 * 256) # 全连接层,将隐藏层映射到 7*7*256 的图像
self.deconv1 = nn.ConvTranspose2d(256, 128, kernel_size=4, stride=2, padding=1) # 上采样层,输入为 7*7*256,输出为 14*14*128
self.deconv2 = nn.ConvTranspose2d(128, 64, kernel_size=4, stride=2, padding=1) # 上采样层,输入为 14*14*128,输出为 28*28*64
self.deconv3 = nn.ConvTranspose2d(64, 3, kernel_size=4, stride=2, padding=1) # 上采样层,输入为 28*28*64,输出为 28*28*3
def forward(self, z):
x = self.fc1(z) # 输入 z,通过全连接层 fc1 得到隐藏层向量 x
x = nn.functional.leaky_relu(x, 0.2) # 在隐藏层中应用 LeakyReLU 激活函数
x = self.fc2(x) # 将隐藏层映射到 7*7*256 的图像
x = x.view(-1, 256, 7, 7) # 将输出展平成图片张量形式
x = F.relu(self.deconv1(x)) # 在上采样层中应用 ReLU 激活函数
x = F.relu(self.deconv2(x)) # 在上采样层中应用 ReLU 激活函数
x = F.tanh(self.deconv3(x)) # 将输出值映射到 [-1, 1] 的范围
return x.view(-1, 1, 28, 28) # 将输出展平成图片张量形式
# 定义判别器
class Discriminator(nn.Module):
def __init__(self, hidden_dim=128):
super(Discriminator, self).__init__() # 继承 nn.Module 类并初始化
self.hidden_dim = hidden_dim # 隐藏层维度
self.conv1 = nn.Conv2d(1, 64, kernel_size=4, stride=2, padding=1) # 卷积层,输入为 1 维,输出为 64 维,kernel_size=4 表示卷积核大小为 4*4,stride=2 表示步幅为 2,padding=1 表示填充 1 个像素
self.conv2 = nn.Conv2d(64, 128, kernel_size=4, stride=2, padding=1) # 卷积层,输入为 64 维,输出为 128 维,kernel_size=4 表示卷积核大小为 4*4,stride=2 表示步幅为 2,padding=1 表示填充 1 个像素
self.conv3 = nn.Conv2d(128, 256, kernel_size=4, stride=2, padding=1) # 卷积层,输入为 128 维,输出为 256 维,kernel_size=4 表示卷积核大小为 4*4,stride=2 表示步幅为 2,padding=1 表示填充 1 个像素
self.conv4 = nn.Conv2d(256, 512, kernel_size=4, stride=2, padding=1) # 卷积层,输入为 256 维,输出为 512 维,kernel_size=4 表示卷积核大小为 4*4,stride=2 表示步幅为 2,padding=1 表示填充 1 个像素
self.fc1 = nn.Linear(512 * 4 * 4, hidden_dim) # 全连接层,输入为 512*4*4 维,输出为 hidden_dim 维
self.fc2 = nn.Linear(hidden_dim, 1) # 只有一个输出,表示输入是否是真实的图像。
def forward(self, x):
x = F.leaky_relu(self.conv1(x), 0.2) # 在卷积层中应用 LeakyReLU 激活函数
x = F.leaky_relu(self.conv2(x), 0.2) # 在卷积层中应用 LeakyReLU 激活函数
x = F.leaky_relu(self.conv3(x), 0.2) # 在卷积层中应用 LeakyReLU 激活函数
x = F.leaky_relu(self.conv4(x), 0.2) # 在卷积层中应用 LeakyReLU 激活函数
x = x.view(-1, 512 * 4 * 4) # 将输入展平成向量
x = F.leaky_relu(self.fc1(x), 0.2) # 在全连接层中应用 LeakyReLU 激活函数
x = self.fc2(x) # 将隐藏层输出映射到单个输出值
x = nn.functional.sigmoid(x) # 将输出值映射到 [0, 1] 的范围,表示输入是否是真实图像的概率
return x
# 定义超参数
lr = 0.0004
z_dim = 100
num_epochs = 100
generator = Generator(z_dim).to(device)
discriminator = Discriminator().to(device)
# 定义优化器和损失函数
optimizer_G = torch.optim.Adam(generator.parameters(), lr=lr)
optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=lr)
criterion = nn.BCELoss()
# 训练网络,使用给定的 epoch 数量
for epoch in range(num_epochs):
# 遍历数据集的 mini-batches
for i, (real_images, _) in enumerate(data_loader):
# 将真实图像传递给设备
real_images = real_images.to(device)
real_labels = torch.ones(real_images.size(0), 1).to(device)
fake_labels = torch.zeros(real_images.size(0), 1).to(device)
# 训练生成器
# 生成随机的噪音 z
z = torch.randn(real_images.size(0), z_dim).to(device)
fake_images = generator(z)
fake_output = discriminator(fake_images)
# 计算生成器的损失值 loss_G
# 需要将 fake_output 与真实标签 real_labels 进行比较
loss_G = criterion(fake_output, real_labels)
optimizer_G.zero_grad()
# 计算 generator 的梯度
loss_G.backward()
# 更新 generator 参数,使用优化器 optimizer_G
optimizer_G.step()
# 训练判别器
real_output = discriminator(real_images)
# 计算判别器对真实图像的损失值 loss_D_real
# 需要将 real_output 与真实标签 real_labels 进行比较
loss_D_real = criterion(real_output, real_labels)
# 计算判别器对生成器生成的 fake_images 的损失值 loss_D_fake
# 需要将 fake_output 与假的标签 fake_labels 进行比较
fake_output = discriminator(fake_images.detach())
loss_D_fake = criterion(fake_output, fake_labels)
loss_D = loss_D_real + loss_D_fake
optimizer_D.zero_grad()
# 计算 discriminator 的梯度
loss_D.backward()
# 更新 discriminator 参数,使用优化器 optimizer_D
optimizer_D.step()
# 输出损失值 每100次迭代输出一次
if (i + 1) % 100 == 0:
print('Epoch [{}/{}], Step [{}/{}], d_loss: {:.4f}, g_loss: {:.4f}'
.format(epoch+1, num_epochs, i+1, len(data_loader), loss_D.item(), loss_G.item()))
from matplotlib import pyplot as plt
# 生成一些测试数据
# 随机生成一些长度为 z_dim 的、位于设备上的向量 z
z = torch.randn(16, z_dim).to(device)
# 使用生成器从 z 中生成一些假的图片
fake_images = generator(z).detach().cpu()
# 显示生成的图像
# 创建一个图形对象,大小为 4x4 英寸
fig = plt.figure(figsize=(4, 4))
# 在图形对象中创建4x4的网格,以显示输出的16张假图像
for i in range(16):
plt.subplot(4, 4, i+1)
plt.imshow(fake_images[i][0], cmap='gray')
plt.axis('off')
# 显示绘制的图形
plt.show()
除此外,代码还有无其他问题
引用 皆我百晓生 小程序回复内容作答:
在代码中,训练生成器时计算生成器的损失值时出现了错误。错误的原因是在使用BCELoss函数计算损失值时,纠正真实和生成图像的标签出现了问题。
在生成图像的标签生成代码中,使用了错误的标签张量。可以修改代码如下:
fake_labels = torch.ones(fake_images.size(0), 1).to(device)
将上述代码放置在以下代码段的前面:
# 训练生成器
# 生成随机的噪音 z
z = torch.randn(real_images.size(0), z_dim).to(device)
fake_images = generator(z)
fake_output = discriminator(fake_images)
修改后的代码片段如下:
# 训练生成器
# 生成随机的噪音 z
z = torch.randn(real_images.size(0), z_dim).to(device)
fake_images = generator(z)
fake_output = discriminator(fake_images)
# 计算生成器的损失值 loss_G
# 需要将 fake_output 与真实标签 fake_labels 进行比较
loss_G = criterion(fake_output, fake_labels)
optimizer_G.zero_grad()
# 计算 generator 的梯度
loss_G.backward()
# 更新 generator 参数,使用优化器 optimizer_G
optimizer_G.step()
通过将真实图像和生成图像的标签分别与真实标签real_labels和假标签fake_labels进行比较,计算生成器的损失值。这样就可以纠正该错误并正常训练生成器。
【以下回答由 GPT 生成】
你的代码中有几处问题需要修复。
首先,关于生成器定义和在GPU上运行的问题,在下面的代码中加入了注释来解释每一步的作用,并进行了一些修改:
import torch
import torch.nn as nn
import torch.nn.functional as F
# 定义生成器
class Generator(nn.Module):
def __init__(self, z_dim=100, hidden_dim=128):
super(Generator, self).__init__()
self.z_dim = z_dim
self.hidden_dim = hidden_dim
self.fc1 = nn.Linear(z_dim, hidden_dim)
self.fc2 = nn.Linear(hidden_dim, 7 * 7 * 256)
self.deconv1 = nn.ConvTranspose2d(256, 128, kernel_size=4, stride=2, padding=1)
self.deconv2 = nn.ConvTranspose2d(128, 64, kernel_size=4, stride=2, padding=1)
self.deconv3 = nn.ConvTranspose2d(64, 1, kernel_size=4, stride=2, padding=1) # 输出通道数应该是1,因为MNIST是单通道的
def forward(self, z):
x = self.fc1(z)
x = F.leaky_relu(x, 0.2) # 使用 torch.nn.functional 的时候需要加上前缀 F.
x = x.view(-1, 256, 7, 7)
x = self.deconv1(x)
x = F.leaky_relu(x, 0.2)
x = self.deconv2(x)
x = F.leaky_relu(x, 0.2)
x = self.deconv3(x)
x = torch.tanh(x)
return x
# 创建生成器实例并将其移动到GPU上
generator = Generator().to(device)
另外,还需要对数据集进行一些处理。在 MNIST 数据集中,图像是单通道的,所以在生成器中将输出通道数设置为 1,同时标签的范围应该在 -1 到 1 之间。根据代码,你已经处理了图像的归一化,在数据加载处需要对标签进行处理:
import torch
from torchvision import datasets, transforms
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=0.5, std=0.5)
])
mnist_data = datasets.MNIST(root='D:/data/FashionMNIST',
train=True,
transform=transform,
download=True)
# 为了使生成器的输出和标签一致,这里对标签进行了处理
label_transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=0.5, std=0.5)
])
mnist_data.targets = label_transform(mnist_data.targets.unsqueeze(1)).squeeze(1)
data_loader = torch.utils.data.DataLoader(mnist_data,
batch_size=128,
shuffle=True,
drop_last=True,
num_workers=6)
请尝试以上修改后的代码,看是否能够解决你的问题。如果还有其他问题,请随时提问。
【相关推荐】
import torch
import torch.nn as nn
import torch.nn.functional as F
# 定义生成器
class Generator(nn.Module):
def __init__(self, z_dim=100, hidden_dim=128):
super(Generator, self).__init__()
self.z_dim = z_dim
self.hidden_dim = hidden_dim
self.fc1 = nn.Linear(z_dim, hidden_dim)
self.fc2 = nn.Linear(hidden_dim, 7 * 7 * 256)
self.deconv1 = nn.ConvTranspose2d(256, 128, kernel_size=4, stride=2, padding=1)
self.deconv2 = nn.ConvTranspose2d(128, 64, kernel_size=4, stride=2, padding=1)
self.deconv3 = nn.ConvTranspose2d(64, 1, kernel_size=4, stride=2, padding=1) # 输出通道数应该是1,因为MNIST是单通道的
def forward(self, z):
x = self.fc1(z)
x = F.leaky_relu(x, 0.2) # 使用 torch.nn.functional 的时候需要加上前缀 F.
x = x.view(-1, 256, 7, 7)
x = self.deconv1(x)
x = F.leaky_relu(x, 0.2)
x = self.deconv2(x)
x = F.leaky_relu(x, 0.2)
x = self.deconv3(x)
x = torch.tanh(x)
return x
# 创建生成器实例并将其移动到GPU上
generator = Generator().to(device)
援引讯飞星火:
代码中存在一个问题,即在定义生成器和判别器的全连接层时,输入维度不正确。生成器的全连接层输入维度应为 z_dim * 256 * 7 * 7,判别器的全连接层输入维度应为 1024 * 7 * 7。请参考以下修改后的代码:
# 定义生成器
class Generator(nn.Module):
def __init__(self, z_dim=100, hidden_dim=128):
super(Generator, self).__init__() # 继承 nn.Module 类并初始化
self.z_dim = z_dim # 输入向量的维度
self.hidden_dim = hidden_dim # 隐藏层维度
self.fc1 = nn.Linear(z_dim, hidden_dim) # 全连接层,输入为 z_dim 维,输出为 hidden_dim 维
self.fc2 = nn.Linear(hidden_dim, 7 * 7 * 256) # 全连接层,将隐藏层映射到 7*7*256 的图像
self.deconv1 = nn.ConvTranspose2d(256, 128, kernel_size=4, stride=2, padding=1) # 上采样层,输入为 7*7*256,输出为 14*14*128
self.deconv2 = nn.ConvTranspose2d(128, 64, kernel_size=4, stride=2, padding=1) # 上采样层,输入为 14*14*128,输出为 28*28*64
self.deconv3 = nn.ConvTranspose2d(64, 3, kernel_size=4, stride=2, padding=1) # 上采样层,输入为 28*28*64,输出为 28*28*3
def forward(self, z):
x = self.fc1(z) # 输入 z,通过全连接层 fc1 得到隐藏层向量 x
x = nn.functional.leaky_relu(x, 0.2) # 在隐藏层中应用 LeakyReLU 激活函数
x = self.fc2(x) # 将隐藏层映射到 7*7*256 的图像
x = x.view(-1, 28, 28, 7, 7) # 将输出展平成图片形式张量
x = F.relu(self.deconv1(x)) # 在上采样层中应用 ReLU 激活函数
x = F.relu(self.deconv2(x)) # 在上采样层中应用 ReLU 激活函数
x = F.tanh(self.deconv3(x)) # 将输出值映射到 [-1, 1] 的范围
return x.view(-1, 1, 28, 28) # 将输出展平成图片形式张量
# 定义判别器
class Discriminator(nn.Module):
def __init__(self, hidden_dim=128):
super(Discriminator', self).__init__() # 继承 nn.Module 类并初始化
self.hidden_dim = hidden_dim # 隐藏层维度
self.conv1 = nn.Conv2d(1, 64, kernel_size=4, stride=2, padding=1) # 卷积层,输入为 1 维,输出为 64 维,kernel_size 为 4,stride 为 2,padding 为 1
self.conv2 = nn.Conv2d(64, 128, kernel_size=4, stride=2, padding=1) # 卷积层,输入为 64 维,输出为 128 维,kernel_size 为 4,stride 为 2,padding 为 1
self.conv3 = nn.Conv2d(128, 256, kernel_size=4, stride=2, padding=1) # 卷积层,输入为 128 维,输出为 256 维,kernel_size 为 4,stride 为 2,padding 为 1
self.conv4 = nn.Conv2d(256, 512, kernel_size=4, stride=2, padding=1) # 卷积层,输入为 256 维,输出为 512 维,kernel_size 为 4,stride 为 2,padding 为 1
self.fc1 = nn.Linear(512 * 4 * 4, hidden_dim) # 全连接层,输入为512*4*4 维,输出为 hidden_dim 维
self.fc2 = nn.Linear(hidden_dim, 1) # 只有一个输出,表示输入是否是真实的图像。
def forward(self, x):
x = F.leaky_relu(self.conv1(x), 0.2) # 在卷积层中应用 LeakyReLU 激活函数
x = F.leaky_relu(self.conv2(x), 0.2) # 在卷积层中应用 LeakyReLU 激活函数
x = F.leaky_relu(self.conv3(x), 0.2) # 在卷积层中应用 LeakyReLU 激活函数
x = F.leaky_relu(self.conv4(x), 0.2) # 在卷积层中应用 LeakyReLU 激活函数
x = x.view(-1, 512 * 4 * 4) # 将输入展平成向量
x = F.leaky_relu(self.fc1(x), 0.2) # 在全连接层中应用 LeakyReLU 激活函数
x = self.fc2(x) # 将隐藏层输出映射到单个输出值
x = nn.functional.sigmoid(x) # 将输出值映射到 [0, 1] 的范围,表示输入是否是真实图像的概率
return x
其他部分代码看起来没有问题。
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
代码中存在一个问题,即在定义生成器和判别器的全连接层时,输入维度不正确。生成器的最后一层全连接层的输入维度应为 7 * 7 * 256,而不是 512 * 4 * 4。同样,判别器的第一层全连接层的输入维度应为 100 * 28 * 28,而不是 512 * 4 * 4。请参考以下修改后的代码:
# 定义生成器
class Generator(nn.Module):
def __init__(self, z_dim=100, hidden_dim=128):
super(Generator, self).__init__() # 继承 nn.Module 类并初始化
self.z_dim = z_dim # 输入向量的维度
self.hidden_dim = hidden_dim # 隐藏层维度
self.fc1 = nn.Linear(z_dim, hidden_dim) # 全连接层,输入为 z_dim 维,输出为 hidden_dim 维
self.fc2 = nn.Linear(hidden_dim, 7 * 7 * 256) # 全连接层,输入为 hidden_dim 维,输出为 7*7*256 的图像
self.deconv1 = nn.ConvTranspose2d(256, 128, kernel_size=4, stride=2, padding=1) # 上采样层,输入为 7*7*256,输出为 14*14*128
self.deconv2 = nn.ConvTranspose2d(128, 64, kernel_size=4, stride=2, padding=1) # 上采样层,输入为 14*14*128,输出为 28*28*64
self.deconv3 = nn.ConvTranspose2d(64, 3, kernel_size=4, stride=2, padding=1) # 上采样层,输入为 28*28*64,输出为 28*28*3
def forward(self, z):
x = self.fc1(z) # 输入 z,通过全连接层 fc1 得到隐藏层向量 x
x = nn.functional.leaky_relu(x, 0.2) # 在隐藏层中应用 LeakyReLU 激活函数
x = self.fc2(x) # 将隐藏层映射到 7*7*256 的图像
x = x.view(-1, 28, 28, 7) # 将输出展平成图片张量形式
x = F.relu(self.deconv1(x)) # 在上采样层中应用 ReLU 激活函数
x = F.relu(self.deconv2(x)) # 在上采样层中应用 ReLU 激活函数
x = F.tanh(self.deconv3(x)) # 将输出值映射到 [-1, 1] 的范围
return x.view(-1, 1, 28, 28) # 将输出展平成图片张量形式
# 定义判别器
class Discriminator(nn.Module):
def __init__(self, hidden_dim=128):
super(Discriminator, self).__init__() # 继承 nn.Module 类并初始化
self.hidden_dim = hidden_dim # 隐藏层维度
self.fc1 = nn.Linear(hidden_dim, 100 * 28 * 28) # 全连接层,输入为 hidden_dim 维,输出为 100*28*28 的图像
self.fc2 = nn.Linear(100 * 28 * 28, 1) # 只有一个输出,表示输入是否是真实的图像
def forward(self, x):
x = F.leaky_relu(self.fc1(x), 0.2) # 在全连接层中应用 LeakyReLU 激活函数
x = F.leaky_relu(self.fc2(x), 0.2) # 在全连接层中应用 LeakyReLU 激活函数
x = torch.sigmoid(x) # 将输出值映射到 [0, 1] 的范围,表示输入是否是真实图像的概率
return x
其他部分看起来没有问题。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
1.在判别器(Discriminator)的 forward 方法中,不再建议使用 nn.functional.sigmoid 来进行 sigmoid 操作。PyTorch 1.6 版本之后,您应该使用 torch.sigmoid。因此,将这一行代码:
x = nn.functional.sigmoid(x) # 将输出值映射到 [0, 1] 的范围,表示输入是否是真实图像的概率
更改为:
x = torch.sigmoid(x) # 将输出值映射到 [0, 1] 的范围,表示输入是否是真实图像的概率
2.在生成器(Generator)的 forward 方法中,使用 F.tanh 来映射输出到 [-1, 1] 的范围是正确的,但请注意,从 PyTorch 1.6 版本开始,建议使用 torch.tanh 代替 F.tanh。因此,将这一行代码:
x = F.tanh(self.deconv3(x)) # 将输出值映射到 [-1, 1] 的范围
更改为:
x = torch.tanh(self.deconv3(x)) # 将输出值映射到 [-1, 1] 的范围
3.在训练循环中,您使用了 criterion 计算损失值。要在代码的顶部导入了损失函数 nn.BCELoss,否则会出现 NameError。
传递的shape不对奥
结合GPT给出回答如下请题主参考
以下是一个使用GAN模型训练MNIST数据集的示例代码,包括全连接层和卷积层:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
from torch.autograd import Variable
# 定义生成器
class Generator(nn.Module):
def __init__(self):
super(Generator, self).__init__()
self.fc1 = nn.Linear(100, 256)
self.conv1 = nn.ConvTranspose2d(64, 32, 4, 2, 1)
self.conv2 = nn.ConvTranspose2d(32, 1, 4, 2, 1)
def forward(self, x):
x = self.fc1(x)
x = x.view(-1, 64, 2, 2)
x = nn.functional.relu(self.conv1(x))
x = nn.functional.sigmoid(self.conv2(x))
return x
# 定义判别器
class Discriminator(nn.Module):
def __init__(self):
super(Discriminator, self).__init__()
self.conv1 = nn.Conv2d(1, 32, 5, stride=2, padding=2)
self.conv2 = nn.Conv2d(32, 64, 5, stride=2, padding=2)
self.fc1 = nn.Linear(7 * 7 * 64, 1)
def forward(self, x):
x = nn.functional.relu(self.conv1(x))
x = nn.functional.relu(self.conv2(x))
x = x.view(-1, 7 * 7 * 64)
x = nn.functional.sigmoid(self.fc1(x))
return x
# 定义是否使用GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 加载数据集
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = datasets.MNIST(root='./data/', train=True, transform=transform, download=True)
train_loader = DataLoader(train_dataset, batch_size=100, shuffle=True)
# 实例化生成器和判别器
generator = Generator().to(device)
discriminator = Discriminator().to(device)
# 定义损失函数和优化器
criterion = nn.BCELoss()
optimizer_g = optim.Adam(generator.parameters(), lr=0.0002, betas=(0.5, 0.999))
optimizer_d = optim.Adam(discriminator.parameters(), lr=0.0002, betas=(0.5, 0.999))
# 训练模型
for epoch in range(200):
for i, (data, _) in enumerate(train_loader):
# 训练判别器
discriminator.zero_grad()
real_data = Variable(data.to(device))
real_label = Variable(torch.ones(data.size(0)).to(device))
fake_label = Variable(torch.zeros(data.size(0)).to(device))
# 真实数据的损失
output = discriminator(real_data).view(-1)
loss_d_real = criterion(output, real_label)
# 生成数据的损失
noise = Variable(torch.randn(data.size(0), 100).to(device))
fake_data = generator(noise)
output = discriminator(fake_data.detach()).view(-1)
loss_d_fake = criterion(output, fake_label)
# 计算总损失
loss_d = loss_d_real + loss_d_fake
loss_d.backward()
optimizer_d.step()
# 训练生成器
generator.zero_grad()
label = Variable(torch.ones(data.size(0)).to(device))
output = discriminator(fake_data).view(-1)
loss_g = criterion(output, label)
loss_g.backward()
optimizer_g.step()
# 打印损失
if i % 100 == 0:
print('Epoch [%d/%d], Step[%d/%d], Loss_D: %.4f, Loss_G: %.4f'
% (epoch, 200, i, len(train_dataset) // 100, loss_d.item(), loss_g.item()))
# 保存模型
torch.save(generator.state_dict(), './generator.pth')
这个代码中,生成器采用了全连接层和卷积层的结合,判别器采用了卷积层。在训练过程中,先训练判别器,再训练生成器。打印出损失,以便检查模型的训练状态。最后,保存生成器的模型参数。你可以根据你的需要修改代码以满足你的任务需求。