想象你走进一家蛋糕店,师傅手艺高超,但有个怪毛病——他只凭心情做蛋糕。你今天特别想吃草莓蛋糕,他端上来的却可能是巧克力味、抹茶味,甚至是榴莲味。你气得跺脚,师傅也很委屈:“我会做蛋糕,可你没法告诉我你想要什么呀!” 这正是原始GAN的窘境。它确实能生成逼真的图片——手写数字、人脸、风景——但完全是随机发挥,你永远无法指定“我要一张写着数字7的图”。直到CGAN的出现,一切才变得可控。CGAN给这场“随机创作”加了一本订单簿:顾客在订单上写清需求(标签),师傅按订单做蛋糕(生成器),品鉴师也拿订单核对“这蛋糕是不是顾客要的那款”(判别器)。从此,生成不再靠运气,而是“按需定制”。 这篇文章,我们就用这家“订单定制蛋糕店”的故事,带你彻底搞懂CGAN——条件生成对抗网络。你会学到它如何改造生成器和判别器、条件信息怎么拼接进模型、以及它是怎么一步步训练出来的。

岗位关联

对AI从业者而言,CGAN是“可控生成”思想的奠基之作。理解它,你就掌握了文本转图像、风格迁移、可控数据增强等现代AIGC应用的底层逻辑,是进阶生成式AI的必修课。

目录
  1. 可视化演示
  2. CGAN背景
  3. 核心思想
  4. 网络结构
  5. 拼接方式
  6. 训练流程
  7. 损失函数
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示CGAN如何通过条件标签控制生成过程,以及与无条件GAN在架构和生成效果上的核心差异。

本节配有交互动效(进入视口后自动加载,约 3KB)。

CGAN架构流程 噪声z与条件标签c拼接后输入生成器G 生成器输出样本x与条件c共同输入判别器D 判别器评估样本与条件的一致性输出分数 min_G max_D E[log D(x,c) + log(1-D(G(z,c),c))] 条件信息贯穿生成与判别全过程。

CGAN背景

蛋糕店里的老师傅手艺精湛,却总让顾客失望——他想做啥就做啥,顾客的偏好完全被无视。2014年Goodfellow提出的原始GAN,就是这样一位“任性的大师傅”。它能生成逼真的手写数字,但当你问“请生成一个7”,它只能回你一个随机的数字。原因在于,原始GAN的生成器只接收一个从随机噪声分布中采样的向量,这个向量里没有任何“顾客需求”信息。

这种“自由发挥”让GAN的生成质量虽然惊艳,却难以落地——我们想要的不是一个“随便什么数字”,而是“指定的那个数字”。业界迫切需要一种能让生成过程变得可控的机制。于是,CGAN(Conditional GAN,条件生成对抗网络)应运而生。它的核心想法简单得惊人:在训练时给模型额外提供一个条件,让模型学会在条件的约束下生成数据。

原始GAN的训练目标可以用下面这个博弈公式描述:

可惜,这个游戏中没有任何“菜单”。直到CGAN把一张订单塞进师傅和品鉴师手里,这场对抗才真正从“天马行空”变成“按需定制”。

min⁡Gmax⁡DV(D,G)=Ex∼pdata(x)[log⁡D(x)]+Ez∼pz(z)[log⁡(1−D(G(z)))]\displaystyle \min_G \max_D V(D,G) = \mathbb{E}_{x \sim p_{data}(x)}[\log D(x)] + \mathbb{E}_{z \sim p_z(z)}[\log(1 - D(G(z)))]
这个公式可以理解为“师傅想最小化被识破的概率,品鉴师想最大化识破概率”,是一组零和博弈的数学表达。
  1. min-max博弈结构外层是生成器G在求最小值,内层是判别器D在求最大值,双方目标相反,像师傅与品鉴师在玩一场对抗游戏。
    min⁡Gmax⁡D\min_G \max_D
  2. 第一项期望从真实数据分布中采样真实样本x,判别器要对它打出接近1的高分,表示“这蛋糕是真的”。
    Ex∼pdata(x)[log⁡D(x)]\mathbb{E}_{x \sim p_{data}(x)}[\log D(x)]
  3. 第二项期望从随机噪声分布中采样z,生成器用G(z)生成假样本,判别器要对其打出接近0的低分,表示“这是假货”。
    Ez∼pz(z)[log⁡(1−D(G(z)))]\mathbb{E}_{z \sim p_z(z)}[\log(1 - D(G(z)))]

