昇思25天学习打卡营第42天|生成式-CycleGAN图像风格迁移互换

昇思25天学习打卡营第42天|生成式-CycleGAN图像风格迁移互换

CycleGAN简介

CycleGAN(Cycle Generative Adversarial Network) 即循环对抗生成网络,实现了一种在没有配对示例的情况下学习将图像从源域 X 转换到目标域 Y 的方法,有效解决了数据集难以获取的问题,扩展性更好,应用范围更广。

网络结构

CycleGAN 网络本质上是由两个镜像对称的 GAN 网络组成,即包括两个生成器和判别器,进行双向生成。

  • 生成器G:负责将源域图像(例如夏天的风景)转换为目标域图像(例如冬天的风景)。
  • 生成器F:负责将目标域图像转换回源域图像,确保风格迁移的一致性。
  • 判别器D_X:负责区分源域图像和生成的目标域图像,以促使生成器生成更加逼真的图像。
  • 判别器D_Y:负责区分目标域图像生成的源域图像

训练过程中,生成器不仅要欺骗判别器使其认为生成的图像是现实的,还需要通过循环一致性损失来确保图像在转换后能够恢复到原始样貌。这种循环一致性损失确保了源图像经过目标域风格转换后再转换回源域时,可以接近原始图像,从而保留了图像的基本内容和结构。

损失函数

对抗损失

  • 生成器 G 的对抗损失:鼓励 G 生成逼真的目标域图像 G(X),使得 D_Y 无法区分 G(X)和真实的 Y。
  • 生成器 F 的对抗损失:鼓励 F 生成逼真的源域图像 F(Y),使得 D_X 无法区分 F(Y) 和真实的 X。

循环一致性损失

  • 源域图像的循环一致性损失:确保将源域图像 X 转换为目标域图像 G(X)后,再转换回源域图像 F(G(X)) 时,能够重建出原始图像 X。
  • 目标域图像的循环一致性损失:确保将目标域图像 Y 转换为源域图像 F(Y) 后,再转换回目标域图像 G(F(Y)) 时,能够重建出原始图像 Y。

CycleGAN与cGAN比较

输入的区别

  • cGAN:生成器和判别器都接收额外的条件信息 y。生成器的输入是 (z,y),判别器的输入是 (x,y) 。
  • CycleGAN:输入是无需配对的训练数据,使用来自两个不同域的图像集(例如,域A的图像和域B的图像)。

输出的区别

  • cGAN:生成器输出是符合条件 y 的样本,判别器输出是在条件 y下数据是否真实的概率。
  • CycleGAN:生成器生成风格转换后的图像,例如将域A的图像转换为域B的风格;判别器分别对两个域的图像进行区分,判定图像是否来自真实数据。

优点

  1. 不需要配对数据,直接使用来自两个域的未配对图像,这在实际应用中更为灵活。
  2. 通过循环一致性约束,能够更好地保留图像内容的一致性,即使在风格转换后也能保持图像的结构特征。

缺点

  1. 模型训练更加复杂,计算量大,因为需要同时训练两个生成器和两个判别器。

基于“图像池”技术的前向计算

“图像池”技术:使用生成器生成的历史图像,而不是最新生成的图像,来更新判别器,以此来防止判别器过快地适应生成器的更新,增强生成器和判别器之间的对抗性。

import mindspore as ms

# 前向计算

def generator(img_a, img_b):
    fake_a = net_rg_b(img_b)
    fake_b = net_rg_a(img_a)
    rec_a = net_rg_b(fake_b)
    rec_b = net_rg_a(fake_a)
    identity_a = net_rg_b(img_a)
    identity_b = net_rg_a(img_b)
    return fake_a, fake_b, rec_a, rec_b, identity_a, identity_b

lambda_a = 10.0
lambda_b = 10.0
lambda_idt = 0.5

def generator_forward(img_a, img_b):
    true = Tensor(True, dtype.bool_)
    fake_a, fake_b, rec_a, rec_b, identity_a, identity_b = generator(img_a, img_b)
    loss_g_a = gan_loss(net_d_b(fake_b), true)
    loss_g_b = gan_loss(net_d_a(fake_a), true)
    loss_c_a = l1_loss(rec_a, img_a) * lambda_a
    loss_c_b = l1_loss(rec_b, img_b) * lambda_b
    loss_idt_a = l1_loss(identity_a, img_a) * lambda_a * lambda_idt
    loss_idt_b = l1_loss(identity_b, img_b) * lambda_b * lambda_idt
    loss_g = loss_g_a + loss_g_b + loss_c_a + loss_c_b + loss_idt_a + loss_idt_b
    return fake_a, fake_b, loss_g, loss_g_a, loss_g_b, loss_c_a, loss_c_b, loss_idt_a, loss_idt_b

def generator_forward_grad(img_a, img_b):
    _, _, loss_g, _, _, _, _, _, _ = generator_forward(img_a, img_b)
    return loss_g

def discriminator_forward(img_a, img_b, fake_a, fake_b):
    false = Tensor(False, dtype.bool_)
    true = Tensor(True, dtype.bool_)
    d_fake_a = net_d_a(fake_a)
    d_img_a = net_d_a(img_a)
    d_fake_b = net_d_b(fake_b)
    d_img_b = net_d_b(img_b)
    loss_d_a = gan_loss(d_fake_a, false) + gan_loss(d_img_a, true)
    loss_d_b = gan_loss(d_fake_b, false) + gan_loss(d_img_b, true)
    loss_d = (loss_d_a + loss_d_b) * 0.5
    return loss_d

def discriminator_forward_a(img_a, fake_a):
    false = Tensor(False, dtype.bool_)
    true = Tensor(True, dtype.bool_)
    d_fake_a = net_d_a(fake_a)
    d_img_a = net_d_a(img_a)
    loss_d_a = gan_loss(d_fake_a, false) + gan_loss(d_img_a, true)
    return loss_d_a