核心思想

CGAN给蛋糕店引入了第一本订单簿。顾客在订单上写明“我要草莓味、圆形、八寸”——这个订单就是条件标签y。师傅做蛋糕前先看一眼订单,品鉴师评判时也拿起对应订单核对。于是,原来“无目的的对抗”变成了“有条件的对抗”:生成器学习的目标,从“建模整体的数据分布”变成了“建模给定类别下的条件分布”。

在数学上,这个转变意味着目标从无条件概率转而学习条件概率。想象一下:如果一家蛋糕店的顾客永远只点三种蛋糕——草莓、抹茶、巧克力,那么师傅需要学习的并不是“所有蛋糕的总体风格”,而是“草莓蛋糕长什么样”“抹茶蛋糕长什么样”“巧克力蛋糕长什么样”这三套分别的技艺。CGAN正是通过将标签y贯穿到生成过程中,把“一锅乱炖的分布”分解为“各归其位的类别分布”。

给定订单y时,生成器产出的样本分布可以写作:

订单簿上一笔一划,把师傅的创造力牢牢框定在顾客要求的边界内。这正是CGAN思想的精髓:引入条件,让生成从“随机”走向“可控”。

pg(x∣y)=Ez∼pz(z)[δ(x−G(z∣y))]\displaystyle p_g(x|y) = \mathbb{E}_{z \sim p_z(z)}\big[\delta\big(x - G(z|y)\big)\big]
这个公式说的是:生成器在固定订单y下,用不同随机灵感z做出的所有蛋糕,构成了一个“按订单条件化的蛋糕分布”。
  1. 条件分布记号\( p_g(x|y) \) 表示生成器在收到订单y后,做出蛋糕x的概率分布。
  2. 期望运算对无穷多种随机灵感z取平均,相当于师傅无数次尝试后产出的整体风格。
    Ez∼pz(z)\mathbb{E}_{z \sim p_z(z)}
  3. 狄拉克δ函数只统计“做出来的蛋糕恰好等于x”的那部分灵感z,保证每个蛋糕x都被精确记录。
    δ(x−G(z∣y))\delta(x - G(z|y))

网络结构

有了订单簿,蛋糕店要重新装修了。师傅的工作台(生成器)原来只有一个入口——灵感罐(噪声z),现在多了一个入口——订单夹(条件y)。品鉴师(判别器)的柜台原来只有一个盘子——待评蛋糕x,现在也多了一个夹子——同一份订单y。师傅根据“灵感+订单”做出蛋糕,品鉴师根据“蛋糕+订单”打出真假分。

在CGAN中,生成器和判别器的网络结构在原始GAN基础上各做了一处关键改造:生成器的输入从“只有噪声z”变为“噪声z拼接条件y”;判别器的输入从“只有样本x”变为“样本x拼接条件y”。值得强调的是,真实样本也必须与条件标签配对使用。训练数据中的每一张蛋糕图片,都必须伴随它对应的订单标签,否则品鉴师无从判断“这蛋糕是否真的符合订单”。

两个网络的输入输出关系可以简洁地记为:

改造后的蛋糕店焕然一新:师傅有了明确的奋斗方向,品鉴师也成了“带着标准答案挑刺”的严格考官。

G(z∣y)=x^,D(x~∣y)∈[0,1]\displaystyle G(z|y) = \hat{x}, \quad D(\tilde{x}|y) \in [0,1]
第一条表示生成器输入噪声和标签输出假样本,第二条表示判别器输入任意样本和标签输出一个真假分数。
  1. 生成器函数\( G(z|y) \) 读作“在条件y下的生成器”,师傅看了订单y和灵感z,产出蛋糕\(\hat{x}\)。
    G(z∣y)=x^G(z|y) = \hat{x}
  2. 判别器函数\( D(\tilde{x}|y) \) 表示品鉴师同时看蛋糕\(\tilde{x}\)和订单y,给出一个0到1之间的分数。
    D(x~∣y)∈[0,1]D(\tilde{x}|y) \in [0,1]
  3. 分数含义分数越接近1,说明品鉴师认为“这蛋糕是真的,而且符合订单要求”;越接近0,说明“这蛋糕是假的,或者与订单不符”。

拼接方式

订单和灵感是怎么在师傅手里融合的?答案很简单:钉在一起。师傅把订单纸条和灵感配方单用订书机一订,变成一张完整的工作单,再交给大脑(神经网络)处理。在CGAN中,这个“钉在一起”的操作就是向量拼接(concatenation)。

假设噪声z是一个100维的向量,表示“灵感配方”的各个维度;条件标签y如果表示10个数字类别,常用one-hot编码表示为一个10维向量(想生成数字3,就让第3个位置为1,其余为0)。拼接之后,生成器的输入向量维度变成110维。前100维是随机灵感,后10维是明确的订单要求。信息从输入层开始就融合在一起,后续的每一层网络都能同时“看到”灵感与订单,从而学会将二者关联起来。

这个拼接操作可以写成:

拼接是CGAN中最朴素也最有效的条件注入方式。它不改变网络结构内部的计算逻辑,只在入口处多了一个“合并动作”,却让订单信息从此贯穿整个生成过程。

z~=concat(z,y)=[zy]∈Rdz+dy\displaystyle \tilde{z} = \text{concat}(z, y) = \begin{bmatrix} z \\ y \end{bmatrix} \in \mathbb{R}^{d_z + d_y}
拼接的本质是把两个不同来源的信息向量首尾相接,组成一个更长的新向量,输入维度等于两者维度之和。
  1. 拼接符号\(\text{concat}(z, y)\) 表示把噪声向量z和标签向量y首尾连接,组成新向量\(\tilde{z}\)。
    concat(z,y)\text{concat}(z, y)
  2. 向量堆叠\(\begin{bmatrix} z \\ y \end{bmatrix}\) 形象地说明z在上方、y在下方,两者顺序拼接。
    [zy]\begin{bmatrix} z \\ y \end{bmatrix}
  3. 维度相加拼接后新向量的维度是\(d_z + d_y\),即噪声维度加标签维度。
    Rdz+dy\mathbb{R}^{d_z + d_y}

训练流程

装修完毕,蛋糕店开始营业了。训练采用“师傅与品鉴师对练”的模式,每一轮分成两个半场。上半场,师傅先不动(固定生成器参数),让品鉴师看两拨蛋糕:一拨是“真实蛋糕+订单”,要打高分;一拨是“师傅做的假蛋糕+订单”,要打低分。品鉴师拼命练眼力,提高识别真假的能力。下半场,品鉴师不动(固定判别器参数),师傅根据品鉴师的打分反馈调整自己的手艺——目标是让品鉴师把“假蛋糕+订单”也误判为真品。

两个半场交替进行,就是GAN家族一脉相承的“交替训练”策略。CGAN的特别之处在于,无论上半场还是下半场,订单y都始终出现在训练数据中。真实样本是“(真实蛋糕x, 订单y)”的配对,假样本是“(师傅做的蛋糕G(z|y),同一张订单y)”的配对。品鉴师要学的不仅是“真假”,还有“真且符合订单”才是满分。

一次完整的参数更新可以记作:

日复一日地对练,师傅的手艺越来越贴合订单,品鉴师的眼光也越来越毒辣。直到某一天,师傅做出的蛋糕让品鉴师真假难辨——训练就成功了。

θD←θD−η∇θD[log⁡D(x∣y)+log⁡(1−D(G(z∣y)))]θG←θG−η∇θG[log⁡(1−D(G(z∣y)))]\displaystyle\begin{aligned}\theta_D &\leftarrow \theta_D - \eta \nabla_{\theta_D}\big[\log D(x|y) + \log(1 - D(G(z|y)))\big] \\\theta_G &\leftarrow \theta_G - \eta \nabla_{\theta_G}\big[\log(1 - D(G(z|y)))\big]\end{aligned}
第一行更新判别器的参数,第二行更新生成器的参数,二者交替执行,就像师傅和品鉴师轮流加练。
  1. 判别器参数更新品鉴师沿着让“真实+订单”打高分、让“假蛋糕+订单”打低分的方向调整自己的评判标准。
    θD←θD−η∇θD[log⁡D(x∣y)+log⁡(1−D(G(z∣y)))]\theta_D \leftarrow \theta_D - \eta \nabla_{\theta_D}[\log D(x|y) + \log(1 - D(G(z|y)))]
  2. 生成器参数更新师傅调整手艺,目标是让品鉴师对自己做的假蛋糕打出高分,也就是骗过品鉴师。
    θG←θG−η∇θG[log⁡(1−D(G(z∣y)))]\theta_G \leftarrow \theta_G - \eta \nabla_{\theta_G}[\log(1 - D(G(z|y)))]
  3. 学习率η控制每次调整的步幅,步幅太大容易振荡,太小则收敛缓慢。
    η\eta