def discriminator_forward_b(img_b, fake_b):
    false = Tensor(False, dtype.bool_)
    true = Tensor(True, dtype.bool_)
    d_fake_b = net_d_b(fake_b)
    d_img_b = net_d_b(img_b)
    loss_d_b = gan_loss(d_fake_b, false) + gan_loss(d_img_b, true)
    return loss_d_b

# 保留了一个图像缓冲区,用来存储之前创建的50个图像
pool_size = 50
def image_pool(images):
    num_imgs = 0
    image1 = []
    if isinstance(images, Tensor):
        images = images.asnumpy()
    return_images = []
    for image in images:
        if num_imgs < pool_size:
            num_imgs = num_imgs + 1
            image1.append(image)
            return_images.append(image)
        else:
            if random.uniform(0, 1) > 0.5:
                random_id = random.randint(0, pool_size - 1)

                tmp = image1[random_id].copy()
                image1[random_id] = image
                return_images.append(tmp)

            else:
                return_images.append(image)
    output = Tensor(return_images, ms.float32)
    if output.ndim != 4:
        raise ValueError("img should be 4d, but get shape {}".format(output.shape))
    return output

image_pool 函数:存储生成器生成的历史图像,并根据一定的概率返回这些历史图像或最新生成的图像。

discriminator_forward 函数:对判别器训练并计算损失

generator_forward 函数:对生成器训练并计算损失

<think>嗯,用户想绘制一个包含管理员、系统配置、保安、考勤、绩效、任务、地点、设备这些实体的ER图。首先,我需要理清每个实体的属性和它们之间的关系。管理员和系统配置之间应该是一对多的关系,因为一个管理员可能管理多个配置。保安可能和考勤、绩效、任务有关联。考勤和绩效可能需要记录保安的工作情况,所以可能是保安与考勤、绩效之间的一对多关系。任务可能涉及多个保安和多个地点,所以任务和保安之间是多对多,任务和地点也是一样。设备可能属于某个地点,所以地点和设备是一对多。系统配置由管理员管理,这个关系需要明确。然后,是否需要考虑绩效如何与任务或考勤关联?比如绩效可能基于考勤记录和任务完成情况。另外,设备可能有维护任务,是否需要和设备关联?可能保安负责某些设备,或者设备属于地点。需要确认用户的具体业务逻辑,但根据现有信息,先按照常见情况设计。使用工具的话,Navicat可以生成ER图,但需要先创建表结构,设置外键。可能需要检查是否有遗漏的关系,比如任务和设备是否有联系,或者绩效是否与其他实体有关联。引用中提到多对多关系需要用中间表处理,比如保安任务和任务地点之间的中间表。导出ER图时要注意去掉中文注释,确保SQL正确性。最后,用户可能需要步骤指导,比如创建实体、确定关系、使用工具绘制、验证导出等。需要参考引用中的ER图绘制方法和注意事项。</think>### 如何绘制包含多实体的关系型ER图? #### 步骤1:**明确实体及其属性** 根据需求定义以下实体及核心属性: 1. **管理员**:管理员ID(主键)、姓名、权限等级 2. **系统配置**:配置ID(主键)、参数名称、参数值 3. **保安**:保安ID(主键)、姓名、所属部门 4. **考勤**:考勤ID(主键)、打卡时间、考勤状态 5. **绩效**:绩效ID(主键)、评分日期、综合评分 6. **任务**:任务ID(主键)、任务名称、执行状态 7. **地点**:地点ID(主键)、位置名称、区域编号 8. **设备**:设备ID(主键)、设备类型、维护记录 #### 步骤2:**定义实体间关系** 1. **管理员 ↔ 系统配置** - 1:n(一个管理员管理多个系统配置) - 外键:系统配置表中添加`管理员ID`字段 2. **保安 ↔ 考勤/绩效** - 保安与考勤:1:n(一个保安有多次考勤记录) - 保安与绩效:1:n(一个保安对应多条绩效评分) - 外键:考勤表和绩效表中添加`保安ID`字段 3. **保安 ↔ 任务** - n:m(多个保安执行多个任务) - 需创建中间表`保安任务`,包含`保安ID`和`任务ID` 4. **任务 ↔ 地点** - n:m(任务可能涉及多个地点) - 需创建中间表`任务地点`,包含`任务ID`和`地点ID` 5. **地点 ↔ 设备** - 1:n(一个地点包含多个设备) - 外键:设备表中添加`地点ID` #### 步骤3:**使用工具绘制ER图** 推荐使用Navicat或MySQL Workbench: 1. **创建表结构**:根据上述实体和关系设计数据库表 2. **添加外键约束**:通过工具设置关联关系(如管理员ID关联系统配置) 3. **生成ER图**:Navicat中右键数据库选择“逆向数据库到模型”[^3] 4. **调整布局**:手动优化实体位置,明确多对多关系(如任务与地点) #### 步骤4:**验证与导出** 1. **检查关系**:确保外键正确映射,删除冗余字段 2. **导出ER图**:保存为PNG或PDF格式,注意去掉表名中文注释[^4] 3. **生成SQL脚本**:用于后续部署到测试服务器 --- ### ER图示例(逻辑结构) ```plaintext 管理员 (1) ———— 管理 ———— (n) 系统配置 保安 (1) ———— 关联 ———— (n) 考勤 保安 (1) ———— 关联 ———— (n) 绩效 保安 (n) ———— 保安任务 ———— (m) 任务 任务 (n) ———— 任务地点 ———— (m) 地点 地点 (1) ———— 包含 ———— (n) 设备 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值