损失函数

蛋糕店的对练规则,最终浓缩成一张“拔河比赛计分表”——损失函数。品鉴师像一头往“识别真相”方向死命拉绳的选手,师傅像一头往“蒙混过关”方向反方向拉绳的选手,而绳子中央系着的正是目标函数。

判别器的损失函数由两个期望项构成:第一项鼓励它对真实配对打出高分,第二项鼓励它对假配对打出低分。生成器的损失函数则恰好相反,它希望自己的假配对也能拿到高分。CGAN与原始GAN在公式形式上几乎一模一样,唯一的区别,是公式中处处多了一个“|y“——条件标签如同拔河场边的裁判,时刻提醒双方”这场比赛是带着订单打的”。

CGAN的完整目标函数为:

拔河比赛没有绝对胜负,而是在动态平衡中让双方都变得更强。CGAN的损失函数正是这样一根绳子:它在无数轮对抗中,硬生生把“按订单定制蛋糕”这门手艺,从师父手里教了出来。

min⁡Gmax⁡DV(D,G)=Ex∼pdata(x∣y)[log⁡D(x∣y)]+Ez∼pz(z)[log⁡(1−D(G(z∣y)))]\displaystyle \min_G \max_D V(D,G) = \mathbb{E}_{x \sim p_{data}(x|y)}[\log D(x|y)] + \mathbb{E}_{z \sim p_z(z)}[\log(1 - D(G(z|y)))]
这是CGAN论文中的核心公式:判别器最大化该式,生成器最小化该式,二者形成动态博弈。
  1. 外层min-max生成器要最小化整个目标函数,判别器要最大化它,双方在同一个公式中拔河。
    min⁡Gmax⁡DV(D,G)\min_G \max_D V(D,G)
  2. 真实配对期望从“真实蛋糕+订单”的联合分布中采样,判别器要对其输出接近1的分数。
    Ex∼pdata(x∣y)[log⁡D(x∣y)]\mathbb{E}_{x \sim p_{data}(x|y)}[\log D(x|y)]
  3. 假配对期望从噪声中采样z,生成器做出假蛋糕,判别器要对其输出接近0的分数。
    Ez∼pz(z)[log⁡(1−D(G(z∣y)))]\mathbb{E}_{z \sim p_z(z)}[\log(1 - D(G(z|y)))]
  4. 条件贯穿始终两个期望项中都带条件y,订单同时出现在真实路径和生成路径中,这是区别于原始GAN的关键语法。
    D(x∣y),G(z∣y)D(x|y), \quad G(z|y)

AI 应用场景

按需生成手写数字样本

阶段:数据增强与合成

解决的问题:训练手写数字识别模型需要大量带标签的真实样本,人工标注成本高,且采集到的数据风格有限。传统做法是收集大量真实书写样本,费时费力且难以覆盖所有书写风格。CGAN只需输入标签"7",就能批量合成大量不同风格的数字7图片,极大扩充训练集。

具体案例:金融科技公司在开发支票OCR识别系统时,使用CGAN合成各类手写数字变体,补充罕见书写风格数据,使识别模型在真实场景中的准确率提升了约15%。

可控人脸属性生成

阶段:图像生成与编辑

解决的问题:普通GAN生成人脸时无法指定“微笑”、“戴眼镜”、“金发”等属性,生成结果不可控。CGAN通过将属性标签作为条件输入,让生成器能够针对指定属性合成对应的人脸图像。

具体案例:短视频特效团队训练CGAN式条件生成模型,用户选择“微笑+卷发”标签后,模型实时合成符合该属性组合的虚拟头像,替代了原来需要人工修图的流程,特效素材生产效率提升数倍。

文生图模型的奠基

阶段:多模态生成

解决的问题:想让模型根据“一只戴帽子的猫”这样的文字描述生成图片,原始GAN无法建立文本与图像之间的桥梁。CGAN率先验证了“条件信息可以引导生成”这一范式,为后续将标签条件推广到文本条件铺平了道路。

具体案例:从StackGAN到DALL·E 2,这些文生图模型的思路都可以追溯到CGAN——把用户输入的文字描述(条件)注入生成器,让生成过程服从文本的引导。CGAN实践证明:只要条件表达得足够好,生成器就能足够听话。

Python 演示

python120 行
import torchimport torch.nn as nnimport torch.optim as optim torch.manual_seed(42)  def build_labeled_data(num_samples=1600, num_classes=10):    """构造带类别标签的简单图案数据集:每张图8x8,标签k的图    在两个固定位置点亮像素,方便观察CGAN能否按类别生成对应图案。"""    data, labels = [], []    for i in range(num_samples):        label = i % num_classes        image = torch.zeros(8 * 8)        image[label] = 1.0        image[(label + 3) % num_classes] = 1.0        data.append(image)        labels.append(label)    data = torch.stack(data).float()    labels = torch.tensor(labels, dtype=torch.long)    return data, labels  class Generator(nn.Module):    """生成器:输入(噪声z, 标签y),输出8x8图像"""     def __init__(self, noise_dim, num_classes):        super().__init__()        self.net = nn.Sequential(            nn.Linear(noise_dim + num_classes, 64),            nn.ReLU(),            nn.Linear(64, 64),            nn.ReLU(),            nn.Linear(64, 64),            nn.ReLU(),            nn.Linear(64, 8 * 8),            nn.Sigmoid(),        )     def forward(self, z, y):        return self.net(torch.cat([z, y], dim=1))  class Discriminator(nn.Module):    """判别器:输入(图像x, 标签y),输出真假分数"""     def __init__(self, num_classes):        super().__init__()        self.net = nn.Sequential(            nn.Linear(8 * 8 + num_classes, 64),            nn.ReLU(),            nn.Linear(64, 32),            nn.ReLU(),            nn.Linear(32, 1),        )     def forward(self, x, y):        return self.net(torch.cat([x, y], dim=1))  def train_cgan(epochs=6, batch_size=64, noise_dim=16):    data, labels = build_labeled_data()    num_classes = labels.max().item() + 1    G = Generator(noise_dim, num_classes)    D = Discriminator(num_classes)    g_opt = optim.Adam(G.parameters(), lr=1e-3)    d_opt = optim.Adam(D.parameters(), lr=1e-3)    loss_fn = nn.BCEWithLogitsLoss()    n = len(data)     for epoch in range(epochs):        perm = torch.randperm(n)        epoch_d_loss, epoch_g_loss = 0.0, 0.0        for i in range(0, n, batch_size):            idx = perm[i:i + batch_size]            x_real = data[idx]            y_labels = labels[idx]            y = torch.nn.functional.one_hot(y_labels, num_classes).float()             z = torch.randn(len(idx), noise_dim)            x_fake = G(z, y)             d_opt.zero_grad()            real_logits = D(x_real, y)            fake_logits = D(x_fake.detach(), y)            d_loss = loss_fn(real_logits, torch.ones_like(real_logits)) \                   + loss_fn(fake_logits, torch.zeros_like(fake_logits))            d_loss.backward()            d_opt.step()             g_opt.zero_grad()            fake_logits = D(x_fake, y)            g_loss = loss_fn(fake_logits, torch.ones_like(fake_logits))            g_loss.backward()            g_opt.step()             epoch_d_loss += d_loss.item() * len(idx)            epoch_g_loss += g_loss.item() * len(idx)         print(f"epoch {epoch+1}/{epochs}  d_loss={epoch_d_loss/n:.4f}  "              f"g_loss={epoch_g_loss/n:.4f}")     return G  def demo_generate(G, noise_dim=16, num_classes=10):    """按指定标签生成图案并打印"""    for label in [0, 3, 7, 9]:        y = torch.nn.functional.one_hot(            torch.tensor([label]), num_classes).float()        z = torch.randn(1, noise_dim)        with torch.no_grad():            img = G(z, y).view(8, 8)        print(f"标签 {label} 生成的图案:")        print((img > 0.5).int().numpy())  if __name__ == "__main__":    G = train_cgan(epochs=6)    demo_generate(G)
目的:从零训练一个简化的CGAN模型,演示“给定标签就能生成对应图案”的可控生成过程。
  1. class Generator生成器网络,输入是噪声z和标签y拼接后的向量,输出是一张8×8的图像。
  2. torch.cat([z, y], dim=1)把噪声和标签沿特征维度拼接,这正是CGAN条件注入的核心操作。
  3. class Discriminator判别器网络,输入是图像x和标签y的拼接,输出一个真假logit分数。
  4. one_hot(y_labels, num_classes)将整数标签转换为one-hot向量,作为条件信息输入网络。
  5. x_fake = G(z, y)生成器在噪声和条件的共同作用下产出假样本。
  6. fake_logits = D(x_fake.detach(), y)判别器对假样本打分,detach()让梯度不回流到生成器。
  7. d_loss判别器的损失:真实配对打高分,假配对打低分,两部分相加。
  8. g_loss生成器的损失:让假配对被判别器打高分,即“骗过品鉴师”。
  9. demo_generate训练结束后,给生成器指定标签,观察它能否生成对应类别的图案。

常见误区

误区“CGAN不就是把标签接到生成器的输入里吗?我只改生成器就完事了。”

正解标签必须同时进入生成器和判别器。如果判别器看不到标签,它就无法判断“生成的样本是否与订单相符”,生成器也就没有动力真正按标签生成——最终它会退化成普通GAN,标签形同虚设。这就像品鉴师手里没有订单,自然无法指出“这蛋糕不是顾客要的”,师傅也就懒得看订单了。

为何常见:很多教程用一句话概括CGAN是“给GAN加条件”,初学者容易只注意到生成器端最直观的输入变化,而忽略了判别器端同样关键的改造。

误区“为了生成效果更好,我把性别、发型、肤色、表情等一堆标签全塞进去,模型应该会更强。”

正解条件信息并非多多益善。标签过多会导致条件空间急剧膨胀,训练数据中每个标签组合的样本数变得稀疏,生成器难以学到有效的条件映射。此外,one-hot标签只适合表示离散类别,连续或复杂的属性需要更精细的编码(如嵌入向量、属性向量),否则条件信息会变成噪声。

为何常见:人们容易把“条件信息”类比为“更多的提示词”,直觉上觉得信息越丰富越好,但忽略了模型学习能力和数据分布密度之间的匹配问题。

误区“判别器同时接收了标签和样本,那它的输出应该能告诉我这张图属于哪个类别吧?”

正解CGAN的判别器本质上仍然是一个真假二分类器,输出的是“样本真伪”的分数,而不是类别概率。标签y是以输入条件的形式参与判断的——品鉴师是“拿着订单核对真假”,而不是“被问这是什么蛋糕”。如果要做分类任务,需要额外加分类头或者改用ACGAN等变体。

为何常见:因为判别器同时看到标签和样本,容易让人误以为它具备分类能力,混淆了“输入条件”和“输出类别”两个概念。

误区“CGAN训练好了,我把标签改成训练时没见过的新编号,它应该也能生成对应的新图案吧?”

正解CGAN只能在训练时定义过的类别空间内生成。标签的语义空间在训练前就已固定,比如one-hot总共只有训练类别数那么多个位置。你给它一个从未见过的标签编号,它根本不知道该对应什么,只能输出无意义的结果。想让模型支持新类别,必须在训练数据中加入该类别样本并重新训练或微调。

为何常见:人们常把CGAN误认为万能的条件生成器,以为“条件”可以随心所欲地扩展,忽略了神经网络本质上是训练数据分布的拟合器。

面试题

Q1. CGAN相比于原始GAN,核心改进是什么?

单选题 · easy

  • A.增大了网络层数
  • B.引入条件标签控制生成← 正确答案
  • C.使用了新激活函数
  • D.增加了训练轮次数

答案:B。CGAN的关键创新是在生成器和判别器中同时引入条件标签y,使得生成类别可控。增大网络层数、换激活函数、加训练轮次都是通用技巧,并非CGAN的专属贡献。

Q2. CGAN中类别标签最常用的编码方式是哪种?

单选题 · easy

  • A.ASCII编码
  • B.二进制编码
  • C.one-hot编码← 正确答案
  • D.随机编码

答案:C。CGAN通常使用one-hot编码表示离散类别标签,每个类别对应一个高维向量中的唯一位置。ASCII和二进制不便于神经网络直接学习类别语义,随机编码会破坏类别的确定性。

Q3. CGAN中生成器的输入是什么?

单选题 · mid

  • A.仅噪声向量
  • B.仅条件标签
  • C.真实样本
  • D.噪声与标签拼接← 正确答案

答案:D。生成器接收的是随机噪声z与条件标签y拼接后的向量,这样它既保留随机变化的灵感来源,又受订单标签的约束。仅有噪声无法指定类别,仅有标签则失去了生成的多样性。

Q4. CGAN的判别器输入中必须包含哪些内容?

单选题 · mid

  • A.只有生成样本
  • B.只有真实样本
  • C.样本与其对应标签← 正确答案
  • D.只有标签向量

答案:C。判别器需要同时看到样本和标签,才能判断“这样本是否为真,且是否符合标签要求”。如果只有样本,判别器无法核对订单;如果只有标签,则根本看不到待评判的样本。

Q5. 关于CGAN训练流程,下列说法正确的有哪些?

多选题 · mid

  • A.固定生成器更新判别器← 正确答案
  • B.固定判别器更新生成器← 正确答案
  • C.只更新生成器
  • D.每轮使用真实与假样本← 正确答案

答案:ABD。CGAN沿用GAN的交替训练策略:先固定一方更新另一方。判别器训练时看真实配对和假配对,生成器训练时通过假配对骗高分。只更新任何一方都会导致博弈失衡,无法收敛。

Q6. CGAN目标函数中“真实样本条件期望”对应的表达式是?

单选题 · mid

  • A.E\[log D(x)\]
  • B.E\[log D(x|y)\]← 正确答案
  • C.E\[log(1-D(G(z)))\]
  • D.E\[log(1-D(x|y))\]

答案:B。真实样本期望在原始GAN中是E\[log D(x)\],CGAN引入了条件,变为E\[log D(x|y)\],即品鉴师在订单y的监督下对真实配对打高分。C项是假样本部分,A项是无条件版本,D项符号含义错误。

Q7. 如果只把标签拼进生成器而不拼进判别器,会发生什么?

单选题 · hard

  • A.生成器完全无法训练
  • B.生成器学不到条件约束← 正确答案
  • C.判别器可预测类别
  • D.训练速度立刻提升

答案:B。当判别器看不到标签时,它只会对“样本真假”打分,不会惩罚“不符合标签”的生成结果。生成器缺乏来自判别器的条件反馈,最终可能忽略标签,退化成普通GAN。这就像品鉴师手里没订单,师傅逐渐也就不看订单了。

Q8. 关于CGAN中one-hot标签向量,正确的说法有哪些?

多选题 · hard

  • A.其维度等于类别数← 正确答案
  • B.只有一个位置为1← 正确答案
  • C.可表示连续属性
  • D.可与噪声直接拼接← 正确答案

答案:ABD。one-hot向量的维度就是类别总数,每个类别让唯一一个位置为1。它是离散编码,无法表示连续属性;在CGAN中它直接与噪声向量拼接后送入网络。C选项描述的是连续数值向量而非one-hot。

Q9. CGAN最典型的应用方式是哪种?

单选题 · easy

  • A.股票趋势预测
  • B.按标签生成手写数字← 正确答案
  • C.数据库索引优化
  • D.网络流量分类

答案:B。CGAN的经典应用是按指定标签生成对应类别数据,例如输入标签"7"就生成数字7的图片。股票预测、数据库优化、流量分类都是判别式或非生成式任务,不是CGAN的用武之地。

Q10. CGAN相比原始GAN,以下说法正确的有哪些?

多选题 · hard

  • A.生成器输入增加条件← 正确答案
  • B.判别器输入增加条件← 正确答案
  • C.输出样本类别可控← 正确答案
  • D.无需使用任何标签

答案:ABC。CGAN在生成器和判别器两端都注入了条件标签,使输出样本的类别变得可控——这正是它相比原始GAN的核心优势。D选项完全说反了,CGAN必须使用带标签的数据进行训练,标签是模型工作的前提。